Commit 062009c7 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by Kevin Modzelewski

AST interpreter cleanup

- Move internal definitions from header to source file
- Fix root_stack_set bug carried over from llvm_interpreter
- Cut off access to the old llvm interpreter
- Slightly tune the tiering thresholds
 - They seem too high but our LLVM compilation is overly expensive right now
 - Our AST interpreter is also somewhat slow due to its string handling
parent a3f136e1
...@@ -24,3 +24,14 @@ the JIT'd code. ...@@ -24,3 +24,14 @@ the JIT'd code.
There's a gprof-based profile, but that doesn't support any JIT'd code. It can be quite handy for profiling the Pyston There's a gprof-based profile, but that doesn't support any JIT'd code. It can be quite handy for profiling the Pyston
codegen + LLVM cost. codegen + LLVM cost.
We also have a few internal timers that log important sections of code. You can see their totals by passing '-s' to
the executable (ARGS=-s to a Make recipe).
Some common ones are:
- us_compiling: total amount of time (in microseconds) spent in 'codegen', from
the time we decide we want to run some Python code to the point that we can
start executing it
- us_compiling_irgen: total time creating the LLVM IR. includes some analysis time
- us_compiling_jitting: subset of us_compiling which is spent in LLVM
compilation (time from giving LLVM its IR to when we get machine code back)
...@@ -70,8 +70,8 @@ public: ...@@ -70,8 +70,8 @@ public:
// assert(name[0] != '#' && "should test this"); // assert(name[0] != '#' && "should test this");
return true; return true;
} }
bool refersToClosure(const std::string name) override { return false; } bool refersToClosure(const std::string& name) override { return false; }
bool saveInClosure(const std::string name) override { return false; } bool saveInClosure(const std::string& name) override { return false; }
const std::unordered_set<std::string>& getClassDefLocalNames() override { RELEASE_ASSERT(0, ""); } const std::unordered_set<std::string>& getClassDefLocalNames() override { RELEASE_ASSERT(0, ""); }
}; };
...@@ -141,13 +141,13 @@ public: ...@@ -141,13 +141,13 @@ public:
return true; return true;
return usage->written.count(name) == 0 && usage->got_from_closure.count(name) == 0; return usage->written.count(name) == 0 && usage->got_from_closure.count(name) == 0;
} }
bool refersToClosure(const std::string name) override { bool refersToClosure(const std::string& name) override {
// HAX // HAX
if (isCompilerCreatedName(name)) if (isCompilerCreatedName(name))
return false; return false;
return usage->got_from_closure.count(name) != 0; return usage->got_from_closure.count(name) != 0;
} }
bool saveInClosure(const std::string name) override { bool saveInClosure(const std::string& name) override {
// HAX // HAX
if (isCompilerCreatedName(name)) if (isCompilerCreatedName(name))
return false; return false;
......
...@@ -36,8 +36,8 @@ public: ...@@ -36,8 +36,8 @@ public:
virtual void setTakesGenerator(bool b = true) { isGeneratorValue = b; } virtual void setTakesGenerator(bool b = true) { isGeneratorValue = b; }
virtual bool refersToGlobal(const std::string& name) = 0; virtual bool refersToGlobal(const std::string& name) = 0;
virtual bool refersToClosure(const std::string name) = 0; virtual bool refersToClosure(const std::string& name) = 0;
virtual bool saveInClosure(const std::string name) = 0; virtual bool saveInClosure(const std::string& name) = 0;
// Get the names set within a classdef that should be forwarded on to // Get the names set within a classdef that should be forwarded on to
// the metaclass constructor. // the metaclass constructor.
......
...@@ -14,15 +14,19 @@ ...@@ -14,15 +14,19 @@
#include "codegen/ast_interpreter.h" #include "codegen/ast_interpreter.h"
#include <llvm/ADT/StringMap.h>
#include <unordered_map> #include <unordered_map>
#include "analysis/function_analysis.h" #include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h"
#include "codegen/irgen.h"
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
#include "codegen/irgen/irgenerator.h" #include "codegen/irgen/irgenerator.h"
#include "codegen/irgen/util.h" #include "codegen/irgen/util.h"
#include "codegen/osrentry.h" #include "codegen/osrentry.h"
#include "core/ast.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/common.h" #include "core/common.h"
#include "core/stats.h" #include "core/stats.h"
...@@ -32,19 +36,112 @@ ...@@ -32,19 +36,112 @@
#include "runtime/import.h" #include "runtime/import.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
#include "runtime/types.h" #include "runtime/types.h"
namespace pyston { namespace pyston {
typedef std::vector<const ASTInterpreter::SymMap*> root_stack_t; #define OSR_THRESHOLD 100
static threading::PerThreadSet<root_stack_t> root_stack_set; #define REOPT_THRESHOLD 100
union Value {
bool b;
int64_t n;
double d;
Box* o;
Value(bool b) : b(b) {}
Value(int64_t n = 0) : n(n) {}
Value(double d) : d(d) {}
Value(Box* o) : o(o) {}
};
class ASTInterpreter {
public:
typedef llvm::StringMap<Box*> SymMap;
ASTInterpreter(CompiledFunction* compiled_function, void* frame_addr);
~ASTInterpreter();
void initArguments(int nargs, BoxedClosure* closure, BoxedGenerator* generator, Box* arg1, Box* arg2, Box* arg3,
Box** args);
Value execute(CFGBlock* block = 0);
private:
Box* createFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body);
Value doBinOp(Box* left, Box* right, int op, BinExpType exp_type);
void doStore(AST_expr* node, Value value);
void doStore(const std::string& name, Value value);
void eraseDeadSymbols();
Value visit_assert(AST_Assert* node);
Value visit_assign(AST_Assign* node);
Value visit_binop(AST_BinOp* node);
Value visit_call(AST_Call* node);
Value visit_classDef(AST_ClassDef* node);
Value visit_compare(AST_Compare* node);
Value visit_delete(AST_Delete* node);
Value visit_functionDef(AST_FunctionDef* node);
Value visit_global(AST_Global* node);
Value visit_module(AST_Module* node);
Value visit_print(AST_Print* node);
Value visit_raise(AST_Raise* node);
Value visit_return(AST_Return* node);
Value visit_stmt(AST_stmt* node);
Value visit_unaryop(AST_UnaryOp* node);
Value visit_attribute(AST_Attribute* node);
Value visit_dict(AST_Dict* node);
Value visit_expr(AST_expr* node);
Value visit_expr(AST_Expr* node);
Value visit_index(AST_Index* node);
Value visit_lambda(AST_Lambda* node);
Value visit_list(AST_List* node);
Value visit_name(AST_Name* node);
Value visit_num(AST_Num* node);
Value visit_repr(AST_Repr* node);
Value visit_set(AST_Set* node);
Value visit_slice(AST_Slice* node);
Value visit_str(AST_Str* node);
Value visit_subscript(AST_Subscript* node);
Value visit_tuple(AST_Tuple* node);
Value visit_yield(AST_Yield* node);
// pseudo
Value visit_augBinOp(AST_AugBinOp* node);
Value visit_branch(AST_Branch* node);
Value visit_clsAttribute(AST_ClsAttribute* node);
Value visit_invoke(AST_Invoke* node);
Value visit_jump(AST_Jump* node);
Value visit_langPrimitive(AST_LangPrimitive* node);
void* frame_addr;
CompiledFunction* compiled_func;
SourceInfo* source_info;
ScopeInfo* scope_info;
SymMap sym_table;
CFGBlock* next_block, *current_block;
AST* current_inst;
Box* last_exception;
BoxedClosure* passed_closure, *created_closure;
BoxedGenerator* generator;
unsigned edgecount;
public:
LineInfo* getCurrentLineInfo();
BoxedModule* getParentModule() { return source_info->parent_module; }
const SymMap& getSymbolTable() { return sym_table; }
};
static_assert(THREADING_USE_GIL, "have to make the interpreter map thread safe!");
static std::unordered_map<void*, ASTInterpreter*> s_interpreterMap; static std::unordered_map<void*, ASTInterpreter*> s_interpreterMap;
Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2,
Box* arg3, Box** args) { Box* arg3, Box** args) {
if (unlikely(cf->times_called > 100)) { if (unlikely(cf->times_called > REOPT_THRESHOLD)) {
CompiledFunction* optimized = reoptCompiledFuncInternal(cf); CompiledFunction* optimized = reoptCompiledFuncInternal(cf);
if (closure && generator) if (closure && generator)
return optimized->closure_generator_call((BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, return optimized->closure_generator_call((BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2,
...@@ -58,36 +155,38 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge ...@@ -58,36 +155,38 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
++cf->times_called; ++cf->times_called;
ASTInterpreter interpreter(cf); void* frame_addr = __builtin_frame_address(0);
s_interpreterMap[__builtin_frame_address(0)] = &interpreter; ASTInterpreter interpreter(cf, frame_addr);
interpreter.initArguments(nargs, (BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, arg3, args); interpreter.initArguments(nargs, (BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, arg3, args);
Value v = interpreter.execute(); Value v = interpreter.execute();
s_interpreterMap.erase(__builtin_frame_address(0));
return v.o ? v.o : None; return v.o ? v.o : None;
} }
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) { const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
ASTInterpreter* interpreter = s_interpreterMap[frame_ptr]; ASTInterpreter* interpreter = s_interpreterMap[frame_ptr];
assert(interpreter); assert(interpreter);
SourceInfo* info = interpreter->source_info; return interpreter->getCurrentLineInfo();
LineInfo* line_info = new LineInfo(interpreter->current_inst->lineno, interpreter->current_inst->col_offset, }
info->parent_module->fn, info->getName());
LineInfo* ASTInterpreter::getCurrentLineInfo() {
LineInfo* line_info = new LineInfo(current_inst->lineno, current_inst->col_offset, source_info->parent_module->fn,
source_info->getName());
return line_info; return line_info;
} }
BoxedModule* getModuleForInterpretedFrame(void* frame_ptr) { BoxedModule* getModuleForInterpretedFrame(void* frame_ptr) {
ASTInterpreter* interpreter = s_interpreterMap[frame_ptr]; ASTInterpreter* interpreter = s_interpreterMap[frame_ptr];
assert(interpreter); assert(interpreter);
return interpreter->source_info->parent_module; return interpreter->getParentModule();
} }
BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) { BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
ASTInterpreter* interpreter = s_interpreterMap[frame_ptr]; ASTInterpreter* interpreter = s_interpreterMap[frame_ptr];
assert(interpreter); assert(interpreter);
BoxedDict* rtn = new BoxedDict(); BoxedDict* rtn = new BoxedDict();
for (auto&& l : interpreter->sym_table) { for (auto&& l : interpreter->getSymbolTable()) {
if (only_user_visible && (l.getKey()[0] == '!' || l.getKey()[0] == '#')) if (only_user_visible && (l.getKey()[0] == '!' || l.getKey()[0] == '#'))
continue; continue;
...@@ -97,31 +196,31 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) { ...@@ -97,31 +196,31 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
} }
void gatherInterpreterRoots(GCVisitor* visitor) { void gatherInterpreterRoots(GCVisitor* visitor) {
root_stack_set.forEachValue(std::function<void(root_stack_t*, GCVisitor*)>([](root_stack_t* v, GCVisitor* visitor) { for (const auto& p : s_interpreterMap) {
for (const ASTInterpreter::SymMap* sym_map : *v) { for (const auto& p2 : p.second->getSymbolTable()) {
for (const auto& p2 : *sym_map) {
visitor->visitPotential(p2.second); visitor->visitPotential(p2.second);
} }
} }
}),
visitor);
} }
ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function) ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function, void* frame_addr)
: source_info(compiled_function->clfunc->source), next_block(0), current_block(0), current_inst(0), : frame_addr(frame_addr), compiled_func(compiled_function), source_info(compiled_function->clfunc->source),
last_exception(0), passed_closure(0), created_closure(0), generator(0), scope_info(0), scope_info(0), next_block(0), current_block(0), current_inst(0), last_exception(0), passed_closure(0),
compiled_func(compiled_function), edgecount(0) { created_closure(0), generator(0), edgecount(0) {
s_interpreterMap[frame_addr] = this;
CLFunction* f = compiled_function->clfunc; CLFunction* f = compiled_function->clfunc;
if (!source_info->cfg) if (!source_info->cfg)
source_info->cfg = computeCFG(f->source, f->source->body); source_info->cfg = computeCFG(f->source, f->source->body);
scope_info = source_info->getScopeInfo(); scope_info = source_info->getScopeInfo();
root_stack_set.get()->push_back(&sym_table);
} }
ASTInterpreter::~ASTInterpreter() { ASTInterpreter::~ASTInterpreter() {
root_stack_set.get()->pop_back(); assert(s_interpreterMap[frame_addr] == this);
s_interpreterMap.erase(frame_addr);
} }
void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGenerator* _generator, Box* arg1, Box* arg2, void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGenerator* _generator, Box* arg1, Box* arg2,
...@@ -283,7 +382,7 @@ Value ASTInterpreter::visit_branch(AST_Branch* node) { ...@@ -283,7 +382,7 @@ Value ASTInterpreter::visit_branch(AST_Branch* node) {
Value ASTInterpreter::visit_jump(AST_Jump* node) { Value ASTInterpreter::visit_jump(AST_Jump* node) {
if (ENABLE_OSR && node->target->idx < current_block->idx && compiled_func) { if (ENABLE_OSR && node->target->idx < current_block->idx && compiled_func) {
++edgecount; ++edgecount;
if (edgecount > 10) { if (edgecount > OSR_THRESHOLD) {
eraseDeadSymbols(); eraseDeadSymbols();
OSRExit exit(compiled_func, OSREntryDescriptor::create(compiled_func, node)); OSRExit exit(compiled_func, OSREntryDescriptor::create(compiled_func, node));
...@@ -298,7 +397,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -298,7 +397,7 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
if (phis->isPotentiallyUndefinedAfter(name, current_block)) { if (phis->isPotentiallyUndefinedAfter(name, current_block)) {
bool is_defined = it != sym_table.end(); bool is_defined = it != sym_table.end();
sorted_symbol_table["!is_defined_" + name] = (Box*)is_defined; sorted_symbol_table[getIsDefinedName(name)] = (Box*)is_defined;
sorted_symbol_table[name] = is_defined ? it->getValue() : NULL; sorted_symbol_table[name] = is_defined ? it->getValue() : NULL;
} else { } else {
ASSERT(it != sym_table.end(), "%s", name.c_str()); ASSERT(it != sym_table.end(), "%s", name.c_str());
...@@ -307,24 +406,26 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) { ...@@ -307,24 +406,26 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
} }
if (generator) if (generator)
sorted_symbol_table["!passed_generator"] = generator; // TODO use PASSED_GENERATOR_NAME instead sorted_symbol_table[PASSED_GENERATOR_NAME] = generator;
if (passed_closure) if (passed_closure)
sorted_symbol_table["!passed_closure"] = passed_closure; // TODO use PASSED_CLOSURE_NAME instead sorted_symbol_table[PASSED_CLOSURE_NAME] = passed_closure;
if (created_closure) if (created_closure)
sorted_symbol_table["!created_closure"] = created_closure; // TODO use CREATED_CLOSURE_NAME instead sorted_symbol_table[CREATED_CLOSURE_NAME] = created_closure;
std::vector<Box*> arg_array; std::vector<Box*> arg_array;
for (auto& it : sorted_symbol_table) { for (auto& it : sorted_symbol_table) {
if (startswith(it.first, "!is_defined")) if (isIsDefinedName(it.first))
exit.entry->args[it.first] = BOOL; exit.entry->args[it.first] = BOOL;
else if (it.first == "!passed_generator") // TODO use PASSED_GENERATOR_NAME else if (it.first == PASSED_GENERATOR_NAME)
exit.entry->args[it.first] = GENERATOR; exit.entry->args[it.first] = GENERATOR;
else if (it.first == "!passed_closure" || it.first == "!created_closure") // TODO don't hardcode else if (it.first == PASSED_CLOSURE_NAME || it.first == CREATED_CLOSURE_NAME)
exit.entry->args[it.first] = CLOSURE; exit.entry->args[it.first] = CLOSURE;
else else {
assert(it.first[0] != '!');
exit.entry->args[it.first] = UNKNOWN; exit.entry->args[it.first] = UNKNOWN;
}
arg_array.push_back(it.second); arg_array.push_back(it.second);
} }
......
...@@ -15,12 +15,6 @@ ...@@ -15,12 +15,6 @@
#ifndef PYSTON_CODEGEN_ASTINTERPRETER_H #ifndef PYSTON_CODEGEN_ASTINTERPRETER_H
#define PYSTON_CODEGEN_ASTINTERPRETER_H #define PYSTON_CODEGEN_ASTINTERPRETER_H
#include <llvm/ADT/StringMap.h>
#include "codegen/compvars.h"
#include "core/ast.h"
#include "runtime/objmodel.h"
namespace pyston { namespace pyston {
namespace gc { namespace gc {
...@@ -28,7 +22,9 @@ class GCVisitor; ...@@ -28,7 +22,9 @@ class GCVisitor;
} }
class Box; class Box;
class CLFunction; class BoxedDict;
class BoxedModule;
struct CompiledFunction;
struct LineInfo; struct LineInfo;
Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3, Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3,
...@@ -37,90 +33,8 @@ Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* gen ...@@ -37,90 +33,8 @@ Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* gen
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr); const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr);
BoxedModule* getModuleForInterpretedFrame(void* frame_ptr); BoxedModule* getModuleForInterpretedFrame(void* frame_ptr);
union Value { void gatherInterpreterRoots(gc::GCVisitor* visitor);
bool b; BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible);
int64_t n;
double d;
Box* o;
Value(bool b) : b(b) {}
Value(int64_t n = 0) : n(n) {}
Value(double d) : d(d) {}
Value(Box* o) : o(o) {}
};
class ASTInterpreter {
public:
typedef llvm::StringMap<Box*> SymMap;
ASTInterpreter(CompiledFunction* compiled_function);
~ASTInterpreter();
void initArguments(int nargs, BoxedClosure* closure, BoxedGenerator* generator, Box* arg1, Box* arg2, Box* arg3,
Box** args);
Value execute(CFGBlock* block = 0);
private:
Box* createFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body);
Value doBinOp(Box* left, Box* right, int op, BinExpType exp_type);
void doStore(AST_expr* node, Value value);
void doStore(const std::string& name, Value value);
void eraseDeadSymbols();
Value visit_assert(AST_Assert* node);
Value visit_assign(AST_Assign* node);
Value visit_binop(AST_BinOp* node);
Value visit_call(AST_Call* node);
Value visit_classDef(AST_ClassDef* node);
Value visit_compare(AST_Compare* node);
Value visit_delete(AST_Delete* node);
Value visit_functionDef(AST_FunctionDef* node);
Value visit_global(AST_Global* node);
Value visit_module(AST_Module* node);
Value visit_print(AST_Print* node);
Value visit_raise(AST_Raise* node);
Value visit_return(AST_Return* node);
Value visit_stmt(AST_stmt* node);
Value visit_unaryop(AST_UnaryOp* node);
Value visit_attribute(AST_Attribute* node);
Value visit_dict(AST_Dict* node);
Value visit_expr(AST_expr* node);
Value visit_expr(AST_Expr* node);
Value visit_index(AST_Index* node);
Value visit_lambda(AST_Lambda* node);
Value visit_list(AST_List* node);
Value visit_name(AST_Name* node);
Value visit_num(AST_Num* node);
Value visit_repr(AST_Repr* node);
Value visit_set(AST_Set* node);
Value visit_slice(AST_Slice* node);
Value visit_str(AST_Str* node);
Value visit_subscript(AST_Subscript* node);
Value visit_tuple(AST_Tuple* node);
Value visit_yield(AST_Yield* node);
// pseudo
Value visit_augBinOp(AST_AugBinOp* node);
Value visit_branch(AST_Branch* node);
Value visit_clsAttribute(AST_ClsAttribute* node);
Value visit_invoke(AST_Invoke* node);
Value visit_jump(AST_Jump* node);
Value visit_langPrimitive(AST_LangPrimitive* node);
public:
SourceInfo* source_info;
SymMap sym_table;
CFGBlock* next_block, *current_block;
AST* current_inst;
Box* last_exception;
BoxedClosure* passed_closure, *created_closure;
BoxedGenerator* generator;
ScopeInfo* scope_info;
CompiledFunction* compiled_func;
unsigned edgecount;
};
} }
#endif #endif
...@@ -279,7 +279,7 @@ computeBlockTraversalOrder(const BlockSet& full_blocks, const BlockSet& partial_ ...@@ -279,7 +279,7 @@ computeBlockTraversalOrder(const BlockSet& full_blocks, const BlockSet& partial_
} }
static ConcreteCompilerType* getTypeAtBlockStart(TypeAnalysis* types, const std::string& name, CFGBlock* block) { static ConcreteCompilerType* getTypeAtBlockStart(TypeAnalysis* types, const std::string& name, CFGBlock* block) {
if (startswith(name, "!is_defined")) if (isIsDefinedName(name))
return BOOL; return BOOL;
else if (name == PASSED_GENERATOR_NAME) else if (name == PASSED_GENERATOR_NAME)
return GENERATOR; return GENERATOR;
...@@ -410,7 +410,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -410,7 +410,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
assert(p.first[0] != '!'); assert(p.first[0] != '!');
std::string is_defined_name = "!is_defined_" + p.first; std::string is_defined_name = getIsDefinedName(p.first);
llvm::BasicBlock* defined_join = nullptr, * defined_prev = nullptr, * defined_check = nullptr; llvm::BasicBlock* defined_join = nullptr, * defined_prev = nullptr, * defined_check = nullptr;
if (entry_descriptor->args.count(is_defined_name)) { if (entry_descriptor->args.count(is_defined_name)) {
// relying on the fact that we are iterating over the names in order // relying on the fact that we are iterating over the names in order
...@@ -658,7 +658,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -658,7 +658,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
for (const auto& s : source->phis->getAllRequiredFor(block)) { for (const auto& s : source->phis->getAllRequiredFor(block)) {
names.insert(s); names.insert(s);
if (source->phis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) { if (source->phis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) {
names.insert("!is_defined_" + s); names.insert(getIsDefinedName(s));
} }
} }
...@@ -840,7 +840,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -840,7 +840,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
llvm_phi->addIncoming(v->getValue(), osr_unbox_block); llvm_phi->addIncoming(v->getValue(), osr_unbox_block);
} }
std::string is_defined_name = "!is_defined_" + it->first; std::string is_defined_name = getIsDefinedName(it->first);
for (int i = 0; i < block_guards.size(); i++) { for (int i = 0; i < block_guards.size(); i++) {
GuardList::BlockEntryGuard* guard = block_guards[i]; GuardList::BlockEntryGuard* guard = block_guards[i];
......
...@@ -79,6 +79,13 @@ public: ...@@ -79,6 +79,13 @@ public:
ExcInfo exc_info) = 0; ExcInfo exc_info) = 0;
}; };
extern const std::string CREATED_CLOSURE_NAME;
extern const std::string PASSED_CLOSURE_NAME;
extern const std::string PASSED_GENERATOR_NAME;
std::string getIsDefinedName(const std::string& name);
bool isIsDefinedName(const std::string& name);
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor, CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix); EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix);
......
...@@ -256,6 +256,14 @@ const std::string CREATED_CLOSURE_NAME = "!created_closure"; ...@@ -256,6 +256,14 @@ const std::string CREATED_CLOSURE_NAME = "!created_closure";
const std::string PASSED_CLOSURE_NAME = "!passed_closure"; const std::string PASSED_CLOSURE_NAME = "!passed_closure";
const std::string PASSED_GENERATOR_NAME = "!passed_generator"; const std::string PASSED_GENERATOR_NAME = "!passed_generator";
std::string getIsDefinedName(const std::string& name) {
return "!is_defined_" + name;
}
bool isIsDefinedName(const std::string& name) {
return startswith(name, "!is_defined_");
}
class IRGeneratorImpl : public IRGenerator { class IRGeneratorImpl : public IRGenerator {
private: private:
IRGenState* irstate; IRGenState* irstate;
...@@ -411,8 +419,8 @@ private: ...@@ -411,8 +419,8 @@ private:
if (p.first[0] == '!' || p.first[0] == '#') if (p.first[0] == '!' || p.first[0] == '#')
continue; continue;
ConcreteCompilerVariable* is_defined_var = static_cast<ConcreteCompilerVariable*>( ConcreteCompilerVariable* is_defined_var
_getFake(_getFakeName("is_defined", p.first.c_str()), true)); = static_cast<ConcreteCompilerVariable*>(_getFake(getIsDefinedName(p.first), true));
static const std::string setitem_str("__setitem__"); static const std::string setitem_str("__setitem__");
if (!is_defined_var) { if (!is_defined_var) {
...@@ -822,7 +830,7 @@ private: ...@@ -822,7 +830,7 @@ private:
return undefVariable(); return undefVariable();
} }
std::string defined_name = _getFakeName("is_defined", node->id.c_str()); std::string defined_name = getIsDefinedName(node->id);
ConcreteCompilerVariable* is_defined_var ConcreteCompilerVariable* is_defined_var
= static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true)); = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true));
...@@ -1272,12 +1280,6 @@ private: ...@@ -1272,12 +1280,6 @@ private:
return rtn; return rtn;
} }
static std::string _getFakeName(const char* prefix, const char* token) {
char buf[40];
snprintf(buf, 40, "!%s_%s", prefix, token);
return std::string(buf);
}
void _setFake(std::string name, CompilerVariable* val) { void _setFake(std::string name, CompilerVariable* val) {
assert(name[0] == '!'); assert(name[0] == '!');
CompilerVariable*& cur = symbol_table[name]; CompilerVariable*& cur = symbol_table[name];
...@@ -1326,8 +1328,8 @@ private: ...@@ -1326,8 +1328,8 @@ private:
val->incvref(); val->incvref();
// Clear out the is_defined name since it is now definitely defined: // Clear out the is_defined name since it is now definitely defined:
assert(!startswith(name, "!is_defined")); assert(!isIsDefinedName(name));
std::string defined_name = _getFakeName("is_defined", name.c_str()); std::string defined_name = getIsDefinedName(name);
_popFake(defined_name, true); _popFake(defined_name, true);
if (scope_info->saveInClosure(name)) { if (scope_info->saveInClosure(name)) {
...@@ -1614,7 +1616,7 @@ private: ...@@ -1614,7 +1616,7 @@ private:
return; return;
} }
std::string defined_name = _getFakeName("is_defined", target->id.c_str()); std::string defined_name = getIsDefinedName(target->id);
ConcreteCompilerVariable* is_defined_var = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true)); ConcreteCompilerVariable* is_defined_var = static_cast<ConcreteCompilerVariable*>(_getFake(defined_name, true));
if (is_defined_var) { if (is_defined_var) {
...@@ -2141,7 +2143,7 @@ private: ...@@ -2141,7 +2143,7 @@ private:
} }
bool allowableFakeEndingSymbol(const std::string& name) { bool allowableFakeEndingSymbol(const std::string& name) {
return startswith(name, "!is_defined") || name == PASSED_CLOSURE_NAME || name == CREATED_CLOSURE_NAME return isIsDefinedName(name) || name == PASSED_CLOSURE_NAME || name == CREATED_CLOSURE_NAME
|| name == PASSED_GENERATOR_NAME; || name == PASSED_GENERATOR_NAME;
} }
...@@ -2159,7 +2161,7 @@ private: ...@@ -2159,7 +2161,7 @@ private:
continue; continue;
} }
// ASSERT(it->first[0] != '!' || startswith(it->first, "!is_defined"), "left a fake variable in the real // ASSERT(it->first[0] != '!' || isIsDefinedName(it->first), "left a fake variable in the real
// symbol table? '%s'", it->first.c_str()); // symbol table? '%s'", it->first.c_str());
if (!source->liveness->isLiveAtEnd(it->first, myblock)) { if (!source->liveness->isLiveAtEnd(it->first, myblock)) {
...@@ -2200,7 +2202,7 @@ private: ...@@ -2200,7 +2202,7 @@ private:
assert(!scope_info->refersToGlobal(*it)); assert(!scope_info->refersToGlobal(*it));
CompilerVariable*& cur = symbol_table[*it]; CompilerVariable*& cur = symbol_table[*it];
std::string defined_name = _getFakeName("is_defined", it->c_str()); std::string defined_name = getIsDefinedName(*it);
if (cur != NULL) { if (cur != NULL) {
// printf("defined on this path; "); // printf("defined on this path; ");
...@@ -2291,7 +2293,7 @@ public: ...@@ -2291,7 +2293,7 @@ public:
assert(it->second->getVrefs() == 1); assert(it->second->getVrefs() == 1);
// this conversion should have already happened... should refactor this. // this conversion should have already happened... should refactor this.
ConcreteCompilerType* ending_type; ConcreteCompilerType* ending_type;
if (startswith(it->first, "!is_defined")) { if (isIsDefinedName(it->first)) {
assert(it->second->getType() == BOOL); assert(it->second->getType() == BOOL);
ending_type = BOOL; ending_type = BOOL;
} else if (it->first == PASSED_CLOSURE_NAME) { } else if (it->first == PASSED_CLOSURE_NAME) {
......
...@@ -29,12 +29,14 @@ class Box; ...@@ -29,12 +29,14 @@ class Box;
class BoxedDict; class BoxedDict;
struct LineInfo; struct LineInfo;
#if 0
Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3, Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3,
Box** args); Box** args);
void gatherInterpreterRoots(gc::GCVisitor* visitor); void gatherInterpreterRoots(gc::GCVisitor* visitor);
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr); const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr);
BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible); BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible);
#endif
} }
#endif #endif
...@@ -308,7 +308,7 @@ public: ...@@ -308,7 +308,7 @@ public:
int code = unw_get_proc_info(&this->cursor, &pip); int code = unw_get_proc_info(&this->cursor, &pip);
RELEASE_ASSERT(code == 0, "%d", code); RELEASE_ASSERT(code == 0, "%d", code);
if (pip.start_ip == (intptr_t)interpretFunction || pip.start_ip == (intptr_t)astInterpretFunction) { if (pip.start_ip == (intptr_t)astInterpretFunction) {
unw_word_t bp; unw_word_t bp;
unw_get_reg(&this->cursor, UNW_TDEP_BP, &bp); unw_get_reg(&this->cursor, UNW_TDEP_BP, &bp);
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include <setjmp.h> #include <setjmp.h>
#include <vector> #include <vector>
#include "codegen/ast_interpreter.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/llvm_interpreter.h"
#include "core/common.h" #include "core/common.h"
#include "core/threading.h" #include "core/threading.h"
#include "gc/collector.h" #include "gc/collector.h"
......
# expected: fail
def f((a,b)):
print a,b
f(range(2))
f((1, 2))
def gen():
while True:
for i in xrange(100):
range(100) * 1000 # allocate memory to force GC collections
b = yield 0
if b:
break
done = []
def thread_run(g):
for i in xrange(5):
g.next()
try:
g.send(1)
assert 0
except StopIteration:
pass
done.append(0)
g = gen()
for i in xrange(5):
g.next()
from thread import start_new_thread
t = start_new_thread(thread_run, (g,))
g = ""
def f():
pass
f()
f()
import time
while not done:
time.sleep(0.1)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment