62
62
63
63
@ NodeInfo (shortName = "read_caller_fame" )
64
64
public final class ReadCallerFrameNode extends Node {
65
+ public enum FrameSelector {
66
+ ALL_PYTHON_FRAMES {
67
+ @ Override
68
+ public boolean skip (RootNode rootNode ) {
69
+ return false ;
70
+ }
71
+ },
72
+ /**
73
+ * Skips any internal code frames including internal Python level frames.
74
+ */
75
+ SKIP_PYTHON_INTERNAL {
76
+ @ Override
77
+ public boolean skip (RootNode rootNode ) {
78
+ return PRootNode .isPythonInternal (rootNode );
79
+ }
80
+ },
81
+ /**
82
+ * Skips only builtins frames, not internal Python level frames.
83
+ */
84
+ SKIP_PYTHON_BUILTIN {
85
+ @ Override
86
+ public boolean skip (RootNode rootNode ) {
87
+ return PRootNode .isPythonBuiltin (rootNode );
88
+ }
89
+ };
90
+
91
+ public abstract boolean skip (RootNode rootNode );
92
+
93
+ public final boolean skip (PFrame .Reference ref ) {
94
+ Node callNode = ref .getCallNode ();
95
+ return callNode == null || skip (callNode .getRootNode ());
96
+ }
97
+ }
98
+
65
99
@ CompilationFinal private ConditionProfile cachedCallerFrameProfile ;
66
100
@ Child private MaterializeFrameNode materializeNode ;
67
101
@@ -73,26 +107,30 @@ public static ReadCallerFrameNode create() {
73
107
}
74
108
75
109
public final PFrame executeWith (VirtualFrame frame , int level ) {
76
- return executeWith (frame , PArguments .getCurrentFrameInfo (frame ), true , level );
110
+ return executeWith (frame , PArguments .getCurrentFrameInfo (frame ), FrameSelector .SKIP_PYTHON_INTERNAL , level );
111
+ }
112
+
113
+ public final PFrame executeWith (VirtualFrame frame , FrameSelector selector , int level ) {
114
+ return executeWith (frame , PArguments .getCurrentFrameInfo (frame ), selector , level );
77
115
}
78
116
79
117
public final PFrame executeWith (VirtualFrame frame , Frame startFrame , int level ) {
80
- return executeWith (frame , PArguments .getCurrentFrameInfo (startFrame ), true , level );
118
+ return executeWith (frame , PArguments .getCurrentFrameInfo (startFrame ), FrameSelector . SKIP_PYTHON_INTERNAL , level );
81
119
}
82
120
83
121
public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , int level ) {
84
- return executeWith (frame , startFrameInfo , true , level );
122
+ return executeWith (frame , startFrameInfo , FrameSelector . SKIP_PYTHON_INTERNAL , level );
85
123
}
86
124
87
125
public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , int level ) {
88
- return executeWith (frame , startFrameInfo , frameAccess , true , level );
126
+ return executeWith (frame , startFrameInfo , frameAccess , FrameSelector . SKIP_PYTHON_INTERNAL , level );
89
127
}
90
128
91
- public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , boolean skipInternal , int level ) {
92
- return executeWith (frame , startFrameInfo , FrameInstance .FrameAccess .READ_ONLY , skipInternal , level );
129
+ public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameSelector selector , int level ) {
130
+ return executeWith (frame , startFrameInfo , FrameInstance .FrameAccess .READ_ONLY , selector , level );
93
131
}
94
132
95
- public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , boolean skipInternal , int level ) {
133
+ public PFrame executeWith (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
96
134
PFrame .Reference curFrameInfo = startFrameInfo ;
97
135
if (cachedCallerFrameProfile == null ) {
98
136
CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -101,28 +139,28 @@ public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, F
101
139
for (int i = 0 ; i <= level ;) {
102
140
PFrame .Reference callerInfo = curFrameInfo .getCallerInfo ();
103
141
if (callerInfo == null ) {
104
- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , skipInternal , level );
142
+ Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
105
143
if (callerFrame != null ) {
106
144
return ensureMaterializeNode ().execute (frame , false , true , callerFrame );
107
145
}
108
146
return null ;
109
- } else if (!( skipInternal && ( callerInfo . getCallNode () == null || PRootNode . isPythonInternal ( callerInfo . getCallNode (). getRootNode ())) )) {
147
+ } else if (!selector . skip ( callerInfo )) {
110
148
i ++;
111
149
}
112
150
curFrameInfo = callerInfo ;
113
151
}
114
152
} else {
115
- curFrameInfo = walkLevels (frame , curFrameInfo , frameAccess , skipInternal , level );
153
+ curFrameInfo = walkLevels (frame , curFrameInfo , frameAccess , selector , level );
116
154
}
117
155
return curFrameInfo .getPyFrame ();
118
156
}
119
157
120
- private PFrame .Reference walkLevels (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , boolean skipInternal , int level ) {
158
+ private PFrame .Reference walkLevels (VirtualFrame frame , PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
121
159
PFrame .Reference currentFrame = startFrameInfo ;
122
160
for (int i = 0 ; i <= level ;) {
123
161
PFrame .Reference callerInfo = currentFrame .getCallerInfo ();
124
162
if (cachedCallerFrameProfile .profile (callerInfo == null )) {
125
- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , skipInternal , level );
163
+ Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
126
164
if (callerFrame != null ) {
127
165
// At this point, we must 'materialize' the frame. Actually, the Truffle frame
128
166
// is never materialized but we ensure that a corresponding PFrame is created
@@ -131,7 +169,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
131
169
return PArguments .getCurrentFrameInfo (callerFrame );
132
170
}
133
171
return PFrame .Reference .EMPTY ;
134
- } else if (!( skipInternal && ( callerInfo . getCallNode () == null || PRootNode . isPythonInternal ( callerInfo . getCallNode (). getRootNode ())) )) {
172
+ } else if (!selector . skip ( callerInfo )) {
135
173
i ++;
136
174
}
137
175
currentFrame = callerInfo ;
@@ -202,7 +240,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
202
240
*/
203
241
public static Frame getCurrentFrame (Node requestingNode , FrameInstance .FrameAccess frameAccess ) {
204
242
CompilerDirectives .transferToInterpreterAndInvalidate ();
205
- return getFrame (Objects .requireNonNull (requestingNode ), null , frameAccess , false , 0 );
243
+ return getFrame (Objects .requireNonNull (requestingNode ), null , frameAccess , FrameSelector . ALL_PYTHON_FRAMES , 0 );
206
244
}
207
245
208
246
/**
@@ -213,15 +251,15 @@ public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAcce
213
251
*
214
252
* @param startFrame - the frame to start counting from (must not be {@code null})
215
253
* @param frameAccess - the desired {@link FrameInstance} access kind
216
- * @param skipInternal - declares if Python internal frames should be skipped or counted
254
+ * @param selector - declares which frames should be skipped or counted
217
255
* @param level - the stack depth to go to. Ignored if {@code startFrame} is {@code null}
218
256
*/
219
- public static Frame getCallerFrame (PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , boolean skipInternal , int level ) {
257
+ public static Frame getCallerFrame (PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
220
258
CompilerDirectives .transferToInterpreterAndInvalidate ();
221
- return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , skipInternal , level );
259
+ return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , selector , level );
222
260
}
223
261
224
- private static Frame getFrame (Node requestingNode , PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , boolean skipInternal , int level ) {
262
+ private static Frame getFrame (Node requestingNode , PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
225
263
assert CompilerDirectives .inInterpreter ();
226
264
final Frame [] outputFrame = new Frame [1 ];
227
265
Truffle .getRuntime ().iterateFrames (new FrameInstanceVisitor <Frame >() {
@@ -272,7 +310,7 @@ public Frame visitFrame(FrameInstance frameInstance) {
272
310
} else {
273
311
// Skip frames of builtin functions (if requested) because these do not have
274
312
// a Python frame in CPython.
275
- if (!( skipInternal && pRootNode . isPythonInternal () )) {
313
+ if (!selector . skip ( pRootNode )) {
276
314
if (i == level || startFrame == null ) {
277
315
Frame frame = frameInstance .getFrame (frameAccess );
278
316
assert PArguments .isPythonFrame (frame );
0 commit comments