Skip to content

Commit

Permalink
Allow interop exceptions as exception state
Browse files Browse the repository at this point in the history
  • Loading branch information
msimacek committed Aug 27, 2024
1 parent 7e3c3f7 commit 623a587
Show file tree
Hide file tree
Showing 22 changed files with 415 additions and 192 deletions.
36 changes: 36 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,42 @@ def test_java_exceptions():
else:
assert False

def test_java_exceptions_reraise():
if __graalpython__.jython_emulation_enabled:
from java.lang import Integer, NumberFormatException
try:
try:
Integer.parseInt("99", 8)
except NumberFormatException:
raise
except NumberFormatException:
pass
else:
assert False

def test_java_exceptions_reraise_explicit():
if __graalpython__.jython_emulation_enabled:
from java.lang import Integer, NumberFormatException
try:
try:
Integer.parseInt("99", 8)
except NumberFormatException as e:
raise e
except NumberFormatException:
pass
else:
assert False

def test_java_exception_state():
if __graalpython__.jython_emulation_enabled:
from java.lang import Integer, NumberFormatException
try:
Integer.parseInt("99", 8)
except NumberFormatException as e:
assert sys.exc_info() == (type(e), e, None)
else:
assert False

@skipIf(is_native, "not supported in native mode")
def test_foreign_object_does_not_leak_Javas_toString():
try:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageSetItem;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
import com.oracle.graal.python.builtins.objects.frame.PFrame;
import com.oracle.graal.python.builtins.objects.frame.PFrame.Reference;
Expand Down Expand Up @@ -248,6 +249,7 @@
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
Expand Down Expand Up @@ -840,17 +842,18 @@ public abstract static class ExcInfoNode extends PythonBuiltinNode {
static PTuple run(VirtualFrame frame,
@Bind("this") Node inliningTarget,
@Cached GetClassNode getClassNode,
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
@Cached GetCaughtExceptionNode getCaughtExceptionNode,
@Cached ExceptionNodes.GetTracebackNode getTracebackNode,
@Cached PythonObjectFactory factory) {
PException currentException = getCaughtExceptionNode.execute(frame);
AbstractTruffleException currentException = getCaughtExceptionNode.execute(frame);
assert currentException != PException.NO_EXCEPTION;
if (currentException == null) {
return factory.createTuple(new PNone[]{PNone.NONE, PNone.NONE, PNone.NONE});
} else {
Object exception = currentException.getEscapedException();
Object traceback = getTracebackNode.execute(inliningTarget, exception);
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exception), exception, traceback});
Object exceptionObject = getEscapedExceptionNode.execute(inliningTarget, currentException);
Object traceback = getTracebackNode.execute(inliningTarget, exceptionObject);
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exceptionObject), exceptionObject, traceback});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins.SetItemNode;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
import com.oracle.graal.python.builtins.objects.exception.PrepareExceptionNode;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
Expand Down Expand Up @@ -133,6 +134,7 @@
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
Expand Down Expand Up @@ -173,6 +175,7 @@ static Object run(Object typ, Object val, Object tb,
@Cached PrepareExceptionNode prepareExceptionNode,
@Cached ExceptionNodes.SetTracebackNode setTracebackNode,
@Cached ExceptionNodes.SetContextNode setContextNode,
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
@Cached TransformExceptionToNativeNode transformExceptionToNativeNode) {
if (typ != PNone.NO_VALUE) {
PythonContext.PythonThreadState threadState = getThreadStateNode.execute(inliningTarget, PythonContext.get(inliningTarget));
Expand All @@ -182,8 +185,9 @@ static Object run(Object typ, Object val, Object tb,
if (tb != PNone.NO_VALUE) {
setTracebackNode.execute(inliningTarget, exception, tb);
}
Object currentException = threadState.getCurrentException().getEscapedException();
setContextNode.execute(inliningTarget, currentException, exception);
AbstractTruffleException currentException = threadState.getCurrentException();
Object currentExceptionObject = getEscapedExceptionNode.execute(inliningTarget, currentException);
setContextNode.execute(inliningTarget, currentExceptionObject, exception);
} else {
PException e = PException.fromExceptionInfo(exception, PythonOptions.isPExceptionWithJavaStacktrace(PythonLanguage.get(inliningTarget)));
transformExceptionToNativeNode.execute(inliningTarget, e, tb instanceof PTraceback ptb ? new LazyTraceback(ptb) : null);
Expand Down Expand Up @@ -399,14 +403,15 @@ Object info(
@Cached GetClassNode getClassNode,
@Cached ExceptionNodes.GetTracebackNode getTracebackNode,
@Cached InlinedBranchProfile noExceptionProfile,
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
@Cached PythonObjectFactory factory) {
PException currentException = getCaughtExceptionNode.executeFromNative();
AbstractTruffleException currentException = getCaughtExceptionNode.executeFromNative();
if (currentException == null) {
noExceptionProfile.enter(inliningTarget);
return getNativeNull();
}
assert currentException != PException.NO_EXCEPTION;
Object exception = currentException.getEscapedException();
Object exception = getEscapedExceptionNode.execute(inliningTarget, currentException);
Object traceback = noneToNativeNull(inliningTarget, getTracebackNode.execute(inliningTarget, exception));
return factory.createTuple(new Object[]{getClassNode.execute(inliningTarget, exception), exception, traceback});
}
Expand All @@ -419,19 +424,21 @@ static Object write(Object msg, Object obj,
@Bind("this") Node inliningTarget,
@Cached GetThreadStateNode getThreadStateNode,
@Cached WriteUnraisableNode writeUnraisableNode,
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode) {
PythonContext.PythonThreadState threadState = getThreadStateNode.execute(inliningTarget, PythonContext.get(inliningTarget));
if (threadState.getCurrentException() == null) {
// This means an invalid call, but this function is not supposed to raise exceptions
return PNone.NONE;
}
threadState.syncTracebackToException();
Object exc = threadState.getCurrentException().getEscapedException();
AbstractTruffleException exception = threadState.getCurrentException();
Object exceptionObject = getEscapedExceptionNode.execute(inliningTarget, exception);
TruffleString m = null;
if (msg instanceof TruffleString) {
m = (TruffleString) msg;
}
writeUnraisableNode.execute(exc, m, (obj == PNone.NO_VALUE) ? PNone.NONE : obj);
writeUnraisableNode.execute(exceptionObject, m, (obj == PNone.NO_VALUE) ? PNone.NONE : obj);
clearCurrentExceptionNode.execute(inliningTarget, threadState);
return PNone.NONE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
import com.oracle.graal.python.builtins.objects.traceback.MaterializeLazyTracebackNode;
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.exception.PException;
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.strings.TruffleString;

Expand Down Expand Up @@ -89,7 +89,7 @@ static int tbHere(PFrame frame,
@Cached PythonObjectFactory factory) {
PythonLanguage language = PythonLanguage.get(inliningTarget);
PythonContext.PythonThreadState threadState = PythonContext.get(inliningTarget).getThreadState(language);
PException currentException = threadState.getCurrentException();
AbstractTruffleException currentException = threadState.getCurrentException();
if (currentException != null) {
PTraceback currentTraceback = null;
if (threadState.getCurrentTraceback() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
Expand Down Expand Up @@ -840,7 +841,7 @@ static void deallocWarn(VirtualFrame frame, PFileIO self,
if (self.getFD() >= 0 && self.isCloseFD()) {
try {
warn.resourceWarning(frame, self, 1, UNCLOSED_FILE, self);
} catch (PException e) {
} catch (AbstractTruffleException e) {
/* Spurious errors can appear at shutdown */
/* (mq) we aren't doing WriteUnraisable as WarnNode will take care of it */
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.complex.PComplex;
import com.oracle.graal.python.builtins.objects.exception.GetEscapedExceptionNode;
import com.oracle.graal.python.builtins.objects.exception.GetUnreifiedExceptionNode;
import com.oracle.graal.python.builtins.objects.floats.PFloat;
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
Expand Down Expand Up @@ -195,6 +197,7 @@
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ArityException;
Expand Down Expand Up @@ -1034,11 +1037,12 @@ public static Object executeUncached(PythonThreadState threadState) {

@Specialization
static Object doGeneric(Node inliningTarget, PythonThreadState threadState,
@Cached GetClassNode getClassNode) {
PException currentException = threadState.getCurrentException();
@Cached GetClassNode getClassNode,
@Cached GetUnreifiedExceptionNode getUnreifiedExceptionNode) {
AbstractTruffleException currentException = threadState.getCurrentException();
if (currentException != null) {
// getClassNode acts as a branch profile
return getClassNode.execute(inliningTarget, currentException.getUnreifiedException());
return getClassNode.execute(inliningTarget, getUnreifiedExceptionNode.execute(inliningTarget, currentException));
}
return null;
}
Expand All @@ -1062,16 +1066,17 @@ public static ExceptionState executeUncached(PythonThreadState threadState) {
static ExceptionState doGeneric(Node inliningTarget, PythonThreadState threadState,
@Cached GetClassNode getClassNode,
@Cached MaterializeLazyTracebackNode materializeTraceback,
@Cached GetEscapedExceptionNode getEscapedExceptionNode,
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode) {
PException currentException = threadState.getCurrentException();
AbstractTruffleException currentException = threadState.getCurrentException();
if (currentException == null) {
/*
* This should be caught in native by checking 'PyErr_Occurred' and avoiding the
* upcall. But let's be defensive and treat that case on a slow path.
*/
return null;
}
Object exception = currentException.getEscapedException();
Object exception = getEscapedExceptionNode.execute(inliningTarget, currentException);
Object traceback = null;
if (threadState.getCurrentTraceback() != null) {
traceback = materializeTraceback.execute(inliningTarget, threadState.getCurrentTraceback());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.PythonContext.GetThreadStateNode;
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
import com.oracle.graal.python.runtime.exception.PException;
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.graal.python.runtime.sequence.storage.NativeObjectSequenceStorage;
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
Expand All @@ -151,6 +150,7 @@
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary;
Expand Down Expand Up @@ -2436,7 +2436,7 @@ static Object doGeneric(PythonThreadState state, @SuppressWarnings("unused") Tru
@Cached ClearCurrentExceptionNode clearCurrentExceptionNode,
@Cached PRaiseNode raiseNode) {
if (lib.isNull(result)) {
PException currentException = state.getCurrentException();
AbstractTruffleException currentException = state.getCurrentException();
// if no exception occurred, the iterator is exhausted -> raise StopIteration
if (currentException == null) {
throw raiseNode.raiseStopIteration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccessFactory;
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.exception.GetUnreifiedExceptionNode;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.PythonContext.PythonThreadState;
Expand Down Expand Up @@ -116,7 +117,7 @@ private static Object allocateCLayout(PythonThreadState threadState) {
writePtrNode.write(ptr, CFields.PyThreadState__small_ints, cApiContext.getOrCreateSmallInts());
if (threadState.getCurrentException() != null) {
// See TransformExceptionToNativeNode
Object exceptionType = GetClassNode.executeUncached(threadState.getCurrentException().getUnreifiedException());
Object exceptionType = GetClassNode.executeUncached(GetUnreifiedExceptionNode.executeUncached(threadState.getCurrentException()));
CStructAccess.WritePointerNode.getUncached().write(ptr, CFields.PyThreadState__curexc_type, PythonToNativeNode.getUncached().execute(exceptionType));
}
return ptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.runtime.GilNode;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.exception.PException;
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
Expand All @@ -116,6 +115,7 @@
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.exception.AbstractTruffleException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
Expand Down Expand Up @@ -401,7 +401,7 @@ public static void pollReferenceQueue() {
* There can be an active exception. Since we might be calling arbitary python, we
* need to stash it.
*/
PException savedException = null;
AbstractTruffleException savedException = null;
LazyTraceback savedTraceback = null;
Object savedNativeException = null;
if (threadState.getCurrentException() != null) {
Expand Down
Loading

0 comments on commit 623a587

Please sign in to comment.