Commit a9813b80 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #648 from kmod/perf6

reduce api conversions
parents 79505a1a 76c861ad
# simple benchmark to test iteration over extension objects
import itertools
def f(c):
for i in c:
pass
l = []
for i in xrange(100):
l.append(itertools.chain(*[range(500) for j in xrange(500)]))
c = itertools.chain(*l)
f(c)
def f(n):
for i in xrange(n):
pass
f(100000000)
def f():
u = u"a" * 100
c = unicode
for i in xrange(2000000):
c(u)
f()
......@@ -743,10 +743,13 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr
if (has_side_effects) {
// We need some fixed amount of space at the beginning of the IC that we can use to invalidate
// it by writing a jmp.
// FIXME this check is conservative, since actually we just have to verify that the return
// TODO this check is conservative, since actually we just have to verify that the return
// address is at least IC_INVALDITION_HEADER_SIZE bytes past the beginning, but we're
// checking based on the beginning of the call. I think the load+call might actually
// always larger than the invalidation jmp.
while (assembler->bytesWritten() < IC_INVALDITION_HEADER_SIZE)
assembler->nop();
assert(assembler->bytesWritten() >= IC_INVALDITION_HEADER_SIZE);
}
......
......@@ -827,7 +827,7 @@ static PyObject* slot_tp_iter(PyObject* self) noexcept {
return PySeqIter_New(self);
}
static PyObject* slot_tp_iternext(PyObject* self) noexcept {
/* Pyston change: static */ PyObject* slot_tp_iternext(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tpiternext", SLOT_AVOIDABILITY(self));
static PyObject* next_str;
......@@ -957,7 +957,7 @@ static PyObject* slot_tp_getattr_hook(PyObject* self, PyObject* name) noexcept {
return res;
}
static PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept {
/* Pyston change: static */ PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_slot_tpnew", SLOT_AVOIDABILITY(self));
try {
......
......@@ -35,6 +35,8 @@ PyObject* mro_external(PyObject* self) noexcept;
int type_set_bases(PyTypeObject* type, PyObject* value, void* context) noexcept;
PyObject* slot_tp_richcompare(PyObject* self, PyObject* other, int op) noexcept;
PyObject* slot_tp_iternext(PyObject* self) noexcept;
PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept;
}
#endif
......@@ -42,57 +42,9 @@ public:
return boxString(self->method_def->ml_name);
}
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs) {
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", (self->cls->is_user_defined ? 10 : 20));
assert(self->cls == capifunc_cls);
assert(varargs->cls == tuple_cls);
assert(kwargs->cls == dict_cls);
threading::GLPromoteRegion _gil_lock;
Box* rtn;
int flags = self->method_def->ml_flags;
auto func = self->method_def->ml_meth;
if (flags == METH_VARARGS) {
assert(kwargs->d.size() == 0);
rtn = (Box*)func(self->passthrough, varargs);
} else if (flags == (METH_VARARGS | METH_KEYWORDS)) {
rtn = (Box*)((PyCFunctionWithKeywords)func)(self->passthrough, varargs, kwargs);
} else if (flags == METH_NOARGS) {
assert(kwargs->d.size() == 0);
assert(varargs->size() == 0);
rtn = (Box*)func(self->passthrough, NULL);
} else if (flags == METH_O) {
if (kwargs->d.size() != 0) {
raiseExcHelper(TypeError, "%s() takes no keyword arguments", self->method_def->ml_name);
}
if (varargs->size() != 1) {
raiseExcHelper(TypeError, "%s() takes exactly one argument (%d given)", self->method_def->ml_name,
varargs->size());
}
rtn = (Box*)func(self->passthrough, varargs->elts[0]);
} else if (flags == METH_OLDARGS) {
/* the really old style */
if (kwargs == NULL || PyDict_Size(kwargs) == 0) {
int size = PyTuple_GET_SIZE(varargs);
Box* arg = varargs;
if (size == 1)
arg = PyTuple_GET_ITEM(varargs, 0);
else if (size == 0)
arg = NULL;
rtn = func(self->passthrough, arg);
} else {
raiseExcHelper(TypeError, "%.200s() takes no keyword arguments", self->method_def->ml_name);
}
} else {
RELEASE_ASSERT(0, "0x%x", flags);
}
checkAndThrowCAPIException();
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs);
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names);
static Box* getname(Box* b, void*) {
RELEASE_ASSERT(b->cls == capifunc_cls, "");
......@@ -102,9 +54,6 @@ public:
return None;
}
static Box* callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == capifunc_cls);
BoxedCApiFunction* o = static_cast<BoxedCApiFunction*>(_o);
......
......@@ -531,7 +531,6 @@ public:
BoxedString* reprICAsString();
bool nonzeroIC();
Box* hasnextOrNullIC();
Box* nextIC();
friend class AttrWrapper;
};
......
......@@ -248,7 +248,7 @@ Box* open(Box* arg1, Box* arg2, Box* arg3) {
extern "C" Box* chr(Box* arg) {
i64 n = PyInt_AsLong(arg);
if (n == -1 && PyErr_Occurred())
raiseExcHelper(TypeError, "an integer is required");
throwCAPIException();
if (n < 0 || n >= 256) {
raiseExcHelper(ValueError, "chr() arg not in range(256)");
......
......@@ -633,25 +633,6 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept {
return internal_print(obj, fp, flags, 0);
};
extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
try {
Box* hasnext = iter->hasnextOrNullIC();
if (hasnext) {
if (hasnext->nonzeroIC())
return iter->nextIC();
else
return NULL;
} else {
return iter->nextIC();
}
} catch (ExcInfo e) {
if (e.matches(StopIteration))
return NULL;
setCAPIException(e);
}
return NULL;
}
extern "C" int PyCallable_Check(PyObject* x) noexcept {
if (x == NULL)
return 0;
......@@ -1457,29 +1438,106 @@ extern "C" char* PyModule_GetFilename(PyObject* m) noexcept {
return PyString_AsString(fileobj);
}
Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
if (argspec != ArgPassSpec(2))
return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs) {
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", (self->cls->is_user_defined ? 10 : 20));
assert(self->cls == capifunc_cls);
assert(varargs->cls == tuple_cls);
assert(kwargs->cls == dict_cls);
assert(arg1->cls == capifunc_cls);
BoxedCApiFunction* capifunc = static_cast<BoxedCApiFunction*>(arg1);
if (capifunc->method_def->ml_flags != METH_O)
return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
// 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);
}
Box* BoxedCApiFunction::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_boxedcapifunction__call__", 10);
assert(_self->cls == capifunc_cls);
BoxedCApiFunction* self = static_cast<BoxedCApiFunction*>(_self);
if (rewrite_args) {
rewrite_args->arg1->addGuard((intptr_t)arg1);
RewriterVar* r_passthrough = rewrite_args->arg1->getAttr(offsetof(BoxedCApiFunction, passthrough));
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)capifunc->method_def->ml_meth, r_passthrough,
rewrite_args->arg2);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->obj->addGuard((intptr_t)self);
}
int flags = self->method_def->ml_flags;
auto func = self->method_def->ml_meth;
ParamReceiveSpec paramspec(0, 0, true, false);
if (flags == METH_VARARGS) {
paramspec = ParamReceiveSpec(0, 0, true, false);
} else if (flags == (METH_VARARGS | METH_KEYWORDS)) {
paramspec = ParamReceiveSpec(0, 0, true, true);
} else if (flags == METH_NOARGS) {
paramspec = ParamReceiveSpec(0, 0, false, false);
} else if (flags == METH_O) {
paramspec = ParamReceiveSpec(1, 0, false, false);
} else if (flags == METH_OLDARGS) {
paramspec = ParamReceiveSpec(1, 0, false, false);
} else {
RELEASE_ASSERT(0, "0x%x", flags);
}
Box* oarg1 = NULL;
Box* oarg2 = NULL;
Box* oarg3 = NULL;
Box** oargs = NULL;
bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->method_def->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, args);
if (!rewrite_success)
rewrite_args = NULL;
RewriterVar* r_passthrough;
if (rewrite_args)
r_passthrough = rewrite_args->rewriter->loadConst((intptr_t)self->passthrough, Location::forArg(0));
Box* rtn;
if (flags == METH_VARARGS) {
rtn = (Box*)func(self->passthrough, oarg1);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1);
} else if (flags == (METH_VARARGS | METH_KEYWORDS)) {
rtn = (Box*)((PyCFunctionWithKeywords)func)(self->passthrough, oarg1, oarg2);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1,
rewrite_args->arg2);
} else if (flags == METH_NOARGS) {
rtn = (Box*)func(self->passthrough, NULL);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(
true, (void*)func, r_passthrough, rewrite_args->rewriter->loadConst(0, Location::forArg(1)));
} else if (flags == METH_O) {
rtn = (Box*)func(self->passthrough, oarg1);
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)func, r_passthrough, rewrite_args->arg1);
} else if (flags == METH_OLDARGS) {
/* the really old style */
rewrite_args = NULL;
int size = PyTuple_GET_SIZE(oarg1);
Box* arg = oarg1;
if (size == 1)
arg = PyTuple_GET_ITEM(oarg1, 0);
else if (size == 0)
arg = NULL;
rtn = func(self->passthrough, arg);
} else {
RELEASE_ASSERT(0, "0x%x", flags);
}
if (rewrite_args) {
rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException);
rewrite_args->out_success = true;
}
Box* r = capifunc->method_def->ml_meth(capifunc->passthrough, arg2);
checkAndThrowCAPIException();
assert(r);
return r;
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
/* extension modules might be compiled with GC support so these
......@@ -1546,8 +1604,8 @@ void setupCAPI() {
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true));
capi_call->f->internal_callable = BoxedCApiFunction::callInternal;
capifunc_cls->giveAttr("__call__", capi_call);
capifunc_cls->tpp_call = BoxedCApiFunction::tppCall;
capifunc_cls->giveAttr("__name__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr(
......
......@@ -347,6 +347,9 @@ Box* BoxedMethodDescriptor::callInternal(BoxedFunctionBase* f, CallRewriteArgs*
RELEASE_ASSERT(0, "0x%x", call_flags);
}
if (!rtn)
throwCAPIException();
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->out_rtn = r_rtn;
rewrite_args->out_success = true;
......
......@@ -68,7 +68,7 @@ protected:
class CallattrIC : public RuntimeIC {
public:
CallattrIC() : RuntimeIC((void*)callattr, 1, 160) {}
CallattrIC() : RuntimeIC((void*)callattr, 1, 320) {}
Box* call(Box* obj, BoxedString* attr, CallattrFlags flags, ArgPassSpec spec, Box* arg0, Box* arg1, Box* arg2,
Box** args, const std::vector<BoxedString*>* keyword_names) {
......
......@@ -41,23 +41,12 @@ public:
void next() override {
STAT_TIMER(t0, "us_timer_iteratorgeneric_next", 0);
assert(iterator);
Box* hasnext = iterator->hasnextOrNullIC();
if (hasnext) {
if (hasnext->nonzeroIC()) {
value = iterator->nextIC();
} else {
*this = *end();
}
} else {
try {
value = iterator->nextIC();
} catch (ExcInfo e) {
if (e.matches(StopIteration))
*this = *end();
else
throw e;
}
Box* next = PyIter_Next(iterator);
if (next)
value = next;
else {
checkAndThrowCAPIException();
*this = *end();
}
}
......
......@@ -132,20 +132,14 @@ bool iterwrapperHasnextUnboxed(Box* s) {
RELEASE_ASSERT(s->cls == iterwrapper_cls, "");
BoxedIterWrapper* self = static_cast<BoxedIterWrapper*>(s);
static BoxedString* next_str = static_cast<BoxedString*>(PyString_InternFromString("next"));
Box* next;
try {
next = callattr(self->iter, next_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = false }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} catch (ExcInfo e) {
if (e.matches(StopIteration)) {
self->next = NULL;
return false;
}
throw e;
}
Box* next = PyIter_Next(self->iter);
self->next = next;
return true;
if (!next) {
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_StopIteration))
throwCAPIException();
PyErr_Clear();
}
return next != NULL;
}
Box* iterwrapperHasnext(Box* s) {
......
......@@ -101,7 +101,7 @@ extern "C" Box* listPop(BoxedList* self, Box* idx) {
int64_t n = PyInt_AsSsize_t(idx);
if (n == -1 && PyErr_Occurred())
raiseExcHelper(TypeError, "an integer is required");
throwCAPIException();
if (n < 0)
n = self->size + n;
......
......@@ -2723,11 +2723,22 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope,
extern "C" Box* callattr(Box* obj, BoxedString* attr, CallattrFlags flags, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) {
STAT_TIMER(t0, "us_timer_slowpath_callattr", 10);
#if 0
#if 0 && STAT_TIMERS
static uint64_t* st_id = Stats::getStatCounter("us_timer_slowpath_callattr_patchable");
static uint64_t* st_id_nopatch = Stats::getStatCounter("us_timer_slowpath_callattr_nopatch");
bool havepatch = (bool)getICInfo(__builtin_extract_return_addr(__builtin_return_address(0)));
ScopedStatTimer st(havepatch ? st_id : st_id_nopatch, 10);
static uint64_t* st_id_megamorphic = Stats::getStatCounter("us_timer_slowpath_callattr_megamorphic");
ICInfo* icinfo = getICInfo(__builtin_extract_return_addr(__builtin_return_address(0)));
uint64_t* counter;
if (!icinfo)
counter = st_id_nopatch;
else if (icinfo->isMegamorphic())
counter = st_id_megamorphic;
else {
//counter = Stats::getStatCounter("us_timer_slowpath_callattr_patchable_" + std::string(obj->cls->tp_name));
counter = Stats::getStatCounter("us_timer_slowpath_callattr_patchable_" + std::string(attr->s()));
}
ScopedStatTimer st(counter, 10);
#endif
ASSERT(gc::isValidGCObject(obj), "%p", obj);
......@@ -3504,6 +3515,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
ASSERT(chosen_cf->spec->rtn_type->isFitBy(r->cls), "%s (%p) was supposed to return %s, but gave a %s",
g.func_addr_registry.getFuncNameAtAddress(chosen_cf->code, true, NULL).c_str(), chosen_cf->code,
chosen_cf->spec->rtn_type->debugName().c_str(), r->cls->tp_name);
assert(!PyErr_Occurred());
return r;
}
......@@ -3514,13 +3526,13 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
int npassed_args = argspec.totalPassed();
if (obj->cls != function_cls && obj->cls != builtin_function_or_method_cls && obj->cls != instancemethod_cls) {
STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20);
// TODO: maybe eventually runtimeCallInternal should just be the default tpp_call?
if (obj->cls->tpp_call) {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
}
STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20);
#if 0
std::string per_name_stat_name = "zzz_runtimecall_nonfunction_" + std::string(obj->cls->tp_name);
uint64_t* counter = Stats::getStatCounter(per_name_stat_name);
......
......@@ -47,6 +47,7 @@ void showBacktrace() {
}
void raiseExc(Box* exc_obj) {
assert(!PyErr_Occurred());
throw ExcInfo(exc_obj->cls, exc_obj, None);
}
......@@ -56,6 +57,7 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, llvm::StringR
Box* exc = runtimeCall(SyntaxError, ArgPassSpec(1), boxString(msg), NULL, NULL, NULL, NULL);
auto tb = new BoxedTraceback(LineInfo(lineno, col_offset, file, func), None);
assert(!PyErr_Occurred());
throw ExcInfo(exc->cls, exc, tb);
}
......@@ -175,6 +177,7 @@ extern "C" void raise0() {
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not NoneType");
exc_info->reraise = true;
assert(!PyErr_Occurred());
throw * exc_info;
}
......@@ -256,6 +259,7 @@ extern "C" void raise3(Box* arg0, Box* arg1, Box* arg2) {
auto exc_info = excInfoForRaise(arg0, arg1, arg2);
exc_info.reraise = reraise;
assert(!PyErr_Occurred());
throw exc_info;
}
......
......@@ -238,9 +238,38 @@ Box* BoxedClass::callHasnextIC(Box* obj, bool null_on_nonexistent) {
ArgPassSpec(0), nullptr, nullptr, nullptr, nullptr, nullptr);
}
extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
if (iter->cls->tp_iternext != slot_tp_iternext) {
PyObject* result;
result = (*iter->cls->tp_iternext)(iter);
if (result == NULL && PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
return result;
}
try {
Box* hasnext = iter->hasnextOrNullIC();
if (hasnext) {
if (hasnext->nonzeroIC())
return iter->cls->callNextIC(iter);
else
return NULL;
} else {
return iter->cls->callNextIC(iter);
}
} catch (ExcInfo e) {
if (!e.matches(StopIteration))
setCAPIException(e);
return NULL;
}
}
Box* BoxedClass::callNextIC(Box* obj) {
assert(obj->cls == this);
// This would work, but it would have been better to just call tp_iternext
assert(this->tp_iternext == slot_tp_iternext);
auto ic = next_ic.get();
if (!ic) {
ic = new CallattrIC();
......@@ -303,11 +332,6 @@ Box* Box::hasnextOrNullIC() {
return this->cls->callHasnextIC(this, true);
}
Box* Box::nextIC() {
return this->cls->callNextIC(this);
}
std::string builtinStr("__builtin__");
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
......@@ -580,6 +604,42 @@ static void assertInitNone(Box* obj) {
}
}
static PyObject* cpython_type_call(PyTypeObject* type, PyObject* args, PyObject* kwds) noexcept {
PyObject* obj;
if (type->tp_new == NULL) {
PyErr_Format(PyExc_TypeError, "cannot create '%.100s' instances", type->tp_name);
return NULL;
}
obj = type->tp_new(type, args, kwds);
if (obj != NULL) {
/* Ugly exception: when the call was type(something),
* don't call tp_init on the result. */
if (type == &PyType_Type && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1
&& (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
return obj;
/* If the returned object is not an instance of type,
* it won't be initialized. */
if (!PyType_IsSubtype(obj->cls, type))
return obj;
type = obj->cls;
if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) && type->tp_init != NULL
&& type->tp_init(obj, args, kwds) < 0) {
Py_DECREF(obj);
obj = NULL;
}
}
return obj;
}
static PyObject* cpythonTypeCall(BoxedClass* type, PyObject* args, PyObject* kwds) {
Box* r = cpython_type_call(type, args, kwds);
if (!r)
throwCAPIException();
return r;
}
static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) {
int npassed_args = argspec.totalPassed();
......@@ -594,6 +654,29 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (cls->tp_new != object_cls->tp_new && cls->tp_new != slot_tp_new) {
// Looks like we're calling an extension class and we're not going to be able to
// separately rewrite the new + init calls. But we can rewrite the fact that we
// should just call the cpython version, which will end up working pretty well.
ParamReceiveSpec paramspec(1, false, true, true);
bool rewrite_success = false;
Box* oarg1, *oarg2, *oarg3, ** oargs = NULL;
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
assert(oarg1 == cls);
if (!rewrite_success)
rewrite_args = NULL;
if (rewrite_args) {
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)cpythonTypeCall, rewrite_args->arg1,
rewrite_args->arg2, rewrite_args->arg3);
rewrite_args->out_success = true;
}
return cpythonTypeCall(cls, oarg2, oarg3);
}
RewriterVar* r_ccls = NULL;
RewriterVar* r_new = NULL;
RewriterVar* r_init = NULL;
......@@ -769,7 +852,10 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
"We should only have allowed the rewrite to continue if we were guaranteed that made "
"would have class cls!");
} else {
made = runtimeCallInternal(new_attr, NULL, new_argspec, cls, arg2, arg3, args, keyword_names);
if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init)
made = objectNewNoArgs(cls);
else
made = runtimeCallInternal(new_attr, NULL, new_argspec, cls, arg2, arg3, args, keyword_names);
}
assert(made);
......
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