Skip to content

Commit 7d08769

Browse files
committed
Make PrepareExceptionNode and its users work with native exceptions
1 parent 6d43dda commit 7d08769

File tree

4 files changed

+51
-41
lines changed

4 files changed

+51
-41
lines changed

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
import com.oracle.graal.python.lib.PyObjectLookupAttr;
105105
import com.oracle.graal.python.lib.PyObjectSetAttr;
106106
import com.oracle.graal.python.lib.PyObjectStrAsObjectNode;
107+
import com.oracle.graal.python.nodes.PRaiseNode;
107108
import com.oracle.graal.python.nodes.WriteUnraisableNode;
108109
import com.oracle.graal.python.nodes.attributes.WriteAttributeToObjectNode;
109110
import com.oracle.graal.python.nodes.call.CallNode;
@@ -149,7 +150,7 @@ Object restore(Object typ, Object val, Object tb,
149150
@Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
150151
PythonContext context = getContext();
151152
PythonLanguage language = getLanguage();
152-
PBaseException exception;
153+
Object exception;
153154
try {
154155
exception = prepareExceptionNode.execute(null, typ, val);
155156
} catch (PException e) {
@@ -267,8 +268,11 @@ Object create(Object type, Object value,
267268
@SuppressWarnings("unused") @Cached IsInstanceNode isInstanceNode,
268269
@SuppressWarnings("unused") @Cached IsSubClassNode isSubClassNode,
269270
@Cached PrepareExceptionNode prepareExceptionNode) {
270-
PBaseException exception = prepareExceptionNode.execute(null, type, value);
271-
throw getRaiseNode().raiseExceptionObject(exception);
271+
Object exception = prepareExceptionNode.execute(null, type, value);
272+
if (exception instanceof PBaseException managedException) {
273+
managedException.ensureReified();
274+
}
275+
throw PRaiseNode.raiseNoReify(this, exception, PythonOptions.isPExceptionWithJavaStacktrace(PythonLanguage.get(this)));
272276
}
273277

274278
protected static boolean isExceptionClass(Object obj, IsTypeNode isTypeNode, IsSubClassNode isSubClassNode) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/PrepareExceptionNode.java

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4646
import com.oracle.graal.python.builtins.modules.BuiltinFunctions;
4747
import com.oracle.graal.python.builtins.objects.PNone;
48+
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
4849
import com.oracle.graal.python.builtins.objects.common.SequenceNodes;
4950
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
5051
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
52+
import com.oracle.graal.python.lib.PyExceptionInstanceCheckNode;
5153
import com.oracle.graal.python.nodes.ErrorMessages;
5254
import com.oracle.graal.python.nodes.PGuards;
5355
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -62,95 +64,97 @@
6264
import com.oracle.truffle.api.dsl.Specialization;
6365
import com.oracle.truffle.api.frame.VirtualFrame;
6466
import com.oracle.truffle.api.nodes.Node;
65-
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
67+
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
6668

6769
/**
6870
* Creates an exception out of type and value, similarly to CPython's
6971
* {@code PyErr_NormalizeException}. Returns the normalized exception.
7072
*/
7173
@ImportStatic(PGuards.class)
7274
public abstract class PrepareExceptionNode extends Node {
73-
public abstract PBaseException execute(VirtualFrame frame, Object type, Object value);
75+
public abstract Object execute(VirtualFrame frame, Object type, Object value);
7476

7577
@Specialization
76-
static PBaseException doException(PBaseException exc, @SuppressWarnings("unused") PNone value) {
78+
static Object doException(PBaseException exc, @SuppressWarnings("unused") PNone value) {
7779
return exc;
7880
}
7981

80-
@Specialization(guards = "!isPNone(value)")
81-
static PBaseException doException(@SuppressWarnings("unused") PBaseException exc, @SuppressWarnings("unused") Object value,
82+
@Specialization(guards = "check.execute(inliningTarget, exc)", limit = "1")
83+
static Object doException(PythonAbstractNativeObject exc, @SuppressWarnings("unused") PNone value,
84+
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
85+
@SuppressWarnings("unused") @Shared @Cached PyExceptionInstanceCheckNode check) {
86+
return exc;
87+
}
88+
89+
@Specialization(guards = {"check.execute(inliningTarget, exc)", "!isPNone(value)"}, limit = "1")
90+
static Object doException(@SuppressWarnings("unused") PBaseException exc, @SuppressWarnings("unused") Object value,
91+
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
92+
@SuppressWarnings("unused") @Shared @Cached PyExceptionInstanceCheckNode check,
8293
@Shared @Cached PRaiseNode raiseNode) {
8394
throw raiseNode.raise(TypeError, ErrorMessages.INSTANCE_EX_MAY_NOT_HAVE_SEP_VALUE);
8495
}
8596

86-
@Specialization(guards = "isTypeNode.execute(type)", limit = "1")
87-
static PBaseException doException(VirtualFrame frame, Object type, PBaseException value,
97+
@Specialization(guards = {"isTypeNode.execute(type)", "!isPNone(value)", "!isPTuple(value)"}, limit = "1")
98+
static Object doExceptionOrCreate(VirtualFrame frame, Object type, Object value,
8899
@Bind("this") Node inliningTarget,
89100
@SuppressWarnings("unused") @Shared("isType") @Cached IsTypeNode isTypeNode,
101+
@Shared @Cached PyExceptionInstanceCheckNode check,
90102
@Cached BuiltinFunctions.IsInstanceNode isInstanceNode,
91-
@Cached InlinedBranchProfile isNotInstanceProfile,
103+
@Cached InlinedConditionProfile isInstanceProfile,
92104
@Shared @Cached IsSubtypeNode isSubtypeNode,
93105
@Shared @Cached PRaiseNode raiseNode,
94106
@Shared("callCtor") @Cached CallNode callConstructor) {
95-
if (isInstanceNode.executeWith(frame, value, type)) {
96-
checkExceptionClass(type, isSubtypeNode, raiseNode);
107+
checkExceptionClass(type, isSubtypeNode, raiseNode);
108+
if (isInstanceProfile.profile(inliningTarget, isInstanceNode.executeWith(frame, value, type))) {
97109
return value;
98110
} else {
99-
isNotInstanceProfile.enter(inliningTarget);
100-
return doCreateObject(frame, type, value, isTypeNode, isSubtypeNode, raiseNode, callConstructor);
111+
Object instance = callConstructor.execute(frame, type, value);
112+
if (check.execute(inliningTarget, instance)) {
113+
return instance;
114+
} else {
115+
return handleInstanceNotAnException(type, instance);
116+
}
101117
}
102118
}
103119

104120
@Specialization(guards = "isTypeNode.execute(type)", limit = "1")
105-
static PBaseException doCreate(VirtualFrame frame, Object type, @SuppressWarnings("unused") PNone value,
121+
static Object doCreate(VirtualFrame frame, Object type, @SuppressWarnings("unused") PNone value,
122+
@Bind("this") Node inliningTarget,
106123
@SuppressWarnings("unused") @Shared("isType") @Cached IsTypeNode isTypeNode,
124+
@Shared @Cached PyExceptionInstanceCheckNode check,
107125
@Shared @Cached IsSubtypeNode isSubtypeNode,
108126
@Shared @Cached PRaiseNode raiseNode,
109127
@Shared("callCtor") @Cached CallNode callConstructor) {
110128
checkExceptionClass(type, isSubtypeNode, raiseNode);
111129
Object instance = callConstructor.execute(frame, type);
112-
if (instance instanceof PBaseException) {
113-
return (PBaseException) instance;
130+
if (check.execute(inliningTarget, instance)) {
131+
return instance;
114132
} else {
115133
return handleInstanceNotAnException(type, instance);
116134
}
117135
}
118136

119137
@Specialization(guards = "isTypeNode.execute(type)", limit = "1")
120-
static PBaseException doCreateTuple(VirtualFrame frame, Object type, PTuple value,
138+
static Object doCreateTuple(VirtualFrame frame, Object type, PTuple value,
121139
@Bind("this") Node inliningTarget,
122140
@SuppressWarnings("unused") @Shared("isType") @Cached IsTypeNode isTypeNode,
141+
@Shared @Cached PyExceptionInstanceCheckNode check,
123142
@Cached SequenceNodes.GetObjectArrayNode getObjectArrayNode,
124143
@Shared @Cached IsSubtypeNode isSubtypeNode,
125144
@Shared @Cached PRaiseNode raiseNode,
126145
@Shared("callCtor") @Cached CallNode callConstructor) {
127146
checkExceptionClass(type, isSubtypeNode, raiseNode);
128147
Object[] args = getObjectArrayNode.execute(inliningTarget, value);
129148
Object instance = callConstructor.execute(frame, type, args);
130-
if (instance instanceof PBaseException) {
131-
return (PBaseException) instance;
132-
} else {
133-
return handleInstanceNotAnException(type, instance);
134-
}
135-
}
136-
137-
@Specialization(guards = {"isTypeNode.execute(type)", "!isPNone(value)", "!isPTuple(value)", "!isPBaseException(value)"}, limit = "1")
138-
static PBaseException doCreateObject(VirtualFrame frame, Object type, Object value,
139-
@SuppressWarnings("unused") @Shared("isType") @Cached IsTypeNode isTypeNode,
140-
@Shared @Cached IsSubtypeNode isSubtypeNode,
141-
@Shared @Cached PRaiseNode raiseNode,
142-
@Shared("callCtor") @Cached CallNode callConstructor) {
143-
checkExceptionClass(type, isSubtypeNode, raiseNode);
144-
Object instance = callConstructor.execute(frame, type, value);
145-
if (instance instanceof PBaseException) {
146-
return (PBaseException) instance;
149+
if (check.execute(inliningTarget, instance)) {
150+
return instance;
147151
} else {
148152
return handleInstanceNotAnException(type, instance);
149153
}
150154
}
151155

152156
@Fallback
153-
static PBaseException doError(Object type, @SuppressWarnings("unused") Object value,
157+
static Object doError(Object type, @SuppressWarnings("unused") Object value,
154158
@Shared @Cached PRaiseNode raiseNode) {
155159
throw raiseNode.raise(TypeError, ErrorMessages.EXCEPTIONS_MUST_BE_CLASSES_OR_INSTANCES_DERIVING_FROM_BASE_EX, type);
156160
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/CommonGeneratorBuiltins.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object val, Ob
294294
runningProfile.enter(inliningTarget);
295295
throw raise(ValueError, ErrorMessages.GENERATOR_ALREADY_EXECUTING);
296296
}
297-
PBaseException instance = prepareExceptionNode.execute(frame, typ, val);
297+
Object instance = prepareExceptionNode.execute(frame, typ, val);
298298
if (hasTb) {
299299
setTracebackNode.execute(inliningTarget, instance, tb);
300300
}
@@ -305,7 +305,9 @@ Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object val, Ob
305305
throw raise(PythonBuiltinClassType.RuntimeError, ErrorMessages.CANNOT_REUSE_CORO);
306306
}
307307
if (startedProfile.profile(inliningTarget, self.isStarted() && !self.isFinished())) {
308-
instance.ensureReified();
308+
if (instance instanceof PBaseException managedException) {
309+
managedException.ensureReified();
310+
}
309311
// Pass it to the generator where it will be thrown by the last yield, the location
310312
// will be filled there
311313
return resumeGeneratorNode.execute(frame, self, new ThrowData(instance, PythonOptions.isPExceptionWithJavaStacktrace(language)));

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/ThrowData.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@
5151
*/
5252
@ValueType
5353
public final class ThrowData {
54-
public final PBaseException pythonException;
54+
public final Object pythonException;
5555
public final boolean withJavaStacktrace;
5656

57-
public ThrowData(PBaseException pythonException, boolean withJavaStacktrace) {
57+
public ThrowData(Object pythonException, boolean withJavaStacktrace) {
5858
this.pythonException = pythonException;
5959
this.withJavaStacktrace = withJavaStacktrace;
6060
}

0 commit comments

Comments
 (0)