Commit 6d47b61a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Lots more refcounting fixes, especially for class creation

parent c4ace2f9
...@@ -1109,6 +1109,9 @@ extern "C" void _Py_NegativeRefcount(const char* fname, int lineno, PyObject* op ...@@ -1109,6 +1109,9 @@ extern "C" void _Py_NegativeRefcount(const char* fname, int lineno, PyObject* op
#endif /* Py_REF_DEBUG */ #endif /* Py_REF_DEBUG */
extern "C" int _PyTrash_delete_nesting = 0;
extern "C" PyObject *_PyTrash_delete_later = NULL;
extern "C" void _PyTrash_thread_deposit_object(PyObject* op) noexcept { extern "C" void _PyTrash_thread_deposit_object(PyObject* op) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
......
...@@ -2036,6 +2036,7 @@ static int recurse_down_subclasses(PyTypeObject* type, PyObject* name, update_ca ...@@ -2036,6 +2036,7 @@ static int recurse_down_subclasses(PyTypeObject* type, PyObject* name, update_ca
RELEASE_ASSERT(isSubclass(subtype, self), ""); RELEASE_ASSERT(isSubclass(subtype, self), "");
BoxedTuple* new_args = BoxedTuple::create(args->size() - 1, &args->elts[1]); BoxedTuple* new_args = BoxedTuple::create(args->size() - 1, &args->elts[1]);
AUTO_DECREF(new_args);
return self->tp_new(subtype, new_args, kwds); return self->tp_new(subtype, new_args, kwds);
} }
......
...@@ -466,11 +466,11 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) { ...@@ -466,11 +466,11 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
jit->emitSetGlobal(globals, name.getBox(), value); jit->emitSetGlobal(globals, name.getBox(), value);
setGlobal(globals, name.getBox(), value.o); setGlobal(globals, name.getBox(), value.o);
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(0 && "check refcounting");
if (jit) if (jit)
jit->emitSetItemName(name.getBox(), value); jit->emitSetItemName(name.getBox(), value);
assert(frame_info.boxedLocals != NULL); assert(frame_info.boxedLocals != NULL);
// TODO should probably pre-box the names when it's a scope that usesNameLookup // TODO should probably pre-box the names when it's a scope that usesNameLookup
AUTO_DECREF(value.o);
setitem(frame_info.boxedLocals, name.getBox(), value.o); setitem(frame_info.boxedLocals, name.getBox(), value.o);
} else { } else {
bool closure = vst == ScopeInfo::VarScopeType::CLOSURE; bool closure = vst == ScopeInfo::VarScopeType::CLOSURE;
...@@ -508,8 +508,8 @@ void ASTInterpreter::doStore(AST_expr* node, STOLEN(Value) value) { ...@@ -508,8 +508,8 @@ void ASTInterpreter::doStore(AST_expr* node, STOLEN(Value) value) {
if (jit) { if (jit) {
jit->emitSetAttr(node, o, attr->attr.getBox(), value); jit->emitSetAttr(node, o, attr->attr.getBox(), value);
} }
AUTO_DECREF(o.o);
pyston::setattr(o.o, attr->attr.getBox(), value.o); pyston::setattr(o.o, attr->attr.getBox(), value.o);
Py_DECREF(o.o);
} else if (node->type == AST_TYPE::Tuple) { } else if (node->type == AST_TYPE::Tuple) {
AST_Tuple* tuple = (AST_Tuple*)node; AST_Tuple* tuple = (AST_Tuple*)node;
Box** array = unpackIntoArray(value.o, tuple->elts.size()); Box** array = unpackIntoArray(value.o, tuple->elts.size());
...@@ -927,7 +927,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) { ...@@ -927,7 +927,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
v = Value(boxBool(exceptionMatches(obj.o, cls.o)), jit ? jit->emitExceptionMatches(obj, cls) : NULL); v = Value(boxBool(exceptionMatches(obj.o, cls.o)), jit ? jit->emitExceptionMatches(obj, cls) : NULL);
} else if (node->opcode == AST_LangPrimitive::LOCALS) { } else if (node->opcode == AST_LangPrimitive::LOCALS) {
assert(frame_info.boxedLocals != NULL); assert(frame_info.boxedLocals != NULL);
v = Value(frame_info.boxedLocals, jit ? jit->emitGetBoxedLocals() : NULL); v = Value(incref(frame_info.boxedLocals), jit ? jit->emitGetBoxedLocals() : NULL);
} else if (node->opcode == AST_LangPrimitive::NONZERO) { } else if (node->opcode == AST_LangPrimitive::NONZERO) {
assert(node->args.size() == 1); assert(node->args.size() == 1);
Value obj = visit_expr(node->args[0]); Value obj = visit_expr(node->args[0]);
...@@ -1152,12 +1152,13 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) { ...@@ -1152,12 +1152,13 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
assert(scope_info); assert(scope_info);
BoxedTuple* basesTuple = BoxedTuple::create(node->bases.size()); BoxedTuple* basesTuple = BoxedTuple::create(node->bases.size());
AUTO_DECREF(basesTuple);
int base_idx = 0; int base_idx = 0;
for (AST_expr* b : node->bases) { for (AST_expr* b : node->bases) {
basesTuple->elts[base_idx++] = visit_expr(b).o; basesTuple->elts[base_idx++] = visit_expr(b).o;
} }
std::vector<Box*> decorators; std::vector<DecrefHandle<Box>> decorators;
for (AST_expr* d : node->decorator_list) for (AST_expr* d : node->decorator_list)
decorators.push_back(visit_expr(d).o); decorators.push_back(visit_expr(d).o);
...@@ -1174,13 +1175,15 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) { ...@@ -1174,13 +1175,15 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
Box* passed_globals = NULL; Box* passed_globals = NULL;
if (!getMD()->source->scoping->areGlobalsFromModule()) if (!getMD()->source->scoping->areGlobalsFromModule())
passed_globals = globals; passed_globals = globals;
Box* attrDict DecrefHandle<Box> attrDict = runtimeCall(autoDecref(createFunctionFromMetadata(md, closure, passed_globals, {})),
= runtimeCall(createFunctionFromMetadata(md, closure, passed_globals, {}), ArgPassSpec(0), 0, 0, 0, 0, 0); ArgPassSpec(0), 0, 0, 0, 0, 0);
Box* classobj = createUserClass(node->name.getBox(), basesTuple, attrDict); Box* classobj = createUserClass(node->name.getBox(), basesTuple, attrDict);
for (int i = decorators.size() - 1; i >= 0; i--) for (int i = decorators.size() - 1; i >= 0; i--) {
AUTO_DECREF(classobj);
classobj = runtimeCall(decorators[i], ArgPassSpec(1), classobj, 0, 0, 0, 0); classobj = runtimeCall(decorators[i], ArgPassSpec(1), classobj, 0, 0, 0, 0);
}
return Value(classobj, NULL); return Value(classobj, NULL);
} }
......
...@@ -312,7 +312,7 @@ RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) { ...@@ -312,7 +312,7 @@ RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) {
} }
RewriterVar* JitFragmentWriter::emitGetBoxedLocals() { RewriterVar* JitFragmentWriter::emitGetBoxedLocals() {
return getInterp()->getAttr(ASTInterpreterJitInterface::getBoxedLocalsOffset()); return getInterp()->getAttr(ASTInterpreterJitInterface::getBoxedLocalsOffset())->setType(RefType::BORROWED);
} }
RewriterVar* JitFragmentWriter::emitGetClsAttr(RewriterVar* obj, BoxedString* s) { RewriterVar* JitFragmentWriter::emitGetClsAttr(RewriterVar* obj, BoxedString* s) {
......
This diff is collapsed.
...@@ -1377,8 +1377,10 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict) ...@@ -1377,8 +1377,10 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict)
assert(_bases->cls == tuple_cls); assert(_bases->cls == tuple_cls);
BoxedTuple* bases = static_cast<BoxedTuple*>(_bases); BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
static BoxedString* metaclass_str = getStaticString("__metaclass__");
Box* metaclass = NULL; Box* metaclass = NULL;
metaclass = attr_dict->getOrNull(boxString("__metaclass__")); metaclass = attr_dict->getOrNull(metaclass_str);
if (metaclass != NULL) { if (metaclass != NULL) {
} else if (bases->size() > 0) { } else if (bases->size() > 0) {
...@@ -1398,6 +1400,17 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict) ...@@ -1398,6 +1400,17 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict)
try { try {
Box* r = runtimeCall(metaclass, ArgPassSpec(3), name, _bases, _attr_dict, NULL, NULL); Box* r = runtimeCall(metaclass, ArgPassSpec(3), name, _bases, _attr_dict, NULL, NULL);
RELEASE_ASSERT(r, ""); RELEASE_ASSERT(r, "");
// XXX Hack: the classes vector lists all classes that have untracked references to them.
// This is pretty much any class created in C code, since the C code will tend to hold on
// to a reference to the created class. So in the BoxedClass constructor we add the new class to
// "classes", which will cause the class to get decref'd at the end.
// But for classes created from Python, we don't have this extra untracked reference.
// Rather than fix up the plumbing for now, just reach into the other system and remove this
// class from the list.
RELEASE_ASSERT(classes.back() == r, "");
classes.pop_back();
return r; return r;
} catch (ExcInfo e) { } catch (ExcInfo e) {
RELEASE_ASSERT(e.matches(BaseException), ""); RELEASE_ASSERT(e.matches(BaseException), "");
......
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