Skip to content

Commit 51f63d8

Browse files
committed
Add an interface for state assumptions that all nodes using the IndirectCallContext.enter method must implement and use stackWalk when top frame info wasn't pushed
1 parent 00f3601 commit 51f63d8

22 files changed

+505
-168
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,7 +2192,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
21922192
// Make slots into a tuple
21932193
}
21942194
PythonContext context = getContextRef().get();
2195-
PException caughtException = ForeignCallContext.enter(frame, context, this);
2195+
Object state = ForeignCallContext.enter(frame, context, this);
21962196
try {
21972197
PTuple newSlots = copySlots(name, slotList, slotlen, addDict, false, namespace);
21982198
pythonClass.setAttribute(__SLOTS__, newSlots);
@@ -2206,7 +2206,7 @@ private PythonClass typeMetaclass(VirtualFrame frame, String name, PTuple bases,
22062206
addNativeSlots(pythonClass, newSlots);
22072207
}
22082208
} finally {
2209-
ForeignCallContext.exit(frame, context, caughtException);
2209+
ForeignCallContext.exit(frame, context, state);
22102210
}
22112211
}
22122212

@@ -2670,15 +2670,15 @@ Object methodBuiltin(@SuppressWarnings("unused") LazyPythonClass cls, PBuiltinFu
26702670
Object methodGeneric(VirtualFrame frame, @SuppressWarnings("unused") LazyPythonClass cls, Object func, Object self,
26712671
@CachedLibrary(limit = "3") PythonObjectLibrary dataModelLibrary) {
26722672
PythonContext context = getContextRef().get();
2673-
PException caughtException = IndirectCallContext.enter(frame, context, this);
2673+
Object state = IndirectCallContext.enter(frame, context, this);
26742674
try {
26752675
if (dataModelLibrary.isCallable(func)) {
26762676
return factory().createMethod(self, func);
26772677
} else {
26782678
throw raise(TypeError, "first argument must be callable");
26792679
}
26802680
} finally {
2681-
IndirectCallContext.exit(frame, context, caughtException);
2681+
IndirectCallContext.exit(frame, context, state);
26822682
}
26832683
}
26842684
}
@@ -2822,11 +2822,11 @@ protected boolean isBuiltinMapping(Object o) {
28222822

28232823
protected boolean isSequence(VirtualFrame frame, Object o, PythonObjectLibrary library) {
28242824
PythonContext context = getContextRef().get();
2825-
PException caughtException = IndirectCallContext.enter(frame, context, this);
2825+
Object state = IndirectCallContext.enter(frame, context, this);
28262826
try {
28272827
return library.isSequence(o);
28282828
} finally {
2829-
IndirectCallContext.exit(frame, context, caughtException);
2829+
IndirectCallContext.exit(frame, context, state);
28302830
}
28312831
}
28322832
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ public abstract static class CreateDynamic extends PythonBuiltinNode {
176176
public Object run(VirtualFrame frame, PythonObject moduleSpec, @SuppressWarnings("unused") Object filename,
177177
@CachedLibrary(limit = "1") InteropLibrary interop) {
178178
PythonContext context = getContextRef().get();
179-
PException caughtException = ForeignCallContext.enter(frame, context, this);
179+
Object state = ForeignCallContext.enter(frame, context, this);
180180
try {
181181
return run(moduleSpec, interop);
182182
} finally {
183-
ForeignCallContext.exit(frame, context, caughtException);
183+
ForeignCallContext.exit(frame, context, state);
184184
}
185185
}
186186

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,11 @@ private static FilterOptions createFilterById(int id) {
254254

255255
private boolean isSequence(VirtualFrame frame, ContextReference<PythonContext> contextRef, Object obj, PythonObjectLibrary library) {
256256
PythonContext context = contextRef.get();
257-
PException caughtException = IndirectCallContext.enter(frame, context, this);
257+
Object state = IndirectCallContext.enter(frame, context, this);
258258
try {
259259
return library.isSequence(obj);
260260
} finally {
261-
IndirectCallContext.exit(frame, context, caughtException);
261+
IndirectCallContext.exit(frame, context, state);
262262
}
263263
}
264264

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import com.oracle.graal.python.builtins.objects.str.PString;
6868
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
6969
import com.oracle.graal.python.builtins.objects.type.LazyPythonClass;
70+
import com.oracle.graal.python.nodes.IndirectCallNode;
7071
import com.oracle.graal.python.nodes.PNodeWithContext;
7172
import com.oracle.graal.python.nodes.PRaiseNode;
7273
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -76,9 +77,11 @@
7677
import com.oracle.graal.python.runtime.PythonContext;
7778
import com.oracle.graal.python.runtime.exception.PException;
7879
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
80+
import com.oracle.truffle.api.Assumption;
7981
import com.oracle.truffle.api.CompilerAsserts;
8082
import com.oracle.truffle.api.CompilerDirectives;
8183
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
84+
import com.oracle.truffle.api.Truffle;
8285
import com.oracle.truffle.api.dsl.Cached;
8386
import com.oracle.truffle.api.dsl.CachedContext;
8487
import com.oracle.truffle.api.dsl.Fallback;
@@ -504,11 +507,23 @@ public static MarshallerNode create() {
504507
}
505508
}
506509

507-
public abstract static class UnmarshallerNode extends PNodeWithState {
510+
public abstract static class UnmarshallerNode extends PNodeWithState implements IndirectCallNode {
508511
public abstract Object execute(VirtualFrame frame, byte[] dataBytes, int version);
509512

510513
@Child private HashingStorageNodes.SetItemNode setItemNode;
511514
@Child private CodeNodes.CreateCodeNode createCodeNode;
515+
private final Assumption dontNeedExceptionState = Truffle.getRuntime().createAssumption();
516+
private final Assumption dontNeedCallerFrame = Truffle.getRuntime().createAssumption();
517+
518+
@Override
519+
public Assumption needNotPassFrameAssumption() {
520+
return dontNeedCallerFrame;
521+
}
522+
523+
@Override
524+
public Assumption needNotPassExceptionAssumption() {
525+
return dontNeedExceptionState;
526+
}
512527

513528
private int index;
514529
private byte[] data;
@@ -739,11 +754,11 @@ Object readObject(VirtualFrame frame, byte[] dataBytes, @SuppressWarnings("unuse
739754
@CachedContext(PythonLanguage.class) PythonContext context) {
740755
reset();
741756
this.data = dataBytes;
742-
PException savedExceptionState = IndirectCallContext.enter(frame, context, this);
757+
Object state = IndirectCallContext.enter(frame, context, this);
743758
try {
744759
return readObject(0);
745760
} finally {
746-
IndirectCallContext.exit(frame, context, savedExceptionState);
761+
IndirectCallContext.exit(frame, context, state);
747762
}
748763
}
749764

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
import com.oracle.graal.python.runtime.PosixResources;
7272
import com.oracle.graal.python.runtime.PythonContext;
7373
import com.oracle.graal.python.runtime.PythonOptions;
74-
import com.oracle.graal.python.runtime.exception.PException;
7574
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
7675
import com.oracle.truffle.api.dsl.Cached;
7776
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -102,12 +101,12 @@ int forkExec(VirtualFrame frame, PList args, @SuppressWarnings("unused") PList e
102101
@SuppressWarnings("unused") boolean restore_signals, @SuppressWarnings("unused") boolean call_setsid, @SuppressWarnings("unused") PNone preexec_fn) {
103102

104103
PythonContext context = getContext();
105-
PException caughtException = IndirectCallContext.enter(frame, context, this);
104+
Object state = IndirectCallContext.enter(frame, context, this);
106105
try {
107106
return forkExec(args, execList, closeFds, fdsToKeep, cwd, env, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, errpipe_read, errpipe_write, restore_signals, call_setsid,
108107
preexec_fn);
109108
} finally {
110-
IndirectCallContext.exit(frame, context, caughtException);
109+
IndirectCallContext.exit(frame, context, state);
111110
}
112111
}
113112

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

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
145145
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
146146
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetTypeFlagsNode;
147+
import com.oracle.graal.python.nodes.IndirectCallNode;
147148
import com.oracle.graal.python.nodes.PGuards;
148149
import com.oracle.graal.python.nodes.PNodeWithContext;
149150
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -196,8 +197,10 @@
196197
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
197198
import com.oracle.graal.python.runtime.sequence.storage.MroSequenceStorage;
198199
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
200+
import com.oracle.truffle.api.Assumption;
199201
import com.oracle.truffle.api.CompilerAsserts;
200202
import com.oracle.truffle.api.CompilerDirectives;
203+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
201204
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
202205
import com.oracle.truffle.api.RootCallTarget;
203206
import com.oracle.truffle.api.Truffle;
@@ -767,7 +770,7 @@ public static CheckFunctionResultNode create() {
767770
}
768771
}
769772

770-
abstract static class ExternalFunctionNode extends PRootNode {
773+
abstract static class ExternalFunctionNode extends PRootNode implements IndirectCallNode {
771774
private final Signature signature;
772775
private final TruffleObject cwrapper;
773776
private final TruffleObject callable;
@@ -777,6 +780,26 @@ abstract static class ExternalFunctionNode extends PRootNode {
777780
@Child private PForeignToPTypeNode fromForeign = PForeignToPTypeNode.create();
778781
@Child private InteropLibrary lib;
779782
@Child private CalleeContext calleeContext = CalleeContext.create();
783+
@CompilationFinal private Assumption nativeCodeDoesntNeedExceptionState = Truffle.getRuntime().createAssumption();
784+
@CompilationFinal private Assumption nativeCodeDoesntNeedMyFrame = Truffle.getRuntime().createAssumption();
785+
786+
@Override
787+
public Assumption needNotPassFrameAssumption() {
788+
return nativeCodeDoesntNeedMyFrame;
789+
}
790+
791+
@Override
792+
public Assumption needNotPassExceptionAssumption() {
793+
return nativeCodeDoesntNeedExceptionState;
794+
}
795+
796+
@Override
797+
public Node copy() {
798+
ExternalFunctionNode node = (ExternalFunctionNode) super.copy();
799+
node.nativeCodeDoesntNeedMyFrame = Truffle.getRuntime().createAssumption();
800+
node.nativeCodeDoesntNeedExceptionState = Truffle.getRuntime().createAssumption();
801+
return node;
802+
}
780803

781804
ExternalFunctionNode(PythonLanguage lang, String name, TruffleObject cwrapper, TruffleObject callable, Signature signature) {
782805
super(lang);
@@ -815,7 +838,7 @@ Object doIt(VirtualFrame frame,
815838
}
816839
// If any code requested the caught exception (i.e. used 'sys.exc_info()'), we store
817840
// it to the context since we cannot propagate it through the native frames.
818-
PException savedExceptionState = ForeignCallContext.enter(frame, ctx, this);
841+
Object state = ForeignCallContext.enter(frame, ctx, this);
819842

820843
try {
821844
return fromNative(asPythonObjectNode.execute(checkResultNode.execute(name, lib.execute(fun, arguments))));
@@ -827,7 +850,7 @@ Object doIt(VirtualFrame frame,
827850
// special case after calling a C function: transfer caught exception back to frame
828851
// to simulate the global state semantics
829852
PArguments.setException(frame, ctx.getCaughtException());
830-
ForeignCallContext.exit(frame, ctx, savedExceptionState);
853+
ForeignCallContext.exit(frame, ctx, state);
831854
calleeContext.exit(frame, this);
832855
}
833856
}
@@ -2446,11 +2469,11 @@ abstract static class PyFloat_AsDouble extends PythonUnaryBuiltinNode {
24462469
@Shared("asPythonObjectNode") @Cached CExtNodes.AsPythonObjectNode asPythonObjectNode,
24472470
@Shared("asDoubleNode") @Cached CExtNodes.AsNativeDoubleNode asDoubleNode,
24482471
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
2449-
PException exceptionState = IndirectCallContext.enter(frame, context, this);
2472+
Object state = IndirectCallContext.enter(frame, context, this);
24502473
try {
24512474
return asDoubleNode.execute(asPythonObjectNode.execute(object));
24522475
} finally {
2453-
IndirectCallContext.exit(frame, context, exceptionState);
2476+
IndirectCallContext.exit(frame, context, state);
24542477
}
24552478
}
24562479

@@ -2684,11 +2707,11 @@ boolean doGeneric(VirtualFrame frame, Object object,
26842707
@CachedLibrary(limit = "1") PythonObjectLibrary dataModelLibrary,
26852708
@CachedContext(PythonLanguage.class) ContextReference<PythonContext> contextRef) {
26862709
PythonContext context = contextRef.get();
2687-
PException caughtException = IndirectCallContext.enter(frame, context, this);
2710+
Object state = IndirectCallContext.enter(frame, context, this);
26882711
try {
26892712
return dataModelLibrary.isSequence(object);
26902713
} finally {
2691-
IndirectCallContext.exit(frame, context, caughtException);
2714+
IndirectCallContext.exit(frame, context, state);
26922715
}
26932716
}
26942717
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
6565
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
6666
import com.oracle.graal.python.runtime.PythonContext;
67-
import com.oracle.graal.python.runtime.exception.PException;
6867
import com.oracle.graal.python.runtime.exception.PythonErrorType;
6968
import com.oracle.truffle.api.CompilerAsserts;
7069
import com.oracle.truffle.api.CompilerDirectives;
@@ -207,7 +206,7 @@ Object call(VirtualFrame frame, Object callable, Object arg1, Object arg2,
207206
@Cached("create()") BranchProfile typeError,
208207
@CachedLibrary("callable") InteropLibrary interop,
209208
@CachedContext(PythonLanguage.class) PythonContext context) {
210-
PException savedExceptionState = IndirectCallContext.enter(frame, context, this);
209+
Object state = IndirectCallContext.enter(frame, context, this);
211210
try {
212211
return interop.execute(callable, arg1, arg2);
213212
} catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) {
@@ -221,7 +220,7 @@ Object call(VirtualFrame frame, Object callable, Object arg1, Object arg2,
221220
// just re-throw
222221
throw e;
223222
} finally {
224-
IndirectCallContext.exit(frame, context, savedExceptionState);
223+
IndirectCallContext.exit(frame, context, state);
225224
}
226225
}
227226
}
@@ -236,14 +235,14 @@ Object call(VirtualFrame frame, Object callable, Object arg1, Number arg2,
236235
@Cached("create()") BranchProfile typeError,
237236
@CachedLibrary("callable") InteropLibrary interop,
238237
@CachedContext(PythonLanguage.class) PythonContext context) {
239-
PException savedExceptionState = IndirectCallContext.enter(frame, context, this);
238+
Object state = IndirectCallContext.enter(frame, context, this);
240239
try {
241240
return interop.execute(callable, arg1, arg2);
242241
} catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) {
243242
typeError.enter();
244243
throw raise(TypeError, "%s", e);
245244
} finally {
246-
IndirectCallContext.exit(frame, context, savedExceptionState);
245+
IndirectCallContext.exit(frame, context, state);
247246
}
248247
}
249248
}

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

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
102102
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode.LookupAndCallUnaryDynamicNode;
103103
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
104+
import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode;
104105
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
105106
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
106107
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -131,6 +132,7 @@
131132
import com.oracle.truffle.api.dsl.Specialization;
132133
import com.oracle.truffle.api.dsl.TypeSystemReference;
133134
import com.oracle.truffle.api.frame.Frame;
135+
import com.oracle.truffle.api.frame.FrameInstance;
134136
import com.oracle.truffle.api.frame.VirtualFrame;
135137
import com.oracle.truffle.api.interop.ArityException;
136138
import com.oracle.truffle.api.interop.InteropLibrary;
@@ -2267,16 +2269,42 @@ void doWithFrame(Frame frame, PException e,
22672269
transformToNative(context, PArguments.getCurrentFrameInfo(frame), e);
22682270
}
22692271

2272+
protected static ConditionProfile[] getFlag() {
2273+
ConditionProfile[] flag = new ConditionProfile[1];
2274+
return flag;
2275+
}
2276+
22702277
@Specialization(guards = "frame == null")
22712278
void doWithoutFrame(@SuppressWarnings("unused") Frame frame, PException e,
2279+
@Cached(value = "getFlag()", dimensions = 1) ConditionProfile[] flag,
22722280
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
2273-
transformToNative(context, context.peekTopFrameInfo(), e);
2281+
PFrame.Reference ref = context.peekTopFrameInfo();
2282+
if (flag[0] == null) {
2283+
CompilerDirectives.transferToInterpreterAndInvalidate();
2284+
// executed the first time, don't pollute the profile, we'll mark the caller to pass the info on the next call
2285+
flag[0] = ConditionProfile.createBinaryProfile();
2286+
if (ref == null) {
2287+
ref = PArguments.getCurrentFrameInfo(ReadCallerFrameNode.getCallerFrame(null, FrameInstance.FrameAccess.READ_ONLY, true, 0));
2288+
}
2289+
}
2290+
if (flag[0].profile(ref == null)) {
2291+
ref = PArguments.getCurrentFrameInfo(ReadCallerFrameNode.getCallerFrame(null, FrameInstance.FrameAccess.READ_ONLY, true, 0));
2292+
}
2293+
transformToNative(context, ref, e);
22742294
}
22752295

22762296
@Specialization(replaces = {"doWithFrame", "doWithoutFrame"})
22772297
void doGeneric(Frame frame, PException e,
22782298
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
2279-
PFrame.Reference ref = frame == null ? context.peekTopFrameInfo() : PArguments.getCurrentFrameInfo(frame);
2299+
PFrame.Reference ref;
2300+
if (frame == null) {
2301+
ref = context.peekTopFrameInfo();
2302+
if (ref == null) {
2303+
ref = PArguments.getCurrentFrameInfo(ReadCallerFrameNode.getCallerFrame(ref, FrameInstance.FrameAccess.READ_ONLY, true, 0));
2304+
}
2305+
} else {
2306+
ref = PArguments.getCurrentFrameInfo(frame);
2307+
}
22802308
transformToNative(context, ref, e);
22812309
}
22822310

0 commit comments

Comments
 (0)