Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More small optimizations #824

Merged
merged 3 commits into from
Aug 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/capi/typeobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2558,11 +2558,11 @@ static int mro_internal(PyTypeObject* type) noexcept {
extern "C" int PyType_IsSubtype(PyTypeObject* a, PyTypeObject* b) noexcept {
PyObject* mro;

if (!(a->tp_flags & Py_TPFLAGS_HAVE_CLASS))
if (unlikely(!(a->tp_flags & Py_TPFLAGS_HAVE_CLASS)))
return b == a || b == &PyBaseObject_Type;

mro = a->tp_mro;
if (mro != NULL) {
if (likely(mro != NULL)) {
/* Deal with multiple inheritance without recursion
by walking the MRO tuple */
Py_ssize_t i, n;
Expand Down Expand Up @@ -3217,10 +3217,10 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
}

bool rewrite_success = false;
Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL;
Box** oargs = NULL;
try {
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
oargs, keyword_names);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
Expand Down Expand Up @@ -3251,7 +3251,7 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
rewrite_args->out_success = true;
}

Box* r = self->cls->tp_call(self, oarg1, oarg2);
Box* r = self->cls->tp_call(self, arg1, arg2);
if (!r && S == CXX)
throwCAPIException();
return r;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/builtin_modules/builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ template <ExceptionStyle S> Box* getattrFunc(Box* obj, Box* _str, Box* default_v
throw e;
}

if (!isSubclass(_str->cls, str_cls)) {
if (!PyString_Check(_str)) {
if (S == CAPI) {
PyErr_SetString(TypeError, "getattr(): attribute name must be string");
return NULL;
Expand Down
17 changes: 7 additions & 10 deletions src/runtime/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1524,14 +1524,11 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
RELEASE_ASSERT(0, "0x%x", flags);
}

Box* oarg1 = NULL;
Box* oarg2 = NULL;
Box* oarg3 = NULL;
Box** oargs = NULL;

bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->method_def->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, oargs);
arg2, arg3, args, oargs, keyword_names);

if (!rewrite_success)
rewrite_args = NULL;
Expand All @@ -1542,11 +1539,11 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa

Box* rtn;
if (flags == METH_VARARGS) {
rtn = (Box*)func(self->passthrough, oarg1);
rtn = (Box*)func(self->passthrough, arg1);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1);
} else if (flags == (METH_VARARGS | METH_KEYWORDS)) {
rtn = (Box*)((PyCFunctionWithKeywords)func)(self->passthrough, oarg1, oarg2);
rtn = (Box*)((PyCFunctionWithKeywords)func)(self->passthrough, arg1, arg2);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1,
rewrite_args->arg2);
Expand All @@ -1556,18 +1553,18 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
rewrite_args->out_rtn = rewrite_args->rewriter->call(
true, (void*)func, r_passthrough, rewrite_args->rewriter->loadConst(0, Location::forArg(1)));
} else if (flags == METH_O) {
rtn = (Box*)func(self->passthrough, oarg1);
rtn = (Box*)func(self->passthrough, arg1);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1);
} else if (flags == METH_OLDARGS) {
/* the really old style */

rewrite_args = NULL;

int size = PyTuple_GET_SIZE(oarg1);
Box* arg = oarg1;
int size = PyTuple_GET_SIZE(arg1);
Box* arg = arg1;
if (size == 1)
arg = PyTuple_GET_ITEM(oarg1, 0);
arg = PyTuple_GET_ITEM(arg1, 0);
else if (size == 0)
arg = NULL;
rtn = func(self->passthrough, arg);
Expand Down
46 changes: 19 additions & 27 deletions src/runtime/descr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,45 +292,41 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
RELEASE_ASSERT(0, "0x%x", call_flags);
}

Box* oarg1 = NULL;
Box* oarg2 = NULL;
Box* oarg3 = NULL;
Box** oargs = NULL;

Box* oargs_array[1];
if (paramspec.totalReceived() >= 3) {
if (paramspec.totalReceived() > 3) {
assert((paramspec.totalReceived() - 3) <= sizeof(oargs_array) / sizeof(oargs_array[0]));
oargs = oargs_array;
}

bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->method->ml_name, defaults, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, oargs);
arg2, arg3, args, oargs, keyword_names);

if (!rewrite_success)
rewrite_args = NULL;

if (ml_flags & METH_CLASS) {
rewrite_args = NULL;
if (!isSubclass(oarg1->cls, type_cls))
if (!isSubclass(arg1->cls, type_cls))
raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name,
getFullTypeName(oarg1).c_str());
getFullTypeName(arg1).c_str());
} else {
if (!isSubclass(oarg1->cls, self->type))
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' oarg1 but received a '%s'",
self->method->ml_name, getFullNameOfClass(self->type).c_str(),
getFullTypeName(oarg1).c_str());
if (!isSubclass(arg1->cls, self->type))
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' arg1 but received a '%s'", self->method->ml_name,
getFullNameOfClass(self->type).c_str(), getFullTypeName(arg1).c_str());
}

