Skip to content

Commit

Permalink
Merge pull request #1011 from undingen/new_frame_intro2
Browse files Browse the repository at this point in the history
Cheaper frame introspection
  • Loading branch information
undingen committed Dec 4, 2015
2 parents b2d7f22 + 199448f commit ff657c1
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 244 deletions.
10 changes: 3 additions & 7 deletions src/analysis/scoping_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ static InternedString mangleName(InternedString id, llvm::StringRef private_name
return rtn;
}

static bool isCompilerCreatedName(llvm::StringRef name) {
return name[0] == '!' || name[0] == '#';
}

class ModuleScopeInfo : public ScopeInfo {
public:
ScopeInfo* getParent() override { return NULL; }
Expand All @@ -121,7 +117,7 @@ class ModuleScopeInfo : public ScopeInfo {
bool passesThroughClosure() override { return false; }

VarScopeType getScopeTypeOfName(InternedString name) override {
if (isCompilerCreatedName(name))
if (name.isCompilerCreatedName())
return VarScopeType::FAST;
else
return VarScopeType::GLOBAL;
Expand Down Expand Up @@ -185,7 +181,7 @@ class EvalExprScopeInfo : public ScopeInfo {
bool passesThroughClosure() override { return false; }

VarScopeType getScopeTypeOfName(InternedString name) override {
if (isCompilerCreatedName(name))
if (name.isCompilerCreatedName())
return VarScopeType::FAST;
else if (forced_globals.find(name) != forced_globals.end())
return VarScopeType::GLOBAL;
Expand Down Expand Up @@ -341,7 +337,7 @@ class ScopeInfoBase : public ScopeInfo {
bool passesThroughClosure() override { return usage->passthrough_accesses.size() > 0 && !createsClosure(); }

VarScopeType getScopeTypeOfName(InternedString name) override {
if (isCompilerCreatedName(name))
if (name.isCompilerCreatedName())
return VarScopeType::FAST;

if (usage->forced_globals.count(name) > 0)
Expand Down
107 changes: 48 additions & 59 deletions src/codegen/ast_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class ASTInterpreter {

Box** vregs;
ExcInfo last_exception;
BoxedClosure* passed_closure, *created_closure;
BoxedClosure* created_closure;
BoxedGenerator* generator;
unsigned edgecount;
FrameInfo frame_info;
Expand Down Expand Up @@ -174,7 +174,7 @@ class ASTInterpreter {

FunctionMetadata* getMD() { return md; }
FrameInfo* getFrameInfo() { return &frame_info; }
BoxedClosure* getPassedClosure() { return passed_closure; }
BoxedClosure* getPassedClosure() { return frame_info.passed_closure; }
Box** getVRegs() { return vregs; }
const ScopeInfo* getScopeInfo() { return scope_info; }

Expand Down Expand Up @@ -203,9 +203,9 @@ void ASTInterpreter::setGenerator(Box* gen) {
}

void ASTInterpreter::setPassedClosure(Box* closure) {
assert(!this->passed_closure); // This should only used for initialization
assert(closure->cls == closure_cls);
this->passed_closure = static_cast<BoxedClosure*>(closure);
assert(!frame_info.passed_closure); // This should only used for initialization
assert(!closure || closure->cls == closure_cls);
frame_info.passed_closure = static_cast<BoxedClosure*>(closure);
}

void ASTInterpreter::setCreatedClosure(Box* closure) {
Expand Down Expand Up @@ -236,7 +236,6 @@ ASTInterpreter::ASTInterpreter(FunctionMetadata* md, Box** vregs)
phis(NULL),
vregs(vregs),
last_exception(NULL, NULL, NULL),
passed_closure(0),
created_closure(0),
generator(0),
edgecount(0),
Expand All @@ -246,17 +245,18 @@ ASTInterpreter::ASTInterpreter(FunctionMetadata* md, Box** vregs)
should_jit(false) {

scope_info = source_info->getScopeInfo();
frame_info.vregs = vregs;

assert(scope_info);
}

void ASTInterpreter::initArguments(BoxedClosure* _closure, BoxedGenerator* _generator, Box* arg1, Box* arg2, Box* arg3,
Box** args) {
passed_closure = _closure;
setPassedClosure(_closure);
generator = _generator;

if (scope_info->createsClosure())
created_closure = createClosure(passed_closure, scope_info->getClosureSize());
created_closure = createClosure(_closure, scope_info->getClosureSize());

const ParamNames& param_names = md->param_names;

Expand Down Expand Up @@ -407,17 +407,6 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b

Box* ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block, AST_stmt* start_at) {
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_interpreter");

// Note: due to some (avoidable) restrictions, this check is pretty constrained in where
// it can go, due to the fact that it can throw an exception.
// It can't go in the ASTInterpreter constructor, since that will cause the C++ runtime to
// delete the partially-constructed memory which we don't currently handle. It can't go into
// executeInner since we want the SyntaxErrors to happen *before* the stack frame is entered.
// (For instance, throwing the exception will try to fetch the current statement, but we determine
// that by looking at the cfg.)
if (!interpreter.source_info->cfg)
interpreter.source_info->cfg = computeCFG(interpreter.source_info, interpreter.source_info->body);

return executeInnerAndSetupFrame(interpreter, start_block, start_at);
}

Expand Down Expand Up @@ -724,8 +713,8 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
if (generator)
sorted_symbol_table[source_info->getInternedStrings().get(PASSED_GENERATOR_NAME)] = generator;

if (passed_closure)
sorted_symbol_table[source_info->getInternedStrings().get(PASSED_CLOSURE_NAME)] = passed_closure;
if (frame_info.passed_closure)
sorted_symbol_table[source_info->getInternedStrings().get(PASSED_CLOSURE_NAME)] = frame_info.passed_closure;

if (created_closure)
sorted_symbol_table[source_info->getInternedStrings().get(CREATED_CLOSURE_NAME)] = created_closure;
Expand Down Expand Up @@ -1038,9 +1027,9 @@ Value ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::
closure_var = jit->getInterp()->getAttr(offsetof(ASTInterpreter, created_closure));
} else {
assert(scope_info->passesThroughClosure());
closure = passed_closure;
closure = frame_info.passed_closure;
if (jit)
closure_var = jit->getInterp()->getAttr(offsetof(ASTInterpreter, passed_closure));
closure_var = jit->getInterp()->getAttr(offsetof(ASTInterpreter, frame_info.passed_closure));
}
assert(closure);
}
Expand Down Expand Up @@ -1105,7 +1094,7 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
BoxedClosure* closure = NULL;
if (scope_info->takesClosure()) {
if (this->scope_info->passesThroughClosure())
closure = passed_closure;
closure = getPassedClosure();
else
closure = created_closure;
assert(closure);
Expand Down Expand Up @@ -1633,8 +1622,8 @@ void ASTInterpreterJitInterface::delNameHelper(void* _interpreter, InternedStrin
Box* ASTInterpreterJitInterface::derefHelper(void* _interpreter, InternedString s) {
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
DerefInfo deref_info = interpreter->scope_info->getDerefInfo(s);
assert(interpreter->passed_closure);
BoxedClosure* closure = interpreter->passed_closure;
assert(interpreter->getPassedClosure());
BoxedClosure* closure = interpreter->getPassedClosure();
for (int i = 0; i < deref_info.num_parents_from_passed_closure; i++) {
closure = closure->parent;
}
Expand Down Expand Up @@ -1698,28 +1687,6 @@ extern "C" Box* executeInnerFromASM(ASTInterpreter& interpreter, CFGBlock* start
return ASTInterpreter::executeInner(interpreter, start_block, start_at);
}

static int calculateNumVRegs(FunctionMetadata* md) {
SourceInfo* source_info = md->source.get();

CFG* cfg = source_info->cfg;

// Note: due to some (avoidable) restrictions, this check is pretty constrained in where
// it can go, due to the fact that it can throw an exception.
// It can't go in the ASTInterpreter constructor, since that will cause the C++ runtime to
// delete the partially-constructed memory which we don't currently handle. It can't go into
// executeInner since we want the SyntaxErrors to happen *before* the stack frame is entered.
// (For instance, throwing the exception will try to fetch the current statement, but we determine
// that by looking at the cfg.)
if (!cfg)
cfg = source_info->cfg = computeCFG(source_info, source_info->body);

if (!cfg->hasVregsAssigned()) {
ScopeInfo* scope_info = md->source->getScopeInfo();
cfg->assignVRegs(md->param_names, scope_info);
}
return cfg->sym_vreg_map.size();
}

Box* astInterpretFunction(FunctionMetadata* md, Box* closure, Box* generator, Box* globals, Box* arg1, Box* arg2,
Box* arg3, Box** args) {
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_interpreter");
Expand Down Expand Up @@ -1785,8 +1752,18 @@ Box* astInterpretFunction(FunctionMetadata* md, Box* closure, Box* generator, Bo
}
}

// Note: due to some (avoidable) restrictions, this check is pretty constrained in where
// it can go, due to the fact that it can throw an exception.
// It can't go in the ASTInterpreter constructor, since that will cause the C++ runtime to
// delete the partially-constructed memory which we don't currently handle. It can't go into
// executeInner since we want the SyntaxErrors to happen *before* the stack frame is entered.
// (For instance, throwing the exception will try to fetch the current statement, but we determine
// that by looking at the cfg.)
if (!source_info->cfg)
source_info->cfg = computeCFG(source_info, source_info->body);

Box** vregs = NULL;
int num_vregs = calculateNumVRegs(md);
int num_vregs = md->calculateNumVRegs();
if (num_vregs > 0) {
vregs = (Box**)alloca(sizeof(Box*) * num_vregs);
memset(vregs, 0, sizeof(Box*) * num_vregs);
Expand Down Expand Up @@ -1816,8 +1793,19 @@ Box* astInterpretFunction(FunctionMetadata* md, Box* closure, Box* generator, Bo
Box* astInterpretFunctionEval(FunctionMetadata* md, Box* globals, Box* boxedLocals) {
++md->times_interpreted;

// Note: due to some (avoidable) restrictions, this check is pretty constrained in where
// it can go, due to the fact that it can throw an exception.
// It can't go in the ASTInterpreter constructor, since that will cause the C++ runtime to
// delete the partially-constructed memory which we don't currently handle. It can't go into
// executeInner since we want the SyntaxErrors to happen *before* the stack frame is entered.
// (For instance, throwing the exception will try to fetch the current statement, but we determine
// that by looking at the cfg.)
SourceInfo* source_info = md->source.get();
if (!source_info->cfg)
source_info->cfg = computeCFG(source_info, source_info->body);

Box** vregs = NULL;
int num_vregs = calculateNumVRegs(md);
int num_vregs = md->calculateNumVRegs();
if (num_vregs > 0) {
vregs = (Box**)alloca(sizeof(Box*) * num_vregs);
memset(vregs, 0, sizeof(Box*) * num_vregs);
Expand Down Expand Up @@ -1848,7 +1836,7 @@ static Box* astInterpretDeoptInner(FunctionMetadata* md, AST_expr* after_expr, A
SourceInfo* source_info = md->source.get();

Box** vregs = NULL;
int num_vregs = calculateNumVRegs(md);
int num_vregs = md->calculateNumVRegs();
if (num_vregs > 0) {
vregs = (Box**)alloca(sizeof(Box*) * num_vregs);
memset(vregs, 0, sizeof(Box*) * num_vregs);
Expand Down Expand Up @@ -1973,15 +1961,16 @@ FrameInfo* getFrameInfoForInterpretedFrame(void* frame_ptr) {
return interpreter->getFrameInfo();
}

BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
Box** getVRegsForInterpretedFrame(void* frame_ptr) {
ASTInterpreter* interpreter = getInterpreterFromFramePtr(frame_ptr);
assert(interpreter);
BoxedDict* rtn = new BoxedDict();
for (auto& l : interpreter->getSymVRegMap()) {
if (only_user_visible && (l.first.s()[0] == '!' || l.first.s()[0] == '#'))
continue;
return interpreter->getVRegs();
}

Box* val = interpreter->getVRegs()[l.second];
BoxedDict* localsForInterpretedFrame(Box** vregs, CFG* cfg) {
BoxedDict* rtn = new BoxedDict();
for (auto& l : cfg->sym_vreg_map_user_visible) {
Box* val = vregs[l.second];
if (val) {
assert(gc::isValidGCObject(val));
rtn->d[l.first.getBox()] = val;
Expand All @@ -1991,9 +1980,9 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
return rtn;
}

BoxedClosure* passedClosureForInterpretedFrame(void* frame_ptr) {
BoxedDict* localsForInterpretedFrame(void* frame_ptr) {
ASTInterpreter* interpreter = getInterpreterFromFramePtr(frame_ptr);
assert(interpreter);
return interpreter->getPassedClosure();
return localsForInterpretedFrame(interpreter->getVRegs(), interpreter->getMD()->source->cfg);
}
}
5 changes: 3 additions & 2 deletions src/codegen/ast_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ Box* getGlobalsForInterpretedFrame(void* frame_ptr);
FunctionMetadata* getMDForInterpretedFrame(void* frame_ptr);
struct FrameInfo;
FrameInfo* getFrameInfoForInterpretedFrame(void* frame_ptr);
BoxedClosure* passedClosureForInterpretedFrame(void* frame_ptr);

BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible);
Box** getVRegsForInterpretedFrame(void* frame_ptr);
BoxedDict* localsForInterpretedFrame(Box** vregs, CFG* cfg);
BoxedDict* localsForInterpretedFrame(void* frame_ptr);

// Executes the equivalent of CPython's PRINT_EXPR opcode (call sys.displayhook)
extern "C" void printExprHelper(Box* b);
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/baseline_jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, llvm::

// make space for patchpoint
uint8_t* pp_start = rewrite->getSlotStart() + assembler->bytesWritten();
constexpr int call_size = 16;
constexpr int call_size = 13;
assembler->skipBytes(pp_size + call_size);
uint8_t* pp_end = rewrite->getSlotStart() + assembler->bytesWritten();
assert(assembler->hasFailed() || (pp_start + pp_size + call_size == pp_end));
Expand Down
15 changes: 15 additions & 0 deletions src/codegen/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "codegen/baseline_jit.h"
#include "codegen/compvars.h"
#include "core/ast.h"
#include "core/cfg.h"
#include "core/util.h"
#include "runtime/code.h"
#include "runtime/types.h"
Expand Down Expand Up @@ -72,6 +73,20 @@ BoxedCode* FunctionMetadata::getCode() {
return code_obj;
}

int FunctionMetadata::calculateNumVRegs() {
SourceInfo* source_info = source.get();

CFG* cfg = source_info->cfg;
assert(cfg && "We don't calculate the CFG inside this function because it can raise an exception and its "
"therefore not safe to call at every point");

if (!cfg->hasVregsAssigned()) {
ScopeInfo* scope_info = source->getScopeInfo();
cfg->assignVRegs(param_names, scope_info);
}
return cfg->sym_vreg_map.size();
}

void FunctionMetadata::addVersion(CompiledFunction* compiled) {
assert(compiled);
assert((compiled->spec != NULL) + (compiled->entry_descriptor != NULL) == 1);
Expand Down
1 change: 1 addition & 0 deletions src/codegen/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ void PystonObjectCache::calculateModuleHash(const llvm::Module* M, EffortLevel e
HashOStream hash_stream;
llvm::WriteBitcodeToFile(M, hash_stream);
hash_stream << (int)effort;
hash_stream << USE_REGALLOC_BASIC;
hash_before_codegen = hash_stream.getHash();
}

Expand Down
2 changes: 2 additions & 0 deletions src/codegen/irgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ class IREmitter {
virtual void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val,
llvm::Value* exc_val, bool double_check = false) = 0;

virtual llvm::Value* createDeopt(AST_stmt* current_stmt, AST_expr* node, llvm::Value* node_value) = 0;

virtual Box* getIntConstant(int64_t n) = 0;
virtual Box* getFloatConstant(double d) = 0;
};
Expand Down
Loading

0 comments on commit ff657c1

Please sign in to comment.