Commit ae770511 authored by Kevin Modzelewski's avatar Kevin Modzelewski

capi exceptions for getitems

Less helpful than I thought for now -- the KeyErrors are thrown
by a custom class that does `raise KeyError`, so we won't benefit
from this until we can have jitted code throw (not just receive)
capi exceptions.
parent fc02e94c
...@@ -337,6 +337,10 @@ public: ...@@ -337,6 +337,10 @@ public:
CompilerVariable* slice) override { CompilerVariable* slice) override {
ConcreteCompilerVariable* converted_slice = slice->makeConverted(emitter, slice->getBoxType()); ConcreteCompilerVariable* converted_slice = slice->makeConverted(emitter, slice->getBoxType());
ExceptionStyle target_exception_style = CXX;
if (info.unw_info.capi_exc_dest)
target_exception_style = CAPI;
bool do_patchpoint = ENABLE_ICGETITEMS; bool do_patchpoint = ENABLE_ICGETITEMS;
llvm::Value* rtn; llvm::Value* rtn;
if (do_patchpoint) { if (do_patchpoint) {
...@@ -346,13 +350,20 @@ public: ...@@ -346,13 +350,20 @@ public:
llvm_args.push_back(var->getValue()); llvm_args.push_back(var->getValue());
llvm_args.push_back(converted_slice->getValue()); llvm_args.push_back(converted_slice->getValue());
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::getitem, llvm_args, info.unw_info); llvm::Value* uncasted
= emitter.createIC(pp, (void*)(target_exception_style == CAPI ? pyston::getitem_capi : pyston::getitem),
llvm_args, info.unw_info, target_exception_style);
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr); rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else { } else {
rtn = emitter.createCall2(info.unw_info, g.funcs.getitem, var->getValue(), converted_slice->getValue()); rtn = emitter.createCall2(info.unw_info,
target_exception_style == CAPI ? g.funcs.getitem_capi : g.funcs.getitem,
var->getValue(), converted_slice->getValue(), target_exception_style);
} }
converted_slice->decvref(emitter); converted_slice->decvref(emitter);
if (target_exception_style == CAPI)
emitter.checkAndPropagateCapiException(info.unw_info, rtn, getNullPtr(g.llvm_value_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, rtn, true); return new ConcreteCompilerVariable(UNKNOWN, rtn, true);
} }
...@@ -1550,15 +1561,27 @@ public: ...@@ -1550,15 +1561,27 @@ public:
if (!canStaticallyResolveGetattrs()) if (!canStaticallyResolveGetattrs())
return NULL; return NULL;
ExceptionStyle exception_style = CXX;
if (info.unw_info.capi_exc_dest)
exception_style = CAPI;
Box* rtattr = cls->getattr(attr); Box* rtattr = cls->getattr(attr);
if (rtattr == NULL) { if (rtattr == NULL) {
if (no_attribute) { if (no_attribute) {
*no_attribute = true; *no_attribute = true;
} else { } else {
llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr
: g.funcs.raiseAttributeErrorStrCapi;
llvm::CallSite call = emitter.createCall3( llvm::CallSite call = emitter.createCall3(
info.unw_info, g.funcs.raiseAttributeErrorStr, embedRelocatablePtr(cls->tp_name, g.i8_ptr), info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64)); embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style);
call.setDoesNotReturn(); if (exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
} else {
call.setDoesNotReturn();
}
} }
return undefVariable(); return undefVariable();
} }
...@@ -1589,6 +1612,9 @@ public: ...@@ -1589,6 +1612,9 @@ public:
cf = cl->versions[i]; cf = cl->versions[i];
assert(cf->spec->arg_types.size() == cl->numReceivedArgs()); assert(cf->spec->arg_types.size() == cl->numReceivedArgs());
if (cf->exception_style != exception_style)
continue;
bool fits = true; bool fits = true;
for (int j = 0; j < args.size(); j++) { for (int j = 0; j < args.size(); j++) {
if (!args[j]->canConvertTo(cf->spec->arg_types[j + 1])) { if (!args[j]->canConvertTo(cf->spec->arg_types[j + 1])) {
...@@ -1603,8 +1629,12 @@ public: ...@@ -1603,8 +1629,12 @@ public:
break; break;
} }
assert(found); if (!found && exception_style == CAPI) {
assert(cf->code); std::string name = g.func_addr_registry.getFuncNameAtAddress(cl->versions[0]->code, true);
RELEASE_ASSERT(0, "Please define a capi variant for %s", name.c_str());
}
RELEASE_ASSERT(found, "");
RELEASE_ASSERT(cf->code, "");
std::vector<llvm::Type*> arg_types; std::vector<llvm::Type*> arg_types;
RELEASE_ASSERT(paramspec.num_args == cl->numReceivedArgs(), ""); RELEASE_ASSERT(paramspec.num_args == cl->numReceivedArgs(), "");
......
...@@ -136,7 +136,7 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) { ...@@ -136,7 +136,7 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
return r; return r;
} }
if (expr->type == AST_TYPE::Attribute) { if (expr->type == AST_TYPE::Attribute || expr->type == AST_TYPE::Subscript) {
r = CAPI; r = CAPI;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx); // printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
return r; return r;
......
...@@ -199,6 +199,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -199,6 +199,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(setattr); GET(setattr);
GET(delattr); GET(delattr);
GET(getitem); GET(getitem);
GET(getitem_capi);
GET(setitem); GET(setitem);
GET(delitem); GET(delitem);
GET(getGlobal); GET(getGlobal);
......
...@@ -36,8 +36,8 @@ struct GlobalFuncs { ...@@ -36,8 +36,8 @@ struct GlobalFuncs {
*boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createUserClass, *createClosure, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createUserClass, *createClosure,
*createGenerator, *createSet; *createGenerator, *createSet;
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare, llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
*augbinop, *unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom, *augbinop, *unboxedLen, *getitem, *getitem_capi, *getclsattr, *getGlobal, *setitem, *unaryop, *import,
*importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext; *importFrom, *importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi, llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *assertNameDefined, *assertFail, *raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *assertNameDefined, *assertFail,
......
...@@ -746,7 +746,9 @@ void setupDict() { ...@@ -746,7 +746,9 @@ void setupDict() {
dict_cls->giveAttr("setdefault", dict_cls->giveAttr("setdefault",
new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None })); new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None }));
dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem<CXX>, UNKNOWN, 2))); auto dict_getitem = boxRTFunction((void*)dictGetitem<CXX>, UNKNOWN, 2, ParamNames::empty(), CXX);
addRTFunction(dict_getitem, (void*)dictGetitem<CAPI>, UNKNOWN, CAPI);
dict_cls->giveAttr("__getitem__", new BoxedFunction(dict_getitem));
dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3))); dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3)));
dict_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)dictDelitem, UNKNOWN, 2))); dict_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)dictDelitem, UNKNOWN, 2)));
dict_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)dictContains, BOXED_BOOL, 2))); dict_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)dictContains, BOXED_BOOL, 2)));
......
...@@ -83,6 +83,7 @@ void force() { ...@@ -83,6 +83,7 @@ void force() {
FORCE(augbinop); FORCE(augbinop);
FORCE(unboxedLen); FORCE(unboxedLen);
FORCE(getitem); FORCE(getitem);
FORCE(getitem_capi);
FORCE(getclsattr); FORCE(getclsattr);
FORCE(getGlobal); FORCE(getGlobal);
FORCE(delGlobal); FORCE(delGlobal);
......
...@@ -4481,11 +4481,6 @@ Box* callItemOrSliceAttr(Box* target, BoxedString* item_str, BoxedString* slice_ ...@@ -4481,11 +4481,6 @@ Box* callItemOrSliceAttr(Box* target, BoxedString* item_str, BoxedString* slice_
template <ExceptionStyle S> template <ExceptionStyle S>
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI) { Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI) {
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
// The PyObject_GetItem logic is: // The PyObject_GetItem logic is:
// - call mp_subscript if it exists // - call mp_subscript if it exists
// - if tp_as_sequence exists, try using that (with a number of conditions) // - if tp_as_sequence exists, try using that (with a number of conditions)
...@@ -4497,7 +4492,6 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) ...@@ -4497,7 +4492,6 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args)
PyMappingMethods* m = target->cls->tp_as_mapping; PyMappingMethods* m = target->cls->tp_as_mapping;
if (m && m->mp_subscript && m->mp_subscript != slot_mp_subscript) { if (m && m->mp_subscript && m->mp_subscript != slot_mp_subscript) {
if (rewrite_args) { if (rewrite_args) {
assert(S == CXX);
RewriterVar* r_obj = rewrite_args->target; RewriterVar* r_obj = rewrite_args->target;
RewriterVar* r_slice = rewrite_args->slice; RewriterVar* r_slice = rewrite_args->slice;
RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls)); RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls));
...@@ -4511,7 +4505,8 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) ...@@ -4511,7 +4505,8 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args)
// support calling a RewriterVar (can only call fixed function addresses). // support calling a RewriterVar (can only call fixed function addresses).
r_m->addAttrGuard(offsetof(PyMappingMethods, mp_subscript), (intptr_t)m->mp_subscript); r_m->addAttrGuard(offsetof(PyMappingMethods, mp_subscript), (intptr_t)m->mp_subscript);
RewriterVar* r_rtn = rewrite_args->rewriter->call(true, (void*)m->mp_subscript, r_obj, r_slice); RewriterVar* r_rtn = rewrite_args->rewriter->call(true, (void*)m->mp_subscript, r_obj, r_slice);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException); if (S == CXX)
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->out_success = true; rewrite_args->out_success = true;
rewrite_args->out_rtn = r_rtn; rewrite_args->out_rtn = r_rtn;
} }
...@@ -4521,6 +4516,11 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) ...@@ -4521,6 +4516,11 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args)
return r; return r;
} }
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
static BoxedString* getitem_str = internStringImmortal("__getitem__"); static BoxedString* getitem_str = internStringImmortal("__getitem__");
static BoxedString* getslice_str = internStringImmortal("__getslice__"); static BoxedString* getslice_str = internStringImmortal("__getslice__");
...@@ -4614,6 +4614,39 @@ extern "C" Box* getitem(Box* target, Box* slice) { ...@@ -4614,6 +4614,39 @@ extern "C" Box* getitem(Box* target, Box* slice) {
return rtn; return rtn;
} }
// target[slice]
extern "C" Box* getitem_capi(Box* target, Box* slice) noexcept {
STAT_TIMER(t0, "us_timer_slowpath_getitem", 10);
// This possibly could just be represented as a single callattr; the only tricky part
// are the error messages.
// Ex "(1)[1]" and "(1).__getitem__(1)" give different error messages.
static StatCounter slowpath_getitem("slowpath_getitem");
slowpath_getitem.log();
std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 2, "getitem"));
Box* rtn;
if (rewriter.get()) {
GetitemRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getArg(1),
rewriter->getReturnDestination());
rtn = getitemInternal<CAPI>(target, slice, &rewrite_args);
if (!rewrite_args.out_success) {
rewriter.reset(NULL);
} else {
rewriter->commitReturning(rewrite_args.out_rtn);
}
} else {
rtn = getitemInternal<CAPI>(target, slice, NULL);
}
return rtn;
}
// target[slice] = value // target[slice] = value
extern "C" void setitem(Box* target, Box* slice, Box* value) { extern "C" void setitem(Box* target, Box* slice, Box* value) {
STAT_TIMER(t0, "us_timer_slowpath_setitem", 10); STAT_TIMER(t0, "us_timer_slowpath_setitem", 10);
......
...@@ -83,6 +83,7 @@ extern "C" i64 unboxedLen(Box* obj); ...@@ -83,6 +83,7 @@ extern "C" i64 unboxedLen(Box* obj);
extern "C" Box* binop(Box* lhs, Box* rhs, int op_type); extern "C" Box* binop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type); extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* getitem(Box* value, Box* slice); extern "C" Box* getitem(Box* value, Box* slice);
extern "C" Box* getitem_capi(Box* value, Box* slice) noexcept;
extern "C" void setitem(Box* target, Box* slice, Box* value); extern "C" void setitem(Box* target, Box* slice, Box* value);
extern "C" void delitem(Box* target, Box* slice); extern "C" void delitem(Box* target, Box* slice);
extern "C" Box* getclsattr(Box* obj, BoxedString* attr); extern "C" Box* getclsattr(Box* obj, BoxedString* attr);
......
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