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
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);
else
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
if (kw)
return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, true), args, kw,
NULL, NULL, NULL);
else
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,24 +68,34 @@ 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) {
raiseExcHelper(StopIteration, "");
if (S == CAPI) {
PyErr_SetObject(StopIteration, None);
return NULL;
} else
raiseExcHelper(StopIteration, "");
}
if (!(self->pos >= 0 && self->pos < self->l->size)) {
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];
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