Commit 324397a3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Allow templated tpp_call

parent 643a89bc
...@@ -460,7 +460,8 @@ struct _typeobject { ...@@ -460,7 +460,8 @@ struct _typeobject {
bool _flags[7]; bool _flags[7];
void* _tpp_descr_get; void* _tpp_descr_get;
void* _tpp_hasnext; void* _tpp_hasnext;
void* _tpp_call; void* _tpp_call_capi;
void* _tpp_call_cxx;
}; };
/* The *real* layout of a type object when allocated on the heap */ /* The *real* layout of a type object when allocated on the heap */
......
...@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept { ...@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// We don't cache anything yet that would need to be invalidated: // We don't cache anything yet that would need to be invalidated:
} }
template <ExceptionStyle S>
static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
ParamReceiveSpec paramspec(0, 0, true, true); ParamReceiveSpec paramspec(0, 0, true, true);
if (!argspec.has_kwargs && argspec.num_keywords == 0) { if (!argspec.has_kwargs && argspec.num_keywords == 0) {
paramspec.takes_kwargs = false; paramspec.takes_kwargs = false;
...@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp ...@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
bool rewrite_success = false; bool rewrite_success = false;
Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL; Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL;
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args, try {
keyword_names, oarg1, oarg2, oarg3, oargs); rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
if (!rewrite_success) if (!rewrite_success)
rewrite_args = NULL; rewrite_args = NULL;
...@@ -3213,12 +3223,13 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp ...@@ -3213,12 +3223,13 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj, rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj,
rewrite_args->arg1, rewrite_args->arg2); rewrite_args->arg1, rewrite_args->arg2);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException); if (S == CXX)
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
Box* r = self->cls->tp_call(self, oarg1, oarg2); Box* r = self->cls->tp_call(self, oarg1, oarg2);
if (!r) if (!r && S == CXX)
throwCAPIException(); throwCAPIException();
return r; return r;
} }
...@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->tp_name); assert(cls->tp_name);
if (cls->tp_call) if (cls->tp_call) {
cls->tpp_call = tppProxyToTpCall; cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>;
cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>;
}
try { try {
add_operators(cls); add_operators(cls);
......
...@@ -43,8 +43,9 @@ public: ...@@ -43,8 +43,9 @@ public:
} }
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs); static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
static Box* getname(Box* b, void*) { static Box* getname(Box* b, void*) {
RELEASE_ASSERT(b->cls == capifunc_cls, ""); RELEASE_ASSERT(b->cls == capifunc_cls, "");
......
...@@ -1476,11 +1476,23 @@ Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, B ...@@ -1476,11 +1476,23 @@ Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, B
// Kind of silly to have asked callFunc to rearrange the arguments for us, just to pass things // Kind of silly to have asked callFunc to rearrange the arguments for us, just to pass things
// off to tppCall, but this case should be very uncommon (people explicitly asking for __call__) // off to tppCall, but this case should be very uncommon (people explicitly asking for __call__)
return BoxedCApiFunction::tppCall(self, NULL, ArgPassSpec(0, 0, true, true), varargs, kwargs, NULL, NULL, NULL); return BoxedCApiFunction::tppCall<CXX>(self, NULL, ArgPassSpec(0, 0, true, true), varargs, kwargs, NULL, NULL,
NULL);
} }
template <ExceptionStyle S>
Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10); STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10);
assert(_self->cls == capifunc_cls); assert(_self->cls == capifunc_cls);
...@@ -1634,7 +1646,8 @@ void setupCAPI() { ...@@ -1634,7 +1646,8 @@ void setupCAPI() {
auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true)); auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true));
capifunc_cls->giveAttr("__call__", capi_call); capifunc_cls->giveAttr("__call__", capi_call);
capifunc_cls->tpp_call = BoxedCApiFunction::tppCall; capifunc_cls->tpp_call.capi_val = BoxedCApiFunction::tppCall<CAPI>;
capifunc_cls->tpp_call.cxx_val = BoxedCApiFunction::tppCall<CXX>;
capifunc_cls->giveAttr("__name__", capifunc_cls->giveAttr("__name__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL)); new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr("__doc__", capifunc_cls->giveAttr("__doc__",
......
...@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) { ...@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
// TODO this should be auto-generated as a slot wrapper: // 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) {
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); return BoxedMethodDescriptor::tppCall<CXX>(self, NULL, ArgPassSpec(1, 0, true, true), obj, varargs, kwargs, NULL,
NULL);
} }
template <ExceptionStyle S>
Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10); STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10);
assert(_self->cls == method_cls); assert(_self->cls == method_cls);
...@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds ...@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds
return rtn; return rtn;
} }
template <ExceptionStyle S>
Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedwrapperobject_call", (_self->cls->is_user_defined ? 10 : 20)); STAT_TIMER(t0, "us_timer_boxedwrapperobject_call", (_self->cls->is_user_defined ? 10 : 20));
assert(_self->cls == wrapperobject_cls); assert(_self->cls == wrapperobject_cls);
...@@ -617,7 +640,8 @@ void setupDescr() { ...@@ -617,7 +640,8 @@ void setupDescr() {
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_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->tpp_call.capi_val = BoxedMethodDescriptor::tppCall<CAPI>;
method_cls->tpp_call.cxx_val = BoxedMethodDescriptor::tppCall<CXX>;
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();
...@@ -632,7 +656,8 @@ void setupDescr() { ...@@ -632,7 +656,8 @@ void setupDescr() {
wrapperobject_cls->giveAttr( wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->tpp_call = BoxedWrapperObject::tppCall; wrapperobject_cls->tpp_call.capi_val = BoxedWrapperObject::tppCall<CAPI>;
wrapperobject_cls->tpp_call.cxx_val = BoxedWrapperObject::tppCall<CXX>;
wrapperobject_cls->freeze(); wrapperobject_cls->freeze();
} }
......
...@@ -435,7 +435,8 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset ...@@ -435,7 +435,8 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
is_user_defined(is_user_defined), is_user_defined(is_user_defined),
is_pyston_class(true), is_pyston_class(true),
has___class__(false), has___class__(false),
has_instancecheck(false) { has_instancecheck(false),
tpp_call(NULL, NULL) {
// Zero out the CPython tp_* slots: // Zero out the CPython tp_* slots:
memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name)); memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name));
...@@ -3643,20 +3644,20 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -3643,20 +3644,20 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (obj->cls != function_cls && obj->cls != builtin_function_or_method_cls && obj->cls != instancemethod_cls) { if (obj->cls != function_cls && obj->cls != builtin_function_or_method_cls && obj->cls != instancemethod_cls) {
// TODO: maybe eventually runtimeCallInternal should just be the default tpp_call? // TODO: maybe eventually runtimeCallInternal should just be the default tpp_call?
if (obj->cls->tpp_call) { if (obj->cls->tpp_call.get(S)) {
if (S == CAPI) { return obj->cls->tpp_call.call<S>(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
// TODO rewrite this } else if (S == CAPI && obj->cls->tpp_call.get<CXX>()) {
rewrite_args = NULL; try {
return obj->cls->tpp_call.call<CXX>(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
try { } catch (ExcInfo e) {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); setCAPIException(e);
} catch (ExcInfo e) { return NULL;
setCAPIException(e);
return NULL;
}
} else {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
} }
} else if (S == CXX && obj->cls->tpp_call.get<CAPI>()) {
Box* r = obj->cls->tpp_call.call<CAPI>(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
if (!r)
throwCAPIException();
return r;
} }
STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20); STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20);
......
...@@ -602,8 +602,19 @@ extern "C" CLFunction* unboxCLFunction(Box* b) { ...@@ -602,8 +602,19 @@ extern "C" CLFunction* unboxCLFunction(Box* b) {
static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names);
template <ExceptionStyle S>
static Box* typeTppCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* typeTppCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) { Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
if (S == CAPI) {
try {
return typeTppCall<CXX>(self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(S == CXX);
int npassed_args = argspec.totalPassed(); int npassed_args = argspec.totalPassed();
if (argspec.has_starargs || argspec.has_kwargs) { if (argspec.has_starargs || argspec.has_kwargs) {
...@@ -3471,7 +3482,8 @@ void setupRuntime() { ...@@ -3471,7 +3482,8 @@ void setupRuntime() {
add_operators(type_cls); add_operators(type_cls);
type_cls->freeze(); type_cls->freeze();
type_cls->tp_new = type_new; type_cls->tp_new = type_new;
type_cls->tpp_call = &typeTppCall; type_cls->tpp_call.capi_val = &typeTppCall<CAPI>;
type_cls->tpp_call.cxx_val = &typeTppCall<CXX>;
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1))); none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1)));
none_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1))); none_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1)));
......
...@@ -242,9 +242,8 @@ public: ...@@ -242,9 +242,8 @@ public:
pyston_inquiry tpp_hasnext; pyston_inquiry tpp_hasnext;
typedef Box* (*pyston_call)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**, ExceptionSwitchableFunction<Box*, Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*); const std::vector<BoxedString*>*> tpp_call;
pyston_call tpp_call;
bool hasGenericGetattr() { bool hasGenericGetattr() {
if (tp_getattr || tp_getattro != object_cls->tp_getattro) if (tp_getattr || tp_getattro != object_cls->tp_getattro)
...@@ -985,8 +984,9 @@ public: ...@@ -985,8 +984,9 @@ public:
DEFAULT_CLASS(wrapperobject_cls); DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds); static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
static void gcHandler(GCVisitor* v, Box* _o); static void gcHandler(GCVisitor* v, Box* _o);
}; };
...@@ -1001,8 +1001,9 @@ public: ...@@ -1001,8 +1001,9 @@ 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);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
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