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
param_names(this->source->ast, this->source->getInternedStrings()),
always_use_version(NULL),
code_obj(NULL),
times_interpreted(0) {
times_interpreted(0),
internal_callable(NULL, NULL) {
assert(num_args >= num_defaults);
}
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
param_names(param_names),
always_use_version(NULL),
code_obj(NULL),
times_interpreted(0) {
times_interpreted(0),
internal_callable(NULL, NULL) {
assert(num_args >= num_defaults);
}
......
......@@ -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.
// TODO: implement this for real
......
......@@ -716,6 +716,7 @@ void CompiledFunction::speculationFailed() {
}
CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
ExceptionStyle::ExceptionStyle exception_style,
const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL),
func(func),
......@@ -723,6 +724,7 @@ CompiledFunction::CompiledFunction(llvm::Function* func, FunctionSpecialization*
entry_descriptor(entry_descriptor),
code(code),
effort(effort),
exception_style(exception_style),
times_called(0),
times_speculation_failed(0),
location_map(nullptr) {
......@@ -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);
}
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.vararg.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,
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(takes_varargs || param_names.vararg.str() == "");
assert(takes_kwargs || param_names.kwarg.str() == "");
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;
}
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);
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) {
......@@ -862,7 +867,8 @@ static ConcreteCompilerType* processType(ConcreteCompilerType* 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());
#ifndef NDEBUG
for (ConcreteCompilerType* t : arg_types)
......@@ -870,6 +876,6 @@ void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
#endif
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 {
};
};
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;
template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
......@@ -264,6 +283,7 @@ public:
int code_size;
EffortLevel effort;
ExceptionStyle::ExceptionStyle exception_style;
int64_t times_called, times_speculation_failed;
ICInvalidator dependent_callsites;
......@@ -273,7 +293,7 @@ public:
std::vector<ICInfo*> ics;
CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, void* code, EffortLevel effort,
const OSREntryDescriptor* entry_descriptor);
ExceptionStyle::ExceptionStyle exception_style, const OSREntryDescriptor* entry_descriptor);
ConcreteCompilerType* getReturnType();
......@@ -352,9 +372,9 @@ public:
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
// such as typeCall.
typedef Box* (*InternalCallable)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*);
InternalCallable internal_callable = NULL;
typedef ExceptionSwitchableFunction<Box*, BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*,
Box**, const std::vector<BoxedString*>*> InternalCallable;
InternalCallable internal_callable;
CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
std::unique_ptr<SourceInfo> source);
......@@ -393,12 +413,16 @@ public:
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
const ParamNames& param_names = ParamNames::empty());
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,
const ParamNames& param_names = ParamNames::empty());
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type);
const ParamNames& param_names = ParamNames::empty(),
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,
const std::vector<ConcreteCompilerType*>& arg_types);
const std::vector<ConcreteCompilerType*>& arg_types,
ExceptionStyle::ExceptionStyle exception_style = ExceptionStyle::CXX);
CLFunction* unboxRTFunction(Box*);
// Compiles a new version of the function with the given signature and adds it to the list;
......
......@@ -1382,7 +1382,7 @@ void setupBuiltins() {
builtins_module->giveAttr("repr", repr_obj);
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");
builtins_module->giveAttr("len", len_obj);
......
......@@ -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 {
try {
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
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, false), args,
NULL, NULL, NULL, NULL);
}
extern "C" int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) noexcept {
......
......@@ -98,8 +98,8 @@ void generatorEntry(BoxedGenerator* g) {
BoxedFunctionBase* func = g->function;
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,
g->arg3, args);
callCLFunc<ExceptionStyle::CXX>(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g,
func->globals, g->arg1, g->arg2, g->arg3, args);
} catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller
g->exception = e;
......
......@@ -22,6 +22,9 @@
namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
BoxedListIterator::BoxedListIterator(BoxedList* l, int start) : l(l), pos(start) {
}
......@@ -65,16 +68,24 @@ i1 listiterHasnextUnboxed(Box* s) {
return ans;
}
Box* listiterNext(Box* s) {
template <enum ExceptionStyle S> Box* listiterNext(Box* s) noexcept(S == CAPI) {
assert(s->cls == list_iterator_cls);
BoxedListIterator* self = static_cast<BoxedListIterator*>(s);
if (!self->l) {
if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, "");
}
if (!(self->pos >= 0 && self->pos < self->l->size)) {
self->l = NULL;
if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, "");
}
......@@ -82,7 +93,9 @@ Box* listiterNext(Box* s) {
self->pos++;
return rtn;
}
// force instantiation:
template Box* listiterNext<CAPI>(Box*);
template Box* listiterNext<CXX>(Box*);
Box* listReversed(Box* s) {
assert(isSubclass(s->cls, list_cls));
......
......@@ -704,7 +704,7 @@ private:
public:
PyCmpComparer(Box* cmp) : cmp(cmp) {}
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))
raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name);
return static_cast<BoxedInt*>(r)->n < 0;
......@@ -1169,7 +1169,10 @@ void setupList() {
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
list_iterator_cls->giveAttr(
"__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->tpp_hasnext = listiterHasnextUnboxed;
......
......@@ -35,7 +35,7 @@ Box* listIter(Box* self);
Box* listIterIter(Box* self);
Box* listiterHasnext(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* listreviterHasnext(Box* self);
i1 listreviterHasnextUnboxed(Box* self);
......
This diff is collapsed.
......@@ -111,8 +111,10 @@ struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
struct CallRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
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;
template <ExceptionStyle::ExceptionStyle S>
......@@ -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* 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* 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 {
CLASS_ONLY = 1,
......@@ -169,8 +173,10 @@ bool isUserDefined(BoxedClass* cls);
Box* processDescriptor(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,
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() {
if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) {
......
......@@ -638,7 +638,7 @@ static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args
if (argspec.has_starargs || argspec.num_args == 0) {
// Get callFunc to expand the arguments.
// 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);
......@@ -996,7 +996,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (new_npassed_args >= 4)
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) {
rewrite_args = NULL;
......@@ -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)
made = objectNewNoArgs(cls);
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);
......@@ -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,
// 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) {
rewrite_args = NULL;
......@@ -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 (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
initrtn
= runtimeCallInternal(init_attr, NULL, init_argspec, arg2, arg3, args[0], &args[1], keyword_names);
initrtn = runtimeCallInternal<ExceptionStyle::CXX>(init_attr, NULL, init_argspec, arg2, arg3, args[0],
&args[1], keyword_names);
}
assertInitNone(initrtn);
} else {
......@@ -3414,7 +3418,7 @@ void setupRuntime() {
// 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);
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("__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