Commit 218d8cd5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #228 from kmod/interp2

New AST interpreter
parents bb3a19e1 062009c7
...@@ -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)
...@@ -459,7 +459,13 @@ bool PhiAnalysis::isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* ...@@ -459,7 +459,13 @@ bool PhiAnalysis::isPotentiallyUndefinedAfter(const std::string& name, CFGBlock*
if (block->successors.size() != 1) if (block->successors.size() != 1)
return false; return false;
for (CFGBlock* pred : block->successors[0]->predecessors) { return isPotentiallyUndefinedAt(name, block->successors[0]);
}
bool PhiAnalysis::isPotentiallyUndefinedAt(const std::string& name, CFGBlock* block) {
assert(!startswith(name, "!"));
for (CFGBlock* pred : block->predecessors) {
DefinednessAnalysis::DefinitionLevel dlevel = definedness.isDefinedAtEnd(name, pred); DefinednessAnalysis::DefinitionLevel dlevel = definedness.isDefinedAtEnd(name, pred);
if (dlevel != DefinednessAnalysis::Defined) if (dlevel != DefinednessAnalysis::Defined)
return true; return true;
......
...@@ -84,8 +84,9 @@ class PhiAnalysis { ...@@ -84,8 +84,9 @@ class PhiAnalysis {
public: public:
typedef std::unordered_set<std::string> RequiredSet; typedef std::unordered_set<std::string> RequiredSet;
private:
DefinednessAnalysis definedness; DefinednessAnalysis definedness;
private:
LivenessAnalysis* liveness; LivenessAnalysis* liveness;
std::unordered_map<CFGBlock*, const RequiredSet> required_phis; std::unordered_map<CFGBlock*, const RequiredSet> required_phis;
...@@ -97,6 +98,7 @@ public: ...@@ -97,6 +98,7 @@ public:
const RequiredSet& getAllRequiredAfter(CFGBlock* block); const RequiredSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllRequiredFor(CFGBlock* block); const RequiredSet& getAllRequiredFor(CFGBlock* block);
bool isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block); bool isPotentiallyUndefinedAfter(const std::string& name, CFGBlock* block);
bool isPotentiallyUndefinedAt(const std::string& name, CFGBlock* block);
}; };
LivenessAnalysis* computeLivenessInfo(CFG*); LivenessAnalysis* computeLivenessInfo(CFG*);
......
...@@ -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.
......
This diff is collapsed.
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CODEGEN_ASTINTERPRETER_H
#define PYSTON_CODEGEN_ASTINTERPRETER_H
namespace pyston {
namespace gc {
class GCVisitor;
}
class Box;
class BoxedDict;
class BoxedModule;
struct CompiledFunction;
struct LineInfo;
Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3,
Box** args);
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr);
BoxedModule* getModuleForInterpretedFrame(void* frame_ptr);
void gatherInterpreterRoots(gc::GCVisitor* visitor);
BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible);
}
#endif
This diff is collapsed.
...@@ -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);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "analysis/function_analysis.h" #include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "asm_writing/icinfo.h" #include "asm_writing/icinfo.h"
#include "codegen/ast_interpreter.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "codegen/irgen.h" #include "codegen/irgen.h"
...@@ -137,7 +138,6 @@ static std::unordered_map<std::string, CompiledFunction*> machine_name_to_cf; ...@@ -137,7 +138,6 @@ static std::unordered_map<std::string, CompiledFunction*> machine_name_to_cf;
CompiledFunction* cfForMachineFunctionName(const std::string& machine_name) { CompiledFunction* cfForMachineFunctionName(const std::string& machine_name) {
assert(machine_name.size()); assert(machine_name.size());
auto r = machine_name_to_cf[machine_name]; auto r = machine_name_to_cf[machine_name];
ASSERT(r, "%s", machine_name.c_str());
return r; return r;
} }
...@@ -185,17 +185,29 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E ...@@ -185,17 +185,29 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
// Do the analysis now if we had deferred it earlier: // Do the analysis now if we had deferred it earlier:
if (source->cfg == NULL) { if (source->cfg == NULL) {
assert(source->ast);
source->cfg = computeCFG(source, source->body); source->cfg = computeCFG(source, source->body);
source->liveness = computeLivenessInfo(source->cfg);
source->phis = computeRequiredPhis(source->arg_names, source->cfg, source->liveness, source->getScopeInfo());
} }
CompiledFunction* cf = doCompile(source, entry, effort, spec, name); if (effort != EffortLevel::INTERPRETED) {
if (source->liveness == NULL)
source->liveness = computeLivenessInfo(source->cfg);
if (source->phis == NULL)
source->phis
= computeRequiredPhis(source->arg_names, source->cfg, source->liveness, source->getScopeInfo());
}
registerMachineName(cf->func->getName(), cf);
compileIR(cf, effort); CompiledFunction* cf = 0;
if (effort == EffortLevel::INTERPRETED) {
cf = new CompiledFunction(0, spec, true, NULL, NULL, effort, 0);
} else {
cf = doCompile(source, entry, effort, spec, name);
registerMachineName(cf->func->getName(), cf);
compileIR(cf, effort);
}
f->addVersion(cf); f->addVersion(cf);
assert(f->versions.size()); assert(f->versions.size());
...@@ -252,10 +264,6 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -252,10 +264,6 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
ScopingAnalysis* scoping = runScopingAnalysis(m); ScopingAnalysis* scoping = runScopingAnalysis(m);
SourceInfo* si = new SourceInfo(bm, scoping, m, m->body); SourceInfo* si = new SourceInfo(bm, scoping, m, m->body);
si->cfg = computeCFG(si, m->body);
si->liveness = computeLivenessInfo(si->cfg);
si->phis = computeRequiredPhis(si->arg_names, si->cfg, si->liveness, si->getScopeInfo());
CLFunction* cl_f = new CLFunction(0, 0, false, false, si); CLFunction* cl_f = new CLFunction(0, 0, false, false, si);
EffortLevel::EffortLevel effort = initialEffort(); EffortLevel::EffortLevel effort = initialEffort();
...@@ -265,7 +273,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -265,7 +273,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
} }
if (cf->is_interpreted) if (cf->is_interpreted)
interpretFunction(cf->func, 0, NULL, NULL, NULL, NULL, NULL, NULL); astInterpretFunction(cf, 0, NULL, NULL, NULL, NULL, NULL, NULL);
else else
((void (*)())cf->code)(); ((void (*)())cf->code)();
} }
...@@ -311,7 +319,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel ...@@ -311,7 +319,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
} }
static StatCounter stat_osrexits("OSR exits"); static StatCounter stat_osrexits("OSR exits");
void* compilePartialFunc(OSRExit* exit) { CompiledFunction* compilePartialFuncInternal(OSRExit* exit) {
LOCK_REGION(codegen_rwlock.asWrite()); LOCK_REGION(codegen_rwlock.asWrite());
assert(exit); assert(exit);
...@@ -334,11 +342,16 @@ void* compilePartialFunc(OSRExit* exit) { ...@@ -334,11 +342,16 @@ void* compilePartialFunc(OSRExit* exit) {
assert(compiled = new_cf); assert(compiled = new_cf);
} }
return new_cf->code; return new_cf;
} }
void* compilePartialFunc(OSRExit* exit) {
return compilePartialFuncInternal(exit)->code;
}
static StatCounter stat_reopt("reopts"); static StatCounter stat_reopt("reopts");
extern "C" char* reoptCompiledFunc(CompiledFunction* cf) { extern "C" CompiledFunction* reoptCompiledFuncInternal(CompiledFunction* cf) {
if (VERBOSITY("irgen") >= 1) if (VERBOSITY("irgen") >= 1)
printf("In reoptCompiledFunc, %p, %ld\n", cf, cf->times_called); printf("In reoptCompiledFunc, %p, %ld\n", cf, cf->times_called);
stat_reopt.log(); stat_reopt.log();
...@@ -347,7 +360,12 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) { ...@@ -347,7 +360,12 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) {
assert(cf->clfunc->versions.size()); assert(cf->clfunc->versions.size());
CompiledFunction* new_cf = _doReopt(cf, (EffortLevel::EffortLevel(cf->effort + 1))); CompiledFunction* new_cf = _doReopt(cf, (EffortLevel::EffortLevel(cf->effort + 1)));
assert(!new_cf->is_interpreted); assert(!new_cf->is_interpreted);
return (char*)new_cf->code; return new_cf;
}
extern "C" char* reoptCompiledFunc(CompiledFunction* cf) {
return (char*)reoptCompiledFuncInternal(cf)->code;
} }
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs) { CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs) {
......
...@@ -23,7 +23,9 @@ struct CompiledFunction; ...@@ -23,7 +23,9 @@ struct CompiledFunction;
class CLFunction; class CLFunction;
class OSRExit; class OSRExit;
CompiledFunction* compilePartialFuncInternal(OSRExit* exit);
void* compilePartialFunc(OSRExit*); void* compilePartialFunc(OSRExit*);
extern "C" CompiledFunction* reoptCompiledFuncInternal(CompiledFunction*);
extern "C" char* reoptCompiledFunc(CompiledFunction*); extern "C" char* reoptCompiledFunc(CompiledFunction*);
class AST_Module; class AST_Module;
......
...@@ -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)) {
...@@ -1496,7 +1498,7 @@ private: ...@@ -1496,7 +1498,7 @@ private:
decorators.push_back(evalExpr(d, exc_info)); decorators.push_back(evalExpr(d, exc_info));
} }
CLFunction* cl = _wrapFunction(node, nullptr, node->body); CLFunction* cl = wrapFunction(node, nullptr, node->body, irstate->getSourceInfo());
// TODO duplication with _createFunction: // TODO duplication with _createFunction:
CompilerVariable* created_closure = NULL; CompilerVariable* created_closure = NULL;
...@@ -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) {
...@@ -1628,27 +1630,9 @@ private: ...@@ -1628,27 +1630,9 @@ private:
symbol_table.erase(target->id); symbol_table.erase(target->id);
} }
CLFunction* _wrapFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body) {
// Different compilations of the parent scope of a functiondef should lead
// to the same CLFunction* being used:
static std::unordered_map<AST*, CLFunction*> made;
CLFunction*& cl = made[node];
if (cl == NULL) {
SourceInfo* source = irstate->getSourceInfo();
SourceInfo* si = new SourceInfo(source->parent_module, source->scoping, node, body);
if (args)
cl = new CLFunction(args->args.size(), args->defaults.size(), args->vararg.size(), args->kwarg.size(),
si);
else
cl = new CLFunction(0, 0, 0, 0, si);
}
return cl;
}
CompilerVariable* _createFunction(AST* node, ExcInfo exc_info, AST_arguments* args, CompilerVariable* _createFunction(AST* node, ExcInfo exc_info, AST_arguments* args,
const std::vector<AST_stmt*>& body) { const std::vector<AST_stmt*>& body) {
CLFunction* cl = this->_wrapFunction(node, args, body); CLFunction* cl = wrapFunction(node, args, body, irstate->getSourceInfo());
std::vector<ConcreteCompilerVariable*> defaults; std::vector<ConcreteCompilerVariable*> defaults;
for (auto d : args->defaults) { for (auto d : args->defaults) {
...@@ -2159,7 +2143,7 @@ private: ...@@ -2159,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;
} }
...@@ -2177,7 +2161,7 @@ private: ...@@ -2177,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)) {
...@@ -2218,7 +2202,7 @@ private: ...@@ -2218,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; ");
...@@ -2309,7 +2293,7 @@ public: ...@@ -2309,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) {
...@@ -2456,4 +2440,20 @@ IRGenerator* createIRGenerator(IRGenState* irstate, std::unordered_map<CFGBlock* ...@@ -2456,4 +2440,20 @@ IRGenerator* createIRGenerator(IRGenState* irstate, std::unordered_map<CFGBlock*
const GuardList& in_guards, bool is_partial) { const GuardList& in_guards, bool is_partial) {
return new IRGeneratorImpl(irstate, entry_blocks, myblock, types, out_guards, in_guards, is_partial); return new IRGeneratorImpl(irstate, entry_blocks, myblock, types, out_guards, in_guards, is_partial);
} }
CLFunction* wrapFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body, SourceInfo* source) {
// Different compilations of the parent scope of a functiondef should lead
// to the same CLFunction* being used:
static std::unordered_map<AST*, CLFunction*> made;
CLFunction*& cl = made[node];
if (cl == NULL) {
SourceInfo* si = new SourceInfo(source->parent_module, source->scoping, node, body);
if (args)
cl = new CLFunction(args->args.size(), args->defaults.size(), args->vararg.size(), args->kwarg.size(), si);
else
cl = new CLFunction(0, 0, 0, 0, si);
}
return cl;
}
} }
...@@ -46,6 +46,7 @@ extern const std::string CREATED_CLOSURE_NAME; ...@@ -46,6 +46,7 @@ extern const std::string CREATED_CLOSURE_NAME;
extern const std::string PASSED_CLOSURE_NAME; extern const std::string PASSED_CLOSURE_NAME;
extern const std::string PASSED_GENERATOR_NAME; extern const std::string PASSED_GENERATOR_NAME;
// Class that holds state of the current IR generation, that might not be local // Class that holds state of the current IR generation, that might not be local
// to the specific phase or pass we're in. // to the specific phase or pass we're in.
// TODO this probably shouldn't be here // TODO this probably shouldn't be here
...@@ -205,6 +206,8 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock, IRG ...@@ -205,6 +206,8 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock, IRG
IRGenerator* createIRGenerator(IRGenState* irstate, std::unordered_map<CFGBlock*, llvm::BasicBlock*>& entry_blocks, IRGenerator* createIRGenerator(IRGenState* irstate, std::unordered_map<CFGBlock*, llvm::BasicBlock*>& entry_blocks,
CFGBlock* myblock, TypeAnalysis* types, GuardList& out_guards, CFGBlock* myblock, TypeAnalysis* types, GuardList& out_guards,
const GuardList& in_guards, bool is_partial); const GuardList& in_guards, bool is_partial);
CLFunction* wrapFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body, SourceInfo* source);
} }
#endif #endif
...@@ -219,8 +219,8 @@ static void set(SymMap& symbols, const llvm::BasicBlock::iterator& it, Val v) { ...@@ -219,8 +219,8 @@ static void set(SymMap& symbols, const llvm::BasicBlock::iterator& it, Val v) {
static std::unordered_map<void*, llvm::Instruction*> cur_instruction_map; static std::unordered_map<void*, llvm::Instruction*> cur_instruction_map;
typedef std::vector<const SymMap*> root_stack_t; typedef std::vector<const SymMap*> root_stack_t;
threading::PerThreadSet<root_stack_t> root_stack_set; static threading::PerThreadSet<root_stack_t> root_stack_set;
/*
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) { root_stack_set.forEachValue(std::function<void(root_stack_t*, GCVisitor*)>([](root_stack_t* v, GCVisitor* visitor) {
for (const SymMap* sym_map : *v) { for (const SymMap* sym_map : *v) {
...@@ -231,7 +231,8 @@ void gatherInterpreterRoots(GCVisitor* visitor) { ...@@ -231,7 +231,8 @@ void gatherInterpreterRoots(GCVisitor* visitor) {
}), }),
visitor); visitor);
} }
*/
#if 0
BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) { BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
llvm::Instruction* inst = cur_instruction_map[frame_ptr]; llvm::Instruction* inst = cur_instruction_map[frame_ptr];
assert(inst); assert(inst);
...@@ -285,6 +286,7 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) { ...@@ -285,6 +286,7 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
return rtn; return rtn;
} }
#endif
class UnregisterHelper { class UnregisterHelper {
private: private:
...@@ -302,6 +304,7 @@ public: ...@@ -302,6 +304,7 @@ public:
}; };
static std::unordered_map<llvm::Instruction*, LineInfo*> line_infos; static std::unordered_map<llvm::Instruction*, LineInfo*> line_infos;
/*
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) { const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
llvm::Instruction* cur_instruction = cur_instruction_map[frame_ptr]; llvm::Instruction* cur_instruction = cur_instruction_map[frame_ptr];
assert(cur_instruction); assert(cur_instruction);
...@@ -319,7 +322,7 @@ const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) { ...@@ -319,7 +322,7 @@ const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
return it->second; return it->second;
} }
} }
*/
void dumpLLVM(llvm::Value* v) { void dumpLLVM(llvm::Value* v) {
v->dump(); v->dump();
} }
......
...@@ -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
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfo.h"
#include "codegen/ast_interpreter.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
...@@ -307,7 +308,7 @@ public: ...@@ -307,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) { 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);
...@@ -401,12 +402,19 @@ CompiledFunction* getTopCompiledFunction() { ...@@ -401,12 +402,19 @@ CompiledFunction* getTopCompiledFunction() {
assert(last_entry->func.size()); assert(last_entry->func.size());
CompiledFunction* cf = cfForMachineFunctionName(last_entry->func); CompiledFunction* cf = cfForMachineFunctionName(last_entry->func);
assert(cf);
return cf; return cf;
} }
BoxedModule* getCurrentModule() { BoxedModule* getCurrentModule() {
return getTopCompiledFunction()->clfunc->source->parent_module; CompiledFunction* compiledFunction = getTopCompiledFunction();
if (compiledFunction)
return compiledFunction->clfunc->source->parent_module;
else {
std::unique_ptr<PythonFrameIterator> frame = getTopPythonFrame();
auto& id = frame->getId();
assert(id.type == PythonFrameId::INTERPRETED);
return getModuleForInterpretedFrame((void*)id.bp);
}
} }
BoxedDict* getLocals(bool only_user_visible) { BoxedDict* getLocals(bool only_user_visible) {
......
...@@ -288,7 +288,6 @@ public: ...@@ -288,7 +288,6 @@ public:
void addVersion(CompiledFunction* compiled) { void addVersion(CompiledFunction* compiled) {
assert(compiled); assert(compiled);
assert((source == NULL) == (compiled->func == NULL));
assert(compiled->spec); assert(compiled->spec);
assert(compiled->spec->arg_types.size() == num_args + (takes_varargs ? 1 : 0) + (takes_kwargs ? 1 : 0)); assert(compiled->spec->arg_types.size() == num_args + (takes_varargs ? 1 : 0) + (takes_kwargs ? 1 : 0));
assert(compiled->clfunc == NULL); assert(compiled->clfunc == NULL);
......
...@@ -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"
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "asm_writing/icinfo.h" #include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h" #include "asm_writing/rewriter.h"
#include "codegen/ast_interpreter.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
...@@ -2486,7 +2487,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg ...@@ -2486,7 +2487,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
assert(chosen_cf->is_interpreted == (chosen_cf->code == NULL)); assert(chosen_cf->is_interpreted == (chosen_cf->code == NULL));
if (chosen_cf->is_interpreted) { if (chosen_cf->is_interpreted) {
return interpretFunction(chosen_cf->func, num_output_args, closure, generator, oarg1, oarg2, oarg3, oargs); return astInterpretFunction(chosen_cf, num_output_args, closure, generator, oarg1, oarg2, oarg3, oargs);
} }
if (rewrite_args) { if (rewrite_args) {
......
...@@ -31,9 +31,11 @@ extern "C" Box* createSet(); ...@@ -31,9 +31,11 @@ extern "C" Box* createSet();
class BoxedSet : public Box { class BoxedSet : public Box {
public: public:
std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*> > s; typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*> > Set;
Set s;
BoxedSet(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {} BoxedSet(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {}
BoxedSet(Set&& s, BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls), s(s) {}
}; };
} }
......
# 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