Skip to content

Commit bdda44c

Browse files
committed
[GR-43631] Allow interop exceptions as exception state
PullRequest: graalpython/3453
2 parents be6de35 + 623a587 commit bdda44c

22 files changed

+415
-192
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_interop.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,42 @@ def test_java_exceptions():
427427
else:
428428
assert False
429429

430+
def test_java_exceptions_reraise():
431+
if __graalpython__.jython_emulation_enabled:
432+
from java.lang import Integer, NumberFormatException
433+
try:
434+
try:
435+
Integer.parseInt("99", 8)
436+
except NumberFormatException:
437+
raise
438+
except NumberFormatException:
439+
pass
440+
else:
441+
assert False
442+
443+
def test_java_exceptions_reraise_explicit():
444+
if __graalpython__.jython_emulation_enabled:
445+
from java.lang import Integer, NumberFormatException
446+
try:
447+
try:
448+
Integer.parseInt("99", 8)
449+
except NumberFormatException as e:
450+
raise e
451+
except NumberFormatException:
452+
pass
453+
else:
454+
assert False
455+
456+
def test_java_exception_state():
457+
if __graalpython__.jython_emulation_enabled:
458+
from java.lang import Integer, NumberFormatException
459+
try:
460+
Integer.parseInt("99", 8)
461+
except NumberFormatException as e:
462+
assert sys.exc_info() == (type(e), e, None)
463+
else:
464+
assert False
465+
430466
@skipIf(is_native, "not supported in native mode")
431467
def test_foreign_object_does_not_leak_Javas_toString():
432468
try:

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageSetItem;
171171
import com.oracle.graal.python.builtins.objects.dict.PDict;
172172
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
173+
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
173174
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
174175
import com.oracle.graal.python.builtins.objects.frame.PFrame;
175176
import com.oracle.graal.python.builtins.objects.frame.PFrame.Reference;
@@ -248,6 +249,7 @@
248249
import com.oracle.truffle.api.dsl.NeverDefault;
249250
import com.oracle.truffle.api.dsl.NodeFactory;
250251
import com.oracle.truffle.api.dsl.Specialization;
252+
import com.oracle.truffle.api.exception.AbstractTruffleException;
251253
import com.oracle.truffle.api.frame.MaterializedFrame;
252254
import com.oracle.truffle.api.frame.VirtualFrame;
253255
import com.oracle.truffle.api.nodes.Node;
@@ -840,17 +842,18 @@ public abstract static class ExcInfoNode extends PythonBuiltinNode {
840842
static PTuple run(VirtualFrame frame,
841843
@Bind("this") Node inliningTarget,
842844
@Cached GetClassNode getClassNode,
845+
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
843846
@Cached GetCaughtExceptionNode getCaughtExceptionNode,
844847
@Cached ExceptionNodes.GetTracebackNode getTracebackNode,
845848
@Cached PythonObjectFactory factory) {
846-
PException currentException = getCaughtExceptionNode.execute(frame);
849+
AbstractTruffleException currentException = getCaughtExceptionNode.execute(frame);
847850
assert currentException != PException.NO_EXCEPTION;
848851
if (currentException == null) {
849852
return factory.createTuple(new PNone[]{PNone.NONE, PNone.NONE, PNone.NONE});
850853
} else {
851-
Object exception = currentException.getEscapedException();
852-
Object traceback = getTracebackNode.execute(inliningTarget, exception);
853-
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exception), exception, traceback});
854+
Object exceptionObject = getEscapedExceptionNode.execute(inliningTarget, currentException);
855+
Object traceback = getTracebackNode.execute(inliningTarget, exceptionObject);
856+
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exceptionObject), exceptionObject, traceback});
854857
}
855858
}
856859

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextErrBuiltins.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins.SetItemNode;
9797
import com.oracle.graal.python.builtins.objects.dict.PDict;
9898
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
99+
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
99100
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
100101
import com.oracle.graal.python.builtins.objects.exception.PrepareExceptionNode;
101102
import com.oracle.graal.python.builtins.objects.function.PKeyword;
@@ -133,6 +134,7 @@
133134
import com.oracle.truffle.api.dsl.Cached.Shared;
134135
import com.oracle.truffle.api.dsl.Fallback;
135136
import com.oracle.truffle.api.dsl.Specialization;
137+
import com.oracle.truffle.api.exception.AbstractTruffleException;
136138
import com.oracle.truffle.api.nodes.Node;
137139
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
138140
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
@@ -173,6 +175,7 @@ static Object run(Object typ, Object val, Object tb,
173175
@Cached PrepareExceptionNode prepareExceptionNode,
174176
@Cached ExceptionNodes.SetTracebackNode setTracebackNode,
175177
@Cached ExceptionNodes.SetContextNode setContextNode,
178+
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
176179
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode) {
177180
if (typ != PNone.NO_VALUE) {
178181
PythonContext.PythonThreadState threadState = getThreadStateNode.execute(inliningTarget, PythonContext.get(inliningTarget));
@@ -182,8 +185,9 @@ static Object run(Object typ, Object val, Object tb,
182185
if (tb != PNone.NO_VALUE) {
183186
setTracebackNode.execute(inliningTarget, exception, tb);
184187
}
185-
Object currentException = threadState.getCurrentException().getEscapedException();
186-
setContextNode.execute(inliningTarget, currentException, exception);
188+
AbstractTruffleException currentException = threadState.getCurrentException();
189+
Object currentExceptionObject = getEscapedExceptionNode.execute(inliningTarget, currentException);
190+
setContextNode.execute(inliningTarget, currentExceptionObject, exception);
187191
} else {
188192
PException e = PException.fromExceptionInfo(exception, PythonOptions.isPExceptionWithJavaStacktrace(PythonLanguage.get(inliningTarget)));
189193
transformExceptionToNativeNode.execute(inliningTarget, e, tb instanceof PTraceback ptb ? new LazyTraceback(ptb) : null);
@@ -399,14 +403,15 @@ Object info(
399403
@Cached GetClassNode getClassNode,
400404
@Cached ExceptionNodes.GetTracebackNode getTracebackNode,
401405
@Cached InlinedBranchProfile noExceptionProfile,
406+
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
402407
@Cached PythonObjectFactory factory) {
403-
PException currentException = getCaughtExceptionNode.executeFromNative();
408+
AbstractTruffleException currentException = getCaughtExceptionNode.executeFromNative();
404409
if (currentException == null) {
405410
noExceptionProfile.enter(inliningTarget);
406411
return getNativeNull();
407412
}
408413
assert currentException != PException.NO_EXCEPTION;
409-
Object exception = currentException.getEscapedException();
414+
Object exception = getEscapedExceptionNode.execute(inliningTarget, currentException);
410415
Object traceback = noneToNativeNull(inliningTarget, getTracebackNode.execute(inliningTarget, exception));
411416
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exception), exception, traceback});
412417
}
@@ -419,19 +424,21 @@ static Object write(Object msg, Object obj,
419424
@Bind("this") Node inliningTarget,
420425
@Cached GetThreadStateNode getThreadStateNode,
421426
@Cached WriteUnraisableNode writeUnraisableNode,
427+
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
422428
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode) {
423429
PythonContext.PythonThreadState threadState = getThreadStateNode.execute(inliningTarget, PythonContext.get(inliningTarget));
424430
if (threadState.getCurrentException() == null) {
425431
// This means an invalid call, but this function is not supposed to raise exceptions
426432
return PNone.NONE;
427433
}
428434
threadState.syncTracebackToException();
429-
Object exc = threadState.getCurrentException().getEscapedException();
435+
AbstractTruffleException exception = threadState.getCurrentException();
436+
Object exceptionObject = getEscapedExceptionNode.execute(inliningTarget, exception);
430437
TruffleString m = null;
431438
if (msg instanceof TruffleString) {
432439
m = (TruffleString) msg;
433440
}
434-
writeUnraisableNode.execute(exc, m, (obj == PNone.NO_VALUE) ? PNone.NONE : obj);
441+
writeUnraisableNode.execute(exceptionObject, m, (obj == PNone.NO_VALUE) ? PNone.NONE : obj);
435442
clearCurrentExceptionNode.execute(inliningTarget, threadState);
436443
return PNone.NONE;
437444
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTracebackBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@
5757
import com.oracle.graal.python.builtins.objects.traceback.MaterializeLazyTracebackNode;
5858
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
5959
import com.oracle.graal.python.runtime.PythonContext;
60-
import com.oracle.graal.python.runtime.exception.PException;
6160
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
6261
import com.oracle.truffle.api.dsl.Bind;
6362
import com.oracle.truffle.api.dsl.Cached;
6463
import com.oracle.truffle.api.dsl.Specialization;
64+
import com.oracle.truffle.api.exception.AbstractTruffleException;
6565
import com.oracle.truffle.api.nodes.Node;
6666
import com.oracle.truffle.api.strings.TruffleString;
6767

@@ -89,7 +89,7 @@ static int tbHere(PFrame frame,
8989
@Cached PythonObjectFactory factory) {
9090
PythonLanguage language = PythonLanguage.get(inliningTarget);
9191
PythonContext.PythonThreadState threadState = PythonContext.get(inliningTarget).getThreadState(language);
92-
PException currentException = threadState.getCurrentException();
92+
AbstractTruffleException currentException = threadState.getCurrentException();
9393
if (currentException != null) {
9494
PTraceback currentTraceback = null;
9595
if (threadState.getCurrentTraceback() != null) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/FileIOBuiltins.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
167167
import com.oracle.truffle.api.dsl.NodeFactory;
168168
import com.oracle.truffle.api.dsl.Specialization;
169+
import com.oracle.truffle.api.exception.AbstractTruffleException;
169170
import com.oracle.truffle.api.frame.VirtualFrame;
170171
import com.oracle.truffle.api.library.CachedLibrary;
171172
import com.oracle.truffle.api.nodes.Node;
@@ -840,7 +841,7 @@ static void deallocWarn(VirtualFrame frame, PFileIO self,
840841
if (self.getFD() >= 0 && self.isCloseFD()) {
841842
try {
842843
warn.resourceWarning(frame, self, 1, UNCLOSED_FILE, self);
843-
} catch (PException e) {
844+
} catch (AbstractTruffleException e) {
844845
/* Spurious errors can appear at shutdown */
845846
/* (mq) we aren't doing WriteUnraisable as WarnNode will take care of it */
846847
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@
121121
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
122122
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
123123
import com.oracle.graal.python.builtins.objects.complex.PComplex;
124+
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
125+
import com.oracle.graal.python.builtins.objects.exception.GetUnreifiedExceptionNode;
124126
import com.oracle.graal.python.builtins.objects.floats.PFloat;
125127
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
126128
import com.oracle.graal.python.builtins.objects.function.PKeyword;
@@ -195,6 +197,7 @@
195197
import com.oracle.truffle.api.dsl.ImportStatic;
196198
import com.oracle.truffle.api.dsl.NeverDefault;
197199
import com.oracle.truffle.api.dsl.Specialization;
200+
import com.oracle.truffle.api.exception.AbstractTruffleException;
198201
import com.oracle.truffle.api.frame.Frame;
199202
import com.oracle.truffle.api.frame.VirtualFrame;
200203
import com.oracle.truffle.api.interop.ArityException;
@@ -1034,11 +1037,12 @@ public static Object executeUncached(PythonThreadState threadState) {
10341037

10351038
@Specialization
10361039
static Object doGeneric(Node inliningTarget, PythonThreadState threadState,
1037-
@Cached GetClassNode getClassNode) {
1038-
PException currentException = threadState.getCurrentException();
1040+
@Cached GetClassNode getClassNode,
1041+
@Cached GetUnreifiedExceptionNode getUnreifiedExceptionNode) {
1042+
AbstractTruffleException currentException = threadState.getCurrentException();
10391043
if (currentException != null) {
10401044
// getClassNode acts as a branch profile
1041-
return getClassNode.execute(inliningTarget, currentException.getUnreifiedException());
1045+
return getClassNode.execute(inliningTarget, getUnreifiedExceptionNode.execute(inliningTarget, currentException));
10421046
}
10431047
return null;
10441048
}
@@ -1062,16 +1066,17 @@ public static ExceptionState executeUncached(PythonThreadState threadState) {
10621066
static ExceptionState doGeneric(Node inliningTarget, PythonThreadState threadState,
10631067
@Cached GetClassNode getClassNode,
10641068
@Cached MaterializeLazyTracebackNode materializeTraceback,
1069+
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
10651070
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode) {
1066-
PException currentException = threadState.getCurrentException();
1071+
AbstractTruffleException currentException = threadState.getCurrentException();
10671072
if (currentException == null) {
10681073
/*
10691074
* This should be caught in native by checking 'PyErr_Occurred' and avoiding the
10701075
* upcall. But let's be defensive and treat that case on a slow path.
10711076
*/
10721077
return null;
10731078
}
1074-
Object exception = currentException.getEscapedException();
1079+
Object exception = getEscapedExceptionNode.execute(inliningTarget, currentException);
10751080
Object traceback = null;
10761081
if (threadState.getCurrentTraceback() != null) {
10771082
traceback = materializeTraceback.execute(inliningTarget, threadState.getCurrentTraceback());

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@
124124
import com.oracle.graal.python.runtime.PythonContext;
125125
import com.oracle.graal.python.runtime.PythonContext.GetThreadStateNode;
126126
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
127-
import com.oracle.graal.python.runtime.exception.PException;
128127
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
129128
import com.oracle.graal.python.runtime.sequence.storage.NativeObjectSequenceStorage;
130129
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
@@ -151,6 +150,7 @@
151150
import com.oracle.truffle.api.dsl.NeverDefault;
152151
import com.oracle.truffle.api.dsl.Specialization;
153152
import com.oracle.truffle.api.dsl.TypeSystemReference;
153+
import com.oracle.truffle.api.exception.AbstractTruffleException;
154154
import com.oracle.truffle.api.frame.VirtualFrame;
155155
import com.oracle.truffle.api.interop.ArityException;
156156
import com.oracle.truffle.api.interop.InteropLibrary;
@@ -2436,7 +2436,7 @@ static Object doGeneric(PythonThreadState state, @SuppressWarnings("unused") Tru
24362436
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode,
24372437
@Cached PRaiseNode raiseNode) {
24382438
if (lib.isNull(result)) {
2439-
PException currentException = state.getCurrentException();
2439+
AbstractTruffleException currentException = state.getCurrentException();
24402440
// if no exception occurred, the iterator is exhausted -> raise StopIteration
24412441
if (currentException == null) {
24422442
throw raiseNode.raiseStopIteration();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/PThreadState.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccessFactory;
5050
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
5151
import com.oracle.graal.python.builtins.objects.dict.PDict;
52+
import com.oracle.graal.python.builtins.objects.exception.GetUnreifiedExceptionNode;
5253
import com.oracle.graal.python.nodes.object.GetClassNode;
5354
import com.oracle.graal.python.runtime.PythonContext;
5455
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
@@ -116,7 +117,7 @@ private static Object allocateCLayout(PythonThreadState threadState) {
116117
writePtrNode.write(ptr, CFields.PyThreadState__small_ints, cApiContext.getOrCreateSmallInts());
117118
if (threadState.getCurrentException() != null) {
118119
// See TransformExceptionToNativeNode
119-
Object exceptionType = GetClassNode.executeUncached(threadState.getCurrentException().getUnreifiedException());
120+
Object exceptionType = GetClassNode.executeUncached(GetUnreifiedExceptionNode.executeUncached(threadState.getCurrentException()));
120121
CStructAccess.WritePointerNode.getUncached().write(ptr, CFields.PyThreadState__curexc_type, PythonToNativeNode.getUncached().execute(exceptionType));
121122
}
122123
return ptr;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/transitions/CApiTransitions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@
9595
import com.oracle.graal.python.nodes.object.GetClassNode;
9696
import com.oracle.graal.python.runtime.GilNode;
9797
import com.oracle.graal.python.runtime.PythonContext;
98-
import com.oracle.graal.python.runtime.exception.PException;
9998
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
10099
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
101100
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
@@ -116,6 +115,7 @@
116115
import com.oracle.truffle.api.dsl.ImportStatic;
117116
import com.oracle.truffle.api.dsl.NeverDefault;
118117
import com.oracle.truffle.api.dsl.Specialization;
118+
import com.oracle.truffle.api.exception.AbstractTruffleException;
119119
import com.oracle.truffle.api.interop.InteropLibrary;
120120
import com.oracle.truffle.api.interop.UnsupportedMessageException;
121121
import com.oracle.truffle.api.library.CachedLibrary;
@@ -401,7 +401,7 @@ public static void pollReferenceQueue() {
401401
* There can be an active exception. Since we might be calling arbitary python, we
402402
* need to stash it.
403403
*/
404-
PException savedException = null;
404+
AbstractTruffleException savedException = null;
405405
LazyTraceback savedTraceback = null;
406406
Object savedNativeException = null;
407407
if (threadState.getCurrentException() != null) {

0 commit comments

Comments
 (0)