Skip to content

Commit dd4c919

Browse files
committed
Port PException to new exception API
1 parent 0172f7c commit dd4c919

File tree

21 files changed

+258
-192
lines changed

21 files changed

+258
-192
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/ParserTestBase.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
import com.oracle.graal.python.test.PythonTests;
5252
import com.oracle.truffle.api.TruffleFile;
5353
import com.oracle.truffle.api.frame.Frame;
54+
import com.oracle.truffle.api.interop.ExceptionType;
55+
import com.oracle.truffle.api.interop.InteropLibrary;
56+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
5457
import com.oracle.truffle.api.nodes.Node;
5558
import com.oracle.truffle.api.source.Source;
5659
import java.io.File;
@@ -127,7 +130,7 @@ public void checkSyntaxError(String source) throws Exception {
127130
try {
128131
parse(source, name.getMethodName(), PythonParser.ParserMode.File);
129132
} catch (PException e) {
130-
thrown = e.isSyntaxError();
133+
thrown = isSyntaxError(e);
131134
}
132135

133136
assertTrue("Expected SyntaxError was not thrown.", thrown);
@@ -138,7 +141,7 @@ public void checkSyntaxErrorMessageContains(String source, String expectedMessag
138141
try {
139142
parse(source, name.getMethodName(), PythonParser.ParserMode.File);
140143
} catch (PException e) {
141-
thrown = e.isSyntaxError();
144+
thrown = isSyntaxError(e);
142145
Assert.assertTrue("The expected message:\n\"" + expectedMessage + "\"\nwas not found in\n\"" + e.getMessage() + "\"", e.getMessage().contains(expectedMessage));
143146
}
144147

@@ -150,13 +153,17 @@ public void checkSyntaxErrorMessage(String source, String expectedMessage) throw
150153
try {
151154
parse(source, name.getMethodName(), PythonParser.ParserMode.File);
152155
} catch (PException e) {
153-
thrown = e.isSyntaxError();
156+
thrown = isSyntaxError(e);
154157
Assert.assertEquals(expectedMessage, e.getMessage());
155158
}
156159

157160
assertTrue("Expected SyntaxError was not thrown.", thrown);
158161
}
159162

163+
private static boolean isSyntaxError(PException e) throws UnsupportedMessageException {
164+
return InteropLibrary.getUncached().getExceptionType(e) == ExceptionType.PARSE_ERROR;
165+
}
166+
160167
public void saveNewTreeResult(File testFile, boolean goldenFileNextToTestFile) throws Exception {
161168
assertTrue("The test files " + testFile.getAbsolutePath() + " was not found.", testFile.exists());
162169
TruffleFile src = context.getEnv().getInternalTruffleFile(testFile.getAbsolutePath());

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ Object run(Object errorMarker,
638638
PException currentException = getContext().getCurrentException();
639639
if (currentException != null) {
640640
// getClassNode acts as a branch profile
641-
return getClassNode.execute(currentException.getExceptionObject());
641+
return getClassNode.execute(currentException.getUnreifiedException());
642642
}
643643
return errorMarker;
644644
}
@@ -1495,7 +1495,7 @@ int tbHere(PFrame frame,
14951495
}
14961496
PTraceback newTraceback = factory().createTraceback(frame, frame.getLine(), traceback);
14971497
boolean withJavaStacktrace = PythonOptions.isPExceptionWithJavaStacktrace(language);
1498-
context.setCurrentException(PException.fromExceptionInfo(currentException.getExceptionObject(), newTraceback, withJavaStacktrace));
1498+
context.setCurrentException(PException.fromExceptionInfo(currentException.getUnreifiedException(), newTraceback, withJavaStacktrace));
14991499
}
15001500

15011501
return 0;

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
import com.oracle.truffle.api.CompilerAsserts;
7272
import com.oracle.truffle.api.CompilerDirectives;
7373
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
74-
import com.oracle.truffle.api.TruffleException;
7574
import com.oracle.truffle.api.dsl.Cached;
7675
import com.oracle.truffle.api.dsl.Cached.Shared;
7776
import com.oracle.truffle.api.dsl.CachedContext;
@@ -83,6 +82,7 @@
8382
import com.oracle.truffle.api.dsl.TypeSystemReference;
8483
import com.oracle.truffle.api.frame.VirtualFrame;
8584
import com.oracle.truffle.api.interop.ArityException;
85+
import com.oracle.truffle.api.interop.ExceptionType;
8686
import com.oracle.truffle.api.interop.InteropLibrary;
8787
import com.oracle.truffle.api.interop.UnsupportedMessageException;
8888
import com.oracle.truffle.api.interop.UnsupportedTypeException;
@@ -211,6 +211,7 @@ Object call(VirtualFrame frame, Object callable, Object arg1, Object arg2,
211211
@Cached BranchProfile syntaxError,
212212
@Cached BranchProfile typeError,
213213
@CachedLibrary("callable") InteropLibrary interop,
214+
@CachedLibrary(limit = "1") InteropLibrary exceptionLib,
214215
@CachedContext(PythonLanguage.class) PythonContext context) {
215216
Object state = IndirectCallContext.enter(frame, context, this);
216217
try {
@@ -219,20 +220,23 @@ Object call(VirtualFrame frame, Object callable, Object arg1, Object arg2,
219220
typeError.enter();
220221
throw raise(TypeError, "%s", e);
221222
} catch (RuntimeException e) {
222-
return handleError(e, syntaxError, potentialSyntaxError);
223+
return handleError(e, syntaxError, potentialSyntaxError, exceptionLib);
223224
} finally {
224225
IndirectCallContext.exit(frame, context, state);
225226
}
226227
}
227228

228-
@TruffleBoundary
229-
private Object handleError(RuntimeException e, BranchProfile syntaxError, BranchProfile potentialSyntaxError) {
230-
if (e instanceof TruffleException) {
231-
potentialSyntaxError.enter(); // this guards the TruffleBoundary invoke
232-
if (((TruffleException) e).isSyntaxError()) {
233-
syntaxError.enter();
234-
throw raise(ValueError, "%s", e);
229+
private Object handleError(RuntimeException e, BranchProfile syntaxError, BranchProfile potentialSyntaxError, InteropLibrary exceptionLib) {
230+
try {
231+
if (exceptionLib.isException(e)) {
232+
potentialSyntaxError.enter();
233+
if (exceptionLib.getExceptionType(e) == ExceptionType.PARSE_ERROR) {
234+
syntaxError.enter();
235+
throw raise(ValueError, "%s", e);
236+
}
235237
}
238+
} catch (UnsupportedMessageException e1) {
239+
throw CompilerDirectives.shouldNotReachHere();
236240
}
237241
// just re-throw
238242
throw e;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ public static Object fast(VirtualFrame frame, GetClassNode getClassNode, GetCaug
333333
if (currentException == null) {
334334
return factory.createTuple(new PNone[]{PNone.NONE});
335335
}
336-
return factory.createTuple(new Object[]{getClassNode.execute(currentException.getExceptionObject())});
336+
return factory.createTuple(new Object[]{getClassNode.execute(currentException.getUnreifiedException())});
337337
}
338338

339339
@Specialization

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ Object doCurExcType(@SuppressWarnings("unused") String key,
154154
PException currentException = context.getCurrentException();
155155
Object result = null;
156156
if (currentException != null) {
157-
result = getClassNode.execute(currentException.getExceptionObject());
157+
result = getClassNode.execute(currentException.getUnreifiedException());
158158
}
159159
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
160160
}
@@ -192,7 +192,7 @@ Object doExcType(@SuppressWarnings("unused") String key,
192192
PException currentException = context.getCaughtException();
193193
Object result = null;
194194
if (currentException != null) {
195-
result = getClassNode.execute(currentException.getExceptionObject());
195+
result = getClassNode.execute(currentException.getUnreifiedException());
196196
}
197197
return toSulongNode.execute(result != null ? result : PNone.NO_VALUE);
198198
}
@@ -349,7 +349,7 @@ static PTraceback doCurExcTraceback(@SuppressWarnings("unused") String key, PTra
349349
@Shared("language") @CachedLanguage PythonLanguage language,
350350
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
351351
PException e = context.getCurrentException();
352-
context.setCurrentException(PException.fromExceptionInfo(e.getExceptionObject(), value, PythonOptions.isPExceptionWithJavaStacktrace(language)));
352+
context.setCurrentException(PException.fromExceptionInfo(e.getUnreifiedException(), value, PythonOptions.isPExceptionWithJavaStacktrace(language)));
353353
return value;
354354
}
355355

@@ -376,7 +376,7 @@ static PTraceback doExcTraceback(@SuppressWarnings("unused") String key, PTraceb
376376
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
377377
PException e = context.getCaughtException();
378378
boolean withJavaStacktrace = PythonOptions.isPExceptionWithJavaStacktrace(language);
379-
context.setCaughtException(PException.fromExceptionInfo(e.getExceptionObject(), value, withJavaStacktrace));
379+
context.setCaughtException(PException.fromExceptionInfo(e.getUnreifiedException(), value, withJavaStacktrace));
380380
return value;
381381
}
382382

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

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,36 @@
4040
*/
4141
package com.oracle.graal.python.builtins.objects.exception;
4242

43+
import com.oracle.graal.python.PythonLanguage;
44+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4345
import com.oracle.graal.python.builtins.objects.PNone;
4446
import com.oracle.graal.python.builtins.objects.frame.PFrame;
4547
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4648
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
4749
import com.oracle.graal.python.builtins.objects.traceback.LazyTraceback;
4850
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
4951
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
52+
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
5053
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetNameNode;
5154
import com.oracle.graal.python.nodes.PRaiseNode;
55+
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromDynamicObjectNode;
5256
import com.oracle.graal.python.runtime.exception.PException;
5357
import com.oracle.graal.python.runtime.formatting.ErrorMessageFormatter;
5458
import com.oracle.graal.python.runtime.sequence.storage.BasicSequenceStorage;
5559
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
56-
import com.oracle.graal.python.util.PythonUtils;
5760
import com.oracle.truffle.api.CompilerAsserts;
61+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5862
import com.oracle.truffle.api.dsl.Cached;
63+
import com.oracle.truffle.api.dsl.CachedLanguage;
64+
import com.oracle.truffle.api.interop.ExceptionType;
65+
import com.oracle.truffle.api.interop.InteropLibrary;
66+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
5967
import com.oracle.truffle.api.library.CachedLibrary;
68+
import com.oracle.truffle.api.library.ExportLibrary;
6069
import com.oracle.truffle.api.library.ExportMessage;
6170
import com.oracle.truffle.api.object.Shape;
6271

72+
@ExportLibrary(InteropLibrary.class)
6373
public final class PBaseException extends PythonObject {
6474
private static final ErrorMessageFormatter FORMATTER = new ErrorMessageFormatter();
6575

@@ -183,6 +193,7 @@ public Object[] getMessageArgs() {
183193
return messageArgs.clone();
184194
}
185195

196+
@TruffleBoundary
186197
public String getFormattedMessage(PythonObjectLibrary lib) {
187198
final Object clazz;
188199
if (lib == null) {
@@ -222,26 +233,6 @@ public LazyTraceback internalReifyException(PFrame.Reference curFrameInfo) {
222233
return traceback;
223234
}
224235

225-
@ExportMessage
226-
@SuppressWarnings("static-method")
227-
boolean isException() {
228-
return true;
229-
}
230-
231-
@ExportMessage
232-
RuntimeException throwException(@CachedLibrary("this") PythonObjectLibrary lib,
233-
@Cached PRaiseNode raiseNode) {
234-
Object[] newArgs = messageArgs;
235-
if (newArgs == null) {
236-
newArgs = PythonUtils.EMPTY_OBJECT_ARRAY;
237-
}
238-
Object format = messageFormat;
239-
if (format == null) {
240-
format = PNone.NO_VALUE;
241-
}
242-
throw raiseNode.execute(lib.getLazyPythonClass(this), this, format, newArgs);
243-
}
244-
245236
/**
246237
* Prepare a {@link PException} for reraising this exception, as done by <code>raise</code>
247238
* without arguments.
@@ -271,4 +262,87 @@ public PException getExceptionForReraise(LazyTraceback reraiseTraceback) {
271262
newException.setHideLocation(true);
272263
return newException;
273264
}
265+
266+
@ExportMessage
267+
@SuppressWarnings("static-method")
268+
boolean isException() {
269+
return true;
270+
}
271+
272+
@ExportMessage
273+
RuntimeException throwException(
274+
@Cached PRaiseNode raiseNode,
275+
@CachedLanguage PythonLanguage language) {
276+
throw raiseNode.raiseExceptionObject(this, language);
277+
}
278+
279+
@ExportMessage
280+
ExceptionType getExceptionType(
281+
@CachedLibrary("this") PythonObjectLibrary lib) {
282+
Object clazz = lib.getLazyPythonClass(this);
283+
if (clazz instanceof PythonBuiltinClass) {
284+
clazz = ((PythonBuiltinClass) clazz).getType();
285+
}
286+
// these are the only ones we'll raise, we don't want to report user subtypes of
287+
// SyntaxError as Truffle syntax errors
288+
if (clazz == PythonBuiltinClassType.SyntaxError || clazz == PythonBuiltinClassType.IndentationError || clazz == PythonBuiltinClassType.TabError) {
289+
return ExceptionType.PARSE_ERROR;
290+
}
291+
if (clazz == PythonBuiltinClassType.SystemExit) {
292+
return ExceptionType.EXIT;
293+
}
294+
return ExceptionType.RUNTIME_ERROR;
295+
}
296+
297+
@ExportMessage
298+
@SuppressWarnings("static-method")
299+
boolean isExceptionIncompleteSource() {
300+
return false;
301+
}
302+
303+
@ExportMessage
304+
@SuppressWarnings("static-method")
305+
boolean hasExceptionMessage() {
306+
return true;
307+
}
308+
309+
@ExportMessage
310+
String getExceptionMessage(@CachedLibrary("this") PythonObjectLibrary lib) {
311+
return getFormattedMessage(lib);
312+
}
313+
314+
@ExportMessage
315+
int getExceptionExitStatus(
316+
@CachedLibrary("this") PythonObjectLibrary lib,
317+
@Cached ReadAttributeFromDynamicObjectNode readNode) throws UnsupportedMessageException {
318+
if (getExceptionType(lib) == ExceptionType.EXIT) {
319+
try {
320+
// Avoiding getattr because this message shouldn't have side-effects
321+
Object code = readNode.execute(this, "code");
322+
if (code == PNone.NO_VALUE) {
323+
return 1;
324+
}
325+
return (int) lib.asJavaLong(code);
326+
} catch (PException e) {
327+
return 1;
328+
}
329+
}
330+
throw UnsupportedMessageException.create();
331+
}
332+
333+
@ExportMessage
334+
boolean hasExceptionCause() {
335+
return cause != null || (!suppressContext && context != null);
336+
}
337+
338+
@ExportMessage
339+
Object getExceptionCause() throws UnsupportedMessageException {
340+
if (cause != null) {
341+
return cause;
342+
}
343+
if (!suppressContext && context != null) {
344+
return context;
345+
}
346+
throw UnsupportedMessageException.create();
347+
}
274348
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ private Object doThrow(VirtualFrame frame, ResumeGeneratorNode resumeGeneratorNo
415415
instance.ensureReified();
416416
// Pass it to the generator where it will be thrown by the last yield, the location
417417
// will be filled there
418-
PException pException = PException.fromObject(instance, null, PythonOptions.isPExceptionWithJavaStacktrace(language));
419-
return resumeGeneratorNode.execute(frame, self, pException);
418+
return resumeGeneratorNode.execute(frame, self, new ThrowData(instance, PythonOptions.isPExceptionWithJavaStacktrace(language)));
420419
} else {
421420
// Unstarted generator, we cannot pass the exception into the generator as there is
422421
// nothing that would handle it.
@@ -477,9 +476,8 @@ Object close(VirtualFrame frame, PGenerator self,
477476
// Pass it to the generator where it will be thrown by the last yield, the location
478477
// will be filled there
479478
boolean withJavaStacktrace = PythonOptions.isPExceptionWithJavaStacktrace(language);
480-
PException pException = PException.fromObject(pythonException, null, withJavaStacktrace);
481479
try {
482-
resumeGeneratorNode.execute(frame, self, pException);
480+
resumeGeneratorNode.execute(frame, self, new ThrowData(pythonException, withJavaStacktrace));
483481
} catch (PException pe) {
484482
if (isGeneratorExit.profileException(pe, GeneratorExit, lib) || isStopIteration.profileException(pe, StopIteration, lib)) {
485483
// This is the "success" path
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.oracle.graal.python.builtins.objects.generator;
2+
3+
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
4+
5+
public final class ThrowData {
6+
public final PBaseException pythonException;
7+
public final boolean withJavaStacktrace;
8+
9+
public ThrowData(PBaseException pythonException, boolean withJavaStacktrace) {
10+
this.pythonException = pythonException;
11+
this.withJavaStacktrace = withJavaStacktrace;
12+
}
13+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ static String doGeneric(VirtualFrame frame, Object self, Object table,
964964
try {
965965
translated = getItemNode.execute(frame, table, original);
966966
} catch (PException e) {
967-
if (!isSubtypeNode.execute(null, plib.getLazyPythonClass(e.getExceptionObject()), PythonBuiltinClassType.LookupError)) {
967+
if (!isSubtypeNode.execute(null, plib.getLazyPythonClass(e.getUnreifiedException()), PythonBuiltinClassType.LookupError)) {
968968
throw e;
969969
}
970970
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/traceback/GetTracebackNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
* <li>When you catch a {@link PException PException} and need to obtain its corresponding
102102
* {@link com.oracle.graal.python.builtins.objects.exception.PBaseException PBaseException}, use the
103103
* {@link PException#setCatchingFrameAndGetEscapedException(VirtualFrame, Node)} method, unless
104-
* you're just doing a simple class check. Try to avoid the {@link PException#getExceptionObject()
104+
* you're just doing a simple class check. Try to avoid the {@link PException#getUnreifiedException()
105105
* getExceptionObject} method unless you know what you're doing.</li>
106106
* <li>{@link PException PException} must never be rethrown after it has been possibly exposed to
107107
* the program, because its Truffle stacktrace may already be frozen and it would not capture more

0 commit comments

Comments
 (0)