Commit 96febb05 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #811 from kmod/exceptions4

more capi exceptions
parents 232e05c4 26dabd18
...@@ -1260,6 +1260,12 @@ $(FROM_CPYTHON_SRCS:.c=.prof.o): %.prof.o: %.c $(BUILD_SYSTEM_DEPS) ...@@ -1260,6 +1260,12 @@ $(FROM_CPYTHON_SRCS:.c=.prof.o): %.prof.o: %.c $(BUILD_SYSTEM_DEPS)
$(ECHO) Compiling C file to $@ $(ECHO) Compiling C file to $@
$(VERB) $(CC_PROFILE) $(EXT_CFLAGS_PROFILE) -c $< -o $@ -g -MMD -MP -MF $(patsubst %.o,%.d,$@) $(VERB) $(CC_PROFILE) $(EXT_CFLAGS_PROFILE) -c $< -o $@ -g -MMD -MP -MF $(patsubst %.o,%.d,$@)
.PHONY: update_section_ordering
update_section_ordering: pyston_release
perf record -o perf_section_ordering.data -- ./pyston_release -q minibenchmarks/combined.py
$(MAKE) pyston_pgo
python tools/generate_section_ordering_from_pgo_build.py pyston_pgo perf_section_ordering.data > section_ordering.txt
rm perf_section_ordering.data
......
...@@ -460,7 +460,8 @@ struct _typeobject { ...@@ -460,7 +460,8 @@ struct _typeobject {
bool _flags[7]; bool _flags[7];
void* _tpp_descr_get; void* _tpp_descr_get;
void* _tpp_hasnext; void* _tpp_hasnext;
void* _tpp_call; void* _tpp_call_capi;
void* _tpp_call_cxx;
}; };
/* The *real* layout of a type object when allocated on the heap */ /* The *real* layout of a type object when allocated on the heap */
......
# CPython has a 2kloc version of this file # CPython has a 2kloc version of this file
from distutils.core import setup, Extension from distutils.core import setup, Extension
import glob
import os import os
import sysconfig import sysconfig
...@@ -132,5 +133,10 @@ ext_modules = [future_builtins_ext(), ...@@ -132,5 +133,10 @@ ext_modules = [future_builtins_ext(),
curses_ext(), curses_ext(),
termios_ext()] termios_ext()]
builtin_headers = map(relpath, glob.glob("Include/*.h"))
for m in ext_modules:
m.depends += builtin_headers
setup(name="Pyston", version="1.0", description="Pyston shared modules", ext_modules=ext_modules) setup(name="Pyston", version="1.0", description="Pyston shared modules", ext_modules=ext_modules)
...@@ -1068,8 +1068,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -1068,8 +1068,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
assert(PyString_CHECK_INTERNED(name) == SSTATE_INTERNED_IMMORTAL); assert(PyString_CHECK_INTERNED(name) == SSTATE_INTERNED_IMMORTAL);
crewrite_args.arg1 = rewrite_args->rewriter->loadConst((intptr_t)name, Location::forArg(1)); crewrite_args.arg1 = rewrite_args->rewriter->loadConst((intptr_t)name, Location::forArg(1));
res = callattrInternal(self, _getattr_str, LookupScope::CLASS_ONLY, &crewrite_args, ArgPassSpec(1), name, NULL, res = callattrInternal<CXX>(self, _getattr_str, LookupScope::CLASS_ONLY, &crewrite_args, ArgPassSpec(1), name,
NULL, NULL, NULL); NULL, NULL, NULL, NULL);
assert(res); assert(res);
if (!crewrite_args.out_success) if (!crewrite_args.out_success)
...@@ -1082,8 +1082,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -1082,8 +1082,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
// the rewrite_args and non-rewrite_args case the same. // the rewrite_args and non-rewrite_args case the same.
// Actually, we might have gotten to the point that doing a runtimeCall on an instancemethod is as // Actually, we might have gotten to the point that doing a runtimeCall on an instancemethod is as
// fast as a callattr, but that hasn't typically been the case. // fast as a callattr, but that hasn't typically been the case.
res = callattrInternal(self, _getattr_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1), name, NULL, NULL, res = callattrInternal<CXX>(self, _getattr_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1), name, NULL, NULL,
NULL, NULL); NULL, NULL);
assert(res); assert(res);
} }
...@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept { ...@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// We don't cache anything yet that would need to be invalidated: // We don't cache anything yet that would need to be invalidated:
} }
template <ExceptionStyle S>
static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, static Box* tppProxyToTpCall(Box* self, 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 == CAPI) {
ParamReceiveSpec paramspec(0, 0, true, true); ParamReceiveSpec paramspec(0, 0, true, true);
if (!argspec.has_kwargs && argspec.num_keywords == 0) { if (!argspec.has_kwargs && argspec.num_keywords == 0) {
paramspec.takes_kwargs = false; paramspec.takes_kwargs = false;
...@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp ...@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
bool rewrite_success = false; bool rewrite_success = false;
Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL; Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL;
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args, try {
keyword_names, oarg1, oarg2, oarg3, oargs); rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
if (!rewrite_success) if (!rewrite_success)
rewrite_args = NULL; rewrite_args = NULL;
...@@ -3213,12 +3223,13 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp ...@@ -3213,12 +3223,13 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj, rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj,
rewrite_args->arg1, rewrite_args->arg2); rewrite_args->arg1, rewrite_args->arg2);
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;
} }
Box* r = self->cls->tp_call(self, oarg1, oarg2); Box* r = self->cls->tp_call(self, oarg1, oarg2);
if (!r) if (!r && S == CXX)
throwCAPIException(); throwCAPIException();
return r; return r;
} }
...@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->tp_name); assert(cls->tp_name);
if (cls->tp_call) if (cls->tp_call) {
cls->tpp_call = tppProxyToTpCall; cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>;
cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>;
}
try { try {
add_operators(cls); add_operators(cls);
......
...@@ -43,8 +43,9 @@ public: ...@@ -43,8 +43,9 @@ public:
} }
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs); static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs, BoxedDict* kwargs);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, 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 == CAPI);
static Box* getname(Box* b, void*) { static Box* getname(Box* b, void*) {
RELEASE_ASSERT(b->cls == capifunc_cls, ""); RELEASE_ASSERT(b->cls == capifunc_cls, "");
......
...@@ -332,6 +332,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) { ...@@ -332,6 +332,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
throw e; throw e;
auto source = getCL()->source.get(); auto source = getCL()->source.get();
stmt->cxx_exception_count++;
exceptionCaughtInInterpreter(LineInfo(stmt->lineno, stmt->col_offset, source->fn, source->getName()), &e); exceptionCaughtInInterpreter(LineInfo(stmt->lineno, stmt->col_offset, source->fn, source->getName()), &e);
next_block = ((AST_Invoke*)stmt)->exc_dest; next_block = ((AST_Invoke*)stmt)->exc_dest;
...@@ -764,6 +765,7 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) { ...@@ -764,6 +765,7 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
abortJITing(); abortJITing();
auto source = getCL()->source.get(); auto source = getCL()->source.get();
node->cxx_exception_count++;
exceptionCaughtInInterpreter(LineInfo(node->lineno, node->col_offset, source->fn, source->getName()), &e); exceptionCaughtInInterpreter(LineInfo(node->lineno, node->col_offset, source->fn, source->getName()), &e);
next_block = node->exc_dest; next_block = node->exc_dest;
......
...@@ -613,7 +613,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -613,7 +613,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
// for (auto a : llvm_args) // for (auto a : llvm_args)
// a->dump(); // a->dump();
bool do_patchpoint = ENABLE_ICCALLSITES && (func_addr == runtimeCall || 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) { if (do_patchpoint) {
assert(func_addr); assert(func_addr);
...@@ -655,26 +656,32 @@ CompilerVariable* UnknownType::call(IREmitter& emitter, const OpInfo& info, Conc ...@@ -655,26 +656,32 @@ CompilerVariable* UnknownType::call(IREmitter& emitter, const OpInfo& info, Conc
bool pass_keywords = (argspec.num_keywords != 0); bool pass_keywords = (argspec.num_keywords != 0);
int npassed_args = argspec.totalPassed(); int npassed_args = argspec.totalPassed();
ExceptionStyle exception_style = ((FORCE_LLVM_CAPI && !info.unw_info.cxx_exc_dest) || info.unw_info.capi_exc_dest)
? ExceptionStyle::CAPI
: ExceptionStyle::CXX;
llvm::Value* func; llvm::Value* func;
if (pass_keywords) if (pass_keywords)
func = g.funcs.runtimeCall; func = g.funcs.runtimeCall.get(exception_style);
else if (npassed_args == 0) else if (npassed_args == 0)
func = g.funcs.runtimeCall0; func = g.funcs.runtimeCall0.get(exception_style);
else if (npassed_args == 1) else if (npassed_args == 1)
func = g.funcs.runtimeCall1; func = g.funcs.runtimeCall1.get(exception_style);
else if (npassed_args == 2) else if (npassed_args == 2)
func = g.funcs.runtimeCall2; func = g.funcs.runtimeCall2.get(exception_style);
else if (npassed_args == 3) else if (npassed_args == 3)
func = g.funcs.runtimeCall3; func = g.funcs.runtimeCall3.get(exception_style);
else else
func = g.funcs.runtimeCallN; func = g.funcs.runtimeCallN.get(exception_style);
void* func_ptr = (exception_style == ExceptionStyle::CXX) ? (void*)runtimeCall : (void*)runtimeCallCapi;
std::vector<llvm::Value*> other_args; std::vector<llvm::Value*> other_args;
other_args.push_back(var->getValue()); other_args.push_back(var->getValue());
llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false); llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false);
other_args.push_back(llvm_argspec); other_args.push_back(llvm_argspec);
return _call(emitter, info, func, CXX, (void*)runtimeCall, other_args, argspec, args, keyword_names, UNKNOWN); return _call(emitter, info, func, exception_style, func_ptr, other_args, argspec, args, keyword_names, UNKNOWN);
} }
CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
...@@ -684,25 +691,35 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info, ...@@ -684,25 +691,35 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
bool pass_keywords = (flags.argspec.num_keywords != 0); bool pass_keywords = (flags.argspec.num_keywords != 0);
int npassed_args = flags.argspec.totalPassed(); 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; llvm::Value* func;
if (pass_keywords) if (pass_keywords)
func = g.funcs.callattr; func = g.funcs.callattr.get(exception_style);
else if (npassed_args == 0) else if (npassed_args == 0)
func = g.funcs.callattr0; func = g.funcs.callattr0.get(exception_style);
else if (npassed_args == 1) else if (npassed_args == 1)
func = g.funcs.callattr1; func = g.funcs.callattr1.get(exception_style);
else if (npassed_args == 2) else if (npassed_args == 2)
func = g.funcs.callattr2; func = g.funcs.callattr2.get(exception_style);
else if (npassed_args == 3) else if (npassed_args == 3)
func = g.funcs.callattr3; func = g.funcs.callattr3.get(exception_style);
else 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; std::vector<llvm::Value*> other_args;
other_args.push_back(var->getValue()); other_args.push_back(var->getValue());
other_args.push_back(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr)); other_args.push_back(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr));
other_args.push_back(getConstantInt(flags.asInt(), g.i64)); 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); UNKNOWN);
} }
...@@ -1700,8 +1717,14 @@ public: ...@@ -1700,8 +1717,14 @@ public:
CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr, CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, BoxedString* attr,
CallattrFlags flags, const std::vector<CompilerVariable*>& args, CallattrFlags flags, const std::vector<CompilerVariable*>& args,
const std::vector<BoxedString*>* keyword_names) override { const std::vector<BoxedString*>* keyword_names) override {
ConcreteCompilerVariable* called_constant ExceptionStyle exception_style = CXX;
= tryCallattrConstant(emitter, info, var, attr, flags.cls_only, flags.argspec, args, keyword_names); // 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) if (called_constant)
return called_constant; return called_constant;
......
...@@ -107,13 +107,23 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) { ...@@ -107,13 +107,23 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
r = CXX; // default r = CXX; // default
assert(invoke->stmt->cxx_exception_count == 0); // could be ok but would be unexpected
// First, check if we think it makes sense:
bool should = (invoke->cxx_exception_count >= 10 || invoke->stmt->type == AST_TYPE::Raise);
if (!should)
return r;
// Second, check if we are able to do it:
// (not all code paths support capi exceptions yet)
if (invoke->stmt->type == AST_TYPE::Raise) { if (invoke->stmt->type == AST_TYPE::Raise) {
AST_Raise* raise_stmt = ast_cast<AST_Raise>(invoke->stmt); AST_Raise* raise_stmt = ast_cast<AST_Raise>(invoke->stmt);
// Currently can't do a re-raise with a capi exception: // Currently can't do a re-raise with a capi exception:
if (raise_stmt->arg0 && !raise_stmt->arg2) { if (raise_stmt->arg0 && !raise_stmt->arg2)
r = CAPI; r = CAPI;
return r; else
} r = CXX;
return r;
} }
AST_expr* expr = NULL; AST_expr* expr = NULL;
...@@ -127,21 +137,18 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) { ...@@ -127,21 +137,18 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
if (!expr) if (!expr)
return r; return r;
if (0 && expr->type == AST_TYPE::Call) { if (expr->type == AST_TYPE::Call) {
AST_Call* call = ast_cast<AST_Call>(expr); r = CAPI;
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; return r;
} }
if (expr->type == AST_TYPE::Attribute || expr->type == AST_TYPE::Subscript) { 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);
return r; return r;
} }
// Some expression type we haven't added yet -- might be worth looking into.
r = CXX;
return r; return r;
} }
...@@ -488,8 +495,7 @@ public: ...@@ -488,8 +495,7 @@ public:
llvm::BasicBlock* exc_dest; llvm::BasicBlock* exc_dest;
bool exc_caught; bool exc_caught;
if (unw_info.hasHandler()) { if (unw_info.capi_exc_dest) {
assert(unw_info.capi_exc_dest);
exc_dest = unw_info.capi_exc_dest; exc_dest = unw_info.capi_exc_dest;
exc_caught = true; exc_caught = true;
} else { } else {
...@@ -508,7 +514,13 @@ public: ...@@ -508,7 +514,13 @@ public:
embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr)); embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr));
if (!exc_caught) { if (!exc_caught) {
getBuilder()->CreateCall(g.funcs.reraiseJitCapiExc); if (unw_info.cxx_exc_dest) {
// TODO: I'm not sure this gets the tracebacks quite right. this is only for testing though:
assert(FORCE_LLVM_CAPI && "this shouldn't happen in non-FORCE mode");
createCall(unw_info, g.funcs.reraiseJitCapiExc);
} else {
getBuilder()->CreateCall(g.funcs.reraiseJitCapiExc);
}
getBuilder()->CreateUnreachable(); getBuilder()->CreateUnreachable();
} }
...@@ -2429,8 +2441,11 @@ private: ...@@ -2429,8 +2441,11 @@ private:
if (landingpad_style == CXX) if (landingpad_style == CXX)
doStmt(invoke->stmt, UnwindInfo(node, NULL, entry_blocks[invoke->exc_dest])); doStmt(invoke->stmt, UnwindInfo(node, NULL, entry_blocks[invoke->exc_dest]));
else else {
// print_ast(invoke);
// printf(" (%d exceptions)\n", invoke->cxx_exception_count);
doStmt(invoke->stmt, UnwindInfo(node, entry_blocks[invoke->exc_dest], NULL)); doStmt(invoke->stmt, UnwindInfo(node, entry_blocks[invoke->exc_dest], NULL));
}
assert(state == RUNNING || state == DEAD); assert(state == RUNNING || state == DEAD);
if (state == RUNNING) { if (state == RUNNING) {
......
...@@ -245,31 +245,62 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -245,31 +245,62 @@ void initGlobalFuncs(GlobalState& g) {
GET(boxedLocalsGet); GET(boxedLocalsGet);
GET(boxedLocalsDel); GET(boxedLocalsDel);
g.funcs.runtimeCall = getFunc((void*)runtimeCall, "runtimeCall"); g.funcs.runtimeCall.cxx_val = getFunc((void*)runtimeCall, "runtimeCall");
g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32); g.funcs.runtimeCall0.cxx_val = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
g.funcs.runtimeCall1 g.funcs.runtimeCall1.cxx_val
= addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr); = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr);
g.funcs.runtimeCall2 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.funcs.runtimeCall2.cxx_val = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCall3 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.funcs.runtimeCall3.cxx_val = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr); g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCallN g.funcs.runtimeCallN.cxx_val
= addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr, = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo()); 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.runtimeCall.capi_val = getFunc((void*)runtimeCallCapi, "runtimeCallCapi");
g.funcs.callattr0 g.funcs.runtimeCall0.capi_val
= addFunc((void*)runtimeCallCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
g.funcs.runtimeCall1.capi_val
= addFunc((void*)runtimeCallCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr);
g.funcs.runtimeCall2.capi_val = addFunc((void*)runtimeCallCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCall3.capi_val = addFunc((void*)runtimeCallCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCallN.capi_val
= addFunc((void*)runtimeCallCapi, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr->getPointerTo());
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); = 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.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.funcs.callattr2.cxx_val
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_boxedstring_type_ptr, g.i64, = 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.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.funcs.callattrN.capi_val = addFunc(
g.llvm_boxedstring_type_ptr, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr, (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->getPointerTo()); 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.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr); g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
......
...@@ -43,8 +43,8 @@ struct GlobalFuncs { ...@@ -43,8 +43,8 @@ struct GlobalFuncs {
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi, *raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
*assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper; *assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout; llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN; 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* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* exec; llvm::Value* exec;
llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel; llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel;
......
...@@ -536,6 +536,8 @@ public: ...@@ -536,6 +536,8 @@ public:
exc_info.reraise = false; exc_info.reraise = false;
return; return;
} }
// TODO: shouldn't fetch this multiple times?
frame_iter.getCurrentStatement()->cxx_exception_count++;
auto line_info = lineInfoForFrame(&frame_iter); auto line_info = lineInfoForFrame(&frame_iter);
BoxedTraceback::here(line_info, &exc_info.traceback); BoxedTraceback::here(line_info, &exc_info.traceback);
} }
......
...@@ -182,6 +182,8 @@ class AST_stmt : public AST { ...@@ -182,6 +182,8 @@ class AST_stmt : public AST {
public: public:
virtual void accept_stmt(StmtVisitor* v) = 0; virtual void accept_stmt(StmtVisitor* v) = 0;
int cxx_exception_count = 0;
AST_stmt(AST_TYPE::AST_TYPE type) : AST(type) {} AST_stmt(AST_TYPE::AST_TYPE type) : AST(type) {}
}; };
......
...@@ -457,11 +457,23 @@ Box* delattrFunc(Box* obj, Box* _str) { ...@@ -457,11 +457,23 @@ Box* delattrFunc(Box* obj, Box* _str) {
return None; return None;
} }
Box* getattrFunc(Box* obj, Box* _str, Box* default_value) { template <ExceptionStyle S> Box* getattrFunc(Box* obj, Box* _str, Box* default_value) noexcept(S == CAPI) {
_str = coerceUnicodeToStr(_str); try {
_str = coerceUnicodeToStr(_str);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
if (!isSubclass(_str->cls, str_cls)) { if (!isSubclass(_str->cls, str_cls)) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string"); if (S == CAPI) {
PyErr_SetString(TypeError, "getattr(): attribute name must be string");
return NULL;
} else
raiseExcHelper(TypeError, "getattr(): attribute name must be string");
} }
Box* rtn = PyObject_GetAttr(obj, _str); Box* rtn = PyObject_GetAttr(obj, _str);
...@@ -470,7 +482,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) { ...@@ -470,7 +482,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
return default_value; return default_value;
} }
if (!rtn) if (S == CXX && !rtn)
throwCAPIException(); throwCAPIException();
return rtn; return rtn;
} }
...@@ -1437,9 +1449,9 @@ void setupBuiltins() { ...@@ -1437,9 +1449,9 @@ void setupBuiltins() {
builtins_module->giveAttr("delattr", builtins_module->giveAttr("delattr",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)delattrFunc, NONE, 2), "delattr")); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)delattrFunc, NONE, 2), "delattr"));
builtins_module->giveAttr( auto getattr_func = boxRTFunction((void*)getattrFunc<CXX>, UNKNOWN, 3, 1, false, false, ParamNames::empty(), CXX);
"getattr", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)getattrFunc, UNKNOWN, 3, 1, false, false), addRTFunction(getattr_func, (void*)getattrFunc<CAPI>, UNKNOWN, CAPI);
"getattr", { NULL })); builtins_module->giveAttr("getattr", new BoxedBuiltinFunctionOrMethod(getattr_func, "getattr", { NULL }));
builtins_module->giveAttr( builtins_module->giveAttr(
"setattr", "setattr",
......
...@@ -1476,11 +1476,23 @@ Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, B ...@@ -1476,11 +1476,23 @@ Box* BoxedCApiFunction::__call__(BoxedCApiFunction* self, BoxedTuple* varargs, B
// Kind of silly to have asked callFunc to rearrange the arguments for us, just to pass things // Kind of silly to have asked callFunc to rearrange the arguments for us, just to pass things
// off to tppCall, but this case should be very uncommon (people explicitly asking for __call__) // off to tppCall, but this case should be very uncommon (people explicitly asking for __call__)
return BoxedCApiFunction::tppCall(self, NULL, ArgPassSpec(0, 0, true, true), varargs, kwargs, NULL, NULL, NULL); return BoxedCApiFunction::tppCall<CXX>(self, NULL, ArgPassSpec(0, 0, true, true), varargs, kwargs, NULL, NULL,
NULL);
} }
template <ExceptionStyle S>
Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* BoxedCApiFunction::tppCall(Box* _self, 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 == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10); STAT_TIMER(t0, "us_timer_boxedcapifunction__call__", 10);
assert(_self->cls == capifunc_cls); assert(_self->cls == capifunc_cls);
...@@ -1634,7 +1646,8 @@ void setupCAPI() { ...@@ -1634,7 +1646,8 @@ void setupCAPI() {
auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true)); auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true));
capifunc_cls->giveAttr("__call__", capi_call); capifunc_cls->giveAttr("__call__", capi_call);
capifunc_cls->tpp_call = BoxedCApiFunction::tppCall; capifunc_cls->tpp_call.capi_val = BoxedCApiFunction::tppCall<CAPI>;
capifunc_cls->tpp_call.cxx_val = BoxedCApiFunction::tppCall<CXX>;
capifunc_cls->giveAttr("__name__", capifunc_cls->giveAttr("__name__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL)); new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr("__doc__", capifunc_cls->giveAttr("__doc__",
......
...@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) { ...@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
// TODO this should be auto-generated as a slot wrapper: // TODO this should be auto-generated as a slot wrapper:
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) { Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]); BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
return BoxedMethodDescriptor::tppCall(self, NULL, ArgPassSpec(1, 0, true, true), obj, varargs, kwargs, NULL, NULL); return BoxedMethodDescriptor::tppCall<CXX>(self, NULL, ArgPassSpec(1, 0, true, true), obj, varargs, kwargs, NULL,
NULL);
} }
template <ExceptionStyle S>
Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10); STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10);
assert(_self->cls == method_cls); assert(_self->cls == method_cls);
...@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds ...@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds
return rtn; return rtn;
} }
template <ExceptionStyle S>
Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* BoxedWrapperObject::tppCall(Box* _self, 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 == CAPI) {
if (S == CAPI) {
try {
return tppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
STAT_TIMER(t0, "us_timer_boxedwrapperobject_call", (_self->cls->is_user_defined ? 10 : 20)); STAT_TIMER(t0, "us_timer_boxedwrapperobject_call", (_self->cls->is_user_defined ? 10 : 20));
assert(_self->cls == wrapperobject_cls); assert(_self->cls == wrapperobject_cls);
...@@ -617,7 +640,8 @@ void setupDescr() { ...@@ -617,7 +640,8 @@ void setupDescr() {
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true); CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true);
method_cls->giveAttr("__call__", new BoxedFunction(method_call_cl)); method_cls->giveAttr("__call__", new BoxedFunction(method_call_cl));
method_cls->tpp_call = BoxedMethodDescriptor::tppCall; method_cls->tpp_call.capi_val = BoxedMethodDescriptor::tppCall<CAPI>;
method_cls->tpp_call.cxx_val = BoxedMethodDescriptor::tppCall<CXX>;
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL)); method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze(); method_cls->freeze();
...@@ -632,7 +656,8 @@ void setupDescr() { ...@@ -632,7 +656,8 @@ void setupDescr() {
wrapperobject_cls->giveAttr( wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->tpp_call = BoxedWrapperObject::tppCall; wrapperobject_cls->tpp_call.capi_val = BoxedWrapperObject::tppCall<CAPI>;
wrapperobject_cls->tpp_call.cxx_val = BoxedWrapperObject::tppCall<CXX>;
wrapperobject_cls->freeze(); wrapperobject_cls->freeze();
} }
......
...@@ -627,9 +627,17 @@ std::string floatFmt(double x, int precision, char code) { ...@@ -627,9 +627,17 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n); return std::string(buf, n);
} }
BoxedFloat* _floatNew(Box* a) { template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == CAPI) {
// FIXME CPython uses PyUnicode_EncodeDecimal: // FIXME CPython uses PyUnicode_EncodeDecimal:
a = coerceUnicodeToStr(a); try {
a = coerceUnicodeToStr(a);
} catch (ExcInfo e) {
if (S == CAPI) {
throwCAPIException();
return NULL;
}
throw e;
}
if (a->cls == float_cls) { if (a->cls == float_cls) {
return static_cast<BoxedFloat*>(a); return static_cast<BoxedFloat*>(a);
...@@ -653,40 +661,70 @@ BoxedFloat* _floatNew(Box* a) { ...@@ -653,40 +661,70 @@ BoxedFloat* _floatNew(Box* a) {
assert(s.data()[s.size()] == '\0'); assert(s.data()[s.size()] == '\0');
const char* startptr = s.data(); const char* startptr = s.data();
double r = strtod(startptr, &endptr); double r = strtod(startptr, &endptr);
if (endptr != startptr + s.size()) if (endptr != startptr + s.size()) {
raiseExcHelper(ValueError, "could not convert string to float: %s", s.data()); if (S == CAPI) {
PyErr_Format(ValueError, "could not convert string to float: %s", s.data());
return NULL;
} else
raiseExcHelper(ValueError, "could not convert string to float: %s", s.data());
}
return new BoxedFloat(r); return new BoxedFloat(r);
} else { } else {
static BoxedString* float_str = internStringImmortal("__float__"); static BoxedString* float_str = internStringImmortal("__float__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) }; Box* r = callattrInternal<S>(a, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
Box* r = callattr(a, float_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
if (!r) { if (!r) {
fprintf(stderr, "TypeError: float() argument must be a string or a number, not '%s'\n", getTypeName(a)); if (S == CAPI) {
raiseExcHelper(TypeError, ""); if (!PyErr_Occurred())
PyErr_Format(TypeError, "float() argument must be a string or a number, not '%s'\n",
getTypeName(a));
return NULL;
} else {
raiseExcHelper(TypeError, "float() argument must be a string or a number, not '%s'\n", getTypeName(a));
}
} }
if (!isSubclass(r->cls, float_cls)) { if (!isSubclass(r->cls, float_cls)) {
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name); if (S == CAPI) {
PyErr_Format(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
return NULL;
} else
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
} }
return static_cast<BoxedFloat*>(r); return static_cast<BoxedFloat*>(r);
} }
} }
Box* floatNew(BoxedClass* _cls, Box* a) { template <ExceptionStyle S> Box* floatNew(BoxedClass* _cls, Box* a) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_cls)) if (!isSubclass(_cls->cls, type_cls)) {
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls)); if (S == CAPI) {
PyErr_Format(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls));
return NULL;
} else
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls));
}
BoxedClass* cls = static_cast<BoxedClass*>(_cls); BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, float_cls)) if (!isSubclass(cls, float_cls)) {
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls), if (S == CAPI) {
getNameOfClass(cls)); PyErr_Format(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls),
getNameOfClass(cls));
return NULL;
} else {
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls),
getNameOfClass(cls));
}
}
if (cls == float_cls) if (cls == float_cls)
return _floatNew(a); return _floatNew<S>(a);
BoxedFloat* f = _floatNew(a); BoxedFloat* f = _floatNew<S>(a);
if (!f) {
assert(S == CAPI);
return NULL;
}
return new (cls) BoxedFloat(f->d); return new (cls) BoxedFloat(f->d);
} }
...@@ -1476,8 +1514,9 @@ void setupFloat() { ...@@ -1476,8 +1514,9 @@ void setupFloat() {
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub); _addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub); _addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
float_cls->giveAttr( auto float_new = boxRTFunction((void*)floatNew<CXX>, UNKNOWN, 2, 1, false, false, ParamNames::empty(), CXX);
"__new__", new BoxedFunction(boxRTFunction((void*)floatNew, UNKNOWN, 2, 1, false, false), { boxFloat(0.0) })); addRTFunction(float_new, (void*)floatNew<CAPI>, UNKNOWN, CAPI);
float_cls->giveAttr("__new__", new BoxedFunction(float_new, { boxFloat(0.0) }));
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, BOXED_FLOAT, 1))); float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, BOXED_FLOAT, 1)));
float_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)floatPos, BOXED_FLOAT, 1))); float_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)floatPos, BOXED_FLOAT, 1)));
......
...@@ -120,7 +120,9 @@ void force() { ...@@ -120,7 +120,9 @@ void force() {
FORCE(getSysStdout); FORCE(getSysStdout);
FORCE(runtimeCall); FORCE(runtimeCall);
FORCE(runtimeCallCapi);
FORCE(callattr); FORCE(callattr);
FORCE(callattrCapi);
FORCE(raise0); FORCE(raise0);
FORCE(raise3); FORCE(raise3);
......
...@@ -884,7 +884,7 @@ extern "C" Box* intIndex(BoxedInt* v) { ...@@ -884,7 +884,7 @@ extern "C" Box* intIndex(BoxedInt* v) {
return boxInt(v->n); return boxInt(v->n);
} }
static Box* _intNew(Box* val, Box* base) { template <ExceptionStyle S> static Box* _intNew(Box* val, Box* base) noexcept(S == CAPI) {
if (val->cls == int_cls) { if (val->cls == int_cls) {
RELEASE_ASSERT(!base, ""); RELEASE_ASSERT(!base, "");
BoxedInt* n = static_cast<BoxedInt*>(val); BoxedInt* n = static_cast<BoxedInt*>(val);
...@@ -904,8 +904,12 @@ static Box* _intNew(Box* val, Box* base) { ...@@ -904,8 +904,12 @@ static Box* _intNew(Box* val, Box* base) {
RELEASE_ASSERT(s->size() == strlen(s->data()), ""); RELEASE_ASSERT(s->size() == strlen(s->data()), "");
Box* r = PyInt_FromString(s->data(), NULL, base_n); Box* r = PyInt_FromString(s->data(), NULL, base_n);
if (!r) if (!r) {
throwCAPIException(); if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r; return r;
} else if (isSubclass(val->cls, unicode_cls)) { } else if (isSubclass(val->cls, unicode_cls)) {
int base_n; int base_n;
...@@ -917,8 +921,12 @@ static Box* _intNew(Box* val, Box* base) { ...@@ -917,8 +921,12 @@ static Box* _intNew(Box* val, Box* base) {
} }
Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n); Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n);
if (!r) if (!r) {
throwCAPIException(); if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r; return r;
} else if (val->cls == float_cls) { } else if (val->cls == float_cls) {
RELEASE_ASSERT(!base, ""); RELEASE_ASSERT(!base, "");
...@@ -952,39 +960,68 @@ static Box* _intNew(Box* val, Box* base) { ...@@ -952,39 +960,68 @@ static Box* _intNew(Box* val, Box* base) {
} else { } else {
RELEASE_ASSERT(!base, ""); RELEASE_ASSERT(!base, "");
static BoxedString* int_str = internStringImmortal("__int__"); static BoxedString* int_str = internStringImmortal("__int__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) }; Box* r = callattrInternal<S>(val, int_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
Box* r = callattr(val, int_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
if (!r) { if (!r) {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val)); if (S == CAPI) {
raiseExcHelper(TypeError, ""); if (!PyErr_Occurred())
PyErr_Format(TypeError, "int() argument must be a string or a number, not '%s'\n",
getTypeName(val));
return NULL;
} else {
raiseExcHelper(TypeError, "int() argument must be a string or a number, not '%s'\n", getTypeName(val));
}
} }
if (!isSubclass(r->cls, int_cls) && !isSubclass(r->cls, long_cls)) { if (!PyInt_Check(r) && !PyLong_Check(r)) {
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name); if (S == CAPI) {
PyErr_Format(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
return NULL;
} else
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
} }
return r; return r;
} }
} }
extern "C" Box* intNew(Box* _cls, Box* val, Box* base) { template <ExceptionStyle S> Box* intNew(Box* _cls, Box* val, Box* base) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_cls)) if (!isSubclass(_cls->cls, type_cls)) {
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)); if (S == CAPI) {
PyErr_Format(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
return NULL;
} else
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
}
BoxedClass* cls = static_cast<BoxedClass*>(_cls); BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, int_cls)) if (!isSubclass(cls, int_cls)) {
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls), if (S == CAPI) {
getNameOfClass(cls)); PyErr_Format(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls),
getNameOfClass(cls));
return NULL;
} else
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls),
getNameOfClass(cls));
}
if (cls == int_cls) if (cls == int_cls)
return _intNew(val, base); return _intNew<S>(val, base);
BoxedInt* n = (BoxedInt*)_intNew<S>(val, base);
if (!n) {
assert(S == CAPI);
return NULL;
}
BoxedInt* n = (BoxedInt*)_intNew(val, base);
if (n->cls == long_cls) { if (n->cls == long_cls) {
if (cls == int_cls) if (cls == int_cls)
return n; return n;
raiseExcHelper(OverflowError, "Python int too large to convert to C long", getNameOfClass(cls),
getNameOfClass(cls)); if (S == CAPI) {
PyErr_Format(OverflowError, "Python int too large to convert to C long");
return NULL;
} else
raiseExcHelper(OverflowError, "Python int too large to convert to C long");
} }
return new (cls) BoxedInt(n->n); return new (cls) BoxedInt(n->n);
} }
...@@ -1138,9 +1175,10 @@ void setupInt() { ...@@ -1138,9 +1175,10 @@ void setupInt() {
int_cls->giveAttr("__index__", new BoxedFunction(boxRTFunction((void*)intIndex, BOXED_INT, 1))); int_cls->giveAttr("__index__", new BoxedFunction(boxRTFunction((void*)intIndex, BOXED_INT, 1)));
int_cls->giveAttr("__int__", new BoxedFunction(boxRTFunction((void*)intInt, BOXED_INT, 1))); int_cls->giveAttr("__int__", new BoxedFunction(boxRTFunction((void*)intInt, BOXED_INT, 1)));
int_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)intNew, UNKNOWN, 3, 2, false, false, auto int_new
ParamNames({ "", "x", "base" }, "", "")), = boxRTFunction((void*)intNew<CXX>, UNKNOWN, 3, 2, false, false, ParamNames({ "", "x", "base" }, "", ""), CXX);
{ boxInt(0), NULL })); addRTFunction(int_new, (void*)intNew<CAPI>, UNKNOWN, CAPI);
int_cls->giveAttr("__new__", new BoxedFunction(int_new, { boxInt(0), NULL }));
int_cls->giveAttr("bit_length", new BoxedFunction(boxRTFunction((void*)intBitLength, BOXED_INT, 1))); int_cls->giveAttr("bit_length", new BoxedFunction(boxRTFunction((void*)intBitLength, BOXED_INT, 1)));
......
This diff is collapsed.
...@@ -65,7 +65,10 @@ extern "C" void delattrMaybeNonstring(Box* obj, Box* attr); ...@@ -65,7 +65,10 @@ extern "C" void delattrMaybeNonstring(Box* obj, Box* attr);
extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs* rewrite_args); extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs* rewrite_args);
extern "C" bool nonzero(Box* obj); extern "C" bool nonzero(Box* obj);
extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<BoxedString*>*); 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* 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* str(Box* obj);
extern "C" BoxedString* repr(Box* obj); extern "C" BoxedString* repr(Box* obj);
extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception
...@@ -132,9 +135,10 @@ enum LookupScope { ...@@ -132,9 +135,10 @@ enum LookupScope {
INST_ONLY = 2, INST_ONLY = 2,
CLASS_OR_INST = 3, CLASS_OR_INST = 3,
}; };
extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallRewriteArgs* rewrite_args, template <ExceptionStyle S>
ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
const std::vector<BoxedString*>* keyword_names); Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
extern "C" void delattr_internal(Box* obj, BoxedString* attr, bool allow_custom, DelattrRewriteArgs* rewrite_args); extern "C" void delattr_internal(Box* obj, BoxedString* attr, bool allow_custom, DelattrRewriteArgs* rewrite_args);
struct CompareRewriteArgs; struct CompareRewriteArgs;
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args); Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
......
...@@ -143,7 +143,7 @@ template <ExceptionStyle S> Box* tupleGetitem(BoxedTuple* self, Box* slice) { ...@@ -143,7 +143,7 @@ template <ExceptionStyle S> Box* tupleGetitem(BoxedTuple* self, Box* slice) {
} }
} }
assert(self->cls == tuple_cls); assert(isSubclass(self->cls, tuple_cls));
if (PyIndex_Check(slice)) { if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError); Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
......
This diff is collapsed.
...@@ -242,9 +242,8 @@ public: ...@@ -242,9 +242,8 @@ public:
pyston_inquiry tpp_hasnext; pyston_inquiry tpp_hasnext;
typedef Box* (*pyston_call)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**, ExceptionSwitchableFunction<Box*, Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*); const std::vector<BoxedString*>*> tpp_call;
pyston_call tpp_call;
bool hasGenericGetattr() { bool hasGenericGetattr() {
if (tp_getattr || tp_getattro != object_cls->tp_getattro) if (tp_getattr || tp_getattro != object_cls->tp_getattro)
...@@ -985,8 +984,9 @@ public: ...@@ -985,8 +984,9 @@ public:
DEFAULT_CLASS(wrapperobject_cls); DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds); static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, 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 == CAPI);
static void gcHandler(GCVisitor* v, Box* _o); static void gcHandler(GCVisitor* v, Box* _o);
}; };
...@@ -1001,12 +1001,12 @@ public: ...@@ -1001,12 +1001,12 @@ public:
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner); static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner);
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args); static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
template <ExceptionStyle S>
static Box* tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, static Box* tppCall(Box* _self, 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 == CAPI);
static void gcHandler(GCVisitor* v, Box* _o); static void gcHandler(GCVisitor* v, Box* _o);
}; };
Box* objectNewNoArgs(BoxedClass* cls);
Box* objectSetattr(Box* obj, Box* attr, Box* value); Box* objectSetattr(Box* obj, Box* attr, Box* value);
Box* unwrapAttrWrapper(Box* b); Box* unwrapAttrWrapper(Box* b);
......
...@@ -41,11 +41,11 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64* ...@@ -41,11 +41,11 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64*
throwCAPIException(); throwCAPIException();
} }
bool isSliceIndex(Box* b) { bool isSliceIndex(Box* b) noexcept {
return b->cls == none_cls || b->cls == int_cls || PyIndex_Check(b); return b->cls == none_cls || b->cls == int_cls || PyIndex_Check(b);
} }
void adjustNegativeIndicesOnObject(Box* obj, i64* start_out, i64* stop_out) { void adjustNegativeIndicesOnObject(Box* obj, i64* start_out, i64* stop_out) noexcept {
i64 start = *start_out; i64 start = *start_out;
i64 stop = *stop_out; i64 stop = *stop_out;
PySequenceMethods* m; PySequenceMethods* m;
......
...@@ -36,9 +36,9 @@ inline void sliceIndex(Box* b, int64_t* out) { ...@@ -36,9 +36,9 @@ inline void sliceIndex(Box* b, int64_t* out) {
throwCAPIException(); throwCAPIException();
} }
bool isSliceIndex(Box* b); bool isSliceIndex(Box* b) noexcept;
void adjustNegativeIndicesOnObject(Box* obj, i64* start, i64* stop); void adjustNegativeIndicesOnObject(Box* obj, i64* start, i64* stop) noexcept;
// Adjust the start and stop bounds of the sequence we are slicing to its size. // Adjust the start and stop bounds of the sequence we are slicing to its size.
// Ensure stop >= start and remain within bounds. // Ensure stop >= start and remain within bounds.
......
from distutils.core import setup, Extension from distutils.core import setup, Extension
import glob
import os
extensions = [
Extension("basic_test", sources = ["basic_test.c"]),
Extension("descr_test", sources = ["descr_test.c"]),
Extension("slots_test", sources = ["slots_test.c"]),
]
def relpath(fn):
r = os.path.join(os.path.dirname(__file__), fn)
return r
print glob.glob("../from_cpython/Include/*.h")
builtin_headers = map(relpath, glob.glob("../../from_cpython/Include/*.h"))
for m in extensions:
m.depends += builtin_headers
setup(name="test", setup(name="test",
version="1.0", version="1.0",
description="test", description="test",
ext_modules=[ ext_modules=extensions,
Extension("basic_test", sources = ["basic_test.c"]),
Extension("descr_test", sources = ["descr_test.c"]),
Extension("slots_test", sources = ["slots_test.c"]),
],
) )
# run_args: -n # run_args: -n
# statcheck: 1 <= noninit_count("slowpath_runtimecall") < 20 # statcheck: 1 <= noninit_count("slowpath_runtimecall") + noninit_count("slowpath_runtimecall_capi") < 20
# Make sure we can patch some basic varargs cases # Make sure we can patch some basic varargs cases
......
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