if (rewrite_args) {
rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)oarg1->cls);
rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)arg1->cls);
}

Box* rtn;
if (call_flags == METH_NOARGS) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = (Box*)self->method->ml_meth(oarg1, NULL);
rtn = (Box*)self->method->ml_meth(arg1, NULL);
}
if (rewrite_args)
rewrite_args->out_rtn
Expand All @@ -339,31 +335,31 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
} else if (call_flags == METH_VARARGS) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = (Box*)self->method->ml_meth(oarg1, oarg2);
rtn = (Box*)self->method->ml_meth(arg1, arg2);
}
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2);
} else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(oarg1, oarg2, oarg3);
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(arg1, arg2, arg3);
}
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2, rewrite_args->arg3);
} else if (call_flags == METH_O) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = (Box*)self->method->ml_meth(oarg1, oarg2);
rtn = (Box*)self->method->ml_meth(arg1, arg2);
}
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2);
} else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = ((Box * (*)(Box*, Box*, Box*, Box**))self->method->ml_meth)(oarg1, oarg2, oarg3, oargs);
rtn = ((Box * (*)(Box*, Box*, Box*, Box**))self->method->ml_meth)(arg1, arg2, arg3, oargs);
}
if (rewrite_args) {
if (paramspec.totalReceived() == 2)
Expand Down Expand Up @@ -536,28 +532,24 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP
RELEASE_ASSERT(0, "%d", flags);
}

Box* oarg1 = NULL;
Box* oarg2 = NULL;
Box* oarg3 = NULL;
Box** oargs = NULL;

bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->descr->wrapper->name.data(), NULL, rewrite_args, rewrite_success, argspec,
arg1, arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, oargs);
arg1, arg2, arg3, args, oargs, keyword_names);

assert(oarg1 && oarg1->cls == tuple_cls);
assert(arg1 && arg1->cls == tuple_cls);
if (!paramspec.takes_kwargs)
assert(oarg2 == NULL);
assert(oarg3 == NULL);
assert(oargs == NULL);
assert(arg2 == NULL);
assert(arg3 == NULL);

if (!rewrite_success)
rewrite_args = NULL;

