Commit d48c5f97 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Prevent non-module-global-functions from getting out of the interpreter for now

We should be able to support them in the JIT, but do the easy thing
for now.

also, put the globals info on the ScopingAnalysis instead of ScopeInfo
parent 467c4fd5
......@@ -104,7 +104,6 @@ public:
bool usesNameLookup() override { return false; }
bool areLocalsFromModule() override { return true; }
bool areGlobalsFromModule() override { return true; }
DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
......@@ -173,7 +172,6 @@ public:
bool usesNameLookup() override { return true; }
bool areLocalsFromModule() override { return false; }
bool areGlobalsFromModule() override { return globals_from_module; }
DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
......@@ -329,7 +327,6 @@ public:
bool usesNameLookup() override { return usesNameLookup_; }
bool areLocalsFromModule() override { return false; }
bool areGlobalsFromModule() override { return globals_from_module; }
DerefInfo getDerefInfo(InternedString name) override {
assert(getScopeTypeOfName(name) == VarScopeType::DEREF);
......
......@@ -92,7 +92,6 @@ public:
virtual bool usesNameLookup() = 0;
virtual bool areLocalsFromModule() = 0;
virtual bool areGlobalsFromModule() = 0;
// For a variable with DEREF lookup, return the DerefInfo used to lookup
// the variable in a passed closure.
......@@ -177,6 +176,7 @@ public:
ScopeInfo* getScopeInfoForNode(AST* node);
InternedStringPool& getInternedStrings();
bool areGlobalsFromModule() { return globals_from_module; }
};
bool containsYield(AST* ast);
......
......@@ -201,9 +201,6 @@ void ASTInterpreter::setFrameInfo(const FrameInfo* frame_info) {
void ASTInterpreter::setGlobals(Box* globals) {
this->globals = globals;
if (globals->cls == dict_cls) {
frame_info.globals = static_cast<BoxedDict*>(globals);
}
}
void ASTInterpreter::gcVisit(GCVisitor* visitor) {
......@@ -216,8 +213,7 @@ void ASTInterpreter::gcVisit(GCVisitor* visitor) {
visitor->visit(generator);
if (frame_info.boxedLocals)
visitor->visit(frame_info.boxedLocals);
if (frame_info.globals)
visitor->visit(frame_info.globals);
visitor->visit(globals);
}
ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
......@@ -445,9 +441,9 @@ Value ASTInterpreter::visit_jump(AST_Jump* node) {
if (backedge)
threading::allowGLReadPreemption();
if (ENABLE_OSR && backedge) {
++edgecount;
if (edgecount > OSR_THRESHOLD_INTERPRETER && !FORCE_INTERPRETER) {
if (ENABLE_OSR && backedge && (globals->cls == module_cls)) {
bool can_osr = !FORCE_INTERPRETER && (globals->cls == module_cls);
if (can_osr && edgecount++ > OSR_THRESHOLD_INTERPRETER) {
eraseDeadSymbols();
const OSREntryDescriptor* found_entry = nullptr;
......@@ -1169,7 +1165,9 @@ const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute;
Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, BoxedDict* globals, Box* arg1,
Box* arg2, Box* arg3, Box** args) {
if (unlikely(cf->times_called > REOPT_THRESHOLD_INTERPRETER && ENABLE_REOPT && !FORCE_INTERPRETER)) {
bool can_reopt = ENABLE_REOPT && !FORCE_INTERPRETER && (globals == NULL);
if (unlikely(can_reopt && cf->times_called > REOPT_THRESHOLD_INTERPRETER)) {
assert(!globals);
CompiledFunction* optimized = reoptCompiledFuncInternal(cf);
if (closure && generator)
return optimized->closure_generator_call((BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2,
......@@ -1190,7 +1188,7 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
interpreter.setBoxedLocals(new BoxedDict());
}
assert((!globals) == scope_info->areGlobalsFromModule());
assert((!globals) == cf->clfunc->source->scoping->areGlobalsFromModule());
if (globals) {
interpreter.setGlobals(globals);
} else {
......@@ -1212,7 +1210,7 @@ Box* astInterpretFunctionEval(CompiledFunction* cf, BoxedDict* globals, Box* box
ScopeInfo* scope_info = cf->clfunc->source->getScopeInfo();
SourceInfo* source_info = cf->clfunc->source;
if (scope_info->areGlobalsFromModule()) {
if (cf->clfunc->source->scoping->areGlobalsFromModule()) {
assert(!globals);
interpreter.setGlobals(source_info->parent_module);
} else {
......@@ -1237,12 +1235,8 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl
ScopeInfo* scope_info = cf->clfunc->source->getScopeInfo();
SourceInfo* source_info = cf->clfunc->source;
if (scope_info->areGlobalsFromModule()) {
interpreter.setGlobals(source_info->parent_module);
} else {
assert(frame_state.frame_info->globals);
interpreter.setGlobals(frame_state.frame_info->globals);
}
assert(cf->clfunc->source->scoping->areGlobalsFromModule());
interpreter.setGlobals(source_info->parent_module);
for (const auto& p : frame_state.locals->d) {
assert(p.first->cls == str_cls);
......
......@@ -69,7 +69,7 @@ struct GlobalState {
llvm::Type* llvm_value_type, *llvm_value_type_ptr, *llvm_value_type_ptr_ptr;
llvm::Type* llvm_class_type, *llvm_class_type_ptr;
llvm::Type* llvm_opaque_type;
llvm::Type* llvm_str_type_ptr;
llvm::Type* llvm_str_type_ptr, *llvm_dict_type_ptr;
llvm::Type* llvm_frame_info_type;
llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr;
llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr;
......
......@@ -727,7 +727,7 @@ ConcreteCompilerVariable* UnknownType::hasnext(IREmitter& emitter, const OpInfo&
}
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariable* closure, bool isGenerator,
const std::vector<ConcreteCompilerVariable*>& defaults) {
BoxedDict* globals, const std::vector<ConcreteCompilerVariable*>& defaults) {
// Unlike the CLFunction*, which can be shared between recompilations, the Box* around it
// should be created anew every time the functiondef is encountered
......@@ -757,12 +757,15 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
llvm::Value* isGenerator_v = llvm::ConstantInt::get(g.i1, isGenerator, false);
assert(globals == NULL);
llvm::Value* globals_v = embedConstantPtr(nullptr, g.llvm_dict_type_ptr);
// We know this function call can't throw, so it's safe to use emitter.getBuilder()->CreateCall() rather than
// emitter.createCall().
llvm::Value* boxed = emitter.getBuilder()->CreateCall(
g.funcs.boxCLFunction,
std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, scratch,
getConstantInt(defaults.size(), g.i64) });
std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, globals_v,
scratch, getConstantInt(defaults.size(), g.i64) });
if (convertedClosure)
convertedClosure->decvref(emitter);
......
......@@ -399,7 +399,7 @@ ConcreteCompilerVariable* makePureImaginary(IREmitter& emitter, double imag);
CompilerVariable* makeStr(const std::string*);
CompilerVariable* makeUnicode(IREmitter& emitter, const std::string*);
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*, CompilerVariable* closure, bool isGenerator,
const std::vector<ConcreteCompilerVariable*>& defaults);
BoxedDict* globals, const std::vector<ConcreteCompilerVariable*>& defaults);
ConcreteCompilerVariable* undefVariable();
CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts);
......
......@@ -316,6 +316,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
EffortLevel effort = initialEffort();
assert(scoping->areGlobalsFromModule());
cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL);
assert(cf->clfunc->versions.size());
}
......@@ -380,6 +382,12 @@ Box* eval(Box* boxedCode) {
}
Box* exec(Box* boxedCode, Box* globals, Box* locals) {
if (globals == None)
globals = NULL;
if (locals == None)
locals = NULL;
// TODO boxedCode is allowed to be a tuple
// TODO need to handle passing in globals
if (locals == NULL) {
......
......@@ -254,6 +254,9 @@ private:
public:
explicit IREmitterImpl(IRGenState* irstate, llvm::BasicBlock*& curblock, IRGenerator* irgenerator)
: irstate(irstate), builder(new IRBuilder(g.context)), curblock(curblock), irgenerator(irgenerator) {
ASSERT(irstate->getSourceInfo()->scoping->areGlobalsFromModule(), "jit doesn't support custom globals yet");
builder->setEmitter(this);
builder->SetInsertPoint(curblock);
}
......@@ -1196,7 +1199,8 @@ private:
// one reason to do this is to pass the closure through if necessary,
// but since the classdef can't create its own closure, shouldn't need to explicitly
// create that scope to pass the closure through.
CompilerVariable* func = makeFunction(emitter, cl, created_closure, false, {});
assert(irstate->getSourceInfo()->scoping->areGlobalsFromModule());
CompilerVariable* func = makeFunction(emitter, cl, created_closure, false, NULL, {});
CompilerVariable* attr_dict = func->call(emitter, getEmptyOpInfo(unw_info), ArgPassSpec(0), {}, NULL);
......@@ -1259,7 +1263,8 @@ private:
assert(created_closure);
}
CompilerVariable* func = makeFunction(emitter, cl, created_closure, is_generator, defaults);
assert(irstate->getSourceInfo()->scoping->areGlobalsFromModule());
CompilerVariable* func = makeFunction(emitter, cl, created_closure, is_generator, NULL, defaults);
for (auto d : defaults) {
d->decvref(emitter);
......
......@@ -135,6 +135,10 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType();
g.llvm_dict_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedDict");
assert(g.llvm_dict_type_ptr);
g.llvm_dict_type_ptr = g.llvm_dict_type_ptr->getPointerTo();
// The LLVM vector type for the arguments that we pass to runtimeCall and related functions.
// It will be a pointer to a type named something like class.std::vector or
// class.std::vector.##. We can figure out exactly what it is by looking at the last
......
......@@ -567,9 +567,8 @@ struct FrameInfo {
ExcInfo exc;
Box* boxedLocals;
BoxedDict* globals;
FrameInfo(ExcInfo exc) : exc(exc), boxedLocals(NULL), globals(NULL) {}
FrameInfo(ExcInfo exc) : exc(exc), boxedLocals(NULL) {}
};
struct CallattrFlags {
......
......@@ -2543,6 +2543,9 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
}
EffortLevel new_effort = initialEffort();
// Only the interpreter currently supports non-module-globals:
if (!f->source->scoping->areGlobalsFromModule())
new_effort = EffortLevel::INTERPRETED;
std::vector<ConcreteCompilerType*> arg_types;
for (int i = 0; i < num_output_args; i++) {
......@@ -2940,6 +2943,8 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
oargs);
}
ASSERT(!globals, "need to update the calling conventions if we want to pass globals");
if (rewrite_args) {
rewrite_args->rewriter->addDependenceOn(chosen_cf->dependent_callsites);
......
......@@ -13,6 +13,7 @@ l = {}
exec """global a
a = 1
b = 2""" in g, l
del g['__builtins__']
print g
print l
......@@ -23,20 +24,28 @@ l = {'b': 2}
exec """global a
del a
del b""" in g, l
del g['__builtins__']
print g
print l
print 'Test global access in a function'
g = {'a': 4, 'b': 5}
l = {}
exec """
def f():
def f(i):
global a, b, c
print 'a =', a
print i, 'a =', a
del b
c = 20
f()
""" in g, {}
for i in xrange(100):
pass
f(-1)
""" in g, l
# Try to trigger a reopt and osr:
for i in xrange(1000):
g['b'] = 6
l['f'](i)
print 'Test global access in comprehensions'
......@@ -50,3 +59,18 @@ print {b for i in xrange(1)}
print {i : b for i in xrange(1)}
print
""" in g, {}
a = 0
exec "a = 1" in None, None
print a
# Adapted from six.py:
def exec_(_code_, _globs_, _locs_):
exec("""exec _code_ in _globs_, _locs_""")
g = {'a': 1}
l = {'b': 2}
exec_("""global a
print a
print b""", g, l)
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