Commit c5d2083e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #881 from undingen/wrapper2

when calling a BoxedWrapperDescriptor don't create a BoxedWrapperObject
parents 0a8385c9 65e3ce5b
......@@ -1878,8 +1878,10 @@ public:
}
ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) override {
static BoxedString* attr = internStringImmortal("__nonzero__");
if (cls == None->cls)
return makeBool(false);
static BoxedString* attr = internStringImmortal("__nonzero__");
bool no_attribute = false;
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL, &no_attribute);
......
......@@ -471,6 +471,106 @@ Box* BoxedWrapperDescriptor::__call__(BoxedWrapperDescriptor* descr, PyObject* s
return BoxedWrapperObject::__call__(wrapper, args, kw);
}
template <ExceptionStyle S>
Box* BoxedWrapperDescriptor::tppCall(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 tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedwrapperdecsriptor_call", (_self->cls->is_user_defined ? 10 : 20));
assert(_self->cls == wrapperdescr_cls);
BoxedWrapperDescriptor* self = static_cast<BoxedWrapperDescriptor*>(_self);
int flags = self->wrapper->flags;
wrapperfunc wrapper = self->wrapper->wrapper;
assert(self->wrapper->offset > 0);
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);
}
Box** oargs = NULL;
bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->wrapper->name.data(), NULL, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, oargs, keyword_names);
if (paramspec.takes_varargs)
assert(arg2 && arg2->cls == tuple_cls);
if (!rewrite_success)
rewrite_args = NULL;
Box* rtn;
if (flags == PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
rtn = (*wk)(arg1, arg2, self->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->wrapped, Location::forArg(2)), rewrite_args->arg3);
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->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->wrapped, Location::forArg(2)));
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->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->wrapped, Location::forArg(1)));
rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true;
}
} else if (flags == PyWrapperFlag_2ARG) {
rtn = (*wrapper)(arg1, arg2, self->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->wrapped, Location::forArg(2)));
rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true;
}
} else {
RELEASE_ASSERT(0, "%d", flags);
}
checkAndThrowCAPIException();
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
void BoxedWrapperDescriptor::gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == wrapperdescr_cls);
BoxedWrapperDescriptor* o = static_cast<BoxedWrapperDescriptor*>(_o);
......@@ -543,110 +643,26 @@ 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) 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);
BoxedWrapperObject* self = static_cast<BoxedWrapperObject*>(_self);
int flags = self->descr->wrapper->flags;
wrapperfunc wrapper = self->descr->wrapper->wrapper;
assert(self->descr->wrapper->offset > 0);
RewriterVar* r_obj = NULL;
Box** new_args = NULL;
if (argspec.totalPassed() >= 3)
new_args = (Box**)alloca(sizeof(Box*) * (argspec.totalPassed() + 1 - 3));
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 if (flags == PyWrapperFlag_1ARG) {
paramspec = ParamReceiveSpec(0, 0, false, false);
} else if (flags == PyWrapperFlag_2ARG) {
paramspec = ParamReceiveSpec(1, 0, false, false);
} else {
RELEASE_ASSERT(0, "%d", flags);
}
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, oargs, keyword_names);
if (paramspec.takes_varargs)
assert(arg1 && arg1->cls == tuple_cls);
if (!rewrite_success)
rewrite_args = NULL;
Box* rtn;
if (flags == PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
rtn = (*wk)(self->obj, arg1, self->descr->wrapped, arg2);
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);
rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true;
}
} else if (flags == PyWrapperFlag_PYSTON || flags == 0) {
rtn = (*wrapper)(self->obj, arg1, 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)));
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)(self->obj, 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, rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(1)));
rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true;
}
} else if (flags == PyWrapperFlag_2ARG) {
rtn = (*wrapper)(self->obj, arg1, 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)));
rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true;
}
} else {
RELEASE_ASSERT(0, "%d", flags);
if (rewrite_args) {
if (!rewrite_args->func_guarded)
rewrite_args->obj->addAttrGuard(offsetof(BoxedWrapperObject, descr), (intptr_t)self->descr);
r_obj = rewrite_args->obj->getAttr(offsetof(BoxedWrapperObject, obj), Location::forArg(0));
}
checkAndThrowCAPIException();
assert(rtn && "should have set + thrown an exception!");
return rtn;
ArgPassSpec new_argspec
= bindObjIntoArgs(self->obj, r_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args);
return BoxedWrapperDescriptor::tppCall<S>(self->descr, rewrite_args, new_argspec, arg1, arg2, arg3, new_args,
keyword_names);
}
void BoxedWrapperObject::gcHandler(GCVisitor* v, Box* _o) {
......@@ -711,6 +727,8 @@ void setupDescr() {
wrapperdescr_cls->giveAttr("__doc__",
new (pyston_getset_cls) BoxedGetsetDescriptor(wrapperdescrGetDoc, NULL, NULL));
wrapperdescr_cls->tp_descr_get = BoxedWrapperDescriptor::descr_get;
wrapperdescr_cls->tpp_call.capi_val = BoxedWrapperDescriptor::tppCall<CAPI>;
wrapperdescr_cls->tpp_call.cxx_val = BoxedWrapperDescriptor::tppCall<CXX>;
add_operators(wrapperdescr_cls);
wrapperdescr_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)wrapperDescrRepr, UNKNOWN, 1)));
wrapperdescr_cls->freeze();
......
......@@ -1123,23 +1123,33 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
return sm->sm_callable;
} else if (descr->cls == wrapperdescr_cls) {
BoxedWrapperDescriptor* self = static_cast<BoxedWrapperDescriptor*>(descr);
Box* inst = obj;
Box* owner = obj->cls;
Box* r = BoxedWrapperDescriptor::descr_get(self, inst, owner);
if (for_call) {
if (rewrite_args) {
rewrite_args->out_success = true;
rewrite_args->out_rtn = r_descr;
rewrite_args->out_return_convention = GetattrRewriteArgs::VALID_RETURN;
*r_bind_obj_out = rewrite_args->obj;
}
*bind_obj_out = obj;
return descr;
} else {
BoxedWrapperDescriptor* self = static_cast<BoxedWrapperDescriptor*>(descr);
Box* inst = obj;
Box* owner = obj->cls;
Box* r = BoxedWrapperDescriptor::descr_get(self, inst, owner);
if (rewrite_args) {
// TODO: inline this?
RewriterVar* r_rtn = rewrite_args->rewriter->call(
/* has_side_effects= */ false, (void*)&BoxedWrapperDescriptor::descr_get, r_descr, rewrite_args->obj,
r_descr->getAttr(offsetof(Box, cls), Location::forArg(2)));
if (rewrite_args) {
// TODO: inline this?
RewriterVar* r_rtn = rewrite_args->rewriter->call(
/* has_side_effects= */ false, (void*)&BoxedWrapperDescriptor::descr_get, r_descr,
rewrite_args->obj, r_descr->getAttr(offsetof(Box, cls), Location::forArg(2)));
rewrite_args->out_success = true;
rewrite_args->out_rtn = r_rtn;
rewrite_args->out_return_convention = GetattrRewriteArgs::VALID_RETURN;
rewrite_args->out_success = true;
rewrite_args->out_rtn = r_rtn;
rewrite_args->out_return_convention = GetattrRewriteArgs::VALID_RETURN;
}
return r;
}
return r;
}
return NULL;
......@@ -2446,20 +2456,20 @@ extern "C" bool nonzero(Box* obj) {
static BoxedString* len_str = internStringImmortal("__len__");
// try __nonzero__
GetattrRewriteArgs grewrite_args(rewriter.get(), r_obj, rewriter ? rewriter->getReturnDestination() : Location());
Box* func = getclsattrInternal(obj, nonzero_str, rewriter ? &grewrite_args : NULL);
if (!grewrite_args.out_success)
CallRewriteArgs crewrite_args(rewriter.get(), r_obj, rewriter ? rewriter->getReturnDestination() : Location());
Box* rtn = callattrInternal0<CXX>(obj, nonzero_str, CLASS_ONLY, rewriter ? &crewrite_args : NULL, ArgPassSpec(0));
if (!crewrite_args.out_success)
rewriter.reset();
if (!func) {
if (!rtn) {
// try __len__
grewrite_args
= GetattrRewriteArgs(rewriter.get(), r_obj, rewriter ? rewriter->getReturnDestination() : Location());
func = getclsattrInternal(obj, len_str, rewriter ? &grewrite_args : NULL);
if (!grewrite_args.out_success)
crewrite_args
= CallRewriteArgs(rewriter.get(), r_obj, rewriter ? rewriter->getReturnDestination() : Location());
rtn = callattrInternal0<CXX>(obj, len_str, CLASS_ONLY, rewriter ? &crewrite_args : NULL, ArgPassSpec(0));
if (!crewrite_args.out_success)
rewriter.reset();
if (func == NULL) {
if (rtn == NULL) {
ASSERT(obj->cls->is_user_defined || obj->cls == classobj_cls || obj->cls == type_cls
|| isSubclass(obj->cls, Exception) || obj->cls == file_cls || obj->cls == traceback_cls
|| obj->cls == instancemethod_cls || obj->cls == module_cls || obj->cls == capifunc_cls
......@@ -2475,11 +2485,8 @@ extern "C" bool nonzero(Box* obj) {
return true;
}
}
CallRewriteArgs cargs(rewriter.get(), grewrite_args.out_rtn,
rewriter ? rewriter->getReturnDestination() : Location());
Box* rtn = runtimeCallInternal0<CXX>(func, rewriter ? &cargs : NULL, ArgPassSpec(0));
if (cargs.out_success) {
RewriterVar* b = rewriter->call(false, (void*)nonzeroHelper, cargs.out_rtn);
if (crewrite_args.out_success) {
RewriterVar* b = rewriter->call(false, (void*)nonzeroHelper, crewrite_args.out_rtn);
rewriter->commitReturning(b);
}
return nonzeroHelper(rtn);
......
......@@ -1008,6 +1008,9 @@ public:
static Box* descr_get(Box* self, Box* inst, Box* owner) noexcept;
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, 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) 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