Skip to content

Commit 635374f

Browse files
committed
Rewrap StackOverflowError into RecursionError
1 parent e76baa0 commit 635374f

File tree

7 files changed

+110
-36
lines changed

7 files changed

+110
-36
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorTryExceptNode.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ public void executeVoid(VirtualFrame frame) {
9393
return;
9494
} catch (ControlFlowException e) {
9595
throw e;
96-
} catch (Exception | StackOverflowError | AssertionError e) {
97-
if (shouldCatchAllExceptions()) {
96+
} catch (Throwable e) {
97+
PException pe = wrapJavaExceptionIfApplicable(e);
98+
if (pe != null) {
9899
gen.setActive(frame, exceptFlag, true);
99-
catchExceptionInGeneratorFirstTime(frame, wrapJavaException(e));
100+
catchExceptionInGeneratorFirstTime(frame, pe);
100101
reset(frame);
101102
return;
102103
} else {
@@ -165,6 +166,13 @@ private void runExceptionHandler(VirtualFrame frame, PException exception, Excep
165166
} catch (PException handlerException) {
166167
tryChainExceptionFromHandler(handlerException, exception);
167168
throw handlerException;
169+
} catch (Throwable e) {
170+
PException handlerException = wrapJavaExceptionIfApplicable(e);
171+
if (handlerException == null) {
172+
throw e;
173+
}
174+
tryChainExceptionFromHandler(handlerException, exception);
175+
throw handlerException;
168176
} finally {
169177
restoreExceptionState(frame, savedExceptionState);
170178
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorTryFinallyNode.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ public void executeVoid(VirtualFrame frame) {
7878
e.markFrameEscaped();
7979
tryChainPreexistingException(frame, e);
8080
gen.setActiveException(frame, activeExceptionIndex, e);
81+
} catch (Throwable e) {
82+
exceptionProfile.enter();
83+
PException pe = wrapJavaExceptionIfApplicable(e);
84+
if (pe == null) {
85+
throw e;
86+
}
87+
activeException = pe;
88+
pe.setCatchingFrameReference(frame);
89+
pe.markFrameEscaped();
90+
tryChainPreexistingException(frame, pe);
91+
gen.setActiveException(frame, activeExceptionIndex, pe);
8192
}
8293
gen.setActive(frame, finallyFlag, true);
8394
}
@@ -92,6 +103,15 @@ public void executeVoid(VirtualFrame frame) {
92103
tryChainExceptionFromHandler(handlerException, activeException);
93104
}
94105
throw handlerException;
106+
} catch (Throwable e) {
107+
PException handlerException = wrapJavaExceptionIfApplicable(e);
108+
if (handlerException == null) {
109+
throw e;
110+
}
111+
if (activeException != null) {
112+
tryChainExceptionFromHandler(handlerException, activeException);
113+
}
114+
throw handlerException;
95115
} finally {
96116
if (activeException != null) {
97117
restoreExceptionState(frame, savedExceptionState);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/GeneratorWithNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ protected void handleException(VirtualFrame frame, Object withObject, Object exi
9696
}
9797

9898
@Override
99-
protected void doLeave(VirtualFrame frame, Object withObject, boolean gotException, Object exitCallable) {
99+
protected void doLeave(VirtualFrame frame, Object withObject, Object exitCallable) {
100100
if (gen.isActive(frame, yieldSlot)) {
101101
gen.setActive(frame, yieldSlot, false);
102102
} else {
103103
reset(frame);
104-
super.doLeave(frame, withObject, gotException, exitCallable);
104+
super.doLeave(frame, withObject, exitCallable);
105105
}
106106
}
107107

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/ExceptionHandlingStatementNode.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.nodes.statement;
4242

43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RecursionError;
44+
4345
import com.oracle.graal.python.PythonLanguage;
4446
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
4547
import com.oracle.graal.python.nodes.util.ExceptionStateNodes;
@@ -184,13 +186,29 @@ protected boolean shouldCatchAllExceptions() {
184186
return shouldCatchAllExceptions;
185187
}
186188

187-
protected PException wrapJavaException(Throwable e) {
189+
private PException wrapJavaException(Throwable e) {
188190
PException pe = PException.fromObject(getBaseException(e), this);
189191
// Re-attach truffle stacktrace
190192
moveTruffleStackTrace(e, pe);
191193
return pe;
192194
}
193195

196+
protected PException wrapJavaExceptionIfApplicable(Throwable e) {
197+
if (e instanceof StackOverflowError) {
198+
return createRecursionError(e);
199+
}
200+
if (shouldCatchAllExceptions() && (e instanceof Exception || e instanceof AssertionError)) {
201+
return wrapJavaException(e);
202+
}
203+
return null;
204+
}
205+
206+
private PException createRecursionError(Throwable e) {
207+
PException pe = PException.fromObject(factory().createBaseException(RecursionError, "maximum recursion depth exceeded", new Object[]{}), this);
208+
moveTruffleStackTrace(e, pe);
209+
return pe;
210+
}
211+
194212
@TruffleBoundary
195213
private static void moveTruffleStackTrace(Throwable e, PException pe) {
196214
pe.initCause(e.getCause());

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/TryExceptNode.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ public void executeVoid(VirtualFrame frame) {
107107
return;
108108
}
109109
}
110-
if (shouldCatchAllExceptions()) {
111-
PException pe = wrapJavaException(e);
110+
PException pe = wrapJavaExceptionIfApplicable(e);
111+
if (pe != null) {
112112
boolean handled = catchException(frame, pe);
113113
if (handled) {
114114
return;
@@ -145,6 +145,13 @@ private boolean catchException(VirtualFrame frame, TruffleException exception) {
145145
} catch (PException handlerException) {
146146
tryChainExceptionFromHandler(handlerException, exception);
147147
throw handlerException;
148+
} catch (Exception | StackOverflowError | AssertionError e) {
149+
PException handlerException = wrapJavaExceptionIfApplicable(e);
150+
if (handlerException == null) {
151+
throw e;
152+
}
153+
tryChainExceptionFromHandler(handlerException, exception);
154+
throw handlerException;
148155
}
149156
return false;
150157
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/TryFinallyNode.java

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,46 @@ public void executeVoid(VirtualFrame frame) {
5151
try {
5252
body.executeVoid(frame);
5353
} catch (PException handledException) {
54-
exceptionProfile.enter();
55-
// any thrown Python exception is visible in the finally block
56-
handledException.setCatchingFrameReference(frame);
57-
tryChainPreexistingException(frame, handledException);
58-
ExceptionState exceptionState = saveExceptionState(frame);
59-
SetCaughtExceptionNode.execute(frame, handledException);
60-
try {
61-
finalbody.executeVoid(frame);
62-
} catch (PException handlerException) {
63-
tryChainExceptionFromHandler(handlerException, handledException);
64-
throw handlerException;
65-
} finally {
66-
restoreExceptionState(frame, exceptionState);
67-
}
68-
throw handledException.getExceptionForReraise();
54+
handleException(frame, handledException);
6955
} catch (ControlFlowException e) {
7056
finalbody.executeVoid(frame);
7157
throw e;
58+
} catch (Throwable e) {
59+
PException pe = wrapJavaExceptionIfApplicable(e);
60+
if (pe == null) {
61+
throw e;
62+
}
63+
handleException(frame, pe);
7264
}
7365
finalbody.executeVoid(frame);
7466
}
7567
}
7668

69+
private void handleException(VirtualFrame frame, PException handledException) {
70+
exceptionProfile.enter();
71+
// any thrown Python exception is visible in the finally block
72+
handledException.setCatchingFrameReference(frame);
73+
tryChainPreexistingException(frame, handledException);
74+
ExceptionState exceptionState = saveExceptionState(frame);
75+
SetCaughtExceptionNode.execute(frame, handledException);
76+
try {
77+
finalbody.executeVoid(frame);
78+
} catch (PException handlerException) {
79+
tryChainExceptionFromHandler(handlerException, handledException);
80+
throw handlerException;
81+
} catch (Throwable e) {
82+
PException handlerException = wrapJavaExceptionIfApplicable(e);
83+
if (handlerException == null) {
84+
throw e;
85+
}
86+
tryChainExceptionFromHandler(handlerException, handledException);
87+
throw handlerException;
88+
} finally {
89+
restoreExceptionState(frame, exceptionState);
90+
}
91+
throw handledException.getExceptionForReraise();
92+
}
93+
7794
public StatementNode getBody() {
7895
return body;
7996
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/WithNode.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ private PRaiseNode getRaiseNode() {
105105

106106
@Override
107107
public void executeVoid(VirtualFrame frame) {
108-
boolean gotException = false;
109108
Object withObject = getWithObject(frame);
110109
Object enterCallable = enterGetter.execute(withObject);
111110
if (enterCallable == PNone.NO_VALUE) {
@@ -121,20 +120,20 @@ public void executeVoid(VirtualFrame frame) {
121120
try {
122121
doBody(frame);
123122
} catch (PException exception) {
124-
gotException = true;
125123
handleException(frame, withObject, exitCallable, exception);
124+
return;
126125
} catch (ControlFlowException e) {
126+
doLeave(frame, withObject, exitCallable);
127127
throw e;
128-
} catch (Exception | StackOverflowError | AssertionError e) {
129-
if (shouldCatchAllExceptions()) {
130-
gotException = true;
131-
handleException(frame, withObject, exitCallable, wrapJavaException(e));
132-
} else {
128+
} catch (Throwable e) {
129+
PException pe = wrapJavaExceptionIfApplicable(e);
130+
if (pe == null) {
133131
throw e;
134132
}
135-
} finally {
136-
doLeave(frame, withObject, gotException, exitCallable);
133+
handleException(frame, withObject, exitCallable, pe);
134+
return;
137135
}
136+
doLeave(frame, withObject, exitCallable);
138137
}
139138

140139
/**
@@ -155,10 +154,8 @@ protected void doBody(VirtualFrame frame) {
155154
* Leave the with-body. Call __exit__ if it hasn't already happened because of an exception, and
156155
* reset the exception state.
157156
*/
158-
protected void doLeave(VirtualFrame frame, Object withObject, boolean gotException, Object exitCallable) {
159-
if (!gotException) {
160-
exitDispatch.execute(frame, exitCallable, new Object[]{withObject, PNone.NONE, PNone.NONE, PNone.NONE}, PKeyword.EMPTY_KEYWORDS);
161-
}
157+
protected void doLeave(VirtualFrame frame, Object withObject, Object exitCallable) {
158+
exitDispatch.execute(frame, exitCallable, new Object[]{withObject, PNone.NONE, PNone.NONE, PNone.NONE}, PKeyword.EMPTY_KEYWORDS);
162159
}
163160

164161
/**
@@ -188,6 +185,13 @@ protected void handleException(VirtualFrame frame, Object withObject, Object exi
188185
} catch (PException handlerException) {
189186
tryChainExceptionFromHandler(handlerException, pException);
190187
throw handlerException;
188+
} catch (Throwable e) {
189+
PException handlerException = wrapJavaExceptionIfApplicable(e);
190+
if (handlerException == null) {
191+
throw e;
192+
}
193+
tryChainExceptionFromHandler(handlerException, pException);
194+
throw handlerException;
191195
} finally {
192196
restoreExceptionState(frame, savedExceptionState);
193197
}

0 commit comments

Comments
 (0)