Commit 3e10ff4d authored by Kevin Modzelewski's avatar Kevin Modzelewski

Recursion-depth-checking fixes

We weren't properly reducing the stack depth when yielding from a generator,
meaning that the recursion depth was effectively decreased by the number
of active generators.
parent 5fdbbfcc
......@@ -360,6 +360,8 @@ static Box* yieldInternal(BoxedGenerator* obj, STOLEN(Box*) value,
llvm::ArrayRef<Box*> live_values) noexcept(S == CAPI) {
STAT_TIMER(t0, "us_timer_generator_switching", 0);
Py_LeaveRecursiveCall();
assert(obj->cls == generator_cls);
BoxedGenerator* self = static_cast<BoxedGenerator*>(obj);
assert(!self->returnValue);
......@@ -395,6 +397,15 @@ static Box* yieldInternal(BoxedGenerator* obj, STOLEN(Box*) value,
ExcInfo e = self->exception;
self->exception = ExcInfo(NULL, NULL, NULL);
Py_CLEAR(self->returnValue);
if (Py_EnterRecursiveCall("resuming generator")) {
e.clear();
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
if (S == CAPI) {
setCAPIException(e);
return NULL;
......@@ -402,6 +413,14 @@ static Box* yieldInternal(BoxedGenerator* obj, STOLEN(Box*) value,
throw e;
}
if (Py_EnterRecursiveCall("resuming generator")) {
Py_CLEAR(self->returnValue);
if (S == CAPI)
return NULL;
else
throwCAPIException();
}
Box* r = self->returnValue;
self->returnValue = NULL;
return r;
......
......@@ -4753,9 +4753,6 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
template <ExceptionStyle S>
static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, BoxedGenerator* generator, Box* globals,
Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs) noexcept(S == CAPI) {
// TODO: this should go into the emitted code
RECURSIVE_BLOCK(S, " in function call");
if (S != chosen_cf->exception_style) {
if (S == CAPI) {
try {
......@@ -4772,6 +4769,9 @@ static Box* callChosenCF(CompiledFunction* chosen_cf, BoxedClosure* closure, Box
}
}
// TODO: this should go into the emitted code
RECURSIVE_BLOCK(S, " in function call");
assert((globals == NULL)
== (!chosen_cf->code_obj->source || chosen_cf->code_obj->source->scoping.areGlobalsFromModule()));
......
# Some regression tests to make sure recursion-checking works properly with generators
def test(n):
l = []
for i in xrange(n):
g = (i for i in xrange(5))
g.next()
l.append(g)
for i in xrange(1000):
test(3500)
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