Commit f4467163 authored by Marius Wachtler's avatar Marius Wachtler

interpreter: mark created_closure as live variable insids yields

without this we would never traverse the variable and the GC would therefore be unable to destroy the generator
parent ccfc1419
......@@ -995,9 +995,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
Value ASTInterpreter::visit_yield(AST_Yield* node) {
Value value = node->value ? visit_expr(node->value) : getNone();
assert(generator && generator->cls == generator_cls);
return Value(yield(generator, value.o), jit ? jit->emitYield(value) : NULL);
return Value(ASTInterpreterJitInterface::yieldHelper(this, value.o), jit ? jit->emitYield(value) : NULL);
}
Value ASTInterpreter::visit_stmt(AST_stmt* node) {
......@@ -1898,6 +1896,15 @@ void ASTInterpreterJitInterface::raise0Helper(void* _interpreter) {
raise0(&interpreter->getFrameInfo()->exc);
}
Box* ASTInterpreterJitInterface::yieldHelper(void* _interpreter, STOLEN(Box*) value) {
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
auto generator = interpreter->generator;
assert(generator && generator->cls == generator_cls);
Box* live_values = { interpreter->created_closure };
return yield(generator, value, live_values);
}
const void* interpreter_instr_addr = (void*)&executeInnerAndSetupFrame;
// small wrapper around executeInner because we can not directly call the member function from asm.
......
......@@ -53,6 +53,7 @@ struct ASTInterpreterJitInterface {
static void setLocalClosureHelper(void* interp, long vreg, InternedString id, Box* v);
static void uncacheExcInfoHelper(void* interp);
static void raise0Helper(void* interp) __attribute__((noreturn));
static Box* yieldHelper(void* interp, STOLEN(Box*) value);
};
class RewriterVar;
......
......@@ -536,10 +536,7 @@ std::vector<RewriterVar*> JitFragmentWriter::emitUnpackIntoArray(RewriterVar* v,
}
RewriterVar* JitFragmentWriter::emitYield(RewriterVar* v) {
RewriterVar* generator = getInterp()->getAttr(ASTInterpreterJitInterface::getGeneratorOffset());
static_assert(sizeof(llvm::ArrayRef<Box*>) == sizeof(void*) * 2,
"we pass two 0ul args to initalize the llvm::ArrayRef");
auto rtn = call(false, (void*)yield, generator, v, imm(0ul), imm(0ul))->setType(RefType::OWNED);
auto rtn = call(false, (void*)ASTInterpreterJitInterface::yieldHelper, getInterp(), v)->setType(RefType::OWNED);
v->refConsumed();
return rtn;
}
......
# Test a generator cycle involving an unfinished generator.
# this used to leak in the interpreter
import gc
def f(z):
l = ((lambda x, l: x**y)(z, l) for y in xrange(10))
return l
def test():
g = f(4)
print g.next()
return g
g = test()
print g.next()
gc.collect()
print gc.garbage
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