Commit b8b126e3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #769 from kmod/exceptions2

Templatize runtimeCall for different exception styles
parents c011fb3a a62ba58f
...@@ -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 runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL); return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, true), args, kw,
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,16 +68,24 @@ i1 listiterHasnextUnboxed(Box* s) { ...@@ -65,16 +68,24 @@ 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) {
if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, ""); 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;
if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, ""); raiseExcHelper(StopIteration, "");
} }
...@@ -82,7 +93,9 @@ Box* listiterNext(Box* s) { ...@@ -82,7 +93,9 @@ Box* listiterNext(Box* s) {
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,7 +1890,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1886,7 +1890,7 @@ 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;
...@@ -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,23 +3104,23 @@ static inline RewriterVar* getArg(int idx, CallRewriteArgs* rewrite_args) { ...@@ -3100,23 +3104,23 @@ 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; bool works = true;
...@@ -3132,10 +3136,17 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa ...@@ -3132,10 +3136,17 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
if (!works) if (!works)
continue; continue;
}
if (cf->exception_style == S)
return cf; 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,12 +3781,23 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg ...@@ -3739,12 +3781,23 @@ 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;
} }
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); 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);
} }
if (!r) {
assert(S == CAPI);
} else {
ASSERT(chosen_cf->spec->rtn_type->isFitBy(r->cls), "%s (%p) was supposed to return %s, but gave a %s", 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, 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); chosen_cf->spec->rtn_type->debugName().c_str(), r->cls->tp_name);
assert(!PyErr_Occurred()); 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) {
if (S == CAPI) {
try {
return obj->cls->tpp_call(obj, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); 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));
} }
try {
if (rewrite_args) { if (rewrite_args) {
rtn = callattrInternal(obj, call_str, CLASS_ONLY, rewrite_args, argspec, arg1, arg2, arg3, args, rtn = callattrInternal(obj, call_str, CLASS_ONLY, rewrite_args, argspec, arg1, arg2, arg3, args,
keyword_names); keyword_names);
} else { } else {
rtn = callattrInternal(obj, call_str, CLASS_ONLY, NULL, argspec, arg1, arg2, arg3, args, keyword_names); rtn = callattrInternal(obj, call_str, CLASS_ONLY, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} }
if (!rtn) } 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)); 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