Commit 63a6c334 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Refcount typeCallInner and rearrangeArguments

parent 2ac91905
...@@ -1859,7 +1859,7 @@ Box* processDescriptor(Box* obj, Box* inst, Box* owner) { ...@@ -1859,7 +1859,7 @@ Box* processDescriptor(Box* obj, Box* inst, Box* owner) {
Box* descr_r = processDescriptorOrNull(obj, inst, owner); Box* descr_r = processDescriptorOrNull(obj, inst, owner);
if (descr_r) if (descr_r)
return descr_r; return descr_r;
return obj; return incref(obj);
} }
...@@ -3403,7 +3403,7 @@ static int placeKeyword(const ParamNames* param_names, llvm::SmallVector<bool, 8 ...@@ -3403,7 +3403,7 @@ static int placeKeyword(const ParamNames* param_names, llvm::SmallVector<bool, 8
raiseExcHelper(TypeError, "%.200s() got multiple values for keyword argument '%s'", func_name_cb(), raiseExcHelper(TypeError, "%.200s() got multiple values for keyword argument '%s'", func_name_cb(),
kw_name->c_str()); kw_name->c_str());
} }
getArg(j, oarg1, oarg2, oarg3, oargs) = kw_val; getArg(j, oarg1, oarg2, oarg3, oargs) = incref(kw_val);
params_filled[j] = true; params_filled[j] = true;
return j; return j;
} }
...@@ -3415,7 +3415,8 @@ static int placeKeyword(const ParamNames* param_names, llvm::SmallVector<bool, 8 ...@@ -3415,7 +3415,8 @@ static int placeKeyword(const ParamNames* param_names, llvm::SmallVector<bool, 8
raiseExcHelper(TypeError, "%.200s() got multiple values for keyword argument '%s'", func_name_cb(), raiseExcHelper(TypeError, "%.200s() got multiple values for keyword argument '%s'", func_name_cb(),
kw_name->c_str()); kw_name->c_str());
} }
v = kw_val; incref(kw_name);
v = incref(kw_val);
return -1; return -1;
} else { } else {
raiseExcHelper(TypeError, "%.200s() got an unexpected keyword argument '%s'", func_name_cb(), kw_name->c_str()); raiseExcHelper(TypeError, "%.200s() got an unexpected keyword argument '%s'", func_name_cb(), kw_name->c_str());
...@@ -3470,6 +3471,8 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3470,6 +3471,8 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
rewrite_args = NULL; rewrite_args = NULL;
} }
assert(!rewrite_args && "check refcounting");
/* /*
* Procedure: * Procedure:
* - First match up positional arguments; any extra go to varargs. error if too many. * - First match up positional arguments; any extra go to varargs. error if too many.
...@@ -3491,6 +3494,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3491,6 +3494,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
// Super fast path: // Super fast path:
if (argspec.num_keywords == 0 && !argspec.has_starargs && !paramspec.takes_varargs && !argspec.has_kwargs if (argspec.num_keywords == 0 && !argspec.has_starargs && !paramspec.takes_varargs && !argspec.has_kwargs
&& argspec.num_args == paramspec.num_args && !paramspec.takes_kwargs) { && argspec.num_args == paramspec.num_args && !paramspec.takes_kwargs) {
assert(0 && "check refcounting");
rewrite_success = true; rewrite_success = true;
if (num_output_args > 3) if (num_output_args > 3)
memcpy(oargs, args, sizeof(Box*) * (num_output_args - 3)); memcpy(oargs, args, sizeof(Box*) * (num_output_args - 3));
...@@ -3501,6 +3505,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3501,6 +3505,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
// django-admin test this covers something like 93% of all calls to callFunc. // django-admin test this covers something like 93% of all calls to callFunc.
if (argspec.num_keywords == 0 && argspec.has_starargs == paramspec.takes_varargs && !argspec.has_kwargs if (argspec.num_keywords == 0 && argspec.has_starargs == paramspec.takes_varargs && !argspec.has_kwargs
&& argspec.num_args == paramspec.num_args && (!paramspec.takes_kwargs || paramspec.kwargsIndex() < 3)) { && argspec.num_args == paramspec.num_args && (!paramspec.takes_kwargs || paramspec.kwargsIndex() < 3)) {
assert(0 && "check refcounting");
// TODO could also do this for empty varargs // TODO could also do this for empty varargs
if (paramspec.takes_kwargs) { if (paramspec.takes_kwargs) {
...@@ -3589,7 +3594,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3589,7 +3594,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
} }
} }
PyObject* varargs = NULL; DecrefHandle<PyObject, true> varargs(NULL);
size_t varargs_size = 0; size_t varargs_size = 0;
if (argspec.has_starargs) { if (argspec.has_starargs) {
assert(!rewrite_args); assert(!rewrite_args);
...@@ -3604,13 +3609,13 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3604,13 +3609,13 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
// First, match up positional parameters to positional/varargs: // First, match up positional parameters to positional/varargs:
int positional_to_positional = std::min(argspec.num_args, paramspec.num_args); int positional_to_positional = std::min(argspec.num_args, paramspec.num_args);
for (int i = 0; i < positional_to_positional; i++) { for (int i = 0; i < positional_to_positional; i++) {
getArg(i, oarg1, oarg2, oarg3, oargs) = getArg(i, arg1, arg2, arg3, args); getArg(i, oarg1, oarg2, oarg3, oargs) = incref(getArg(i, arg1, arg2, arg3, args));
} }
int varargs_to_positional = std::min((int)varargs_size, paramspec.num_args - positional_to_positional); int varargs_to_positional = std::min((int)varargs_size, paramspec.num_args - positional_to_positional);
for (int i = 0; i < varargs_to_positional; i++) { for (int i = 0; i < varargs_to_positional; i++) {
assert(!rewrite_args && "would need to be handled here"); assert(!rewrite_args && "would need to be handled here");
getArg(i + positional_to_positional, oarg1, oarg2, oarg3, oargs) = PySequence_Fast_GET_ITEM(varargs, i); getArg(i + positional_to_positional, oarg1, oarg2, oarg3, oargs) = incref(PySequence_Fast_GET_ITEM(varargs, i));
} }
llvm::SmallVector<bool, 8> params_filled(num_output_args); llvm::SmallVector<bool, 8> params_filled(num_output_args);
...@@ -3620,7 +3625,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3620,7 +3625,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
// unussed_positional relies on the fact that all the args (including a potentially-created varargs) will keep its // unussed_positional relies on the fact that all the args (including a potentially-created varargs) will keep its
// contents alive // contents alive
llvm::SmallVector<Box*, 4> unused_positional; llvm::SmallVector<BORROWED(Box*), 4> unused_positional;
unused_positional.reserve(argspec.num_args - positional_to_positional + varargs_size - varargs_to_positional); unused_positional.reserve(argspec.num_args - positional_to_positional + varargs_size - varargs_to_positional);
RewriterVar::SmallVector unused_positional_rvars; RewriterVar::SmallVector unused_positional_rvars;
...@@ -3645,6 +3650,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3645,6 +3650,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
if (paramspec.takes_varargs) { if (paramspec.takes_varargs) {
int varargs_idx = paramspec.num_args; int varargs_idx = paramspec.num_args;
if (rewrite_args) { if (rewrite_args) {
assert(0 && "check refcounting");
assert(!varargs_size); assert(!varargs_size);
assert(!argspec.has_starargs); assert(!argspec.has_starargs);
...@@ -3686,9 +3692,9 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3686,9 +3692,9 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
assert(varargs_size == unused_positional.size()); assert(varargs_size == unused_positional.size());
if (!varargs) if (!varargs)
ovarargs = EmptyTuple; ovarargs = incref(EmptyTuple);
else else
ovarargs = varargs; ovarargs = incref(varargs.get()); // TODO we could have DecrefHandle be smart and hand off it's reference
} else { } else {
ovarargs = BoxedTuple::create(unused_positional.size(), unused_positional.data()); ovarargs = BoxedTuple::create(unused_positional.size(), unused_positional.data());
} }
...@@ -3700,8 +3706,6 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3700,8 +3706,6 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
(paramspec.num_args == 1 ? "" : "s"), argspec.num_args + argspec.num_keywords + varargs_size); (paramspec.num_args == 1 ? "" : "s"), argspec.num_args + argspec.num_keywords + varargs_size);
} }
Py_XDECREF(varargs);
//// ////
// Second, apply any keywords: // Second, apply any keywords:
...@@ -3802,7 +3806,11 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3802,7 +3806,11 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
BoxedDict* d = new BoxedDict(); BoxedDict* d = new BoxedDict();
dictMerge(d, kwargs); dictMerge(d, kwargs);
kwargs = d; kwargs = d;
} else {
Py_INCREF(kwargs);
} }
DecrefHandle<Box> _kwargs_handle(kwargs);
assert(PyDict_Check(kwargs)); assert(PyDict_Check(kwargs));
BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs); BoxedDict* d_kwargs = static_cast<BoxedDict*>(kwargs);
...@@ -3835,7 +3843,8 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3835,7 +3843,8 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
raiseExcHelper(TypeError, "%s() got multiple values for keyword argument '%s'", func_name_cb(), raiseExcHelper(TypeError, "%s() got multiple values for keyword argument '%s'", func_name_cb(),
s->data()); s->data());
} }
v = p.second; v = incref(p.second);
incref(p.first);
assert(!rewrite_args); assert(!rewrite_args);
} }
} }
...@@ -3861,6 +3870,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3861,6 +3870,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
Box* default_obj = defaults[default_idx]; Box* default_obj = defaults[default_idx];
if (rewrite_args) { if (rewrite_args) {
assert(0 && "check refcounting");
if (arg_idx == 0) if (arg_idx == 0)
rewrite_args->arg1 = rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::forArg(0)); rewrite_args->arg1 = rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::forArg(0));
else if (arg_idx == 1) else if (arg_idx == 1)
...@@ -3872,7 +3882,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa ...@@ -3872,7 +3882,7 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
rewrite_args->rewriter->loadConst((intptr_t)default_obj)); rewrite_args->rewriter->loadConst((intptr_t)default_obj));
} }
getArg(arg_idx, oarg1, oarg2, oarg3, oargs) = default_obj; getArg(arg_idx, oarg1, oarg2, oarg3, oargs) = incref(default_obj);
} }
} }
......
...@@ -294,6 +294,8 @@ struct CompareRewriteArgs { ...@@ -294,6 +294,8 @@ struct CompareRewriteArgs {
// The caller is responsible for guarding for paramspec, argspec, param_names, and defaults. // The caller is responsible for guarding for paramspec, argspec, param_names, and defaults.
// TODO Fix this function's signature. should we pass back out through args? the common case is that they // TODO Fix this function's signature. should we pass back out through args? the common case is that they
// match anyway. Or maybe it should call a callback function, which could save on the common case. // match anyway. Or maybe it should call a callback function, which could save on the common case.
//
// Reference semantics: takes borrowed references, and everything written out is an owned reference.
template <Rewritable rewritable = REWRITABLE> template <Rewritable rewritable = REWRITABLE>
void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_names, const char* func_name, void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_names, const char* func_name,
Box** defaults, _CallRewriteArgsBase* rewrite_args, bool& rewrite_success, ArgPassSpec argspec, Box** defaults, _CallRewriteArgsBase* rewrite_args, bool& rewrite_success, ArgPassSpec argspec,
......
...@@ -793,7 +793,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -793,7 +793,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
RewriterVar* r_ccls = NULL; RewriterVar* r_ccls = NULL;
RewriterVar* r_new = NULL; RewriterVar* r_new = NULL;
RewriterVar* r_init = NULL; RewriterVar* r_init = NULL;
Box* new_attr, * init_attr = NULL; Box* init_attr = NULL;
if (rewrite_args) { if (rewrite_args) {
assert(!argspec.has_starargs); assert(!argspec.has_starargs);
assert(!argspec.has_kwargs); assert(!argspec.has_kwargs);
...@@ -825,8 +825,10 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -825,8 +825,10 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
} }
} }
DecrefHandle<Box, true> new_attr(nullptr);
static BoxedString* new_str = getStaticString("__new__"); static BoxedString* new_str = getStaticString("__new__");
if (rewrite_args) { if (rewrite_args) {
assert(0 && "check refcounting");
GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, r_ccls, rewrite_args->destination); GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, r_ccls, rewrite_args->destination);
// TODO: if tp_new != Py_CallPythonNew, call that instead? // TODO: if tp_new != Py_CallPythonNew, call that instead?
new_attr = typeLookup(cls, new_str, &grewrite_args); new_attr = typeLookup(cls, new_str, &grewrite_args);
...@@ -856,7 +858,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -856,7 +858,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
} }
} }
} else { } else {
new_attr = typeLookup(cls, new_str); new_attr = incref(typeLookup(cls, new_str));
try { try {
if (new_attr->cls != function_cls) // optimization if (new_attr->cls != function_cls) // optimization
new_attr = processDescriptor(new_attr, None, cls); new_attr = processDescriptor(new_attr, None, cls);
...@@ -1152,6 +1154,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1152,6 +1154,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
Box* initrtn; Box* initrtn;
// If there's a Python-level __init__ function, try calling it. // If there's a Python-level __init__ function, try calling it.
if (init_attr && init_attr->cls == function_cls) { if (init_attr && init_attr->cls == function_cls) {
assert(0 && "check refcounting");
if (rewrite_args) { if (rewrite_args) {
// We are going to rewrite as a call to cls.init: // We are going to rewrite as a call to cls.init:
assert(which_init == MAKES_CLS); assert(which_init == MAKES_CLS);
...@@ -1232,6 +1235,9 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1232,6 +1235,9 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
assert(!arg3 || arg3->cls == dict_cls); assert(!arg3 || arg3->cls == dict_cls);
int err = tpinit(made, arg2, arg3); int err = tpinit(made, arg2, arg3);
Py_DECREF(made);
Py_DECREF(arg2);
Py_XDECREF(arg3);
if (err == -1) { if (err == -1) {
if (S == CAPI) if (S == CAPI)
return NULL; return NULL;
......
...@@ -361,6 +361,30 @@ public: ...@@ -361,6 +361,30 @@ public:
Py_DECREF(b); Py_DECREF(b);
} }
operator B*() { return b; } operator B*() { return b; }
B* operator->() { return b; }
explicit operator intptr_t() { return (intptr_t)b; }
bool operator==(B* rhs) {
return b == rhs;
}
bool operator!=(B* rhs) {
return b != rhs;
}
// Hacky, but C API macros like to use direct C casts. At least this is "explicit"
template <typename B2> explicit operator B2*() { return (B2*)(b); }
B* get() {
return b;
}
void operator=(B* new_b) {
B* old_b = b;
b = new_b;
if (Nullable)
Py_XDECREF(old_b);
else
Py_DECREF(old_b);
}
}; };
template <typename B, bool Nullable = false> DecrefHandle<B, Nullable> autoDecref(B* b) { template <typename B, bool Nullable = false> DecrefHandle<B, Nullable> autoDecref(B* b) {
return DecrefHandle<B, Nullable>(b); return DecrefHandle<B, Nullable>(b);
......
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