Commit 368c76f7 authored by Marius Wachtler's avatar Marius Wachtler Committed by Kevin Modzelewski

use a CAPI IC for calling "next" in order to reduce c++ exceptions

This reduces the number of c++ exceptions we throw for iterators writen in python
parent 5b98eb1c
......@@ -435,6 +435,7 @@ class Rewriter;
class RewriterVar;
class RuntimeIC;
class CallattrIC;
class CallattrCapiIC;
class NonzeroIC;
class BinopIC;
......
......@@ -77,6 +77,17 @@ public:
}
};
class CallattrCapiIC : public RuntimeIC {
public:
CallattrCapiIC() : RuntimeIC((void*)callattrCapi, 1, 320) {}
Box* call(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg0, Box* arg1, Box* arg2, Box** args,
const std::vector<BoxedString*>* keyword_names) {
return (Box*)call_ptr(obj, attr, flags, arg0, arg1, arg2, args, keyword_names);
}
};
class BinopIC : public RuntimeIC {
public:
BinopIC() : RuntimeIC((void*)binop, 2, 240) {}
......
......@@ -3573,6 +3573,16 @@ static Box* astInterpretHelper(CLFunction* f, int num_args, BoxedClosure* closur
return astInterpretFunction(f, num_args, closure, generator, globals, arg1, arg2, arg3, (Box**)args);
}
static Box* astInterpretHelperCapi(CLFunction* f, int num_args, BoxedClosure* closure, BoxedGenerator* generator,
Box* globals, Box** _args) noexcept {
try {
return astInterpretHelper(f, num_args, closure, generator, globals, _args);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
// TODO: is it better to take the func_ptr last (requiring passing all the args), or is it better to put it
// first (requiring moving all the args)?
static Box* capiCallCxxHelper(Box* (*func_ptr)(void*, void*, void*, void*, void*), void* a, void* b, void* c, void* d,
......@@ -3592,7 +3602,7 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
CompiledFunction* chosen_cf = pickVersion(f, S, num_output_args, oarg1, oarg2, oarg3, oargs);
if (!chosen_cf) {
if (rewrite_args && S == CXX) {
if (rewrite_args) {
RewriterVar::SmallVector arg_vec;
rewrite_args->rewriter->addDependenceOn(f->dependent_interp_callsites);
......@@ -3619,8 +3629,10 @@ Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_arg
if (num_output_args >= 4)
arg_array->setAttr(24, rewrite_args->args);
assert(S == CXX);
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)astInterpretHelper, arg_vec);
if (S == CXX)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)astInterpretHelper, arg_vec);
else
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)astInterpretHelperCapi, arg_vec);
rewrite_args->out_success = true;
}
......
......@@ -239,32 +239,27 @@ Box* BoxedClass::callHasnextIC(Box* obj, bool null_on_nonexistent) {
}
extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
if (iter->cls->tp_iternext != slot_tp_iternext) {
PyObject* result;
Box* result = NULL;
if (iter->cls->tp_iternext != slot_tp_iternext)
result = (*iter->cls->tp_iternext)(iter);
if (result == NULL && PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
return result;
}
try {
Box* hasnext = iter->hasnextOrNullIC();
if (hasnext) {
if (hasnext->nonzeroIC())
return iter->cls->callNextIC(iter);
else
else {
try {
Box* hasnext = iter->hasnextOrNullIC();
if (hasnext && !hasnext->nonzeroIC())
return NULL;
} else {
return iter->cls->callNextIC(iter);
}
} catch (ExcInfo e) {
if (!e.matches(StopIteration))
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
return NULL;
}
result = iter->cls->call_nextIC(iter);
}
if (result == NULL && PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
PyErr_Clear();
return result;
}
Box* BoxedClass::callNextIC(Box* obj) {
Box* BoxedClass::call_nextIC(Box* obj) noexcept {
assert(obj->cls == this);
// This would work, but it would have been better to just call tp_iternext
......@@ -272,7 +267,7 @@ Box* BoxedClass::callNextIC(Box* obj) {
auto ic = next_ic.get();
if (!ic) {
ic = new CallattrIC();
ic = new CallattrCapiIC();
next_ic.reset(ic);
}
......
......@@ -186,10 +186,11 @@ public:
HCAttrs attrs;
// TODO: these don't actually get deallocated right now
std::unique_ptr<CallattrIC> hasnext_ic, next_ic, repr_ic;
std::unique_ptr<CallattrCapiIC> next_ic;
std::unique_ptr<CallattrIC> hasnext_ic, repr_ic;
std::unique_ptr<NonzeroIC> nonzero_ic;
Box* callHasnextIC(Box* obj, bool null_on_nonexistent);
Box* callNextIC(Box* obj);
Box* call_nextIC(Box* obj) noexcept;
Box* callReprIC(Box* obj);
bool callNonzeroIC(Box* obj);
......
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