Пример #1
0
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);
}
Пример #2
0
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;
}