Commit d8bf75e3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make some getattrs (in try blocks) use capi exceptions

Eventually we'll want to have a more sophisticated way of
determining when to switch to capi exceptions; they do add
noticeable overhead when no exception gets thrown.
parent 65f9d4b5
......@@ -489,14 +489,24 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm::Value* rtn_val = NULL;
ExceptionStyle target_exception_style = CXX;
if (info.unw_info.capi_exc_dest)
target_exception_style = CAPI;
llvm::Value* llvm_func;
void* raw_func;
if (cls_only) {
assert(target_exception_style == CXX);
llvm_func = g.funcs.getclsattr;
raw_func = (void*)pyston::getclsattr;
} else {
llvm_func = g.funcs.getattr;
raw_func = (void*)pyston::getattr;
if (target_exception_style == CXX) {
llvm_func = g.funcs.getattr;
raw_func = (void*)pyston::getattr;
} else {
llvm_func = g.funcs.getattr_capi;
raw_func = (void*)pyston::getattr_capi;
}
}
bool do_patchpoint = ENABLE_ICGETATTRS;
......@@ -507,11 +517,15 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr);
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info);
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info, target_exception_style);
rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else {
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr);
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr, target_exception_style);
}
if (target_exception_style == CAPI)
emitter.checkAndPropagateCapiException(info.unw_info, rtn_val, getNullPtr(g.llvm_value_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, rtn_val, true);
}
......@@ -1480,10 +1494,18 @@ public:
if (canStaticallyResolveGetattrs()) {
Box* rtattr = typeLookup(cls, attr, nullptr);
if (rtattr == NULL) {
ExceptionStyle exception_style = info.unw_info.capi_exc_dest ? CAPI : CXX;
llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr
: g.funcs.raiseAttributeErrorStrCapi;
llvm::CallSite call = emitter.createCall3(
info.unw_info, g.funcs.raiseAttributeErrorStr, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64));
call.setDoesNotReturn();
info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style);
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();
}
......
......@@ -106,6 +106,35 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
// printf("Added %d\n", invoke->exc_dest->idx);
r = CXX; // default
// print_ast(invoke);
// printf("\n");
AST_expr* expr = NULL;
if (invoke->stmt->type == AST_TYPE::Assign) {
expr = ast_cast<AST_Assign>(invoke->stmt)->value;
} else if (invoke->stmt->type == AST_TYPE::Expr) {
expr = ast_cast<AST_Expr>(invoke->stmt)->value;
}
if (!expr)
return r;
if (0 && expr->type == AST_TYPE::Call) {
AST_Call* call = ast_cast<AST_Call>(expr);
if (call->func->type != AST_TYPE::Attribute && call->func->type != AST_TYPE::ClsAttribute) {
r = CAPI;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
}
return r;
}
if (expr->type == AST_TYPE::Attribute) {
r = CAPI;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
return r;
}
return r;
}
......
......@@ -195,6 +195,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(createSet);
GET(getattr);
GET(getattr_capi);
GET(setattr);
GET(delattr);
GET(getitem);
......@@ -223,6 +224,8 @@ void initGlobalFuncs(GlobalState& g) {
GET(unpackIntoArray);
GET(raiseAttributeError);
GET(raiseAttributeErrorStr);
GET(raiseAttributeErrorCapi);
GET(raiseAttributeErrorStrCapi);
GET(raiseIndexErrorStr);
GET(raiseNotIterableError);
GET(assertNameDefined);
......
......@@ -35,12 +35,13 @@ struct GlobalFuncs {
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxCLFunction, *unboxCLFunction, *boxInstanceMethod,
*boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createUserClass, *createClosure,
*createGenerator, *createSet;
llvm::Value* getattr, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare, *augbinop, *unboxedLen,
*getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom, *importStar, *repr, *str,
*strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
*augbinop, *unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import, *importFrom,
*importStar, *repr, *str, *strOrUnicode, *exceptionMatches, *yield, *getiterHelper, *hasnext;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
*raiseIndexErrorStr, *assertNameDefined, *assertFail, *assertFailDerefNameDefined;
llvm::Value* unpackIntoArray, *raiseAttributeError, *raiseAttributeErrorStr, *raiseAttributeErrorCapi,
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *assertNameDefined, *assertFail,
*assertFailDerefNameDefined;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN;
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN;
......
......@@ -74,6 +74,7 @@ void force() {
FORCE(decodeUTF8StringPtr);
FORCE(getattr);
FORCE(getattr_capi);
FORCE(setattr);
FORCE(delattr);
FORCE(nonzero);
......@@ -101,6 +102,8 @@ void force() {
FORCE(unpackIntoArray);
FORCE(raiseAttributeError);
FORCE(raiseAttributeErrorStr);
FORCE(raiseAttributeErrorCapi);
FORCE(raiseAttributeErrorStrCapi);
FORCE(raiseIndexErrorStr);
FORCE(raiseNotIterableError);
FORCE(assertNameDefined);
......
......@@ -271,7 +271,12 @@ extern "C" void assertFailDerefNameDefined(const char* name) {
extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) {
assert(attr.data()[attr.size()] == '\0');
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", typeName, attr);
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", typeName, attr.data());
}
extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef attr) noexcept {
assert(attr.data()[attr.size()] == '\0');
PyErr_Format(AttributeError, "'%s' object has no attribute '%s'", typeName, attr.data());
}
extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) {
......@@ -285,6 +290,17 @@ extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) {
}
}
extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept {
if (obj->cls == type_cls) {
// Slightly different error message:
assert(attr.data()[attr.size()] == '\0');
PyErr_Format(AttributeError, "type object '%s' has no attribute '%s'",
getNameOfClass(static_cast<BoxedClass*>(obj)), attr.data());
} else {
raiseAttributeErrorStrCapi(getTypeName(obj), attr);
}
}
extern "C" void raiseIndexErrorStr(const char* typeName) {
raiseExcHelper(IndexError, "%s index out of range", typeName);
}
......@@ -1876,6 +1892,25 @@ Box* getattrMaybeNonstring(Box* obj, Box* attr) {
return r;
}
extern "C" Box* getattr_capi(Box* obj, BoxedString* attr) noexcept {
STAT_TIMER(t0, "us_timer_slowpath_getattr_capi", 10);
static StatCounter slowpath_getattr_capi("slowpath_getattr_capi");
slowpath_getattr_capi.log();
assert(!PyErr_Occurred());
Box* val = getattrInternal<CAPI>(obj, attr, NULL);
if (val)
return val;
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", obj->cls->tp_name,
PyString_AS_STRING(attr));
return NULL;
}
extern "C" Box* getattr(Box* obj, BoxedString* attr) {
STAT_TIMER(t0, "us_timer_slowpath_getattr", 10);
......@@ -1954,6 +1989,13 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) {
if (val) {
return val;
if (S == CAPI) {
if (!PyErr_Occurred())
raiseAttributeErrorCapi(obj, attr->s());
return NULL;
} else {
raiseAttributeError(obj, attr->s());
}
raiseAttributeError(obj, attr->s());
......
......@@ -55,6 +55,7 @@ extern "C" bool softspace(Box* b, bool newval);
extern "C" void printHelper(Box* dest, Box* var, bool nl);
extern "C" void my_assert(bool b);
extern "C" Box* getattr(Box* obj, BoxedString* attr);
extern "C" Box* getattr_capi(Box* obj, BoxedString* attr) noexcept;
extern "C" Box* getattrMaybeNonstring(Box* obj, Box* attr);
extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val);
extern "C" void setattrMaybeNonstring(Box* obj, Box* attr, Box* attr_val);
......@@ -153,6 +154,8 @@ Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_
extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeErrorStrCapi(const char* typeName, llvm::StringRef attr) noexcept;
extern "C" void raiseAttributeErrorCapi(Box* obj, llvm::StringRef attr) noexcept;
extern "C" void raiseNotIterableError(const char* typeName) __attribute__((__noreturn__));
extern "C" void raiseIndexErrorStr(const char* typeName) __attribute__((__noreturn__));
......
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