Commit a62ba58f authored by Kevin Modzelewski's avatar Kevin Modzelewski

Templatize runtimeCall for different exception styles

Which also involves templatizing most of the things that it
calls as well.

CompiledFunction's now have an additional parameter "exception_style",
and we will try to call a version of the function with the requested
style.  All of our runtime functions are written to the CXX style,
and there's not a whole lot of benefit until we templatize the runtime
functions individually.
parent 75e203a2
...@@ -43,7 +43,8 @@ CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool ...@@ -43,7 +43,8 @@ CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool
param_names(this->source->ast, this->source->getInternedStrings()), param_names(this->source->ast, this->source->getInternedStrings()),
always_use_version(NULL), always_use_version(NULL),
code_obj(NULL), code_obj(NULL),
times_interpreted(0) { times_interpreted(0),
internal_callable(NULL, NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
...@@ -53,7 +54,8 @@ CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool ...@@ -53,7 +54,8 @@ CLFunction::CLFunction(int num_args, int num_defaults, bool takes_varargs, bool
param_names(param_names), param_names(param_names),
always_use_version(NULL), always_use_version(NULL),
code_obj(NULL), code_obj(NULL),
times_interpreted(0) { times_interpreted(0),
internal_callable(NULL, NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
......
...@@ -1016,7 +1016,7 @@ CompiledFunction* doCompile(CLFunction* clfunc, SourceInfo* source, ParamNames* ...@@ -1016,7 +1016,7 @@ CompiledFunction* doCompile(CLFunction* clfunc, SourceInfo* source, ParamNames*
} }
CompiledFunction* cf = new CompiledFunction(NULL, spec, NULL, effort, entry_descriptor); CompiledFunction* cf = new CompiledFunction(NULL, spec, NULL, effort, ExceptionStyle::CXX, entry_descriptor);
// Make sure that the instruction memory keeps the module object alive. // Make sure that the instruction memory keeps the module object alive.
// TODO: implement this for real // TODO: implement this for real
......
...@@ -716,6 +716,7 @@ void CompiledFunction::speculationFailed() { ...@@ -716,6 +716,7 @@ void CompiledFunction::speculationFailed() {
} }
CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort, CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle::ExceptionStyle exception_style,
const OSREntryDescriptor* entry_descriptor) const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL), : clfunc(NULL),
func(func), func(func),
...@@ -723,6 +724,7 @@ CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* ...@@ -723,6 +724,7 @@ CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization*
entry_descriptor(entry_descriptor), entry_descriptor(entry_descriptor),
code(code), code(code),
effort(effort), effort(effort),
exception_style(exception_style),
times_called(0), times_called(0),
times_speculation_failed(0), times_speculation_failed(0),
location_map(nullptr) { location_map(nullptr) {
...@@ -831,29 +833,32 @@ CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, ...@@ -831,29 +833,32 @@ CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs,
return new CLFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names); return new CLFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names);
} }
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, const ParamNames& param_names) { CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, const ParamNames& param_names,
ExceptionStyle::ExceptionStyle exception_style) {
assert(!param_names.takes_param_names || num_args == param_names.args.size()); assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(param_names.vararg.str() == ""); assert(param_names.vararg.str() == "");
assert(param_names.kwarg.str() == ""); assert(param_names.kwarg.str() == "");
return boxRTFunction(f, rtn_type, num_args, 0, false, false, param_names); return boxRTFunction(f, rtn_type, num_args, 0, false, false, param_names, exception_style);
} }
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, int num_defaults, bool takes_varargs, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, int num_defaults, bool takes_varargs,
bool takes_kwargs, const ParamNames& param_names) { bool takes_kwargs, const ParamNames& param_names,
ExceptionStyle::ExceptionStyle exception_style) {
assert(!param_names.takes_param_names || num_args == param_names.args.size()); assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(takes_varargs || param_names.vararg.str() == ""); assert(takes_varargs || param_names.vararg.str() == "");
assert(takes_kwargs || param_names.kwarg.str() == ""); assert(takes_kwargs || param_names.kwarg.str() == "");
CLFunction* cl_f = createRTFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names); CLFunction* cl_f = createRTFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names);
addRTFunction(cl_f, f, rtn_type); addRTFunction(cl_f, f, rtn_type, exception_style);
return cl_f; return cl_f;
} }
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type) { void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
ExceptionStyle::ExceptionStyle exception_style) {
std::vector<ConcreteCompilerType*> arg_types(cl_f->numReceivedArgs(), UNKNOWN); std::vector<ConcreteCompilerType*> arg_types(cl_f->numReceivedArgs(), UNKNOWN);
return addRTFunction(cl_f, f, rtn_type, arg_types); return addRTFunction(cl_f, f, rtn_type, arg_types, exception_style);
} }
static ConcreteCompilerType* processType(ConcreteCompilerType* type) { static ConcreteCompilerType* processType(ConcreteCompilerType* type) {
...@@ -862,7 +867,8 @@ static ConcreteCompilerType* processType(ConcreteCompilerType* type) { ...@@ -862,7 +867,8 @@ static ConcreteCompilerType* processType(ConcreteCompilerType* type) {
} }
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types) { const std::vector<ConcreteCompilerType*>& arg_types,
ExceptionStyle::ExceptionStyle exception_style) {
assert(arg_types.size() == cl_f->numReceivedArgs()); assert(arg_types.size() == cl_f->numReceivedArgs());
#ifndef NDEBUG #ifndef NDEBUG
for (ConcreteCompilerType* t : arg_types) for (ConcreteCompilerType* t : arg_types)
...@@ -870,6 +876,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, ...@@ -870,6 +876,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
#endif #endif
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types); FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
cl_f->addVersion(new CompiledFunction(NULL, spec, f, EffortLevel::MAXIMAL, NULL)); cl_f->addVersion(new CompiledFunction(NULL, spec, f, EffortLevel::MAXIMAL, exception_style, NULL));
} }
} }
...@@ -75,6 +75,25 @@ enum ExceptionStyle { ...@@ -75,6 +75,25 @@ enum ExceptionStyle {
}; };
}; };
template <typename R, typename... Args> struct ExceptionSwitchableFunction {
public:
typedef R (*FTy)(Args...);
FTy capi_ptr;
FTy cxx_ptr;
ExceptionSwitchableFunction(FTy capi_ptr, FTy cxx_ptr) : capi_ptr(capi_ptr), cxx_ptr(cxx_ptr) {}
template <ExceptionStyle::ExceptionStyle S> FTy get() {
if (S == ExceptionStyle::CAPI)
return capi_ptr;
else
return cxx_ptr;
}
template <ExceptionStyle::ExceptionStyle S> R call(Args... args) noexcept(S == ExceptionStyle::CAPI) {
return get()(args...);
}
};
class CompilerType; class CompilerType;
template <class V> class ValuedCompilerType; template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType; typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
...@@ -264,6 +283,7 @@ public: ...@@ -264,6 +283,7 @@ public:
int code_size; int code_size;
EffortLevel effort; EffortLevel effort;
ExceptionStyle::ExceptionStyle exception_style;
int64_t times_called, times_speculation_failed; int64_t times_called, times_speculation_failed;
ICInvalidator dependent_callsites; ICInvalidator dependent_callsites;
...@@ -273,7 +293,7 @@ public: ...@@ -273,7 +293,7 @@ public:
std::vector<ICInfo*> ics; std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort, CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
const OSREntryDescriptor* entry_descriptor); ExceptionStyle::ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ConcreteCompilerType* getReturnType(); ConcreteCompilerType* getReturnType();
...@@ -352,9 +372,9 @@ public: ...@@ -352,9 +372,9 @@ public:
// of the normal dispatch through the functionlist. // of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves, // This can be used to implement functions which know how to rewrite themselves,
// such as typeCall. // such as typeCall.
typedef Box* (*InternalCallable)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**, typedef ExceptionSwitchableFunction<Box*, BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*,
const std::vector<BoxedString*>*); Box**, const std::vector<BoxedString*>*> InternalCallable;
InternalCallable internal_callable = NULL; InternalCallable internal_callable;
CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
std::unique_ptr<SourceInfo> source); std::unique_ptr<SourceInfo> source);
...@@ -393,12 +413,16 @@ public: ...@@ -393,12 +413,16 @@ public:
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
const ParamNames& param_names = ParamNames::empty()); const ParamNames& param_names = ParamNames::empty());
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, int num_defaults, bool takes_varargs, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, int num_defaults, bool takes_varargs,
bool takes_kwargs, const ParamNames& param_names = ParamNames::empty()); bool takes_kwargs, const ParamNames& param_names = ParamNames::empty(),
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs,
const ParamNames& param_names = ParamNames::empty()); const ParamNames& param_names = ParamNames::empty(),
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type); ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types); const std::vector<ConcreteCompilerType*>& arg_types,
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
CLFunction* unboxRTFunction(Box*); CLFunction* unboxRTFunction(Box*);
// Compiles a new version of the function with the given signature and adds it to the list; // Compiles a new version of the function with the given signature and adds it to the list;
......
...@@ -1382,7 +1382,7 @@ void setupBuiltins() { ...@@ -1382,7 +1382,7 @@ void setupBuiltins() {
builtins_module->giveAttr("repr", repr_obj); builtins_module->giveAttr("repr", repr_obj);
auto len_func = boxRTFunction((void*)len, UNKNOWN, 1); auto len_func = boxRTFunction((void*)len, UNKNOWN, 1);
len_func->internal_callable = lenCallInternal; len_func->internal_callable.cxx_ptr = lenCallInternal;
len_obj = new BoxedBuiltinFunctionOrMethod(len_func, "len"); len_obj = new BoxedBuiltinFunctionOrMethod(len_func, "len");
builtins_module->giveAttr("len", len_obj); builtins_module->giveAttr("len", len_obj);
......
...@@ -578,15 +578,12 @@ extern "C" int PyObject_Not(PyObject* o) noexcept { ...@@ -578,15 +578,12 @@ extern "C" int PyObject_Not(PyObject* o) noexcept {
} }
extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) noexcept { extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) noexcept {
try { if (kw)
if (kw) return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, true), args, kw,
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL); NULL, NULL, NULL);
else else
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL); return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, false), args,
} catch (ExcInfo e) { NULL, NULL, NULL, NULL);
setCAPIException(e);
return NULL;
}
} }
extern "C" int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) noexcept { extern "C" int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) noexcept {
......
...@@ -98,8 +98,8 @@ void generatorEntry(BoxedGenerator* g) { ...@@ -98,8 +98,8 @@ void generatorEntry(BoxedGenerator* g) {
BoxedFunctionBase* func = g->function; BoxedFunctionBase* func = g->function;
Box** args = g->args ? &g->args->elts[0] : nullptr; Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2, callCLFunc<ExceptionStyle::CXX>(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g,
g->arg3, args); func->globals, g->arg1, g->arg2, g->arg3, args);
} catch (ExcInfo e) { } catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller // unhandled exception: propagate the exception to the caller
g->exception = e; g->exception = e;
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
namespace pyston { namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
BoxedListIterator::BoxedListIterator(BoxedList* l, int start) : l(l), pos(start) { BoxedListIterator::BoxedListIterator(BoxedList* l, int start) : l(l), pos(start) {
} }
...@@ -65,24 +68,34 @@ i1 listiterHasnextUnboxed(Box* s) { ...@@ -65,24 +68,34 @@ i1 listiterHasnextUnboxed(Box* s) {
return ans; return ans;
} }
Box* listiterNext(Box* s) { template <enum ExceptionStyle S> Box* listiterNext(Box* s) noexcept(S == CAPI) {
assert(s->cls == list_iterator_cls); assert(s->cls == list_iterator_cls);
BoxedListIterator* self = static_cast<BoxedListIterator*>(s); BoxedListIterator* self = static_cast<BoxedListIterator*>(s);
if (!self->l) { if (!self->l) {
raiseExcHelper(StopIteration, ""); if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, "");
} }
if (!(self->pos >= 0 && self->pos < self->l->size)) { if (!(self->pos >= 0 && self->pos < self->l->size)) {
self->l = NULL; self->l = NULL;
raiseExcHelper(StopIteration, ""); if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, "");
} }
Box* rtn = self->l->elts->elts[self->pos]; Box* rtn = self->l->elts->elts[self->pos];
self->pos++; self->pos++;
return rtn; return rtn;
} }
// force instantiation:
template Box* listiterNext<CAPI>(Box*);
template Box* listiterNext<CXX>(Box*);
Box* listReversed(Box* s) { Box* listReversed(Box* s) {
assert(isSubclass(s->cls, list_cls)); assert(isSubclass(s->cls, list_cls));
......
...@@ -704,7 +704,7 @@ private: ...@@ -704,7 +704,7 @@ private:
public: public:
PyCmpComparer(Box* cmp) : cmp(cmp) {} PyCmpComparer(Box* cmp) : cmp(cmp) {}
bool operator()(Box* lhs, Box* rhs) { bool operator()(Box* lhs, Box* rhs) {
Box* r = runtimeCallInternal(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL); Box* r = runtimeCallInternal<ExceptionStyle::CXX>(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL);
if (!isSubclass(r->cls, int_cls)) if (!isSubclass(r->cls, int_cls))
raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name); raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name);
return static_cast<BoxedInt*>(r)->n < 0; return static_cast<BoxedInt*>(r)->n < 0;
...@@ -1169,7 +1169,10 @@ void setupList() { ...@@ -1169,7 +1169,10 @@ void setupList() {
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
list_iterator_cls->giveAttr( list_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1))); "__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1)));
list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 1)));
CLFunction* listiter_next = boxRTFunction((void*)listiterNext<ExceptionStyle::CXX>, UNKNOWN, 1);
addRTFunction(listiter_next, (void*)listiterNext<ExceptionStyle::CAPI>, UNKNOWN, ExceptionStyle::CAPI);
list_iterator_cls->giveAttr("next", new BoxedFunction(listiter_next));
list_iterator_cls->freeze(); list_iterator_cls->freeze();
list_iterator_cls->tpp_hasnext = listiterHasnextUnboxed; list_iterator_cls->tpp_hasnext = listiterHasnextUnboxed;
......
...@@ -35,7 +35,7 @@ Box* listIter(Box* self); ...@@ -35,7 +35,7 @@ Box* listIter(Box* self);
Box* listIterIter(Box* self); Box* listIterIter(Box* self);
Box* listiterHasnext(Box* self); Box* listiterHasnext(Box* self);
i1 listiterHasnextUnboxed(Box* self); i1 listiterHasnextUnboxed(Box* self);
Box* listiterNext(Box* self); template <ExceptionStyle::ExceptionStyle S> Box* listiterNext(Box* self) noexcept(S == ExceptionStyle::CAPI);
Box* listReversed(Box* self); Box* listReversed(Box* self);
Box* listreviterHasnext(Box* self); Box* listreviterHasnext(Box* self);
i1 listreviterHasnextUnboxed(Box* self); i1 listreviterHasnextUnboxed(Box* self);
......
...@@ -80,19 +80,23 @@ void REWRITE_ABORTED(const char* reason) { ...@@ -80,19 +80,23 @@ void REWRITE_ABORTED(const char* reason) {
#define REWRITE_ABORTED(reason) ((void)(reason)) #define REWRITE_ABORTED(reason) ((void)(reason))
#endif #endif
template <enum ExceptionStyle S>
static inline Box* runtimeCallInternal0(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec) { static inline Box* runtimeCallInternal0(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec) {
return runtimeCallInternal(obj, rewrite_args, argspec, NULL, NULL, NULL, NULL, NULL); return runtimeCallInternal<S>(obj, rewrite_args, argspec, NULL, NULL, NULL, NULL, NULL);
} }
template <enum ExceptionStyle S>
static inline Box* runtimeCallInternal1(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1) { static inline Box* runtimeCallInternal1(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1) {
return runtimeCallInternal(obj, rewrite_args, argspec, arg1, NULL, NULL, NULL, NULL); return runtimeCallInternal<S>(obj, rewrite_args, argspec, arg1, NULL, NULL, NULL, NULL);
} }
template <enum ExceptionStyle S>
static inline Box* runtimeCallInternal2(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, static inline Box* runtimeCallInternal2(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2) { Box* arg2) {
return runtimeCallInternal(obj, rewrite_args, argspec, arg1, arg2, NULL, NULL, NULL); return runtimeCallInternal<S>(obj, rewrite_args, argspec, arg1, arg2, NULL, NULL, NULL);
} }
template <enum ExceptionStyle S>
static inline Box* runtimeCallInternal3(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, static inline Box* runtimeCallInternal3(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3) { Box* arg2, Box* arg3) {
return runtimeCallInternal(obj, rewrite_args, argspec, arg1, arg2, arg3, NULL, NULL); return runtimeCallInternal<S>(obj, rewrite_args, argspec, arg1, arg2, arg3, NULL, NULL);
} }
bool checkClass(LookupScope scope) { bool checkClass(LookupScope scope) {
...@@ -1430,7 +1434,7 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS ...@@ -1430,7 +1434,7 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS
if (prop->prop_get == NULL || prop->prop_get == None) { if (prop->prop_get == NULL || prop->prop_get == None) {
raiseExcHelper(AttributeError, "unreadable attribute"); raiseExcHelper(AttributeError, "unreadable attribute");
} }
return runtimeCallInternal1(prop->prop_get, NULL, ArgPassSpec(1), obj); return runtimeCallInternal1<CXX>(prop->prop_get, NULL, ArgPassSpec(1), obj);
} }
// Special case: data descriptor: getset descriptor // Special case: data descriptor: getset descriptor
...@@ -1774,8 +1778,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1774,8 +1778,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
crewrite_args.arg1 = r_descr; crewrite_args.arg1 = r_descr;
crewrite_args.arg2 = rewrite_args->obj; crewrite_args.arg2 = rewrite_args->obj;
crewrite_args.arg3 = rewrite_args->obj->getAttr(offsetof(Box, cls), Location::any()); crewrite_args.arg3 = rewrite_args->obj->getAttr(offsetof(Box, cls), Location::any());
res = runtimeCallInternal(_get_, &crewrite_args, ArgPassSpec(3), descr, obj, obj->cls, NULL, res = runtimeCallInternal<CXX>(_get_, &crewrite_args, ArgPassSpec(3), descr, obj, obj->cls,
NULL); NULL, NULL);
if (!crewrite_args.out_success) { if (!crewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
} else { } else {
...@@ -1886,8 +1890,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1886,8 +1890,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
crewrite_args.arg1 = r_val; crewrite_args.arg1 = r_val;
crewrite_args.arg2 = rewrite_args->rewriter->loadConst((intptr_t)None, Location::any()); crewrite_args.arg2 = rewrite_args->rewriter->loadConst((intptr_t)None, Location::any());
crewrite_args.arg3 = rewrite_args->obj; crewrite_args.arg3 = rewrite_args->obj;
res = runtimeCallInternal(local_get, &crewrite_args, ArgPassSpec(3), val, None, obj, NULL, res = runtimeCallInternal<CXX>(local_get, &crewrite_args, ArgPassSpec(3), val, None, obj, NULL,
NULL); NULL);
if (!crewrite_args.out_success) { if (!crewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
} else { } else {
...@@ -1895,7 +1899,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1895,7 +1899,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
rewrite_args->out_rtn = crewrite_args.out_rtn; rewrite_args->out_rtn = crewrite_args.out_rtn;
} }
} else { } else {
res = runtimeCallInternal(local_get, NULL, ArgPassSpec(3), val, None, obj, NULL, NULL); res = runtimeCallInternal<CXX>(local_get, NULL, ArgPassSpec(3), val, None, obj, NULL, NULL);
} }
return res; return res;
} }
...@@ -1943,7 +1947,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1943,7 +1947,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
crewrite_args.arg1 = r_descr; crewrite_args.arg1 = r_descr;
crewrite_args.arg2 = rewrite_args->obj; crewrite_args.arg2 = rewrite_args->obj;
crewrite_args.arg3 = rewrite_args->obj->getAttr(offsetof(Box, cls), Location::any()); crewrite_args.arg3 = rewrite_args->obj->getAttr(offsetof(Box, cls), Location::any());
res = runtimeCallInternal(_get_, &crewrite_args, ArgPassSpec(3), descr, obj, obj->cls, NULL, NULL); res = runtimeCallInternal<CXX>(_get_, &crewrite_args, ArgPassSpec(3), descr, obj, obj->cls, NULL, NULL);
if (!crewrite_args.out_success) { if (!crewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
} else { } else {
...@@ -2211,12 +2215,12 @@ void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* r ...@@ -2211,12 +2215,12 @@ void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* r
crewrite_args.arg1 = r_descr; crewrite_args.arg1 = r_descr;
crewrite_args.arg2 = rewrite_args->obj; crewrite_args.arg2 = rewrite_args->obj;
crewrite_args.arg3 = rewrite_args->attrval; crewrite_args.arg3 = rewrite_args->attrval;
runtimeCallInternal(_set_, &crewrite_args, ArgPassSpec(3), descr, obj, val, NULL, NULL); runtimeCallInternal<CXX>(_set_, &crewrite_args, ArgPassSpec(3), descr, obj, val, NULL, NULL);
if (crewrite_args.out_success) { if (crewrite_args.out_success) {
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
} else { } else {
runtimeCallInternal(_set_, NULL, ArgPassSpec(3), descr, obj, val, NULL, NULL); runtimeCallInternal<CXX>(_set_, NULL, ArgPassSpec(3), descr, obj, val, NULL, NULL);
} }
// We don't need to to the invalidation stuff in this case. // We don't need to to the invalidation stuff in this case.
...@@ -2327,7 +2331,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val) { ...@@ -2327,7 +2331,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val) {
// TODO actually rewrite this? // TODO actually rewrite this?
setattr = processDescriptor(setattr, obj, obj->cls); setattr = processDescriptor(setattr, obj, obj->cls);
runtimeCallInternal(setattr, NULL, ArgPassSpec(2), attr, attr_val, NULL, NULL, NULL); runtimeCallInternal<CXX>(setattr, NULL, ArgPassSpec(2), attr, attr_val, NULL, NULL, NULL);
} else { } else {
STAT_TIMER(t0, "us_timer_slowpath_tpsetattro", 10); STAT_TIMER(t0, "us_timer_slowpath_tpsetattro", 10);
int r = tp_setattro(obj, attr, attr_val); int r = tp_setattro(obj, attr, attr_val);
...@@ -2461,7 +2465,7 @@ extern "C" bool nonzero(Box* obj) { ...@@ -2461,7 +2465,7 @@ extern "C" bool nonzero(Box* obj) {
return true; return true;
} }
Box* r = runtimeCallInternal(func, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); Box* r = runtimeCallInternal<CXX>(func, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
// I believe this behavior is handled by the slot wrappers in CPython: // I believe this behavior is handled by the slot wrappers in CPython:
if (r->cls == bool_cls) { if (r->cls == bool_cls) {
BoxedBool* b = static_cast<BoxedBool*>(r); BoxedBool* b = static_cast<BoxedBool*>(r);
...@@ -2687,7 +2691,7 @@ template BoxedInt* lenInternal<CXX>(Box*, LenRewriteArgs*); ...@@ -2687,7 +2691,7 @@ template BoxedInt* lenInternal<CXX>(Box*, LenRewriteArgs*);
Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* lenCallInternal(BoxedFunctionBase* func, 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) {
if (argspec != ArgPassSpec(1)) if (argspec != ArgPassSpec(1))
return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); return callFunc<CXX>(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
if (rewrite_args) { if (rewrite_args) {
LenRewriteArgs lrewrite_args(rewrite_args->rewriter, rewrite_args->arg1, rewrite_args->destination); LenRewriteArgs lrewrite_args(rewrite_args->rewriter, rewrite_args->arg1, rewrite_args->destination);
...@@ -2993,13 +2997,13 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, ...@@ -2993,13 +2997,13 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope,
Box* rtn; Box* rtn;
ArgPassSpec new_argspec ArgPassSpec new_argspec
= bindObjIntoArgs(bind_obj, r_bind_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args); = bindObjIntoArgs(bind_obj, r_bind_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args);
return runtimeCallInternal(val, rewrite_args, new_argspec, arg1, arg2, arg3, new_args, keyword_names); return runtimeCallInternal<CXX>(val, rewrite_args, new_argspec, arg1, arg2, arg3, new_args, keyword_names);
} else { } else {
if (rewrite_args) { if (rewrite_args) {
rewrite_args->obj = r_val; rewrite_args->obj = r_val;
} }
Box* rtn = runtimeCallInternal(val, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); Box* rtn = runtimeCallInternal<CXX>(val, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
assert(rtn); // not sure why we have this here assert(rtn); // not sure why we have this here
return rtn; return rtn;
} }
...@@ -3100,42 +3104,49 @@ static inline RewriterVar* getArg(int idx, CallRewriteArgs* rewrite_args) { ...@@ -3100,42 +3104,49 @@ static inline RewriterVar* getArg(int idx, CallRewriteArgs* rewrite_args) {
} }
static StatCounter slowpath_pickversion("slowpath_pickversion"); static StatCounter slowpath_pickversion("slowpath_pickversion");
static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oarg1, Box* oarg2, Box* oarg3, static CompiledFunction* pickVersion(CLFunction* f, enum ExceptionStyle S, int num_output_args, Box* oarg1, Box* oarg2,
Box** oargs) { Box* oarg3, Box** oargs) {
LOCK_REGION(codegen_rwlock.asWrite()); LOCK_REGION(codegen_rwlock.asWrite());
if (f->always_use_version) if (f->always_use_version && f->always_use_version->exception_style == S)
return f->always_use_version; return f->always_use_version;
slowpath_pickversion.log(); slowpath_pickversion.log();
CompiledFunction* best_nonexcmatch = NULL;
for (CompiledFunction* cf : f->versions) { for (CompiledFunction* cf : f->versions) {
assert(cf->spec->arg_types.size() == num_output_args); assert(cf->spec->arg_types.size() == num_output_args);
if (!cf->spec->boxed_return_value) if (!cf->spec->boxed_return_value)
continue; continue;
if (cf->spec->accepts_all_inputs) if (!cf->spec->accepts_all_inputs) {
return cf; assert(cf->spec->rtn_type->llvmType() == UNKNOWN->llvmType());
assert(cf->spec->rtn_type->llvmType() == UNKNOWN->llvmType()); bool works = true;
for (int i = 0; i < num_output_args; i++) {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
bool works = true; ConcreteCompilerType* t = cf->spec->arg_types[i];
for (int i = 0; i < num_output_args; i++) { if ((arg && !t->isFitBy(arg->cls)) || (!arg && t != UNKNOWN)) {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs); works = false;
break;
ConcreteCompilerType* t = cf->spec->arg_types[i]; }
if ((arg && !t->isFitBy(arg->cls)) || (!arg && t != UNKNOWN)) {
works = false;
break;
} }
}
if (!works) if (!works)
continue; continue;
}
return cf; if (cf->exception_style == S)
return cf;
else if (!best_nonexcmatch)
best_nonexcmatch = cf;
} }
if (best_nonexcmatch)
return best_nonexcmatch;
if (f->source == NULL) { if (f->source == NULL) {
// TODO I don't think this should be happening any more? // TODO I don't think this should be happening any more?
printf("Error: couldn't find suitable function version and no source to recompile!\n"); printf("Error: couldn't find suitable function version and no source to recompile!\n");
...@@ -3201,7 +3212,7 @@ static Box* _callFuncHelper(BoxedFunctionBase* func, ArgPassSpec argspec, Box* a ...@@ -3201,7 +3212,7 @@ static Box* _callFuncHelper(BoxedFunctionBase* func, ArgPassSpec argspec, Box* a
void** extra_args) { void** extra_args) {
Box** args = (Box**)extra_args[0]; Box** args = (Box**)extra_args[0];
auto keyword_names = (const std::vector<BoxedString*>*)extra_args[1]; auto keyword_names = (const std::vector<BoxedString*>*)extra_args[1];
return callFunc(func, NULL, argspec, arg1, arg2, arg3, args, keyword_names); return callFunc<CXX>(func, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} }
typedef std::function<Box*(int, int, RewriterVar*&)> GetDefaultFunc; typedef std::function<Box*(int, int, RewriterVar*&)> GetDefaultFunc;
...@@ -3556,14 +3567,20 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name ...@@ -3556,14 +3567,20 @@ void rearrangeArguments(ParamReceiveSpec paramspec, const ParamNames* param_name
} }
static StatCounter slowpath_callfunc("slowpath_callfunc"); static StatCounter slowpath_callfunc("slowpath_callfunc");
template <enum ExceptionStyle S>
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* callFunc(BoxedFunctionBase* func, 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 STAT_TIMERS #if STAT_TIMERS
StatTimer::assertActive(); StatTimer::assertActive();
STAT_TIMER(t0, "us_timer_slowpath_callFunc", 0); STAT_TIMER(t0, "us_timer_slowpath_callFunc", 0);
#endif #endif
slowpath_callfunc.log(); slowpath_callfunc.log();
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
CLFunction* f = func->f; CLFunction* f = func->f;
ParamReceiveSpec paramspec = f->paramspec; ParamReceiveSpec paramspec = f->paramspec;
...@@ -3658,6 +3675,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe ...@@ -3658,6 +3675,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
arg_vec.push_back(args_array); arg_vec.push_back(args_array);
for (auto v : arg_vec) for (auto v : arg_vec)
assert(v); assert(v);
assert(S == CXX); // _callFuncHelper currently is CXX-only
RewriterVar* r_rtn = rewriter->call(true, (void*)_callFuncHelper, arg_vec); RewriterVar* r_rtn = rewriter->call(true, (void*)_callFuncHelper, arg_vec);
rewrite_args->out_success = true; rewrite_args->out_success = true;
...@@ -3676,14 +3694,31 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe ...@@ -3676,14 +3694,31 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
// rewrite up to the call to it: // rewrite up to the call to it:
res = createGenerator(func, oarg1, oarg2, oarg3, oargs); res = createGenerator(func, oarg1, oarg2, oarg3, oargs);
} else { } else {
res = callCLFunc(f, rewrite_args, num_output_args, closure, NULL, func->globals, oarg1, oarg2, oarg3, oargs); res = callCLFunc<S>(f, rewrite_args, num_output_args, closure, NULL, func->globals, oarg1, oarg2, oarg3, oargs);
} }
return res; return res;
} }
template <enum ExceptionStyle S>
static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, BoxedGenerator* generator, Box* oarg1, static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, BoxedGenerator* generator, Box* oarg1,
Box* oarg2, Box* oarg3, Box** oargs) { Box* oarg2, Box* oarg3, Box** oargs) noexcept(S == CAPI) {
if (S != chosen_cf->exception_style) {
if (S == CAPI) {
try {
return callChosenCF<CXX>(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
Box* r = callChosenCF<CAPI>(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs);
if (!r)
throwCAPIException();
return r;
}
}
if (closure && generator) if (closure && generator)
return chosen_cf->closure_generator_call(closure, generator, oarg1, oarg2, oarg3, oargs); return chosen_cf->closure_generator_call(closure, generator, oarg1, oarg2, oarg3, oargs);
else if (closure) else if (closure)
...@@ -3707,9 +3742,16 @@ static Box* astInterpretHelper(CLFunction* f, int num_args, BoxedClosure* closur ...@@ -3707,9 +3742,16 @@ static Box* astInterpretHelper(CLFunction* f, int num_args, BoxedClosure* closur
return astInterpretFunction(f, num_args, closure, generator, globals, arg1, arg2, arg3, (Box**)args); return astInterpretFunction(f, num_args, closure, generator, globals, arg1, arg2, arg3, (Box**)args);
} }
template <enum ExceptionStyle S>
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs) { BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3,
CompiledFunction* chosen_cf = pickVersion(f, num_output_args, oarg1, oarg2, oarg3, oargs); Box** oargs) noexcept(S == CAPI) {
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
CompiledFunction* chosen_cf = pickVersion(f, S, num_output_args, oarg1, oarg2, oarg3, oargs);
if (!chosen_cf) { if (!chosen_cf) {
if (rewrite_args) { if (rewrite_args) {
...@@ -3739,11 +3781,22 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg ...@@ -3739,11 +3781,22 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
if (num_output_args >= 4) if (num_output_args >= 4)
arg_array->setAttr(24, rewrite_args->args); arg_array->setAttr(24, rewrite_args->args);
assert(S == CXX);
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)astInterpretHelper, arg_vec); rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)astInterpretHelper, arg_vec);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
return astInterpretFunction(f, num_output_args, closure, generator, globals, oarg1, oarg2, oarg3, oargs); if (S == CAPI) {
try {
return astInterpretFunction(f, num_output_args, closure, generator, globals, oarg1, oarg2, oarg3,
oargs);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
return astInterpretFunction(f, num_output_args, closure, generator, globals, oarg1, oarg2, oarg3, oargs);
}
} }
ASSERT(!globals, "need to update the calling conventions if we want to pass globals"); ASSERT(!globals, "need to update the calling conventions if we want to pass globals");
...@@ -3765,6 +3818,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg ...@@ -3765,6 +3818,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
if (num_output_args >= 4) if (num_output_args >= 4)
arg_vec.push_back(rewrite_args->args); arg_vec.push_back(rewrite_args->args);
assert(S == CXX && chosen_cf->exception_style == CXX);
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)chosen_cf->call, arg_vec); rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)chosen_cf->call, arg_vec);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
...@@ -3775,29 +3829,48 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg ...@@ -3775,29 +3829,48 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
// code and calls that target to builtins. // code and calls that target to builtins.
if (f->source) { if (f->source) {
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_jitted_code"); UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_jitted_code");
r = callChosenCF(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs); r = callChosenCF<S>(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs);
} else { } else {
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
r = callChosenCF(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs); r = callChosenCF<S>(chosen_cf, closure, generator, oarg1, oarg2, oarg3, oargs);
} }
ASSERT(chosen_cf->spec->rtn_type->isFitBy(r->cls), "%s (%p) was supposed to return %s, but gave a %s", if (!r) {
g.func_addr_registry.getFuncNameAtAddress(chosen_cf->code, true, NULL).c_str(), chosen_cf->code, assert(S == CAPI);
chosen_cf->spec->rtn_type->debugName().c_str(), r->cls->tp_name); } else {
assert(!PyErr_Occurred()); 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; return r;
} }
template <enum ExceptionStyle S>
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* runtimeCallInternal(Box* obj, 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) {
int npassed_args = argspec.totalPassed(); int npassed_args = argspec.totalPassed();
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
if (obj->cls != function_cls && obj->cls != builtin_function_or_method_cls && obj->cls != instancemethod_cls) { 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? // TODO: maybe eventually runtimeCallInternal should just be the default tpp_call?
if (obj->cls->tpp_call) { if (obj->cls->tpp_call) {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); if (S == CAPI) {
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);
}
} }
STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20); STAT_TIMER(t0, "us_timer_slowpath_runtimecall_nonfunction", 20);
...@@ -3818,14 +3891,28 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -3818,14 +3891,28 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
assert((obj->cls->tp_call == NULL) == (typeLookup(obj->cls, call_str, NULL) == NULL)); assert((obj->cls->tp_call == NULL) == (typeLookup(obj->cls, call_str, NULL) == NULL));
} }
if (rewrite_args) { try {
rtn = callattrInternal(obj, call_str, CLASS_ONLY, rewrite_args, argspec, arg1, arg2, arg3, args, if (rewrite_args) {
keyword_names); rtn = callattrInternal(obj, call_str, CLASS_ONLY, rewrite_args, argspec, arg1, arg2, arg3, args,
} else { keyword_names);
rtn = callattrInternal(obj, call_str, CLASS_ONLY, NULL, argspec, arg1, arg2, arg3, args, keyword_names); } else {
rtn = callattrInternal(obj, call_str, CLASS_ONLY, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
}
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
if (!rtn) {
if (S == CAPI) {
PyErr_Format(TypeError, "'%s' object is not callable", getTypeName(obj));
return NULL;
} else
raiseExcHelper(TypeError, "'%s' object is not callable", getTypeName(obj));
} }
if (!rtn)
raiseExcHelper(TypeError, "'%s' object is not callable", getTypeName(obj));
return rtn; return rtn;
} }
...@@ -3863,18 +3950,19 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -3863,18 +3950,19 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (obj->cls == function_cls || obj->cls == builtin_function_or_method_cls) { if (obj->cls == function_cls || obj->cls == builtin_function_or_method_cls) {
BoxedFunctionBase* f = static_cast<BoxedFunctionBase*>(obj); BoxedFunctionBase* f = static_cast<BoxedFunctionBase*>(obj);
// Some functions are sufficiently important that we want them to be able to patchpoint themselves;
// they can do this by setting the "internal_callable" field:
CLFunction::InternalCallable callable = f->f->internal_callable;
if (rewrite_args && !rewrite_args->func_guarded) { if (rewrite_args && !rewrite_args->func_guarded) {
rewrite_args->obj->addGuard((intptr_t)f); rewrite_args->obj->addGuard((intptr_t)f);
rewrite_args->func_guarded = true; rewrite_args->func_guarded = true;
rewrite_args->rewriter->addDependenceOn(f->dependent_ics); rewrite_args->rewriter->addDependenceOn(f->dependent_ics);
} }
// Some functions are sufficiently important that we want them to be able to patchpoint themselves;
// they can do this by setting the "internal_callable" field:
auto callable = f->f->internal_callable.get<S>();
if (callable == NULL) { if (callable == NULL) {
callable = callFunc; callable = callFunc<S>;
} }
Box* res = callable(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); Box* res = callable(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
return res; return res;
} else if (obj->cls == instancemethod_cls) { } else if (obj->cls == instancemethod_cls) {
...@@ -3902,7 +3990,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -3902,7 +3990,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (rewrite_args) { if (rewrite_args) {
rewrite_args->obj = r_im_func; rewrite_args->obj = r_im_func;
} }
Box* res = runtimeCallInternal(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); Box* res = runtimeCallInternal<S>(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
return res; return res;
} }
...@@ -3919,11 +4007,16 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -3919,11 +4007,16 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
ArgPassSpec new_argspec ArgPassSpec new_argspec
= bindObjIntoArgs(im->obj, r_bind_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args); = bindObjIntoArgs(im->obj, r_bind_obj, rewrite_args, argspec, arg1, arg2, arg3, args, new_args);
return runtimeCallInternal(im->func, rewrite_args, new_argspec, arg1, arg2, arg3, new_args, keyword_names); return runtimeCallInternal<S>(im->func, rewrite_args, new_argspec, arg1, arg2, arg3, new_args, keyword_names);
} }
assert(0); assert(0);
abort(); abort();
} }
// Force instantiation:
template Box* runtimeCallInternal<CAPI>(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*);
template Box* runtimeCallInternal<CXX>(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*);
extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) { const std::vector<BoxedString*>* keyword_names) {
...@@ -3979,7 +4072,7 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, ...@@ -3979,7 +4072,7 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2,
rewrite_args.arg3 = rewriter->getArg(4); rewrite_args.arg3 = rewriter->getArg(4);
if (npassed_args >= 4) if (npassed_args >= 4)
rewrite_args.args = rewriter->getArg(5); rewrite_args.args = rewriter->getArg(5);
rtn = runtimeCallInternal(obj, &rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); rtn = runtimeCallInternal<CXX>(obj, &rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
if (!rewrite_args.out_success) { if (!rewrite_args.out_success) {
rewriter.reset(NULL); rewriter.reset(NULL);
...@@ -3987,7 +4080,7 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, ...@@ -3987,7 +4080,7 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2,
rewriter->commitReturning(rewrite_args.out_rtn); rewriter->commitReturning(rewrite_args.out_rtn);
} }
} else { } else {
rtn = runtimeCallInternal(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names); rtn = runtimeCallInternal<CXX>(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} }
assert(rtn); assert(rtn);
...@@ -4526,7 +4619,7 @@ extern "C" Box* unaryop(Box* operand, int op_type) { ...@@ -4526,7 +4619,7 @@ extern "C" Box* unaryop(Box* operand, int op_type) {
// TODO: this code looks very old and like it should be a callattr instead? // TODO: this code looks very old and like it should be a callattr instead?
Box* attr_func = getclsattrInternal(operand, op_name, NULL); Box* attr_func = getclsattrInternal(operand, op_name, NULL);
RELEASE_ASSERT(attr_func, "%s.%s", getTypeName(operand), op_name->c_str()); RELEASE_ASSERT(attr_func, "%s.%s", getTypeName(operand), op_name->c_str());
Box* rtn = runtimeCallInternal(attr_func, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); Box* rtn = runtimeCallInternal<CXX>(attr_func, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
return rtn; return rtn;
} }
...@@ -4893,7 +4986,7 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs* ...@@ -4893,7 +4986,7 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs*
Box* delAttr = typeLookup(static_cast<BoxedClass*>(clsAttr->cls), delete_str, NULL); Box* delAttr = typeLookup(static_cast<BoxedClass*>(clsAttr->cls), delete_str, NULL);
if (delAttr != NULL) { if (delAttr != NULL) {
Box* rtn = runtimeCallInternal(delAttr, NULL, ArgPassSpec(2), clsAttr, obj, NULL, NULL, NULL); Box* rtn = runtimeCallInternal<CXX>(delAttr, NULL, ArgPassSpec(2), clsAttr, obj, NULL, NULL, NULL);
return; return;
} }
} }
...@@ -4937,7 +5030,7 @@ extern "C" void delattrInternal(Box* obj, BoxedString* attr, DelattrRewriteArgs* ...@@ -4937,7 +5030,7 @@ extern "C" void delattrInternal(Box* obj, BoxedString* attr, DelattrRewriteArgs*
static BoxedString* delattr_str = internStringImmortal("__delattr__"); static BoxedString* delattr_str = internStringImmortal("__delattr__");
Box* delAttr = typeLookup(obj->cls, delattr_str, NULL); Box* delAttr = typeLookup(obj->cls, delattr_str, NULL);
if (delAttr != NULL) { if (delAttr != NULL) {
Box* rtn = runtimeCallInternal(delAttr, NULL, ArgPassSpec(2), obj, attr, NULL, NULL, NULL); Box* rtn = runtimeCallInternal<CXX>(delAttr, NULL, ArgPassSpec(2), obj, attr, NULL, NULL, NULL);
return; return;
} }
...@@ -5526,7 +5619,7 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) { ...@@ -5526,7 +5619,7 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) {
while (true) { while (true) {
Box* attr_name; Box* attr_name;
try { try {
attr_name = runtimeCallInternal2(all_getitem, NULL, ArgPassSpec(2), all, boxInt(idx)); attr_name = runtimeCallInternal2<CXX>(all_getitem, NULL, ArgPassSpec(2), all, boxInt(idx));
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (e.matches(IndexError)) if (e.matches(IndexError))
break; break;
......
...@@ -111,8 +111,10 @@ struct BinopRewriteArgs; ...@@ -111,8 +111,10 @@ struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args); extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
struct CallRewriteArgs; struct CallRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* runtimeCallInternal(Box* obj, 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 == ExceptionStyle::CAPI);
struct GetitemRewriteArgs; struct GetitemRewriteArgs;
template <ExceptionStyle::ExceptionStyle S> template <ExceptionStyle::ExceptionStyle S>
...@@ -124,8 +126,10 @@ BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == Exce ...@@ -124,8 +126,10 @@ BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == Exce
Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* lenCallInternal(BoxedFunctionBase* f, 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);
template <ExceptionStyle::ExceptionStyle S>
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* callFunc(BoxedFunctionBase* func, 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 == ExceptionStyle::CAPI);
enum LookupScope { enum LookupScope {
CLASS_ONLY = 1, CLASS_ONLY = 1,
...@@ -169,8 +173,10 @@ bool isUserDefined(BoxedClass* cls); ...@@ -169,8 +173,10 @@ bool isUserDefined(BoxedClass* cls);
Box* processDescriptor(Box* obj, Box* inst, Box* owner); Box* processDescriptor(Box* obj, Box* inst, Box* owner);
Box* processDescriptorOrNull(Box* obj, Box* inst, Box* owner); Box* processDescriptorOrNull(Box* obj, Box* inst, Box* owner);
template <ExceptionStyle::ExceptionStyle S>
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs); BoxedGenerator* generator, Box* globals, Box* oarg1, Box* oarg2, Box* oarg3,
Box** oargs) noexcept(S == ExceptionStyle::CAPI);
static const char* objectNewParameterTypeErrorMsg() { static const char* objectNewParameterTypeErrorMsg() {
if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) { if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) {
......
...@@ -638,7 +638,7 @@ static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args ...@@ -638,7 +638,7 @@ static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args
if (argspec.has_starargs || argspec.num_args == 0) { if (argspec.has_starargs || argspec.num_args == 0) {
// Get callFunc to expand the arguments. // Get callFunc to expand the arguments.
// TODO: update this to use rearrangeArguments instead. // TODO: update this to use rearrangeArguments instead.
return callFunc(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); return callFunc<ExceptionStyle::CXX>(f, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
} }
return typeCallInner(rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); return typeCallInner(rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
...@@ -996,7 +996,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -996,7 +996,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (new_npassed_args >= 4) if (new_npassed_args >= 4)
srewrite_args.args = rewrite_args->args; srewrite_args.args = rewrite_args->args;
made = runtimeCallInternal(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3, args, keyword_names); made = runtimeCallInternal<ExceptionStyle::CXX>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3,
args, keyword_names);
if (!srewrite_args.out_success) { if (!srewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
...@@ -1013,7 +1014,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1013,7 +1014,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init) if (cls->tp_new == object_cls->tp_new && cls->tp_init != object_cls->tp_init)
made = objectNewNoArgs(cls); made = objectNewNoArgs(cls);
else else
made = runtimeCallInternal(new_attr, NULL, new_argspec, cls, arg2, arg3, args, keyword_names); made = runtimeCallInternal<ExceptionStyle::CXX>(new_attr, NULL, new_argspec, cls, arg2, arg3, args,
keyword_names);
} }
assert(made); assert(made);
...@@ -1063,7 +1065,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1063,7 +1065,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
// initrtn = callattrInternal(cls, _init_str, INST_ONLY, &srewrite_args, argspec, made, arg2, arg3, args, // initrtn = callattrInternal(cls, _init_str, INST_ONLY, &srewrite_args, argspec, made, arg2, arg3, args,
// keyword_names); // keyword_names);
initrtn = runtimeCallInternal(init_attr, &srewrite_args, argspec, made, arg2, arg3, args, keyword_names); initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, &srewrite_args, argspec, made, arg2, arg3,
args, keyword_names);
if (!srewrite_args.out_success) { if (!srewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
...@@ -1082,10 +1085,11 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1082,10 +1085,11 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
// If we weren't passed the args array, it's not safe to index into it // If we weren't passed the args array, it's not safe to index into it
if (passed <= 2) if (passed <= 2)
initrtn = runtimeCallInternal(init_attr, NULL, init_argspec, arg2, arg3, NULL, NULL, keyword_names); initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, NULL, init_argspec, arg2, arg3, NULL,
NULL, keyword_names);
else else
initrtn initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, NULL, init_argspec, arg2, arg3, args[0],
= runtimeCallInternal(init_attr, NULL, init_argspec, arg2, arg3, args[0], &args[1], keyword_names); &args[1], keyword_names);
} }
assertInitNone(initrtn); assertInitNone(initrtn);
} else { } else {
...@@ -3414,7 +3418,7 @@ void setupRuntime() { ...@@ -3414,7 +3418,7 @@ void setupRuntime() {
// Punting on that until needed; hopefully by then we will have better Pyston slots support. // Punting on that until needed; hopefully by then we will have better Pyston slots support.
auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, true); auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, true);
typeCallObj->internal_callable = &typeCallInternal; typeCallObj->internal_callable.cxx_ptr = &typeCallInternal;
type_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeName, typeSetName, NULL)); type_cls->giveAttr("__name__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeName, typeSetName, NULL));
type_cls->giveAttr("__bases__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeBases, typeSetBases, NULL)); type_cls->giveAttr("__bases__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeBases, typeSetBases, NULL));
......
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