Commit e1ed10e8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Convert BoxedMethodDescriptor call_internal to tppCall

Minor, but should cut down on some overhead
parent a9813b80
...@@ -226,123 +226,89 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) { ...@@ -226,123 +226,89 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
return new BoxedInstanceMethod(type, cm->cm_callable, type); return new BoxedInstanceMethod(type, cm->cm_callable, type);
} }
// TODO this should be auto-generated as a slot wrapper:
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) { Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10);
BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]); BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
return BoxedMethodDescriptor::tppCall(self, NULL, ArgPassSpec(1, 0, true, true), obj, varargs, kwargs, NULL, NULL);
}
assert(self->cls == method_cls); Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
assert(varargs->cls == tuple_cls); Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) {
assert(kwargs->cls == dict_cls); STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10);
assert(_self->cls == method_cls);
BoxedMethodDescriptor* self = static_cast<BoxedMethodDescriptor*>(_self);
int ml_flags = self->method->ml_flags; int ml_flags = self->method->ml_flags;
int call_flags = ml_flags & (~METH_CLASS);
int call_flags; if (rewrite_args && !rewrite_args->func_guarded) {
if (ml_flags & METH_CLASS) { rewrite_args->obj->addAttrGuard(offsetof(BoxedMethodDescriptor, method), (intptr_t)self->method);
if (!isSubclass(obj->cls, type_cls))
raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name,
getFullTypeName(obj).c_str());
call_flags = ml_flags & (~METH_CLASS);
} else {
if (!isSubclass(obj->cls, self->type))
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' object but received a '%s'",
self->method->ml_name, getFullNameOfClass(self->type).c_str(), getFullTypeName(obj).c_str());
call_flags = ml_flags;
} }
threading::GLPromoteRegion _gil_lock; ParamReceiveSpec paramspec(0, 0, false, false);
Box* rtn;
if (call_flags == METH_NOARGS) { if (call_flags == METH_NOARGS) {
RELEASE_ASSERT(varargs->size() == 0, ""); paramspec = ParamReceiveSpec(1, 0, false, false);
RELEASE_ASSERT(kwargs->d.size() == 0, "");
rtn = (Box*)self->method->ml_meth(obj, NULL);
} else if (call_flags == METH_VARARGS) { } else if (call_flags == METH_VARARGS) {
RELEASE_ASSERT(kwargs->d.size() == 0, ""); paramspec = ParamReceiveSpec(1, 0, true, false);
rtn = (Box*)self->method->ml_meth(obj, varargs);
} else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) {
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs); paramspec = ParamReceiveSpec(1, 0, true, true);
} else if (call_flags == METH_O) { } else if (call_flags == METH_O) {
RELEASE_ASSERT(kwargs->d.size() == 0, ""); paramspec = ParamReceiveSpec(2, 0, false, false);
RELEASE_ASSERT(varargs->size() == 1, "");
rtn = (Box*)self->method->ml_meth(obj, varargs->elts[0]);
} else { } else {
RELEASE_ASSERT(0, "0x%x", call_flags); RELEASE_ASSERT(0, "0x%x", call_flags);
} }
checkAndThrowCAPIException(); Box* oarg1 = NULL;
assert(rtn && "should have set + thrown an exception!"); Box* oarg2 = NULL;
return rtn; Box* oarg3 = NULL;
} Box** oargs = NULL;
Box* BoxedMethodDescriptor::callInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
// TODO: could also handle cases where we have starargs but no positional args,
// and similarly for kwargs but no keywords
if (!rewrite_args || argspec.has_kwargs || argspec.has_starargs || argspec.num_keywords > 0 || argspec.num_args > 4)
return callFunc(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
assert(argspec.num_args >= 2); bool rewrite_success = false;
int passed_varargs = argspec.num_args - 2; rearrangeArguments(paramspec, NULL, self->method->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1, arg2,
arg3, args, keyword_names, oarg1, oarg2, oarg3, args);
assert(arg1->cls == method_cls); if (!rewrite_success)
BoxedMethodDescriptor* self = static_cast<BoxedMethodDescriptor*>(arg1); rewrite_args = NULL;
Box* obj = arg2;
RewriterVar* r_obj = rewrite_args->arg2;
// We could also guard on the fields of the method object, but lets just guard on the object itself if (ml_flags & METH_CLASS) {
// for now. rewrite_args = NULL;
// TODO: what if it gets GC'd? if (!isSubclass(oarg1->cls, type_cls))
rewrite_args->arg1->addGuard((intptr_t)self); raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name,
getFullTypeName(oarg1).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());
}
int ml_flags = self->method->ml_flags; if (rewrite_args) {
RELEASE_ASSERT((ml_flags & METH_CLASS) == 0, "unimplemented"); rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)oarg1->cls);
if (!isSubclass(obj->cls, self->type)) }
raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' object but received a '%s'", self->method->ml_name,
getFullNameOfClass(self->type).c_str(), getFullTypeName(obj).c_str());
r_obj->addAttrGuard(offsetof(Box, cls), (intptr_t)obj->cls);
int call_flags = ml_flags;
Box* rtn; Box* rtn;
RewriterVar* r_rtn;
if (call_flags == METH_NOARGS) { if (call_flags == METH_NOARGS) {
RELEASE_ASSERT(passed_varargs == 0, ""); rtn = (Box*)self->method->ml_meth(oarg1, NULL);
rtn = (Box*)(self->method->ml_meth)(obj, NULL); if (rewrite_args)
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, rewrite_args->out_rtn
rewrite_args->rewriter->loadConst(0, Location::forArg(1))); = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
} else if (call_flags & METH_VARARGS) { rewrite_args->rewriter->loadConst(0, Location::forArg(1)));
RELEASE_ASSERT(call_flags == METH_VARARGS || call_flags == (METH_VARARGS | METH_KEYWORDS), ""); } else if (call_flags == METH_VARARGS) {
rtn = (Box*)self->method->ml_meth(oarg1, oarg2);
Box* varargs; if (rewrite_args)
RewriterVar* r_varargs; rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2);
if (passed_varargs == 0) { } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) {
varargs = EmptyTuple; rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(oarg1, oarg2, oarg3);
r_varargs = rewrite_args->rewriter->loadConst((intptr_t)EmptyTuple, Location::forArg(1)); if (rewrite_args)
} else if (passed_varargs == 1) { rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
varargs = BoxedTuple::create1(arg3); rewrite_args->arg2, rewrite_args->arg3);
r_varargs = rewrite_args->rewriter->call(false, (void*)BoxedTuple::create1, rewrite_args->arg3);
} else if (passed_varargs == 2) {
varargs = BoxedTuple::create2(arg3, args[0]);
r_varargs = rewrite_args->rewriter->call(false, (void*)BoxedTuple::create2, rewrite_args->arg3,
rewrite_args->args->getAttr(0, Location::forArg(1)));
} else {
RELEASE_ASSERT(0, "");
}
if (call_flags & METH_KEYWORDS) {
Box* kwargs = NULL;
RewriterVar* r_kwargs = rewrite_args->rewriter->loadConst(0);
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, r_varargs, r_kwargs);
} else {
rtn = (Box*)(self->method->ml_meth)(obj, varargs);
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, r_varargs);
}
} else if (call_flags == METH_O) { } else if (call_flags == METH_O) {
RELEASE_ASSERT(passed_varargs == 1, ""); rtn = (Box*)self->method->ml_meth(oarg1, oarg2);
rtn = (Box*)(self->method->ml_meth)(obj, arg3); if (rewrite_args)
r_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, r_obj, rewrite_args->arg3); rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2);
} else { } else {
RELEASE_ASSERT(0, "0x%x", call_flags); RELEASE_ASSERT(0, "0x%x", call_flags);
} }
...@@ -350,9 +316,11 @@ Box* BoxedMethodDescriptor::callInternal(BoxedFunctionBase* f, CallRewriteArgs* ...@@ -350,9 +316,11 @@ Box* BoxedMethodDescriptor::callInternal(BoxedFunctionBase* f, CallRewriteArgs*
if (!rtn) if (!rtn)
throwCAPIException(); throwCAPIException();
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException); if (rewrite_args) {
rewrite_args->out_rtn = r_rtn; rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException);
rewrite_args->out_success = true; rewrite_args->out_success = true;
}
return rtn; return rtn;
} }
...@@ -597,8 +565,8 @@ void setupDescr() { ...@@ -597,8 +565,8 @@ void setupDescr() {
method_cls->giveAttr("__get__", method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true); CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true);
method_call_cl->internal_callable = BoxedMethodDescriptor::callInternal;
method_cls->giveAttr("__call__", new BoxedFunction(method_call_cl)); method_cls->giveAttr("__call__", new BoxedFunction(method_call_cl));
method_cls->tpp_call = BoxedMethodDescriptor::tppCall;
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL)); method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze(); method_cls->freeze();
......
...@@ -927,8 +927,8 @@ public: ...@@ -927,8 +927,8 @@ public:
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner); static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner);
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args); static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
static Box* callInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names);
static void gcHandler(GCVisitor* v, Box* _o); static void gcHandler(GCVisitor* v, Box* _o);
}; };
......
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