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)
$(ECHO) Compiling C file to $@
$(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 {
bool _flags[7];
void* _tpp_descr_get;
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 */
......
# CPython has a 2kloc version of this file
from distutils.core import setup, Extension
import glob
import os
import sysconfig
......@@ -132,5 +133,10 @@ ext_modules = [future_builtins_ext(),
curses_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)
......@@ -1068,8 +1068,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
assert(PyString_CHECK_INTERNED(name) == SSTATE_INTERNED_IMMORTAL);
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,
NULL, NULL, NULL);
res = callattrInternal<CXX>(self, _getattr_str, LookupScope::CLASS_ONLY, &crewrite_args, ArgPassSpec(1), name,
NULL, NULL, NULL, NULL);
assert(res);
if (!crewrite_args.out_success)
......@@ -1082,8 +1082,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
// 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
// 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,
NULL, NULL);
res = callattrInternal<CXX>(self, _getattr_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1), name, NULL, NULL,
NULL, NULL);
assert(res);
}
......@@ -3184,8 +3184,10 @@ extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// 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,
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);
if (!argspec.has_kwargs && argspec.num_keywords == 0) {
paramspec.takes_kwargs = false;
......@@ -3193,8 +3195,16 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
bool rewrite_success = false;
Box* oarg1, * oarg2 = NULL, *oarg3, ** oargs = NULL;
rearrangeArguments(paramspec, NULL, "", NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args,
keyword_names, oarg1, oarg2, oarg3, oargs);
try {
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)
rewrite_args = NULL;
......@@ -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->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;
}
Box* r = self->cls->tp_call(self, oarg1, oarg2);
if (!r)
if (!r && S == CXX)
throwCAPIException();
return r;
}
......@@ -3267,8 +3278,10 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->tp_name);
if (cls->tp_call)
cls->tpp_call = tppProxyToTpCall;
if (cls->tp_call) {
cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>;
cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>;
}
try {
add_operators(cls);
......
......@@ -43,8 +43,9 @@ public:
}
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,
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*) {
RELEASE_ASSERT(b->cls == capifunc_cls, "");
......
......@@ -332,6 +332,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
throw e;
auto source = getCL()->source.get();
stmt->cxx_exception_count++;
exceptionCaughtInInterpreter(LineInfo(stmt->lineno, stmt->col_offset, source->fn, source->getName()), &e);
next_block = ((AST_Invoke*)stmt)->exc_dest;
......@@ -764,6 +765,7 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
abortJITing();
auto source = getCL()->source.get();
node->cxx_exception_count++;
exceptionCaughtInInterpreter(LineInfo(node->lineno, node->col_offset, source->fn, source->getName()), &e);
next_block = node->exc_dest;
......
......@@ -613,7 +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 == 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);
......@@ -655,26 +656,32 @@ CompilerVariable* UnknownType::call(IREmitter& emitter, const OpInfo& info, Conc
bool pass_keywords = (argspec.num_keywords != 0);
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;
if (pass_keywords)
func = g.funcs.runtimeCall;
func = g.funcs.runtimeCall.get(exception_style);
else if (npassed_args == 0)
func = g.funcs.runtimeCall0;
func = g.funcs.runtimeCall0.get(exception_style);
else if (npassed_args == 1)
func = g.funcs.runtimeCall1;
func = g.funcs.runtimeCall1.get(exception_style);
else if (npassed_args == 2)
func = g.funcs.runtimeCall2;
func = g.funcs.runtimeCall2.get(exception_style);
else if (npassed_args == 3)
func = g.funcs.runtimeCall3;
func = g.funcs.runtimeCall3.get(exception_style);
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;
other_args.push_back(var->getValue());
llvm::Value* llvm_argspec = llvm::ConstantInt::get(g.i32, argspec.asInt(), false);
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,
......@@ -684,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);
}
......@@ -1700,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;
......
......@@ -107,13 +107,23 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
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) {
AST_Raise* raise_stmt = ast_cast<AST_Raise>(invoke->stmt);
// 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;
return r;
}
else
r = CXX;
return r;
}
AST_expr* expr = NULL;
......@@ -127,21 +137,18 @@ ExceptionStyle IRGenState::getLandingpadStyle(AST_Invoke* invoke) {
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);
}
if (expr->type == AST_TYPE::Call) {
r = CAPI;
return r;
}
if (expr->type == AST_TYPE::Attribute || expr->type == AST_TYPE::Subscript) {
r = CAPI;
// printf("Doing a capi exception to %d\n", invoke->exc_dest->idx);
return r;
}
// Some expression type we haven't added yet -- might be worth looking into.
r = CXX;
return r;
}
......@@ -488,8 +495,7 @@ public:
llvm::BasicBlock* exc_dest;
bool exc_caught;
if (unw_info.hasHandler()) {
assert(unw_info.capi_exc_dest);
if (unw_info.capi_exc_dest) {
exc_dest = unw_info.capi_exc_dest;
exc_caught = true;
} else {
......@@ -508,7 +514,13 @@ public:
embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr));
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();
}
......@@ -2429,8 +2441,11 @@ private:
if (landingpad_style == CXX)
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));
}
assert(state == RUNNING || state == DEAD);
if (state == RUNNING) {
......
......@@ -245,31 +245,62 @@ void initGlobalFuncs(GlobalState& g) {
GET(boxedLocalsGet);
GET(boxedLocalsDel);
g.funcs.runtimeCall = getFunc((void*)runtimeCall, "runtimeCall");
g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
g.funcs.runtimeCall1
g.funcs.runtimeCall.cxx_val = getFunc((void*)runtimeCall, "runtimeCall");
g.funcs.runtimeCall0.cxx_val = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
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);
g.funcs.runtimeCall2 = 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.funcs.runtimeCall3 = 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.funcs.runtimeCallN
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.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.funcs.runtimeCallN.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->getPointerTo());
g.funcs.callattr = getFunc((void*)callattr, "callattr");
g.funcs.callattr0
g.funcs.runtimeCall.capi_val = getFunc((void*)runtimeCallCapi, "runtimeCallCapi");
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);
g.funcs.callattr1 = 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.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.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);
......
......@@ -43,8 +43,8 @@ struct GlobalFuncs {
*raiseAttributeErrorStrCapi, *raiseNotIterableError, *raiseIndexErrorStr, *raiseIndexErrorStrCapi,
*assertNameDefined, *assertFail, *assertFailDerefNameDefined, *printExprHelper;
llvm::Value* printFloat, *listAppendInternal, *getSysStdout;
llvm::Value* runtimeCall0, *runtimeCall1, *runtimeCall2, *runtimeCall3, *runtimeCall, *runtimeCallN;
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr, *callattrN;
ExceptionSwitchable<llvm::Value*> runtimeCall0, runtimeCall1, runtimeCall2, runtimeCall3, runtimeCall, runtimeCallN;
ExceptionSwitchable<llvm::Value*> callattr0, callattr1, callattr2, callattr3, callattr, callattrN;
llvm::Value* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* exec;
llvm::Value* boxedLocalsSet, *boxedLocalsGet, *boxedLocalsDel;
......
......@@ -536,6 +536,8 @@ public:
exc_info.reraise = false;
return;
}
// TODO: shouldn't fetch this multiple times?
frame_iter.getCurrentStatement()->cxx_exception_count++;
auto line_info = lineInfoForFrame(&frame_iter);
BoxedTraceback::here(line_info, &exc_info.traceback);
}
......
......@@ -182,6 +182,8 @@ class AST_stmt : public AST {
public:
virtual void accept_stmt(StmtVisitor* v) = 0;
int cxx_exception_count = 0;
AST_stmt(AST_TYPE::AST_TYPE type) : AST(type) {}
};
......
......@@ -457,11 +457,23 @@ Box* delattrFunc(Box* obj, Box* _str) {
return None;
}
Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
_str = coerceUnicodeToStr(_str);
template <ExceptionStyle S> Box* getattrFunc(Box* obj, Box* _str, Box* default_value) noexcept(S == CAPI) {
try {
_str = coerceUnicodeToStr(_str);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
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);
......@@ -470,7 +482,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
return default_value;
}
if (!rtn)
if (S == CXX && !rtn)
throwCAPIException();
return rtn;
}
......@@ -1437,9 +1449,9 @@ void setupBuiltins() {
builtins_module->giveAttr("delattr",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)delattrFunc, NONE, 2), "delattr"));
builtins_module->giveAttr(
"getattr", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)getattrFunc, UNKNOWN, 3, 1, false, false),
"getattr", { NULL }));
auto getattr_func = boxRTFunction((void*)getattrFunc<CXX>, UNKNOWN, 3, 1, false, false, ParamNames::empty(), CXX);
addRTFunction(getattr_func, (void*)getattrFunc<CAPI>, UNKNOWN, CAPI);
builtins_module->giveAttr("getattr", new BoxedBuiltinFunctionOrMethod(getattr_func, "getattr", { NULL }));
builtins_module->giveAttr(
"setattr",
......
......@@ -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
// 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* 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);
assert(_self->cls == capifunc_cls);
......@@ -1634,7 +1646,8 @@ void setupCAPI() {
auto capi_call = new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, true));
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__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr("__doc__",
......
......@@ -230,11 +230,23 @@ static Box* classmethodGet(Box* self, Box* obj, Box* type) {
// TODO this should be auto-generated as a slot wrapper:
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
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* 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);
assert(_self->cls == method_cls);
......@@ -489,8 +501,19 @@ Box* BoxedWrapperObject::__call__(BoxedWrapperObject* self, Box* args, Box* kwds
return rtn;
}
template <ExceptionStyle S>
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));
assert(_self->cls == wrapperobject_cls);
......@@ -617,7 +640,8 @@ void setupDescr() {
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
CLFunction* method_call_cl = boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, 0, true, true);
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->freeze();
......@@ -632,7 +656,8 @@ void setupDescr() {
wrapperobject_cls->giveAttr(
"__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();
}
......
......@@ -627,9 +627,17 @@ std::string floatFmt(double x, int precision, char code) {
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:
a = coerceUnicodeToStr(a);
try {
a = coerceUnicodeToStr(a);
} catch (ExcInfo e) {
if (S == CAPI) {
throwCAPIException();
return NULL;
}
throw e;
}
if (a->cls == float_cls) {
return static_cast<BoxedFloat*>(a);
......@@ -653,40 +661,70 @@ BoxedFloat* _floatNew(Box* a) {
assert(s.data()[s.size()] == '\0');
const char* startptr = s.data();
double r = strtod(startptr, &endptr);
if (endptr != startptr + s.size())
raiseExcHelper(ValueError, "could not convert string to float: %s", s.data());
if (endptr != startptr + s.size()) {
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);
} else {
static BoxedString* float_str = internStringImmortal("__float__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(a, float_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
Box* r = callattrInternal<S>(a, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: float() argument must be a string or a number, not '%s'\n", getTypeName(a));
raiseExcHelper(TypeError, "");
if (S == CAPI) {
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)) {
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);
}
}
Box* floatNew(BoxedClass* _cls, Box* a) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls));
template <ExceptionStyle S> Box* floatNew(BoxedClass* _cls, Box* a) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_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);
if (!isSubclass(cls, float_cls))
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls),
getNameOfClass(cls));
if (!isSubclass(cls, float_cls)) {
if (S == CAPI) {
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)
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);
}
......@@ -1476,8 +1514,9 @@ void setupFloat() {
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
float_cls->giveAttr(
"__new__", new BoxedFunction(boxRTFunction((void*)floatNew, UNKNOWN, 2, 1, false, false), { boxFloat(0.0) }));
auto float_new = boxRTFunction((void*)floatNew<CXX>, UNKNOWN, 2, 1, false, false, ParamNames::empty(), CXX);
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("__pos__", new BoxedFunction(boxRTFunction((void*)floatPos, BOXED_FLOAT, 1)));
......
......@@ -120,7 +120,9 @@ void force() {
FORCE(getSysStdout);
FORCE(runtimeCall);
FORCE(runtimeCallCapi);
FORCE(callattr);
FORCE(callattrCapi);
FORCE(raise0);
FORCE(raise3);
......
......@@ -884,7 +884,7 @@ extern "C" Box* intIndex(BoxedInt* v) {
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) {
RELEASE_ASSERT(!base, "");
BoxedInt* n = static_cast<BoxedInt*>(val);
......@@ -904,8 +904,12 @@ static Box* _intNew(Box* val, Box* base) {
RELEASE_ASSERT(s->size() == strlen(s->data()), "");
Box* r = PyInt_FromString(s->data(), NULL, base_n);
if (!r)
throwCAPIException();
if (!r) {
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r;
} else if (isSubclass(val->cls, unicode_cls)) {
int base_n;
......@@ -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);
if (!r)
throwCAPIException();
if (!r) {
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return r;
} else if (val->cls == float_cls) {
RELEASE_ASSERT(!base, "");
......@@ -952,39 +960,68 @@ static Box* _intNew(Box* val, Box* base) {
} else {
RELEASE_ASSERT(!base, "");
static BoxedString* int_str = internStringImmortal("__int__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(val, int_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
Box* r = callattrInternal<S>(val, int_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val));
raiseExcHelper(TypeError, "");
if (S == CAPI) {
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)) {
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
if (!PyInt_Check(r) && !PyLong_Check(r)) {
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;
}
}
extern "C" Box* intNew(Box* _cls, Box* val, Box* base) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls));
template <ExceptionStyle S> Box* intNew(Box* _cls, Box* val, Box* base) noexcept(S == CAPI) {
if (!isSubclass(_cls->cls, type_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);
if (!isSubclass(cls, int_cls))
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls),
getNameOfClass(cls));
if (!isSubclass(cls, int_cls)) {
if (S == CAPI) {
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)
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 (cls == int_cls)
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);
}
......@@ -1138,9 +1175,10 @@ void setupInt() {
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("__new__", new BoxedFunction(boxRTFunction((void*)intNew, UNKNOWN, 3, 2, false, false,
ParamNames({ "", "x", "base" }, "", "")),
{ boxInt(0), NULL }));
auto int_new
= boxRTFunction((void*)intNew<CXX>, UNKNOWN, 3, 2, false, false, ParamNames({ "", "x", "base" }, "", ""), CXX);
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)));
......
This diff is collapsed.
......@@ -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" 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
......@@ -132,9 +135,10 @@ enum LookupScope {
INST_ONLY = 2,
CLASS_OR_INST = 3,
};
extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallRewriteArgs* rewrite_args,
ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names);
template <ExceptionStyle S>
Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
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);
struct CompareRewriteArgs;
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) {
}
}
assert(self->cls == tuple_cls);
assert(isSubclass(self->cls, tuple_cls));
if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
......
This diff is collapsed.
......@@ -242,9 +242,8 @@ public:
pyston_inquiry tpp_hasnext;
typedef Box* (*pyston_call)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*);
pyston_call tpp_call;
ExceptionSwitchableFunction<Box*, Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<BoxedString*>*> tpp_call;
bool hasGenericGetattr() {
if (tp_getattr || tp_getattro != object_cls->tp_getattro)
......@@ -985,8 +984,9 @@ public:
DEFAULT_CLASS(wrapperobject_cls);
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,
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);
};
......@@ -1001,12 +1001,12 @@ public:
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner);
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,
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);
};
Box* objectNewNoArgs(BoxedClass* cls);
Box* objectSetattr(Box* obj, Box* attr, Box* value);
Box* unwrapAttrWrapper(Box* b);
......
......@@ -41,11 +41,11 @@ void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64*
throwCAPIException();
}
bool isSliceIndex(Box* b) {
bool isSliceIndex(Box* b) noexcept {
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 stop = *stop_out;
PySequenceMethods* m;
......
......@@ -36,9 +36,9 @@ inline void sliceIndex(Box* b, int64_t* out) {
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.
// Ensure stop >= start and remain within bounds.
......
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",
version="1.0",
description="test",
ext_modules=[
Extension("basic_test", sources = ["basic_test.c"]),
Extension("descr_test", sources = ["descr_test.c"]),
Extension("slots_test", sources = ["slots_test.c"]),
],
ext_modules=extensions,
)
# 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
......
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