Skip to content

Commit 1bbb388

Browse files
committed
Add a node for setting traceback
1 parent 072e1ff commit 1bbb388

File tree

6 files changed

+99
-84
lines changed

6 files changed

+99
-84
lines changed

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import static com.oracle.graal.python.lib.PyTraceBackPrintNode.objectLookupAttrAsString;
7575
import static com.oracle.graal.python.lib.PyTraceBackPrintNode.objectRepr;
7676
import static com.oracle.graal.python.lib.PyTraceBackPrintNode.objectStr;
77+
import static com.oracle.graal.python.lib.PyTraceBackPrintNode.setExceptionTraceback;
7778
import static com.oracle.graal.python.lib.PyTraceBackPrintNode.tryCastToString;
7879
import static com.oracle.graal.python.nodes.BuiltinNames.J_BREAKPOINTHOOK;
7980
import static com.oracle.graal.python.nodes.BuiltinNames.J_DISPLAYHOOK;
@@ -1575,14 +1576,7 @@ static Set<Object> createSet() {
15751576

15761577
@Specialization
15771578
Object doHookWithTb(VirtualFrame frame, PythonModule sys, @SuppressWarnings("unused") Object excType, Object value, PTraceback traceBack) {
1578-
if (PGuards.isPBaseException(value)) {
1579-
final PBaseException exc = (PBaseException) value;
1580-
final Object currTb = getExceptionTraceback(exc);
1581-
if (currTb instanceof PTraceback) {
1582-
exc.setTraceback(traceBack);
1583-
}
1584-
}
1585-
1579+
setExceptionTraceback(value, traceBack);
15861580
final MaterializedFrame materializedFrame = frame.materialize();
15871581
Object stdErr = objectLookupAttr(materializedFrame, sys, T_STDERR);
15881582
printExceptionRecursive(materializedFrame, sys, stdErr, value, createSet());

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@
8888
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageGetItem;
8989
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins.SetItemNode;
9090
import com.oracle.graal.python.builtins.objects.dict.PDict;
91+
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
9192
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
9293
import com.oracle.graal.python.builtins.objects.exception.PrepareExceptionNode;
9394
import com.oracle.graal.python.builtins.objects.function.PKeyword;
9495
import com.oracle.graal.python.builtins.objects.module.PythonModule;
95-
import com.oracle.graal.python.builtins.objects.traceback.MaterializeLazyTracebackNode;
9696
import com.oracle.graal.python.builtins.objects.traceback.LazyTraceback;
97+
import com.oracle.graal.python.builtins.objects.traceback.MaterializeLazyTracebackNode;
9798
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
9899
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
99100
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
@@ -118,10 +119,12 @@
118119
import com.oracle.graal.python.runtime.exception.PException;
119120
import com.oracle.graal.python.runtime.exception.PythonErrorType;
120121
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
122+
import com.oracle.truffle.api.dsl.Bind;
121123
import com.oracle.truffle.api.dsl.Cached;
122124
import com.oracle.truffle.api.dsl.Cached.Shared;
123125
import com.oracle.truffle.api.dsl.Fallback;
124126
import com.oracle.truffle.api.dsl.Specialization;
127+
import com.oracle.truffle.api.nodes.Node;
125128
import com.oracle.truffle.api.profiles.BranchProfile;
126129
import com.oracle.truffle.api.profiles.ConditionProfile;
127130
import com.oracle.truffle.api.profiles.LoopConditionProfile;
@@ -141,7 +144,9 @@ Object restore(PNone typ, PNone val, Object tb) {
141144

142145
@Fallback
143146
Object restore(Object typ, Object val, Object tb,
144-
@Cached PrepareExceptionNode prepareExceptionNode) {
147+
@Bind("this") Node inliningTarget,
148+
@Cached PrepareExceptionNode prepareExceptionNode,
149+
@Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
145150
PythonContext context = getContext();
146151
PythonLanguage language = getLanguage();
147152
PBaseException exception;
@@ -151,8 +156,8 @@ Object restore(Object typ, Object val, Object tb,
151156
context.setCurrentException(language, e);
152157
return PNone.NO_VALUE;
153158
}
154-
if (tb instanceof PTraceback pTraceback) {
155-
exception.setTraceback(pTraceback);
159+
if (tb instanceof PTraceback) {
160+
setTracebackNode.execute(inliningTarget, exception, tb);
156161
}
157162
context.setCurrentException(language, PException.fromExceptionInfo(exception, (LazyTraceback) null, PythonOptions.isPExceptionWithJavaStacktrace(language)));
158163
return PNone.NO_VALUE;
@@ -609,7 +614,7 @@ Object setCause(Object exc,
609614
@CApiBuiltin(ret = Void, args = {PyObject, PyObject}, call = Direct)
610615
abstract static class PyException_SetContext extends CApiBinaryBuiltinNode {
611616
@Specialization
612-
Object setCause(Object exc, Object context,
617+
Object setContext(Object exc, Object context,
613618
@Cached PyObjectSetAttr setAttrNode) {
614619
setAttrNode.execute(exc, T___CONTEXT__, context);
615620
return PNone.NONE;
@@ -620,15 +625,10 @@ Object setCause(Object exc, Object context,
620625
abstract static class PyException_SetTraceback extends CApiBinaryBuiltinNode {
621626

622627
@Specialization
623-
static int doClearTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
624-
self.clearTraceback();
625-
return 0;
626-
}
627-
628-
@Specialization
629-
static int doSetTraceback(PBaseException self, PTraceback tb) {
630-
self.setTraceback(tb);
631-
return 0;
628+
Object setTraceback(Object exc, Object traceback,
629+
@Cached PyObjectSetAttr setAttrNode) {
630+
setAttrNode.execute(exc, T___TRACEBACK__, traceback);
631+
return PNone.NONE;
632632
}
633633
}
634634
}

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,18 @@ public static Object getTraceback(Object self, @SuppressWarnings("unused") Objec
346346
}
347347

348348
@Specialization(guards = "!isNoValue(tb)")
349-
public static Object setTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
350-
self.clearTraceback();
349+
public static Object setTraceback(Object self, @SuppressWarnings("unused") PNone tb,
350+
@Bind("this") Node inliningTarget,
351+
@Shared @Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
352+
setTracebackNode.execute(inliningTarget, self, PNone.NONE);
351353
return PNone.NONE;
352354
}
353355

354356
@Specialization
355-
public static Object setTraceback(PBaseException self, PTraceback tb) {
356-
self.setTraceback(tb);
357+
public static Object setTraceback(Object self, PTraceback tb,
358+
@Bind("this") Node inliningTarget,
359+
@Shared @Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
360+
setTracebackNode.execute(inliningTarget, self, tb);
357361
return PNone.NONE;
358362
}
359363

@@ -368,14 +372,18 @@ public Object setTraceback(@SuppressWarnings("unused") Object self, @SuppressWar
368372
public abstract static class WithTracebackNode extends PythonBinaryBuiltinNode {
369373

370374
@Specialization
371-
static PBaseException doClearTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
372-
self.clearTraceback();
375+
static Object doClearTraceback(Object self, @SuppressWarnings("unused") PNone tb,
376+
@Bind("this") Node inliningTarget,
377+
@Shared @Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
378+
setTracebackNode.execute(inliningTarget, self, PNone.NONE);
373379
return self;
374380
}
375381

376382
@Specialization
377-
static PBaseException doSetTraceback(PBaseException self, PTraceback tb) {
378-
self.setTraceback(tb);
383+
static Object doSetTraceback(Object self, PTraceback tb,
384+
@Bind("this") Node inliningTarget,
385+
@Shared @Cached ExceptionNodes.SetTracebackNode setTracebackNode) {
386+
setTracebackNode.execute(inliningTarget, self, tb);
379387
return self;
380388
}
381389
}

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,40 @@ static Object doForeign(@SuppressWarnings("unused") AbstractTruffleException e)
257257
return PNone.NONE;
258258
}
259259
}
260+
261+
@GenerateUncached
262+
@GenerateInline
263+
@GenerateCached(false)
264+
public abstract static class SetTracebackNode extends Node {
265+
public abstract void execute(Node inliningTarget, Object exception, Object value);
266+
267+
public static void executeUncached(Object e, Object value) {
268+
ExceptionNodesFactory.SetTracebackNodeGen.getUncached().execute(null, e, value);
269+
}
270+
271+
@Specialization
272+
static void doManaged(PBaseException exception, @SuppressWarnings("unused") PNone value) {
273+
exception.clearTraceback();
274+
}
275+
276+
@Specialization
277+
static void doManaged(PBaseException exception, PTraceback value) {
278+
exception.setTraceback(value);
279+
}
280+
281+
@Specialization(guards = "check.execute(inliningTarget, exception)")
282+
static void doNative(@SuppressWarnings("unused") Node inliningTarget, PythonAbstractNativeObject exception, Object value,
283+
@SuppressWarnings("unused") @Cached PyExceptionInstanceCheckNode check,
284+
@Cached CApiTransitions.PythonToNativeNode excToNative,
285+
@Cached CApiTransitions.PythonToNativeNode valueToNative,
286+
@Cached CExtNodes.PCallCapiFunction callGetter) {
287+
callGetter.call(NativeMember.TRACEBACK.getSetterFunctionName(), excToNative.execute(exception), valueToNative.execute(noneToNoValue(value)));
288+
}
289+
290+
@Specialization
291+
@SuppressWarnings("unused")
292+
static void doInterop(Node inliningTarget, AbstractTruffleException exception, Object value) {
293+
throw PRaiseNode.raiseUncached(inliningTarget, TypeError, ErrorMessages.CANNOT_SET_PROPERTY_ON_INTEROP_EXCEPTION);
294+
}
295+
}
260296
}

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

Lines changed: 26 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@
5555
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5656
import com.oracle.graal.python.builtins.PythonBuiltins;
5757
import com.oracle.graal.python.builtins.objects.PNone;
58+
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
5859
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
5960
import com.oracle.graal.python.builtins.objects.exception.PrepareExceptionNode;
6061
import com.oracle.graal.python.builtins.objects.frame.PFrame;
6162
import com.oracle.graal.python.builtins.objects.function.PArguments;
62-
import com.oracle.graal.python.builtins.objects.traceback.MaterializeLazyTracebackNode;
6363
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
6464
import com.oracle.graal.python.nodes.ErrorMessages;
6565
import com.oracle.graal.python.nodes.PGuards;
@@ -80,7 +80,6 @@
8080
import com.oracle.graal.python.runtime.exception.PException;
8181
import com.oracle.graal.python.util.PythonUtils;
8282
import com.oracle.truffle.api.CallTarget;
83-
import com.oracle.truffle.api.CompilerDirectives;
8483
import com.oracle.truffle.api.RootCallTarget;
8584
import com.oracle.truffle.api.dsl.Bind;
8685
import com.oracle.truffle.api.dsl.Cached;
@@ -274,38 +273,38 @@ Object send(VirtualFrame frame, PGenerator self, Object value,
274273
@GenerateNodeFactory
275274
public abstract static class ThrowNode extends PythonQuaternaryBuiltinNode {
276275

277-
@Child private MaterializeFrameNode materializeFrameNode;
278-
@Child private MaterializeLazyTracebackNode materializeLazyTracebackNode;
279-
280276
@Specialization
281-
Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object val, @SuppressWarnings("unused") PNone tb,
277+
Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object val, Object tb,
278+
@Bind("this") Node inliningTarget,
279+
@Cached InlinedConditionProfile hasTbProfile,
280+
@Cached InlinedConditionProfile startedProfile,
281+
@Cached InlinedBranchProfile invalidTbProfile,
282+
@Cached InlinedBranchProfile runningProfile,
282283
@Cached PrepareExceptionNode prepareExceptionNode,
283-
@Cached ResumeGeneratorNode resumeGeneratorNode) {
284-
if (self.isRunning()) {
285-
throw raise(ValueError, ErrorMessages.GENERATOR_ALREADY_EXECUTING);
284+
@Cached ResumeGeneratorNode resumeGeneratorNode,
285+
@Cached ExceptionNodes.GetTracebackNode getTracebackNode,
286+
@Cached ExceptionNodes.SetTracebackNode setTracebackNode,
287+
@Cached ExceptionNodes.SetContextNode setContextNode) {
288+
boolean hasTb = hasTbProfile.profile(inliningTarget, !(tb instanceof PNone));
289+
if (hasTb && !(tb instanceof PTraceback)) {
290+
invalidTbProfile.enter(inliningTarget);
291+
throw raise(TypeError, ErrorMessages.THROW_THIRD_ARG_MUST_BE_TRACEBACK);
286292
}
287-
PBaseException instance = prepareExceptionNode.execute(frame, typ, val);
288-
return doThrow(frame, resumeGeneratorNode, self, instance, getLanguage());
289-
}
290-
291-
@Specialization
292-
Object sendThrow(VirtualFrame frame, PGenerator self, Object typ, Object val, PTraceback tb,
293-
@Cached PrepareExceptionNode prepareExceptionNode,
294-
@Cached ResumeGeneratorNode resumeGeneratorNode) {
295293
if (self.isRunning()) {
294+
runningProfile.enter(inliningTarget);
296295
throw raise(ValueError, ErrorMessages.GENERATOR_ALREADY_EXECUTING);
297296
}
298297
PBaseException instance = prepareExceptionNode.execute(frame, typ, val);
299-
instance.setTraceback(tb);
300-
return doThrow(frame, resumeGeneratorNode, self, instance, getLanguage());
301-
}
302-
303-
private Object doThrow(VirtualFrame frame, ResumeGeneratorNode resumeGeneratorNode, PGenerator self, PBaseException instance, PythonLanguage language) {
304-
instance.setContext(null); // Will be filled when caught
298+
if (hasTb) {
299+
setTracebackNode.execute(inliningTarget, instance, tb);
300+
}
301+
PythonLanguage language = getLanguage();
302+
setContextNode.execute(inliningTarget, instance, PNone.NONE); // Will be filled when
303+
// caught
305304
if (self.isCoroutine() && self.isFinished()) {
306305
throw raise(PythonBuiltinClassType.RuntimeError, ErrorMessages.CANNOT_REUSE_CORO);
307306
}
308-
if (self.isStarted() && !self.isFinished()) {
307+
if (startedProfile.profile(inliningTarget, self.isStarted() && !self.isFinished())) {
309308
instance.ensureReified();
310309
// Pass it to the generator where it will be thrown by the last yield, the location
311310
// will be filled there
@@ -321,37 +320,12 @@ private Object doThrow(VirtualFrame frame, ResumeGeneratorNode resumeGeneratorNo
321320
PFrame pFrame = MaterializeFrameNode.materializeGeneratorFrame(location, generatorFrame, PFrame.Reference.EMPTY, factory());
322321
FrameInfo info = (FrameInfo) generatorFrame.getFrameDescriptor().getInfo();
323322
pFrame.setLine(info.getRootNode().getFirstLineno());
324-
PTraceback existingTraceback = null;
325-
if (instance.getTraceback() != null) {
326-
existingTraceback = ensureGetTracebackNode().execute(instance.getTraceback());
327-
}
328-
PTraceback newTraceback = factory().createTraceback(pFrame, pFrame.getLine(), existingTraceback);
329-
instance.setTraceback(newTraceback);
323+
Object existingTracebackObj = getTracebackNode.execute(inliningTarget, instance);
324+
PTraceback newTraceback = factory().createTraceback(pFrame, pFrame.getLine(), (existingTracebackObj instanceof PTraceback existingTraceback) ? existingTraceback : null);
325+
setTracebackNode.execute(inliningTarget, instance, newTraceback);
330326
throw PException.fromObject(instance, location, PythonOptions.isPExceptionWithJavaStacktrace(language));
331327
}
332328
}
333-
334-
@Specialization(guards = {"!isPNone(tb)", "!isPTraceback(tb)"})
335-
@SuppressWarnings("unused")
336-
Object doError(VirtualFrame frame, PGenerator self, Object typ, Object val, Object tb) {
337-
throw raise(TypeError, ErrorMessages.THROW_THIRD_ARG_MUST_BE_TRACEBACK);
338-
}
339-
340-
private MaterializeFrameNode ensureMaterializeFrameNode() {
341-
if (materializeFrameNode == null) {
342-
CompilerDirectives.transferToInterpreterAndInvalidate();
343-
materializeFrameNode = insert(MaterializeFrameNode.create());
344-
}
345-
return materializeFrameNode;
346-
}
347-
348-
private MaterializeLazyTracebackNode ensureGetTracebackNode() {
349-
if (materializeLazyTracebackNode == null) {
350-
CompilerDirectives.transferToInterpreterAndInvalidate();
351-
materializeLazyTracebackNode = insert(MaterializeLazyTracebackNode.create());
352-
}
353-
return materializeLazyTracebackNode;
354-
}
355329
}
356330

357331
@Builtin(name = "close", minNumOfPositionalArgs = 1)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyTraceBackPrintNode.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import com.oracle.graal.python.builtins.objects.PNone;
5959
import com.oracle.graal.python.builtins.objects.code.PCode;
6060
import com.oracle.graal.python.builtins.objects.exception.ExceptionNodes;
61-
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
6261
import com.oracle.graal.python.builtins.objects.frame.PFrame;
6362
import com.oracle.graal.python.builtins.objects.ints.PInt;
6463
import com.oracle.graal.python.builtins.objects.module.PythonModule;
@@ -199,10 +198,14 @@ public static Object getObjectClass(Object object) {
199198
return InlinedGetClassNode.executeUncached(object);
200199
}
201200

202-
public static Object getExceptionTraceback(PBaseException e) {
201+
public static Object getExceptionTraceback(Object e) {
203202
return ExceptionNodes.GetTracebackNode.executeUncached(e);
204203
}
205204

205+
public static void setExceptionTraceback(Object e, Object tb) {
206+
ExceptionNodes.SetTracebackNode.executeUncached(e, tb);
207+
}
208+
206209
public static boolean checkLong(Object object) {
207210
return PyLongCheckNodeGen.getUncached().execute(object);
208211
}

0 commit comments

Comments
 (0)