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