Commit b9367a3f authored by Kevin Modzelewski's avatar Kevin Modzelewski

CAPI exceptions for callattr

parent 409288eb
......@@ -613,8 +613,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// for (auto a : llvm_args)
// a->dump();
bool do_patchpoint = ENABLE_ICCALLSITES
&& (func_addr == runtimeCall || func_addr == runtimeCallCapi || func_addr == pyston::callattr);
bool do_patchpoint = ENABLE_ICCALLSITES && (func_addr == runtimeCall || func_addr == runtimeCallCapi
|| func_addr == pyston::callattr || func_addr == callattrCapi);
if (do_patchpoint) {
assert(func_addr);
......@@ -691,25 +691,35 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
bool pass_keywords = (flags.argspec.num_keywords != 0);
int npassed_args = flags.argspec.totalPassed();
ExceptionStyle exception_style = ((FORCE_LLVM_CAPI && !info.unw_info.cxx_exc_dest && !flags.null_on_nonexistent)
|| info.unw_info.capi_exc_dest)
? ExceptionStyle::CAPI
: ExceptionStyle::CXX;
if (exception_style == CAPI)
assert(!flags.null_on_nonexistent); // Will conflict with CAPI's null-on-exception
llvm::Value* func;
if (pass_keywords)
func = g.funcs.callattr;
func = g.funcs.callattr.get(exception_style);
else if (npassed_args == 0)
func = g.funcs.callattr0;
func = g.funcs.callattr0.get(exception_style);
else if (npassed_args == 1)
func = g.funcs.callattr1;
func = g.funcs.callattr1.get(exception_style);
else if (npassed_args == 2)
func = g.funcs.callattr2;
func = g.funcs.callattr2.get(exception_style);
else if (npassed_args == 3)
func = g.funcs.callattr3;
func = g.funcs.callattr3.get(exception_style);
else
func = g.funcs.callattrN;
func = g.funcs.callattrN.get(exception_style);
void* func_ptr = (exception_style == ExceptionStyle::CXX) ? (void*)pyston::callattr : (void*)callattrCapi;
std::vector<llvm::Value*> other_args;
other_args.push_back(var->getValue());
other_args.push_back(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr));
other_args.push_back(getConstantInt(flags.asInt(), g.i64));
return _call(emitter, info, func, CXX, (void*)pyston::callattr, other_args, flags.argspec, args, keyword_names,
return _call(emitter, info, func, exception_style, func_ptr, other_args, flags.argspec, args, keyword_names,
UNKNOWN);
}
......@@ -1707,8 +1717,14 @@ public:
CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr,
CallattrFlags flags, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) override {
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, flags.cls_only, flags.argspec, args, keyword_names);
ExceptionStyle exception_style = CXX;
// Not safe to force-capi here since most of the functions won't have capi variants:
if (/*FORCE_LLVM_CAPI ||*/ info.unw_info.capi_exc_dest)
exception_style = CAPI;
ConcreteCompilerVariable* called_constant = tryCallattrConstant(
emitter, info, var, attr, flags.cls_only, flags.argspec, args, keyword_names, NULL, exception_style);
if (called_constant)
return called_constant;
......
......@@ -271,19 +271,36 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo());
g.funcs.callattr = getFunc((void*)callattr, "callattr");
g.funcs.callattr0
g.funcs.callattr.cxx_val = getFunc((void*)callattr, "callattr");
g.funcs.callattr0.cxx_val
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64);
g.funcs.callattr1 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.funcs.callattr1.cxx_val = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr);
g.funcs.callattr2 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3
g.funcs.callattr2.cxx_val
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3.cxx_val
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattrN.cxx_val = addFunc(
(void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo());
g.funcs.callattr.capi_val = getFunc((void*)callattrCapi, "callattrCapi");
g.funcs.callattr0.capi_val = addFunc((void*)callattrCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_boxedstring_type_ptr, g.i64);
g.funcs.callattr1.capi_val = addFunc((void*)callattrCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr);
g.funcs.callattr2.capi_val
= addFunc((void*)callattrCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3.capi_val
= addFunc((void*)callattrCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattrN = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr,
g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo());
g.funcs.callattrN.capi_val = addFunc(
(void*)callattrCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo());
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
......
......@@ -44,7 +44,7 @@ struct GlobalFuncs {
*assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
ExceptionSwitchable<llvm::Value*> runtimeCall0, runtimeCall1, runtimeCall2, runtimeCall3, runtimeCall, runtimeCallN;
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN;
ExceptionSwitchable<llvm::Value*> callattr0, callattr1, callattr2, callattr3, callattr, callattrN;
llvm::Value* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* exec;
llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel;
......
......@@ -122,6 +122,7 @@ void force() {
FORCE(runtimeCall);
FORCE(runtimeCallCapi);
FORCE(callattr);
FORCE(callattrCapi);
FORCE(raise0);
FORCE(raise3);
......
......@@ -2747,15 +2747,25 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope,
}
}
extern "C" Box* callattr(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
template <ExceptionStyle S>
Box* _callattrEntry(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names, void* return_addr) {
STAT_TIMER(t0, "us_timer_slowpath_callattr", 10);
if (S == CAPI) {
try {
return _callattrEntry<CXX>(obj, attr, flags, arg1, arg2, arg3, args, keyword_names, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
#if 0 && STAT_TIMERS
static uint64_t* st_id = Stats::getStatCounter("us_timer_slowpath_callattr_patchable");
static uint64_t* st_id_nopatch = Stats::getStatCounter("us_timer_slowpath_callattr_nopatch");
static uint64_t* st_id_megamorphic = Stats::getStatCounter("us_timer_slowpath_callattr_megamorphic");
ICInfo* icinfo = getICInfo(__builtin_extract_return_addr(__builtin_return_address(0)));
ICInfo* icinfo = getICInfo(return_addr);
uint64_t* counter;
if (!icinfo)
counter = st_id_nopatch;
......@@ -2783,10 +2793,9 @@ extern "C" Box* callattr(Box* obj, BoxedString* attr, CallattrFlags flags, Box*
num_orig_args++;
// Uncomment this to help debug if callsites aren't getting rewritten:
// printf("Slowpath call: %p (%s.%s)\n", __builtin_return_address(0), obj->cls->tp_name, attr->c_str());
// printf("Slowpath call: %p (%s.%s)\n", return_addr, obj->cls->tp_name, attr->c_str());
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(
__builtin_extract_return_addr(__builtin_return_address(0)), num_orig_args, "callattr"));
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(return_addr, num_orig_args, "callattr"));
Box* rtn;
LookupScope scope = flags.cls_only ? CLASS_ONLY : CLASS_OR_INST;
......@@ -2831,6 +2840,18 @@ extern "C" Box* callattr(Box* obj, BoxedString* attr, CallattrFlags flags, Box*
return rtn;
}
extern "C" Box* callattr(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) {
return _callattrEntry<CXX>(obj, attr, flags, arg1, arg2, arg3, args, keyword_names,
__builtin_extract_return_addr(__builtin_return_address(0)));
}
extern "C" Box* callattrCapi(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept {
return _callattrEntry<CAPI>(obj, attr, flags, arg1, arg2, arg3, args, keyword_names,
__builtin_extract_return_addr(__builtin_return_address(0)));
}
static inline RewriterVar* getArg(int idx, CallRewriteArgs* rewrite_args) {
if (idx == 0)
return rewrite_args->arg1;
......@@ -3860,6 +3881,7 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2,
extern "C" Box* runtimeCallCapi(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept {
// TODO add rewriting
return runtimeCallInternal<CAPI>(obj, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
}
......
......@@ -67,6 +67,8 @@ extern "C" bool nonzero(Box* obj);
extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*);
extern "C" Box* runtimeCallCapi(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*) noexcept;
extern "C" Box* callattr(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*);
extern "C" Box* callattrCapi(Box*, BoxedString*, CallattrFlags, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*) noexcept;
extern "C" BoxedString* str(Box* obj);
extern "C" BoxedString* repr(Box* obj);
extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception
......
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