Box* wrapperDescrTppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) { if (S == CAPI) { try { return wrapperDescrTppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names); } catch (ExcInfo e) { setCAPIException(e); return NULL; } } if (rewrite_args) { // We are going to embed references to _self->d_base->wrapper and _self->d_wrapped rewrite_args->obj->addGuard((intptr_t)_self); rewrite_args->rewriter->addGCReference(_self); } STAT_TIMER(t0, "us_timer_boxedwrapperdecsriptor_call", (_self->cls->is_user_defined ? 10 : 20)); assert(_self->cls == &PyWrapperDescr_Type); PyWrapperDescrObject* self = reinterpret_cast<PyWrapperDescrObject*>(_self); int flags = self->d_base->flags; wrapperfunc wrapper = self->d_base->wrapper; ParamReceiveSpec paramspec(1, 0, true, false); if (flags == PyWrapperFlag_KEYWORDS) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (flags == PyWrapperFlag_1ARG) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (flags == PyWrapperFlag_2ARG) { paramspec = ParamReceiveSpec(2, 0, false, false); } else { RELEASE_ASSERT(0, "%d", flags); } auto continuation = [=](CallRewriteArgs* rewrite_args, Box* arg1, Box* arg2, Box* arg3, Box** args) { #ifndef NDEBUG if (paramspec.takes_varargs) assert(arg2 && arg2->cls == tuple_cls); #endif Box* rtn; if (flags == PyWrapperFlag_KEYWORDS) { wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; rtn = (*wk)(arg1, arg2, self->d_wrapped, arg3); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wk, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2)), rewrite_args->arg3)->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { rtn = (*wrapper)(arg1, arg2, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_1ARG) { wrapperfunc_1arg wrapper_1arg = (wrapperfunc_1arg)wrapper; rtn = (*wrapper_1arg)(arg1, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(1))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_2ARG) { rtn = (*wrapper)(arg1, arg2, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else { RELEASE_ASSERT(0, "%d", flags); } if (S == CXX && !rtn) throwCAPIException(); return rtn; }; return callCXXFromStyle<S>([&]() { return rearrangeArgumentsAndCall(paramspec, NULL, self->d_base->name, NULL, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names, continuation); }); }
Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { assert(_self->cls == wrapperobject_cls); BoxedWrapperObject* self = static_cast<BoxedWrapperObject*>(_self); int flags = self->descr->wrapper->flags; wrapperfunc wrapper = self->descr->wrapper->wrapper; assert(self->descr->wrapper->offset > 0); if (rewrite_args && !rewrite_args->func_guarded) { rewrite_args->obj->addAttrGuard(offsetof(BoxedWrapperObject, descr), (intptr_t)self->descr); } ParamReceiveSpec paramspec(0, 0, true, false); if (flags == PyWrapperFlag_KEYWORDS) { paramspec = ParamReceiveSpec(0, 0, true, true); } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { paramspec = ParamReceiveSpec(0, 0, true, false); } else { 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, args); assert(oarg1 && oarg1->cls == tuple_cls); if (!paramspec.takes_kwargs) assert(oarg2 == NULL); assert(oarg3 == NULL); assert(oargs == 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); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; auto r_obj = rewrite_args->obj->getAttr(offsetof(BoxedWrapperObject, obj), Location::forArg(0)); rewrite_args->out_rtn = rewriter->call( true, (void*)wk, r_obj, rewrite_args->arg1, rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2)), rewrite_args->arg2); rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { rtn = (*wrapper)(self->obj, oarg1, self->descr->wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; auto r_obj = rewrite_args->obj->getAttr(offsetof(BoxedWrapperObject, obj), Location::forArg(0)); rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, r_obj, rewrite_args->arg1, rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2))); rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->out_success = true; } } else { RELEASE_ASSERT(0, "%d", flags); } checkAndThrowCAPIException(); assert(rtn && "should have set + thrown an exception!"); return rtn; }
Box* methodDescrTppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) { if (S == CAPI) { try { return methodDescrTppCall<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 == &PyMethodDescr_Type || _self->cls == &PyClassMethodDescr_Type); PyMethodDescrObject* self = reinterpret_cast<PyMethodDescrObject*>(_self); bool is_classmethod = (_self->cls == &PyClassMethodDescr_Type); int ml_flags = self->d_method->ml_flags; int call_flags = ml_flags & ~(METH_CLASS | METH_COEXIST | METH_STATIC); if (rewrite_args && !rewrite_args->func_guarded) { rewrite_args->obj->addAttrGuard(offsetof(PyMethodDescrObject, d_method), (intptr_t)self->d_method); } ParamReceiveSpec paramspec(0, 0, false, false); Box** defaults = NULL; if (call_flags == METH_NOARGS) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (call_flags == METH_VARARGS) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (call_flags == METH_O) { paramspec = ParamReceiveSpec(2, 0, false, false); } else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) { int num_args = 0; if (call_flags & METH_O) num_args++; if (call_flags & METH_O2) num_args += 2; int num_defaults = 0; if (call_flags & METH_D1) num_defaults++; if (call_flags & METH_D2) num_defaults += 2; paramspec = ParamReceiveSpec(1 + num_args, num_defaults, false, false); if (num_defaults) { static Box* _defaults[] = { NULL, NULL, NULL }; assert(num_defaults <= 3); defaults = _defaults; } } else { RELEASE_ASSERT(0, "0x%x", call_flags); } bool arg1_class_guarded = false; if (rewrite_args && argspec.num_args >= 1) { // Try to do the guard before rearrangeArguments if possible: rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)arg1->cls); arg1_class_guarded = true; } auto continuation = [=](CallRewriteArgs* rewrite_args, Box* arg1, Box* arg2, Box* arg3, Box** args) { if (is_classmethod) { rewrite_args = NULL; if (!PyType_Check(arg1)) raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->d_method->ml_name, getFullTypeName(arg1).c_str()); } else { if (!isSubclass(arg1->cls, self->d_type)) raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' arg1 but received a '%s'", self->d_method->ml_name, self->d_type->tp_name, getFullTypeName(arg1).c_str()); } if (rewrite_args && !arg1_class_guarded) { 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->d_method->ml_meth(arg1, NULL); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->rewriter->loadConst(0, Location::forArg(1))) ->setType(RefType::OWNED); } else if (call_flags == METH_VARARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->d_method->ml_meth(arg1, arg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)((PyCFunctionWithKeywords)self->d_method->ml_meth)(arg1, arg2, arg3); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3)->setType(RefType::OWNED); } else if (call_flags == METH_O) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->d_method->ml_meth(arg1, arg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); } else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = ((Box * (*)(Box*, Box*, Box*, Box**))self->d_method->ml_meth)(arg1, arg2, arg3, args); } if (rewrite_args) { if (paramspec.totalReceived() == 2) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); else if (paramspec.totalReceived() == 3) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3)->setType(RefType::OWNED); else if (paramspec.totalReceived() > 3) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3, rewrite_args->args)->setType(RefType::OWNED); else abort(); } } else { RELEASE_ASSERT(0, "0x%x", call_flags); } if (!rtn) throwCAPIException(); if (rewrite_args) { rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } return rtn; }; return rearrangeArgumentsAndCall(paramspec, NULL, self->d_method->ml_name, defaults, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names, continuation); }
Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { 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 call_flags = ml_flags & (~METH_CLASS); if (rewrite_args && !rewrite_args->func_guarded) { rewrite_args->obj->addAttrGuard(offsetof(BoxedMethodDescriptor, method), (intptr_t)self->method); } ParamReceiveSpec paramspec(0, 0, false, false); if (call_flags == METH_NOARGS) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (call_flags == METH_VARARGS) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (call_flags == METH_O) { paramspec = ParamReceiveSpec(2, 0, false, false); } else { RELEASE_ASSERT(0, "0x%x", call_flags); } Box* oarg1 = NULL; Box* oarg2 = NULL; Box* oarg3 = NULL; Box** oargs = NULL; bool rewrite_success = false; rearrangeArguments(paramspec, NULL, self->method->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, args); if (!rewrite_success) rewrite_args = NULL; if (ml_flags & METH_CLASS) { rewrite_args = NULL; if (!isSubclass(oarg1->cls, type_cls)) 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()); } if (rewrite_args) { rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)oarg1->cls); } Box* rtn; if (call_flags == METH_NOARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->method->ml_meth(oarg1, NULL); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->rewriter->loadConst(0, Location::forArg(1))); } else if (call_flags == METH_VARARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->method->ml_meth(oarg1, oarg2); } 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); } 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); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->arg2); } else { RELEASE_ASSERT(0, "0x%x", call_flags); } if (!rtn) throwCAPIException(); if (rewrite_args) { rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->out_success = true; } return rtn; }