Commit 3874fd6c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Lots more refcounting fixes

parent 0d01c83e
......@@ -516,13 +516,12 @@ void ASTInterpreter::doStore(AST_expr* node, STOLEN(Value) value) {
RewriterVar* array_var = NULL;
if (jit) {
assert(0 && "check refcounting");
array_var = jit->emitUnpackIntoArray(value, tuple->elts.size());
}
unsigned i = 0;
for (AST_expr* e : tuple->elts) {
doStore(e, Value(array[i], jit ? array_var->getAttr(i * sizeof(void*)) : NULL));
doStore(e, Value(array[i], jit ? array_var->getAttr(i * sizeof(void*))->setType(RefType::OWNED) : NULL));
++i;
}
Py_DECREF(value.o);
......@@ -923,7 +922,9 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
} else if (node->opcode == AST_LangPrimitive::CHECK_EXC_MATCH) {
assert(node->args.size() == 2);
Value obj = visit_expr(node->args[0]);
AUTO_DECREF(obj.o);
Value cls = visit_expr(node->args[1]);
AUTO_DECREF(cls.o);
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);
......@@ -1420,6 +1421,8 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
func = visit_expr(node->func);
}
AUTO_DECREF(func.o);
std::vector<Box*> args;
llvm::SmallVector<RewriterVar*, 8> args_vars;
for (AST_expr* e : node->args) {
......@@ -1450,6 +1453,8 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
args_vars.push_back(v);
}
AUTO_DECREF_ARRAY(&args[0], args.size());
ArgPassSpec argspec(node->args.size(), node->keywords.size(), node->starargs, node->kwargs);
if (is_callattr) {
......@@ -1469,10 +1474,6 @@ Value ASTInterpreter::visit_call(AST_Call* node) {
args.size() > 2 ? args[2] : 0, args.size() > 3 ? &args[3] : 0, keyword_names);
}
Py_DECREF(func.o);
for (auto e : args)
Py_DECREF(e);
return v;
}
......@@ -1657,8 +1658,8 @@ Value ASTInterpreter::visit_tuple(AST_Tuple* node) {
Value ASTInterpreter::visit_attribute(AST_Attribute* node) {
Value v = visit_expr(node->value);
AUTO_DECREF(v.o);
Value r(pyston::getattr(v.o, node->attr.getBox()), jit ? jit->emitGetAttr(v, node->attr.getBox(), node) : NULL);
Py_DECREF(v.o);
return r;
}
}
......
......@@ -797,36 +797,31 @@ void checkAndThrowCAPIException() {
static StatCounter num_checkAndThrowCAPIException("num_checkAndThrowCAPIException");
num_checkAndThrowCAPIException.log();
Box* _type = cur_thread_state.curexc_type;
Box* _type, *value, *tb;
PyErr_Fetch(&_type, &value, &tb);
if (!_type)
assert(!cur_thread_state.curexc_value);
assert(!value);
if (_type) {
BoxedClass* type = static_cast<BoxedClass*>(_type);
assert(PyType_Check(_type) && isSubclass(static_cast<BoxedClass*>(type), BaseException)
&& "Only support throwing subclass of BaseException for now");
Box* value = cur_thread_state.curexc_value;
if (!value)
value = None;
value = incref(None);
Box* tb = cur_thread_state.curexc_traceback;
if (!tb)
tb = None;
// Make sure to call PyErr_Clear() *before* normalizing the exception, since otherwise
// the normalization can think that it had raised an exception, resulting to a call
// to checkAndThrowCAPIException, and boom.
PyErr_Clear();
tb = incref(None);
// This is similar to PyErr_NormalizeException:
if (!isSubclass(value->cls, type)) {
if (value->cls == tuple_cls) {
value = runtimeCall(type, ArgPassSpec(0, 0, true, false), value, NULL, NULL, NULL, NULL);
value = runtimeCall(type, ArgPassSpec(0, 0, true, false), autoDecref(value), NULL, NULL, NULL, NULL);
} else if (value == None) {
value = runtimeCall(type, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} else {
value = runtimeCall(type, ArgPassSpec(1), value, NULL, NULL, NULL, NULL);
value = runtimeCall(type, ArgPassSpec(1), autoDecref(value), NULL, NULL, NULL, NULL);
}
}
......@@ -834,6 +829,8 @@ void checkAndThrowCAPIException() {
if (tb != None)
throw ExcInfo(value->cls, value, tb);
Py_DECREF(type);
Py_DECREF(tb);
raiseExc(value);
}
}
......
......@@ -610,12 +610,19 @@ Box* BoxedWrapperDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args,
rearrangeArguments(paramspec, NULL, self->wrapper->name.data(), NULL, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, oargs, keyword_names);
AUTO_XDECREF(arg1);
AUTO_XDECREF(arg2);
AUTO_XDECREF(arg3);
assert(!oargs);
if (paramspec.takes_varargs)
assert(arg2 && arg2->cls == tuple_cls);
if (!rewrite_success)
rewrite_args = NULL;
assert(!rewrite_args && "check refcounting");
Box* rtn;
if (flags == PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
......
......@@ -26,7 +26,7 @@
namespace pyston {
void raiseExc(Box* exc_obj) {
void raiseExc(STOLEN(Box*) exc_obj) {
assert(!PyErr_Occurred());
throw ExcInfo(incref(exc_obj->cls), exc_obj, incref(None));
}
......
......@@ -176,6 +176,6 @@ extern "C" Box* listAppend(Box* s, Box* v) {
listAppendInternal(self, v);
return None;
Py_RETURN_NONE;
}
}
......@@ -1042,7 +1042,7 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
HCAttrs* attrs = getHCAttrsPtr();
HiddenClass* hcls = attrs->hcls;
if (unlikely(hcls->type == HiddenClass::DICT_BACKED)) {
if (unlikely(hcls && hcls->type == HiddenClass::DICT_BACKED)) {
if (rewrite_args)
assert(!rewrite_args->isSuccessful());
rewrite_args = NULL;
......@@ -1054,7 +1054,7 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
return r;
}
assert(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);
assert(!hcls || hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);
if (unlikely(rewrite_args)) {
if (!rewrite_args->obj_hcls_guarded) {
......@@ -1066,12 +1066,18 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
&& static_cast<BoxedClass*>(this)->is_constant)) {
rewrite_args->obj->addAttrGuard(cls->attrs_offset + offsetof(HCAttrs, hcls), (intptr_t)hcls);
}
if (hcls->type == HiddenClass::SINGLETON)
if (hcls && hcls->type == HiddenClass::SINGLETON)
hcls->addDependence(rewrite_args->rewriter);
}
}
}
if (!hcls) {
if (rewrite_args)
rewrite_args->setReturn(NULL, ReturnConvention::NO_RETURN);
return NULL;
}
int offset = hcls->getOffset(attr);
if (offset == -1) {
if (rewrite_args)
......@@ -1677,6 +1683,7 @@ Box* descriptorClsSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedClass* cls
// This is assuming that r_descr was passed in as a valid object
rewrite_args->setReturn(r_descr, ReturnConvention::HAS_RETURN);
}
Py_INCREF(descr);
return descr;
}
......@@ -1690,6 +1697,7 @@ Box* descriptorClsSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedClass* cls
// This is assuming that r_descr was passed in as a valid object
rewrite_args->setReturn(r_descr, ReturnConvention::HAS_RETURN);
}
Py_INCREF(descr);
return descr;
}
......@@ -2445,6 +2453,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
if (rewrite_args) {
rewrite_args->setReturn(r_descr, ReturnConvention::HAS_RETURN);
}
Py_INCREF(descr);
return descr;
}
......@@ -3224,6 +3233,7 @@ BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI
}
if (rtn->cls != int_cls) {
Py_DECREF(rtn);
if (S == CAPI) {
PyErr_Format(TypeError, "an integer is required");
return NULL;
......@@ -4126,6 +4136,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
for (const auto& p : *d_kwargs) {
auto k = coerceUnicodeToStr<CXX>(p.first);
AUTO_DECREF(k);
if (k->cls != str_cls)
raiseExcHelper(TypeError, "%s() keywords must be strings", func_name_cb());
......@@ -6439,6 +6450,7 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
RELEASE_ASSERT(k->cls == str_cls, "%s", k->cls->tp_name);
BoxedString* s = static_cast<BoxedString*>(k);
internStringMortalInplace(s);
AUTO_DECREF(s);
made->setattr(s, p.second, NULL);
}
......@@ -6789,11 +6801,14 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) {
attr_name = coerceUnicodeToStr<CXX>(attr_name);
if (attr_name->cls != str_cls)
if (attr_name->cls != str_cls) {
Py_DECREF(attr_name);
raiseExcHelper(TypeError, "attribute name must be string, not '%s'", getTypeName(attr_name));
}
BoxedString* casted_attr_name = static_cast<BoxedString*>(attr_name);
internStringMortalInplace(casted_attr_name);
AUTO_DECREF(casted_attr_name);
Box* attr_value = from_module->getattr(casted_attr_name);
if (!attr_value)
......
......@@ -390,9 +390,12 @@ extern "C" void PyString_InternInPlace(PyObject** p) noexcept {
return;
auto& entry = interned_strings[s->s()];
if (entry)
if (entry) {
Py_INCREF(entry);
Py_DECREF(*p);
*p = entry;
else {
} else {
// TODO: do CPython's refcounting here
num_interned_strings.log();
entry = s;
......
......@@ -2158,7 +2158,9 @@ public:
assert(_key->cls == str_cls);
BoxedString* key = static_cast<BoxedString*>(_key);
Py_INCREF(key); // TODO should be able to avoid this (if we change the refcount contract around interning)
internStringMortalInplace(key);
AUTO_DECREF(key);
self->b->setattr(key, value, NULL);
Py_RETURN_NONE;
......@@ -2197,7 +2199,9 @@ public:
assert(_key->cls == str_cls);
BoxedString* key = static_cast<BoxedString*>(_key);
Py_INCREF(key);
internStringMortalInplace(key);
AUTO_DECREF(key);
Box* cur = self->b->getattr(key);
if (cur)
......@@ -2215,6 +2219,7 @@ public:
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
internStringMortalInplace(key);
AUTO_DECREF(key);
Box* r = self->b->getattr(key);
if (!r)
......@@ -2233,6 +2238,7 @@ public:
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
internStringMortalInplace(key);
AUTO_DECREF(key);
Box* r = self->b->getattr(key);
if (!r) {
......@@ -2253,6 +2259,7 @@ public:
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
internStringMortalInplace(key);
AUTO_DECREF(key);
Box* r = self->b->getattr(key);
if (r) {
......@@ -2274,6 +2281,7 @@ public:
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
internStringMortalInplace(key);
AUTO_DECREF(key);
if (self->b->getattr(key))
self->b->delattr(key, NULL);
......@@ -2317,6 +2325,7 @@ public:
RELEASE_ASSERT(_key->cls == str_cls, "");
BoxedString* key = static_cast<BoxedString*>(_key);
internStringMortalInplace(key);
AUTO_DECREF(key);
Box* r = self->b->getattr(key);
return r ? True : False;
......@@ -3384,6 +3393,9 @@ void HiddenClass::dump() noexcept {
void HCAttrs::clear() noexcept {
HiddenClass* hcls = this->hcls;
if (!hcls)
return;
if (unlikely(hcls->type == HiddenClass::DICT_BACKED)) {
Box* d = this->attr_list->attrs[0];
Py_DECREF(d);
......@@ -3396,7 +3408,9 @@ void HCAttrs::clear() noexcept {
for (int i = 0; i < hcls->attributeArraySize(); i++) {
Py_DECREF(this->attr_list->attrs[i]);
}
// TODO need to free the attrs memory
if (this->attr_list)
PyMem_FREE(this->attr_list);
new ((void*)this) HCAttrs(root_hcls);
}
......
......@@ -396,20 +396,24 @@ template <typename B> DecrefHandle<B, true> autoXDecref(B* b) {
#define AUTO_DECREF(x) DecrefHandle<Box, false> CAT(_autodecref_, __LINE__)((x))
#define AUTO_XDECREF(x) DecrefHandle<Box, true> CAT(_autodecref_, __LINE__)((x))
class AutoXDecrefArray {
template <bool Nullable = false> class AutoDecrefArray {
private:
Box** array;
int size;
public:
AutoXDecrefArray(Box** array, int size) : array(array), size(size) {}
~AutoXDecrefArray() {
AutoDecrefArray(Box** array, int size) : array(array), size(size) {}
~AutoDecrefArray() {
for (int i = 0; i < size; i++) {
Py_XDECREF(array[i]);
if (Nullable)
Py_XDECREF(array[i]);
else
Py_DECREF(array[i]);
}
}
};
#define AUTO_XDECREF_ARRAY(x, size) AutoXDecrefArray CAT(_autodecref_, __LINE__)((x), (size))
#define AUTO_DECREF_ARRAY(x, size) AutoDecrefArray<false> CAT(_autodecref_, __LINE__)((x), (size))
#define AUTO_XDECREF_ARRAY(x, size) AutoDecrefArray<true> CAT(_autodecref_, __LINE__)((x), (size))
template <typename B> B* incref(B* b) {
Py_INCREF(b);
......
......@@ -94,7 +94,7 @@ Box* noneIfNull(Box* b) {
template <ExceptionStyle S> Box* coerceUnicodeToStr(Box* unicode) noexcept(S == CAPI) {
if (!isSubclass(unicode->cls, unicode_cls))
return unicode;
return incref(unicode);
Box* r = PyUnicode_AsASCIIString(unicode);
if (!r) {
......
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