Commit 220f702e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Use PySequence_Fast for faster *arg unpacking

Much faster than using pyElements into a std::vector<Box*, StlCompatAllocator>.

I think pyElements is pretty good, but the PySequence_Fast approach can beat it
since we do the entire conversion up-front, and don't pay the dispatching cost
per iteration.  Plus the STL-compat-allocator is just as expensive as a Python
list, and most of the time the extra storage isn't needed anyway.
parent 7df079cb
...@@ -3177,13 +3177,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3177,13 +3177,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
} }
} }
std::vector<Box*, StlCompatAllocator<Box*>> varargs; PyObject* varargs = NULL;
size_t varargs_size = 0;
if (argspec.has_starargs) { if (argspec.has_starargs) {
assert(!rewrite_args); assert(!rewrite_args);
Box* given_varargs = getArg(argspec.num_args + argspec.num_keywords, arg1, arg2, arg3, args); Box* given_varargs = getArg(argspec.num_args + argspec.num_keywords, arg1, arg2, arg3, args);
for (Box* e : given_varargs->pyElements()) { varargs = PySequence_Fast(given_varargs, "argument after * must be a sequence");
varargs.push_back(e); if (!varargs)
} return throwCAPIException();
varargs_size = PySequence_Fast_GET_SIZE(varargs);
} }
//// ////
...@@ -3193,10 +3195,10 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3193,10 +3195,10 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
getArg(i, oarg1, oarg2, oarg3, oargs) = getArg(i, arg1, arg2, arg3, args); getArg(i, oarg1, oarg2, oarg3, oargs) = 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) = varargs[i]; getArg(i + positional_to_positional, oarg1, oarg2, oarg3, oargs) = PySequence_Fast_GET_ITEM(varargs, i);
} }
llvm::SmallVector<bool, 8> params_filled(num_output_args); llvm::SmallVector<bool, 8> params_filled(num_output_args);
...@@ -3219,15 +3221,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3219,15 +3221,15 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
unused_positional_rvars.push_back(rewrite_args->args->getAttr((i - 3) * sizeof(Box*))); unused_positional_rvars.push_back(rewrite_args->args->getAttr((i - 3) * sizeof(Box*)));
} }
} }
for (int i = varargs_to_positional; i < varargs.size(); i++) { for (int i = varargs_to_positional; i < varargs_size; i++) {
assert(!rewrite_args); assert(!rewrite_args);
unused_positional.push_back(varargs[i]); unused_positional.push_back(PySequence_Fast_GET_ITEM(varargs, i));
} }
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(!varargs.size()); assert(!varargs_size);
assert(!argspec.has_starargs); assert(!argspec.has_starargs);
RewriterVar* varargs_val; RewriterVar* varargs_val;
...@@ -3267,7 +3269,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3267,7 +3269,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs; getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
} else if (unused_positional.size()) { } else if (unused_positional.size()) {
raiseExcHelper(TypeError, "%s() takes at most %d argument%s (%ld given)", func_name, paramspec.num_args, raiseExcHelper(TypeError, "%s() takes at most %d argument%s (%ld given)", func_name, paramspec.num_args,
(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);
} }
//// ////
...@@ -3367,7 +3369,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3367,7 +3369,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
if (params_filled[i]) if (params_filled[i])
continue; continue;
raiseExcHelper(TypeError, "%s() takes exactly %d arguments (%ld given)", func_name, paramspec.num_args, raiseExcHelper(TypeError, "%s() takes exactly %d arguments (%ld given)", func_name, paramspec.num_args,
argspec.num_args + argspec.num_keywords + varargs.size()); argspec.num_args + argspec.num_keywords + varargs_size);
} }
for (int arg_idx = paramspec.num_args - paramspec.num_defaults; arg_idx < paramspec.num_args; arg_idx++) { for (int arg_idx = paramspec.num_args - paramspec.num_defaults; arg_idx < paramspec.num_args; arg_idx++) {
......
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