Commit faa290b8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make 'is_generator' be a property of SourceInfo, not ScopeInfo

ScopeInfo involves checking the whole function subtree to resolve
scoping references.  SourceInfo has information about the specific
function.  is_generator used to be in ScopeInfo, but accessing it
would require doing the full subtree analysis, which can be
unnecessary.

This lets us avoid analyzing function subtrees that are never entered.
parent 2a50251c
...@@ -448,13 +448,11 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -448,13 +448,11 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
case AST_TYPE::FunctionDef: case AST_TYPE::FunctionDef:
case AST_TYPE::Lambda: { case AST_TYPE::Lambda: {
ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage); ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage);
scopeInfo->setTakesGenerator(containsYield(node));
this->scopes[node] = scopeInfo; this->scopes[node] = scopeInfo;
break; break;
} }
case AST_TYPE::GeneratorExp: { case AST_TYPE::GeneratorExp: {
ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage); ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage);
scopeInfo->setTakesGenerator(true);
this->scopes[node] = scopeInfo; this->scopes[node] = scopeInfo;
break; break;
} }
......
...@@ -24,7 +24,7 @@ class AST_Module; ...@@ -24,7 +24,7 @@ class AST_Module;
class ScopeInfo { class ScopeInfo {
public: public:
ScopeInfo() : isGeneratorValue(false) {} ScopeInfo() {}
virtual ~ScopeInfo() {} virtual ~ScopeInfo() {}
virtual ScopeInfo* getParent() = 0; virtual ScopeInfo* getParent() = 0;
...@@ -32,9 +32,6 @@ public: ...@@ -32,9 +32,6 @@ public:
virtual bool takesClosure() = 0; virtual bool takesClosure() = 0;
virtual bool passesThroughClosure() = 0; virtual bool passesThroughClosure() = 0;
virtual bool takesGenerator() { return isGeneratorValue; }
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;
...@@ -43,9 +40,6 @@ public: ...@@ -43,9 +40,6 @@ public:
// the metaclass constructor. // the metaclass constructor.
// An error to call this on a non-classdef node. // An error to call this on a non-classdef node.
virtual const std::unordered_set<std::string>& getClassDefLocalNames() = 0; virtual const std::unordered_set<std::string>& getClassDefLocalNames() = 0;
protected:
bool isGeneratorValue;
}; };
class ScopingAnalysis { class ScopingAnalysis {
......
...@@ -136,6 +136,7 @@ public: ...@@ -136,6 +136,7 @@ public:
CompiledFunction* getCF() { return compiled_func; } CompiledFunction* getCF() { return compiled_func; }
const SymMap& getSymbolTable() { return sym_table; } const SymMap& getSymbolTable() { return sym_table; }
void gcVisit(GCVisitor* visitor);
}; };
const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute; const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute;
...@@ -201,11 +202,22 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) { ...@@ -201,11 +202,22 @@ BoxedDict* localsForInterpretedFrame(void* frame_ptr, bool only_user_visible) {
return rtn; return rtn;
} }
void ASTInterpreter::gcVisit(GCVisitor* visitor) {
for (const auto& p2 : getSymbolTable()) {
visitor->visitPotential(p2.second);
}
if (passed_closure)
visitor->visit(passed_closure);
if (created_closure)
visitor->visit(created_closure);
if (generator)
visitor->visit(generator);
}
void gatherInterpreterRoots(GCVisitor* visitor) { void gatherInterpreterRoots(GCVisitor* visitor) {
for (const auto& p : s_interpreterMap) { for (const auto& p : s_interpreterMap) {
for (const auto& p2 : p.second->getSymbolTable()) { p.second->gcVisit(visitor);
visitor->visitPotential(p2.second);
}
} }
} }
...@@ -633,11 +645,22 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v ...@@ -633,11 +645,22 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v
u.d.ptr = &defaults[0]; u.d.ptr = &defaults[0];
u.d.s = defaults.size() - 1; u.d.s = defaults.size() - 1;
ScopeInfo* scope_info_node = source_info->scoping->getScopeInfoForNode(node); bool takes_closure;
bool is_generator = scope_info_node->takesGenerator(); // Optimization: when compiling a module, it's nice to not have to run analyses into the
// entire module's source code.
// If we call getScopeInfoForNode, that will trigger an analysis of that function tree,
// but we're only using it here to figure out if that function takes a closure.
// Top level functions never take a closure, so we can skip the analysis.
if (source_info->ast->type == AST_TYPE::Module)
takes_closure = false;
else {
takes_closure = source_info->scoping->getScopeInfoForNode(node)->takesClosure();
}
bool is_generator = cl->source->is_generator;
BoxedClosure* closure = 0; BoxedClosure* closure = 0;
if (scope_info_node->takesClosure()) { if (takes_closure) {
if (scope_info->createsClosure()) { if (scope_info->createsClosure()) {
closure = created_closure; closure = created_closure;
} else { } else {
......
...@@ -24,12 +24,31 @@ ...@@ -24,12 +24,31 @@
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "analysis/scoping_analysis.h"
#include "core/ast.h"
#include "core/util.h" #include "core/util.h"
namespace pyston { namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock); DS_DEFINE_RWLOCK(codegen_rwlock);
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body)
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), phis(NULL), arg_names(ast), body(body) {
switch (ast->type) {
case AST_TYPE::ClassDef:
case AST_TYPE::Lambda:
case AST_TYPE::Module:
is_generator = false;
break;
case AST_TYPE::FunctionDef:
is_generator = containsYield(ast);
break;
default:
RELEASE_ASSERT(0, "Unknown type: %d", ast->type);
break;
}
}
void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length, void FunctionAddressRegistry::registerFunction(const std::string& name, void* addr, int length,
llvm::Function* llvm_func) { llvm::Function* llvm_func) {
assert(addr); assert(addr);
......
...@@ -718,7 +718,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -718,7 +718,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
if (source->getScopeInfo()->takesClosure()) if (source->getScopeInfo()->takesClosure())
names.insert(PASSED_CLOSURE_NAME); names.insert(PASSED_CLOSURE_NAME);
if (source->getScopeInfo()->takesGenerator()) if (source->is_generator)
names.insert(PASSED_GENERATOR_NAME); names.insert(PASSED_GENERATOR_NAME);
for (const auto& s : names) { for (const auto& s : names) {
...@@ -1138,7 +1138,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_ ...@@ -1138,7 +1138,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
if (source->getScopeInfo()->takesClosure()) if (source->getScopeInfo()->takesClosure())
llvm_arg_types.push_back(g.llvm_closure_type_ptr); llvm_arg_types.push_back(g.llvm_closure_type_ptr);
if (source->getScopeInfo()->takesGenerator()) if (source->is_generator)
llvm_arg_types.push_back(g.llvm_generator_type_ptr); llvm_arg_types.push_back(g.llvm_generator_type_ptr);
for (int i = 0; i < nargs; i++) { for (int i = 0; i < nargs; i++) {
......
...@@ -502,7 +502,7 @@ private: ...@@ -502,7 +502,7 @@ private:
assert(node->args[0]->type == AST_TYPE::Name); assert(node->args[0]->type == AST_TYPE::Name);
RELEASE_ASSERT(irstate->getSourceInfo()->ast->type == AST_TYPE::Module, RELEASE_ASSERT(irstate->getSourceInfo()->ast->type == AST_TYPE::Module,
"import * not supported in functions"); "import * not supported in functions (yet)");
CompilerVariable* module = evalExpr(node->args[0], unw_info); CompilerVariable* module = evalExpr(node->args[0], unw_info);
ConcreteCompilerVariable* converted_module = module->makeConverted(emitter, module->getBoxType()); ConcreteCompilerVariable* converted_module = module->makeConverted(emitter, module->getBoxType());
...@@ -1642,8 +1642,7 @@ private: ...@@ -1642,8 +1642,7 @@ private:
takes_closure = irstate->getScopeInfoForNode(node)->takesClosure(); takes_closure = irstate->getScopeInfoForNode(node)->takesClosure();
} }
// TODO: this lines disables the optimization mentioned above... bool is_generator = cl->source->is_generator;
bool is_generator = irstate->getScopeInfoForNode(node)->takesGenerator();
if (takes_closure) { if (takes_closure) {
if (irstate->getScopeInfo()->createsClosure()) { if (irstate->getScopeInfo()->createsClosure()) {
...@@ -2362,7 +2361,7 @@ public: ...@@ -2362,7 +2361,7 @@ public:
_setFake(CREATED_CLOSURE_NAME, new ConcreteCompilerVariable(getCreatedClosureType(), new_closure, true)); _setFake(CREATED_CLOSURE_NAME, new ConcreteCompilerVariable(getCreatedClosureType(), new_closure, true));
} }
if (scope_info->takesGenerator()) { if (irstate->getSourceInfo()->is_generator) {
_setFake(PASSED_GENERATOR_NAME, new ConcreteCompilerVariable(GENERATOR, AI, true)); _setFake(PASSED_GENERATOR_NAME, new ConcreteCompilerVariable(GENERATOR, AI, true));
++AI; ++AI;
} }
......
...@@ -222,6 +222,7 @@ public: ...@@ -222,6 +222,7 @@ public:
CFG* cfg; CFG* cfg;
LivenessAnalysis* liveness; LivenessAnalysis* liveness;
PhiAnalysis* phis; PhiAnalysis* phis;
bool is_generator;
ScopeInfo* getScopeInfo(); ScopeInfo* getScopeInfo();
...@@ -245,9 +246,7 @@ public: ...@@ -245,9 +246,7 @@ public:
const std::string getName(); const std::string getName();
SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body) SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body);
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), phis(NULL), arg_names(ast),
body(body) {}
}; };
typedef std::vector<CompiledFunction*> FunctionList; typedef std::vector<CompiledFunction*> FunctionList;
......
# We need to be able to parse files with exec statements in them,
# even if we don't support the actual exec statement yet.
def dont_run_me():
exec "1/0"
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