Box* rtn;
if (flags == PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
rtn = (*wk)(self->obj, oarg1, self->descr->wrapped, oarg2);
rtn = (*wk)(self->obj, arg1, self->descr->wrapped, arg2);

if (rewrite_args) {
auto rewriter = rewrite_args->rewriter;
Expand All @@ -569,7 +561,7 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP
rewrite_args->out_success = true;
}
} else if (flags == PyWrapperFlag_PYSTON || flags == 0) {
rtn = (*wrapper)(self->obj, oarg1, self->descr->wrapped);
rtn = (*wrapper)(self->obj, arg1, self->descr->wrapped);

if (rewrite_args) {
auto rewriter = rewrite_args->rewriter;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ template <ExceptionStyle S> Box* intNew(Box* _cls, Box* val, Box* base) noexcept
return n;

if (S == CAPI) {
PyErr_Format(OverflowError, "Python int too large to convert to C long");
PyErr_SetString(OverflowError, "Python int too large to convert to C long");
return NULL;
} else
raiseExcHelper(OverflowError, "Python int too large to convert to C long");
Expand Down
52 changes: 28 additions & 24 deletions src/runtime/objmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,6 @@ extern "C" void my_assert(bool b) {
assert(b);
}

extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent) {
STAT_TIMER(t0, "us_timer_isSubclass", 10);
return PyType_IsSubtype(child, parent);
}

extern "C" void assertFail(Box* assertion_type, Box* msg) {
RELEASE_ASSERT(assertion_type->cls == type_cls, "%s", assertion_type->cls->tp_name);
if (msg) {
Expand Down Expand Up @@ -3052,8 +3047,8 @@ ArgPassSpec bindObjIntoArgs(Box* bind_obj, RewriterVar* r_bind_obj, CallRewriteA

void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_names, const char* func_name,
Box** defaults, CallRewriteArgs* rewrite_args, bool& rewrite_success, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names,
Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs) {
Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** args, Box** oargs,
const std::vector<BoxedString*>* keyword_names) {
/*
* Procedure:
* - First match up positional arguments; any extra go to varargs. error if too many.
Expand All @@ -3066,21 +3061,30 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
int num_passed_args = argspec.totalPassed();

if (num_passed_args >= 1)
assert(gc::isValidGCObject(arg1) || !arg1);
assert(gc::isValidGCObject(oarg1) || !oarg1);
if (num_passed_args >= 2)
assert(gc::isValidGCObject(arg2) || !arg2);
assert(gc::isValidGCObject(oarg2) || !oarg2);
if (num_passed_args >= 3)
assert(gc::isValidGCObject(arg3) || !arg3);
assert(gc::isValidGCObject(oarg3) || !oarg3);
for (int i = 3; i < num_passed_args; i++) {
assert(gc::isValidGCObject(args[i - 3]) || args[i - 3] == NULL);
}

assert((oargs != NULL) == (num_output_args > 3));
assert((defaults != NULL) == (paramspec.num_defaults != 0));

if (rewrite_args) {
rewrite_success = false; // default case
}

// Super fast path:
if (argspec.num_keywords == 0 && !argspec.has_starargs && !paramspec.takes_varargs && !argspec.has_kwargs
&& argspec.num_args == paramspec.num_args && !paramspec.takes_kwargs) {
rewrite_success = true;
if (num_output_args > 3)
memcpy(oargs, args, sizeof(Box*) * (num_output_args - 3));
return;
}

// Fast path: if it's a simple-enough call, we don't have to do anything special. On a simple
// 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
Expand All @@ -3091,7 +3095,7 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
assert(num_output_args == num_passed_args + 1);
int idx = paramspec.kwargsIndex();
assert(idx < 3);
getArg(idx, arg1, arg2, arg3, NULL) = NULL; // pass NULL for kwargs
getArg(idx, oarg1, oarg2, oarg3, NULL) = NULL; // pass NULL for kwargs
if (rewrite_args) {
if (idx == 0)
rewrite_args->arg1 = rewrite_args->rewriter->loadConst(0);
Expand All @@ -3111,31 +3115,31 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
// received by the caller are always tuples).
// This is why we can't pass kwargs here.
if (argspec.has_starargs) {
Box* given_varargs = getArg(argspec.num_args + argspec.num_keywords, arg1, arg2, arg3, args);
Box* given_varargs = getArg(argspec.num_args + argspec.num_keywords, oarg1, oarg2, oarg3, args);
if (given_varargs->cls == tuple_cls) {
if (rewrite_args) {
getArg(argspec.num_args + argspec.num_keywords, rewrite_args)
->addAttrGuard(offsetof(Box, cls), (intptr_t)tuple_cls);
}
rewrite_success = true;
oarg1 = arg1;
oarg2 = arg2;
oarg3 = arg3;
if (num_output_args > 3)
memcpy(oargs, args, sizeof(Box*) * (num_output_args - 3));
return;
}
} else {
rewrite_success = true;
oarg1 = arg1;
oarg2 = arg2;
oarg3 = arg3;
if (num_output_args > 3)
memcpy(oargs, args, sizeof(Box*) * (num_output_args - 3));
return;
}
}

// Save the original values:
Box* arg1 = oarg1;
Box* arg2 = oarg2;
Box* arg3 = oarg3;
oarg1 = oarg2 = oarg3 = NULL;

static StatCounter slowpath_rearrangeargs_slowpath("slowpath_rearrangeargs_slowpath");
slowpath_rearrangeargs_slowpath.log();

Expand Down Expand Up @@ -3410,7 +3414,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
}
}

Box* oarg1, *oarg2, *oarg3, **oargs;
Box** oargs;
bool rewrite_success = false;

int num_output_args = paramspec.totalReceived();
Expand All @@ -3431,7 +3435,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
try {
rearrangeArguments(paramspec, &f->param_names, getFunctionName(f).data(),
paramspec.num_defaults ? func->defaults->elts : NULL, rewrite_args, rewrite_success, argspec,
arg1, arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, oargs);
arg1, arg2, arg3, args, oargs, keyword_names);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
Expand All @@ -3442,7 +3446,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe

#if 0
for (int i = 0; i < num_output_args; i++) {
auto arg = getArg(i, oarg1, oarg2, oarg3, oargs);
auto arg = getArg(i, arg1, arg2, arg3, oargs);
RELEASE_ASSERT(!arg || gc::isValidGCObject(arg), "%p", arg);
}
#endif
Expand Down Expand Up @@ -3518,9 +3522,9 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
if (f->isGenerator()) {
// TODO: we might not have a lot to gain by rewriting into createGenerator, but we could at least
// rewrite up to the call to it:
res = createGenerator(func, oarg1, oarg2, oarg3, oargs);
res = createGenerator(func, arg1, arg2, arg3, oargs);
} else {
res = callCLFunc<S>(f, rewrite_args, num_output_args, closure, NULL, func->globals, oarg1, oarg2, oarg3, oargs);
res = callCLFunc<S>(f, rewrite_args, num_output_args, closure, NULL, func->globals, arg1, arg2, arg3, oargs);
}

return res;
Expand Down
6 changes: 5 additions & 1 deletion src/runtime/objmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size);
extern "C" void assertNameDefined(bool b, const char* name, BoxedClass* exc_cls, bool local_var_msg);
extern "C" void assertFailDerefNameDefined(const char* name);
extern "C" void assertFail(Box* assertion_type, Box* msg);
extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent);

inline bool isSubclass(BoxedClass* child, BoxedClass* parent) {
return child == parent || PyType_IsSubtype(child, parent);
}

extern "C" BoxedClosure* createClosure(BoxedClosure* parent_closure, size_t size);

Box* getiter(Box* o);
Expand Down
Loading