Commit 578297b9 authored by Marius Wachtler's avatar Marius Wachtler

Merge pull request #1173 from undingen/interp_created_closure

interpreter: mark created_closure as live variable inside yields
parents 22b48e18 ec66b76b
......@@ -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) {
......@@ -1897,6 +1895,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;
}
......
......@@ -2360,18 +2360,20 @@ public:
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
if (_key->cls != str_cls)
self->convertToDictBacked();
if (self->isDictBacked()) {
static BoxedString* get_str = getStaticString("get");
return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), get_str, LookupScope::CLASS_ONLY, NULL,
ArgPassSpec(2), _key, def, NULL, NULL, NULL);
}
RELEASE_ASSERT(_key->cls == str_cls, "");
_key = coerceUnicodeToStr<CXX>(_key);
if (_key->cls != str_cls) {
Py_DECREF(_key);
return incref(def);
}
assert(_key->cls == str_cls);
BoxedString* key = static_cast<BoxedString*>(_key);
Py_INCREF(key);
internStringMortalInplace(key);
AUTO_DECREF(key);
......@@ -4053,6 +4055,8 @@ void AttrWrapperIter::dealloc(Box* _o) noexcept {
void BoxedClosure::dealloc(Box* _o) noexcept {
BoxedClosure* o = (BoxedClosure*)_o;
PyObject_GC_UnTrack(o);
for (int i = 0; i < o->nelts; i++) {
Py_XDECREF(o->elts[i]);
}
......@@ -4069,6 +4073,8 @@ int BoxedClosure::traverse(Box* _o, visitproc visit, void* arg) noexcept {
Py_VISIT(o->elts[i]);
}
Py_VISIT(o->parent);
return 0;
}
......@@ -4079,6 +4085,8 @@ int BoxedClosure::clear(Box* _o) noexcept {
Py_CLEAR(o->elts[i]);
}
Py_CLEAR(o->parent);
return 0;
}
......
# 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