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

Allow templated tpp_call

parent 643a89bc
......@@ -460,7 +460,8 @@ struct _typeobject {
bool _flags[7];
void* _tpp_descr_get;
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 */
......
......@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// 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,
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);
if (!argspec.has_kwargs && argspec.num_keywords == 0) {
paramspec.takes_kwargs = false;
......@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
bool rewrite_success = false;
Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL;
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
try {
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)
rewrite_args = NULL;
......@@ -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->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;
}
Box* r = self->cls->tp_call(self, oarg1, oarg2);
if (!r)
if (!r && S == CXX)
throwCAPIException();
return r;
}
......@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->tp_name);
if (cls->tp_call)
cls->tpp_call = tppProxyToTpCall;
if (cls->tp_call) {
cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>;
cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>;
}
try {
add_operators(cls);
......
......@@ -43,8 +43,9 @@ public:
}
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,
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*) {
RELEASE_ASSERT(b->cls == capifunc_cls, "");
......
......@@ -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
// 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* 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);
assert(_self->cls == capifunc_cls);
......@@ -1634,7 +1646,8 @@ void setupCAPI() {
auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true));
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__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr("__doc__",
......
......@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
// TODO this should be auto-generated as a slot wrapper:
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
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* 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);
assert(_self->cls == method_cls);
......@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds
return rtn;
}
template <ExceptionStyle S>
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));
assert(_self->cls == wrapperobject_cls);
......@@ -617,7 +640,8 @@ void setupDescr() {
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true);
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->freeze();
......@@ -632,7 +656,8 @@ void setupDescr() {
wrapperobject_cls->giveAttr(
"__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();
}
......
......@@ -435,7 +435,8 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
is_user_defined(is_user_defined),
is_pyston_class(true),
has___class__(false),
has_instancecheck(false) {
has_instancecheck(false),
tpp_call(NULL, NULL) {
// Zero out the CPython tp_* slots:
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
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?
if (obj->cls->tpp_call) {
if (S == CAPI) {
// TODO rewrite this
rewrite_args = NULL;
try {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
if (obj->cls->tpp_call.get(S)) {
return obj->cls->tpp_call.call<S>(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
} else if (S == CAPI && obj->cls->tpp_call.get<CXX>()) {
try {
return obj->cls->tpp_call.call<CXX>(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} 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);
......
......@@ -602,8 +602,19 @@ extern "C" CLFunction* unboxCLFunction(Box* b) {
static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
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,
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();
if (argspec.has_starargs || argspec.has_kwargs) {
......@@ -3471,7 +3482,8 @@ void setupRuntime() {
add_operators(type_cls);
type_cls->freeze();
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("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1)));
......
......@@ -242,9 +242,8 @@ public:
pyston_inquiry tpp_hasnext;
typedef Box* (*pyston_call)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*);
pyston_call tpp_call;
ExceptionSwitchableFunction<Box*, Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*> tpp_call;
bool hasGenericGetattr() {
if (tp_getattr || tp_getattro != object_cls->tp_getattro)
......@@ -985,8 +984,9 @@ public:
DEFAULT_CLASS(wrapperobject_cls);
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,
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);
};
......@@ -1001,8 +1001,9 @@ public:
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner);
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,
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);
};
......
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