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
#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 {
Py_FatalError("unimplemented");
}
......
......@@ -2036,6 +2036,7 @@ static int recurse_down_subclasses(PyTypeObject* type, PyObject* name, update_ca
RELEASE_ASSERT(isSubclass(subtype, self), "");
BoxedTuple* new_args = BoxedTuple::create(args->size() - 1, &args->elts[1]);
AUTO_DECREF(new_args);
return self->tp_new(subtype, new_args, kwds);
}
......
......@@ -466,11 +466,11 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
jit->emitSetGlobal(globals, name.getBox(), value);
setGlobal(globals, name.getBox(), value.o);
} else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(0 && "check refcounting");
if (jit)
jit->emitSetItemName(name.getBox(), value);
assert(frame_info.boxedLocals != NULL);
// 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);
} else {
bool closure = vst == ScopeInfo::VarScopeType::CLOSURE;
......@@ -508,8 +508,8 @@ void ASTInterpreter::doStore(AST_expr* node, STOLEN(Value) value) {
if (jit) {
jit->emitSetAttr(node, o, attr->attr.getBox(), value);
}
AUTO_DECREF(o.o);
pyston::setattr(o.o, attr->attr.getBox(), value.o);
Py_DECREF(o.o);
} else if (node->type == AST_TYPE::Tuple) {
AST_Tuple* tuple = (AST_Tuple*)node;
Box** array = unpackIntoArray(value.o, tuple->elts.size());
......@@ -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);
} else if (node->opcode == AST_LangPrimitive::LOCALS) {
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) {
assert(node->args.size() == 1);
Value obj = visit_expr(node->args[0]);
......@@ -1152,12 +1152,13 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
assert(scope_info);
BoxedTuple* basesTuple = BoxedTuple::create(node->bases.size());
AUTO_DECREF(basesTuple);
int base_idx = 0;
for (AST_expr* b : node->bases) {
basesTuple->elts[base_idx++] = visit_expr(b).o;
}
std::vector<Box*> decorators;
std::vector<DecrefHandle<Box>> decorators;
for (AST_expr* d : node->decorator_list)
decorators.push_back(visit_expr(d).o);
......@@ -1174,13 +1175,15 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
Box* passed_globals = NULL;
if (!getMD()->source->scoping->areGlobalsFromModule())
passed_globals = globals;
Box* attrDict
= runtimeCall(createFunctionFromMetadata(md, closure, passed_globals, {}), ArgPassSpec(0), 0, 0, 0, 0, 0);
DecrefHandle<Box> attrDict = runtimeCall(autoDecref(createFunctionFromMetadata(md, closure, passed_globals, {})),
ArgPassSpec(0), 0, 0, 0, 0, 0);
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);
}
return Value(classobj, NULL);
}
......
......@@ -312,7 +312,7 @@ RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) {
}
RewriterVar* JitFragmentWriter::emitGetBoxedLocals() {
return getInterp()->getAttr(ASTInterpreterJitInterface::getBoxedLocalsOffset());
return getInterp()->getAttr(ASTInterpreterJitInterface::getBoxedLocalsOffset())->setType(RefType::BORROWED);
}
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)
assert(_bases->cls == tuple_cls);
BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
static BoxedString* metaclass_str = getStaticString("__metaclass__");
Box* metaclass = NULL;
metaclass = attr_dict->getOrNull(boxString("__metaclass__"));
metaclass = attr_dict->getOrNull(metaclass_str);
if (metaclass != NULL) {
} else if (bases->size() > 0) {
......@@ -1398,6 +1400,17 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict)
try {
Box* r = runtimeCall(metaclass, ArgPassSpec(3), name, _bases, _attr_dict, NULL, NULL);
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;
} catch (ExcInfo e) {
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