Commit 0d01c83e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix closures and NAME lookups / sets

parent a9a26051
...@@ -1957,7 +1957,7 @@ bool update_slot(BoxedClass* type, llvm::StringRef attr) noexcept { ...@@ -1957,7 +1957,7 @@ bool update_slot(BoxedClass* type, llvm::StringRef attr) noexcept {
} }
if (ptrs[0] == NULL) if (ptrs[0] == NULL)
return false; /* Not an attribute that affects any slots */ return false; /* Not an attribute that affects any slots */
int r = update_subclasses(type, boxString(attr), update_slots_callback, (void*)ptrs); int r = update_subclasses(type, autoDecref(boxString(attr)), update_slots_callback, (void*)ptrs);
// TODO this is supposed to be a CAPI function! // TODO this is supposed to be a CAPI function!
if (r) if (r)
......
...@@ -169,6 +169,7 @@ public: ...@@ -169,6 +169,7 @@ public:
} }
Py_DECREF(this->globals); Py_DECREF(this->globals);
Py_XDECREF(this->created_closure);
} }
llvm::DenseMap<InternedString, int>& getSymVRegMap() { llvm::DenseMap<InternedString, int>& getSymVRegMap() {
...@@ -485,15 +486,14 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) { ...@@ -485,15 +486,14 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
jit->emitSetLocal(name, node->vreg, closure, value); jit->emitSetLocal(name, node->vreg, closure, value);
} }
if (closure) {
ASTInterpreterJitInterface::setLocalClosureHelper(this, node->vreg, name, value.o);
} else {
assert(getSymVRegMap().count(name)); assert(getSymVRegMap().count(name));
assert(getSymVRegMap()[name] == node->vreg); assert(getSymVRegMap()[name] == node->vreg);
Box* prev = vregs[node->vreg]; Box* prev = vregs[node->vreg];
vregs[node->vreg] = value.o; vregs[node->vreg] = value.o;
Py_XDECREF(prev); Py_XDECREF(prev);
if (closure) {
assert(0 && "check refcounting");
created_closure->elts[scope_info->getClosureOffset(name)] = value.o;
} }
} }
} }
...@@ -1578,7 +1578,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1578,7 +1578,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
return v; return v;
} }
case ScopeInfo::VarScopeType::DEREF: { case ScopeInfo::VarScopeType::DEREF: {
assert(0 && "check refcounting");
return Value(ASTInterpreterJitInterface::derefHelper(this, node->id), return Value(ASTInterpreterJitInterface::derefHelper(this, node->id),
jit ? jit->emitDeref(node->id) : NULL); jit ? jit->emitDeref(node->id) : NULL);
} }
...@@ -1610,7 +1609,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1610,7 +1609,6 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
RELEASE_ASSERT(0, "should be unreachable"); RELEASE_ASSERT(0, "should be unreachable");
} }
case ScopeInfo::VarScopeType::NAME: { case ScopeInfo::VarScopeType::NAME: {
assert(0 && "check refcounting");
Value v; Value v;
if (jit) if (jit)
v.var = jit->emitGetBoxedLocal(node->id.getBox()); v.var = jit->emitGetBoxedLocal(node->id.getBox());
...@@ -1716,6 +1714,7 @@ Box* ASTInterpreterJitInterface::derefHelper(void* _interpreter, InternedString ...@@ -1716,6 +1714,7 @@ Box* ASTInterpreterJitInterface::derefHelper(void* _interpreter, InternedString
if (val == NULL) { if (val == NULL) {
raiseExcHelper(NameError, "free variable '%s' referenced before assignment in enclosing scope", s.c_str()); raiseExcHelper(NameError, "free variable '%s' referenced before assignment in enclosing scope", s.c_str());
} }
Py_INCREF(val);
return val; return val;
} }
...@@ -1740,10 +1739,9 @@ Box* ASTInterpreterJitInterface::landingpadHelper(void* _interpreter) { ...@@ -1740,10 +1739,9 @@ Box* ASTInterpreterJitInterface::landingpadHelper(void* _interpreter) {
return rtn; return rtn;
} }
Box* ASTInterpreterJitInterface::setExcInfoHelper(void* _interpreter, Box* type, Box* value, Box* traceback) { void ASTInterpreterJitInterface::setExcInfoHelper(void* _interpreter, Box* type, Box* value, Box* traceback) {
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter; ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
interpreter->getFrameInfo()->exc = ExcInfo(type, value, traceback); interpreter->getFrameInfo()->exc = ExcInfo(type, value, traceback);
return None;
} }
void ASTInterpreterJitInterface::setLocalClosureHelper(void* _interpreter, long vreg, InternedString id, Box* v) { void ASTInterpreterJitInterface::setLocalClosureHelper(void* _interpreter, long vreg, InternedString id, Box* v) {
...@@ -1751,14 +1749,15 @@ void ASTInterpreterJitInterface::setLocalClosureHelper(void* _interpreter, long ...@@ -1751,14 +1749,15 @@ void ASTInterpreterJitInterface::setLocalClosureHelper(void* _interpreter, long
assert(interpreter->getSymVRegMap().count(id)); assert(interpreter->getSymVRegMap().count(id));
assert(interpreter->getSymVRegMap()[id] == vreg); assert(interpreter->getSymVRegMap()[id] == vreg);
Box* prev = interpreter->vregs[vreg];
interpreter->vregs[vreg] = v; interpreter->vregs[vreg] = v;
interpreter->created_closure->elts[interpreter->scope_info->getClosureOffset(id)] = v; interpreter->created_closure->elts[interpreter->scope_info->getClosureOffset(id)] = incref(v);
Py_XDECREF(prev);
} }
Box* ASTInterpreterJitInterface::uncacheExcInfoHelper(void* _interpreter) { void ASTInterpreterJitInterface::uncacheExcInfoHelper(void* _interpreter) {
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter; ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
interpreter->getFrameInfo()->exc = ExcInfo(NULL, NULL, NULL); interpreter->getFrameInfo()->exc = ExcInfo(NULL, NULL, NULL);
return None;
} }
void ASTInterpreterJitInterface::raise0Helper(void* _interpreter) { void ASTInterpreterJitInterface::raise0Helper(void* _interpreter) {
......
...@@ -45,9 +45,9 @@ struct ASTInterpreterJitInterface { ...@@ -45,9 +45,9 @@ struct ASTInterpreterJitInterface {
static Box* derefHelper(void* interp, InternedString s); static Box* derefHelper(void* interp, InternedString s);
static Box* doOSRHelper(void* interp, AST_Jump* node); static Box* doOSRHelper(void* interp, AST_Jump* node);
static Box* landingpadHelper(void* interp); static Box* landingpadHelper(void* interp);
static Box* setExcInfoHelper(void* interp, Box* type, Box* value, Box* traceback); static void setExcInfoHelper(void* interp, Box* type, Box* value, Box* traceback);
static void setLocalClosureHelper(void* interp, long vreg, InternedString id, Box* v); static void setLocalClosureHelper(void* interp, long vreg, InternedString id, Box* v);
static Box* uncacheExcInfoHelper(void* interp); static void uncacheExcInfoHelper(void* interp);
static void raise0Helper(void* interp) __attribute__((noreturn)); static void raise0Helper(void* interp) __attribute__((noreturn));
}; };
......
...@@ -226,7 +226,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B ...@@ -226,7 +226,7 @@ RewriterVar* JitFragmentWriter::emitCallattr(AST_expr* node, RewriterVar* obj, B
if (keyword_names_var) if (keyword_names_var)
call_args.push_back(keyword_names_var); call_args.push_back(keyword_names_var);
return call(false, (void*)callattrHelper, call_args); return call(false, (void*)callattrHelper, call_args)->setType(RefType::OWNED);
#endif #endif
} }
...@@ -239,29 +239,29 @@ RewriterVar* JitFragmentWriter::emitCreateDict(const llvm::ArrayRef<RewriterVar* ...@@ -239,29 +239,29 @@ RewriterVar* JitFragmentWriter::emitCreateDict(const llvm::ArrayRef<RewriterVar*
const llvm::ArrayRef<RewriterVar*> values) { const llvm::ArrayRef<RewriterVar*> values) {
assert(keys.size() == values.size()); assert(keys.size() == values.size());
if (keys.empty()) if (keys.empty())
return call(false, (void*)createDict); return call(false, (void*)createDict)->setType(RefType::OWNED);
else else
return call(false, (void*)createDictHelper, imm(keys.size()), allocArgs(keys), allocArgs(values)); return call(false, (void*)createDictHelper, imm(keys.size()), allocArgs(keys), allocArgs(values))->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitCreateList(const llvm::ArrayRef<RewriterVar*> values) { RewriterVar* JitFragmentWriter::emitCreateList(const llvm::ArrayRef<RewriterVar*> values) {
auto num = values.size(); auto num = values.size();
if (num == 0) if (num == 0)
return call(false, (void*)createList); return call(false, (void*)createList)->setType(RefType::OWNED);
else else
return call(false, (void*)createListHelper, imm(num), allocArgs(values)); return call(false, (void*)createListHelper, imm(num), allocArgs(values))->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitCreateSet(const llvm::ArrayRef<RewriterVar*> values) { RewriterVar* JitFragmentWriter::emitCreateSet(const llvm::ArrayRef<RewriterVar*> values) {
auto num = values.size(); auto num = values.size();
if (num == 0) if (num == 0)
return call(false, (void*)createSet); return call(false, (void*)createSet)->setType(RefType::OWNED);
else else
return call(false, (void*)createSetHelper, imm(num), allocArgs(values)); return call(false, (void*)createSetHelper, imm(num), allocArgs(values))->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitCreateSlice(RewriterVar* start, RewriterVar* stop, RewriterVar* step) { RewriterVar* JitFragmentWriter::emitCreateSlice(RewriterVar* start, RewriterVar* stop, RewriterVar* step) {
return call(false, (void*)createSlice, start, stop, step); return call(false, (void*)createSlice, start, stop, step)->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar*> values) { RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar*> values) {
...@@ -270,13 +270,13 @@ RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar ...@@ -270,13 +270,13 @@ RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar
if (num == 0) { if (num == 0) {
r = imm(EmptyTuple)->setType(RefType::BORROWED); r = imm(EmptyTuple)->setType(RefType::BORROWED);
} else if (num == 1) } else if (num == 1)
r = call(false, (void*)BoxedTuple::create1, values[0]); r = call(false, (void*)BoxedTuple::create1, values[0])->setType(RefType::OWNED);
else if (num == 2) else if (num == 2)
r = call(false, (void*)BoxedTuple::create2, values[0], values[1]); r = call(false, (void*)BoxedTuple::create2, values[0], values[1])->setType(RefType::OWNED);
else if (num == 3) else if (num == 3)
r = call(false, (void*)BoxedTuple::create3, values[0], values[1], values[2]); r = call(false, (void*)BoxedTuple::create3, values[0], values[1], values[2])->setType(RefType::OWNED);
else else
r = call(false, (void*)createTupleHelper, imm(num), allocArgs(values)); r = call(false, (void*)createTupleHelper, imm(num), allocArgs(values))->setType(RefType::OWNED);
return r; return r;
} }
...@@ -284,14 +284,15 @@ RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar ...@@ -284,14 +284,15 @@ RewriterVar* JitFragmentWriter::emitCreateTuple(const llvm::ArrayRef<RewriterVar
RewriterVar* JitFragmentWriter::emitDeref(InternedString s) { RewriterVar* JitFragmentWriter::emitDeref(InternedString s) {
return call(false, (void*)ASTInterpreterJitInterface::derefHelper, getInterp(), return call(false, (void*)ASTInterpreterJitInterface::derefHelper, getInterp(),
#ifndef NDEBUG #ifndef NDEBUG
imm(asUInt(s).first), imm(asUInt(s).second)); imm(asUInt(s).first), imm(asUInt(s).second))
#else #else
imm(asUInt(s))); imm(asUInt(s)))
#endif #endif
->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar* cls) { RewriterVar* JitFragmentWriter::emitExceptionMatches(RewriterVar* v, RewriterVar* cls) {
return call(false, (void*)exceptionMatchesHelper, v, cls); return call(false, (void*)exceptionMatchesHelper, v, cls)->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node) { RewriterVar* JitFragmentWriter::emitGetAttr(RewriterVar* obj, BoxedString* s, AST_expr* node) {
...@@ -308,7 +309,7 @@ RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s, int vreg) { ...@@ -308,7 +309,7 @@ RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s, int vreg) {
RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) { RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) {
RewriterVar* boxed_locals = emitGetBoxedLocals(); RewriterVar* boxed_locals = emitGetBoxedLocals();
RewriterVar* globals = getInterp()->getAttr(ASTInterpreterJitInterface::getGlobalsOffset()); RewriterVar* globals = getInterp()->getAttr(ASTInterpreterJitInterface::getGlobalsOffset());
return call(false, (void*)boxedLocalsGet, boxed_locals, imm(s), globals); return call(false, (void*)boxedLocalsGet, boxed_locals, imm(s), globals)->setType(RefType::OWNED);
} }
RewriterVar* JitFragmentWriter::emitGetBoxedLocals() { RewriterVar* JitFragmentWriter::emitGetBoxedLocals() {
...@@ -429,7 +430,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj ...@@ -429,7 +430,7 @@ RewriterVar* JitFragmentWriter::emitRuntimeCall(AST_expr* node, RewriterVar* obj
if (keyword_names_var) if (keyword_names_var)
call_args.push_back(keyword_names_var); call_args.push_back(keyword_names_var);
return call(false, (void*)runtimeCallHelper, call_args); return call(false, (void*)runtimeCallHelper, call_args)->setType(RefType::OWNED);
#endif #endif
} }
...@@ -496,7 +497,7 @@ void JitFragmentWriter::emitOSRPoint(AST_Jump* node) { ...@@ -496,7 +497,7 @@ void JitFragmentWriter::emitOSRPoint(AST_Jump* node) {
void JitFragmentWriter::emitPrint(RewriterVar* dest, RewriterVar* var, bool nl) { void JitFragmentWriter::emitPrint(RewriterVar* dest, RewriterVar* var, bool nl) {
if (LOG_BJIT_ASSEMBLY) comment("BJIT: emitPrint() start"); if (LOG_BJIT_ASSEMBLY) comment("BJIT: emitPrint() start");
if (!dest) if (!dest)
dest = call(false, (void*)getSysStdout); dest = call(false, (void*)getSysStdout)->setType(RefType::BORROWED);
if (!var) if (!var)
var = imm(0ul); var = imm(0ul);
call(false, (void*)printHelper, dest, var, imm(nl)); call(false, (void*)printHelper, dest, var, imm(nl));
...@@ -557,7 +558,6 @@ void JitFragmentWriter::emitSetLocal(InternedString s, int vreg, bool set_closur ...@@ -557,7 +558,6 @@ void JitFragmentWriter::emitSetLocal(InternedString s, int vreg, bool set_closur
if (LOG_BJIT_ASSEMBLY) comment("BJIT: emitSetLocal() start"); if (LOG_BJIT_ASSEMBLY) comment("BJIT: emitSetLocal() start");
assert(vreg >= 0); assert(vreg >= 0);
if (set_closure) { if (set_closure) {
assert(0 && "check refcounting");
call(false, (void*)ASTInterpreterJitInterface::setLocalClosureHelper, getInterp(), imm(vreg), call(false, (void*)ASTInterpreterJitInterface::setLocalClosureHelper, getInterp(), imm(vreg),
#ifndef NDEBUG #ifndef NDEBUG
imm(asUInt(s).first), imm(asUInt(s).second), imm(asUInt(s).first), imm(asUInt(s).second),
...@@ -565,6 +565,7 @@ void JitFragmentWriter::emitSetLocal(InternedString s, int vreg, bool set_closur ...@@ -565,6 +565,7 @@ void JitFragmentWriter::emitSetLocal(InternedString s, int vreg, bool set_closur
imm(asUInt(s)), imm(asUInt(s)),
#endif #endif
v); v);
v->refConsumed();
} else { } else {
RewriterVar* prev = vregs_array->getAttr(8 * vreg); RewriterVar* prev = vregs_array->getAttr(8 * vreg);
vregs_array->setAttr(8 * vreg, v); vregs_array->setAttr(8 * vreg, v);
......
...@@ -333,6 +333,8 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) { ...@@ -333,6 +333,8 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) {
return &l->elts->elts[0]; return &l->elts->elts[0];
} }
RELEASE_ASSERT(0, "I don't think this is safe since elts will die");
std::vector<Box*> elts; std::vector<Box*> elts;
for (auto e : obj->pyElements()) { for (auto e : obj->pyElements()) {
elts.push_back(e); elts.push_back(e);
...@@ -2329,7 +2331,6 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -2329,7 +2331,6 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
return val; return val;
} }
} else { } else {
RELEASE_ASSERT(0, "need to check the refcounting for this");
// More complicated when obj is a type // More complicated when obj is a type
// We have to look up the attr in the entire // We have to look up the attr in the entire
// class hierarchy, and we also have to check if it is a descriptor, // class hierarchy, and we also have to check if it is a descriptor,
...@@ -2370,6 +2371,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -2370,6 +2371,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
if (!local_get) { if (!local_get) {
if (rewrite_args) if (rewrite_args)
rewrite_args->setReturn(r_val, ReturnConvention::HAS_RETURN); rewrite_args->setReturn(r_val, ReturnConvention::HAS_RETURN);
Py_INCREF(val);
return val; return val;
} }
......
...@@ -317,6 +317,9 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(FunctionMetadata* md, std::initi ...@@ -317,6 +317,9 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(FunctionMetadata* md, std::initi
doc(NULL) { doc(NULL) {
assert((!globals) == (!md->source || md->source->scoping->areGlobalsFromModule())); assert((!globals) == (!md->source || md->source->scoping->areGlobalsFromModule()));
Py_XINCREF(closure);
Py_XINCREF(globals);
if (defaults.size()) { if (defaults.size()) {
// HAX copy+modify the BoxedTuple constructor so that we can put NULLs into the tuple. // HAX copy+modify the BoxedTuple constructor so that we can put NULLs into the tuple.
// We are going to separately be careful to make sure that those NULLs don't escape // We are going to separately be careful to make sure that those NULLs don't escape
......
...@@ -1094,7 +1094,7 @@ class BoxedStaticmethod : public Box { ...@@ -1094,7 +1094,7 @@ class BoxedStaticmethod : public Box {
public: public:
Box* sm_callable; Box* sm_callable;
BoxedStaticmethod(Box* callable) : sm_callable(callable){}; BoxedStaticmethod(Box* callable) : sm_callable(callable) {}
DEFAULT_CLASS_SIMPLE(staticmethod_cls, true); DEFAULT_CLASS_SIMPLE(staticmethod_cls, true);
...@@ -1107,7 +1107,7 @@ class BoxedClassmethod : public Box { ...@@ -1107,7 +1107,7 @@ class BoxedClassmethod : public Box {
public: public:
Box* cm_callable; Box* cm_callable;
BoxedClassmethod(Box* callable) : cm_callable(callable){}; BoxedClassmethod(Box* callable) : cm_callable(callable) {}
DEFAULT_CLASS_SIMPLE(classmethod_cls, true); DEFAULT_CLASS_SIMPLE(classmethod_cls, true);
...@@ -1125,16 +1125,12 @@ public: ...@@ -1125,16 +1125,12 @@ public:
BoxedClosure(BoxedClosure* parent) : parent(parent) {} BoxedClosure(BoxedClosure* parent) : parent(parent) {}
// TODO: convert this to a var-object and use DEFAULT_CLASS_VAR_SIMPLE
void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) { void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) {
/* BoxedClosure* rtn = static_cast<BoxedClosure*>(_PyObject_GC_Malloc(sizeof(BoxedClosure) + nelts * sizeof(Box*)));
BoxedClosure* rtn
= static_cast<BoxedClosure*>(gc_alloc(_PyObject_VAR_SIZE(closure_cls, nelts), gc::GCKind::PYTHON));
*/
BoxedClosure* rtn
= static_cast<BoxedClosure*>(PyObject_MALLOC(sizeof(BoxedClosure) + nelts * sizeof(Box*)));
rtn->nelts = nelts; rtn->nelts = nelts;
rtn->cls = closure_cls; PyObject_INIT(rtn, closure_cls); \
_Py_NewReference(rtn); _PyObject_GC_TRACK(rtn); \
memset((void*)rtn->elts, 0, sizeof(Box*) * nelts); memset((void*)rtn->elts, 0, sizeof(Box*) * nelts);
return rtn; return rtn;
} }
......
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