45
45
import com .oracle .graal .python .builtins .objects .frame .PFrame ;
46
46
import com .oracle .graal .python .builtins .objects .function .PArguments ;
47
47
import com .oracle .graal .python .nodes .PRootNode ;
48
+ import com .oracle .graal .python .nodes .bytecode_dsl .PBytecodeDSLRootNode ;
48
49
import com .oracle .graal .python .runtime .IndirectCallData ;
49
50
import com .oracle .truffle .api .CompilerDirectives ;
50
51
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
@@ -156,42 +157,42 @@ public PFrame executeWith(PFrame.Reference startFrameInfo, FrameInstance.FrameAc
156
157
for (int i = 0 ; i <= level ;) {
157
158
PFrame .Reference callerInfo = curFrameInfo .getCallerInfo ();
158
159
if (callerInfo == null ) {
159
- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
160
- if (callerFrame != null ) {
161
- return ensureMaterializeNode ().execute (false , true , callerFrame );
162
- }
163
- return null ;
160
+ return getMaterializedCallerFrame (startFrameInfo , frameAccess , selector , level );
164
161
} else if (!selector .skip (callerInfo .getRootNode ())) {
165
162
i ++;
166
163
}
167
164
curFrameInfo = callerInfo ;
168
165
}
166
+ return curFrameInfo .getPyFrame ();
169
167
} else {
170
- curFrameInfo = walkLevels (curFrameInfo , frameAccess , selector , level );
168
+ return walkLevels (curFrameInfo , frameAccess , selector , level );
169
+ }
170
+ }
171
+
172
+ private PFrame getMaterializedCallerFrame (PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
173
+ StackWalkResult callerFrameResult = getCallerFrame (startFrameInfo , frameAccess , selector , level );
174
+ if (callerFrameResult != null ) {
175
+ Node location = callerFrameResult .rootNode ;
176
+ if (location instanceof PBytecodeDSLRootNode rootNode ) {
177
+ location = rootNode .getBytecodeNode ();
178
+ }
179
+ return ensureMaterializeNode ().execute (location , false , true , callerFrameResult .frame );
171
180
}
172
- return curFrameInfo . getPyFrame () ;
181
+ return null ;
173
182
}
174
183
175
- private PFrame . Reference walkLevels (PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
184
+ private PFrame walkLevels (PFrame .Reference startFrameInfo , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
176
185
PFrame .Reference currentFrame = startFrameInfo ;
177
186
for (int i = 0 ; i <= level ;) {
178
187
PFrame .Reference callerInfo = currentFrame .getCallerInfo ();
179
188
if (cachedCallerFrameProfile .profile (callerInfo == null || callerInfo .getPyFrame () == null )) {
180
- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
181
- if (callerFrame != null ) {
182
- // At this point, we must 'materialize' the frame. Actually, the Truffle frame
183
- // is never materialized but we ensure that a corresponding PFrame is created
184
- // and that the locals and arguments are synced.
185
- ensureMaterializeNode ().execute (false , true , callerFrame );
186
- return PArguments .getCurrentFrameInfo (callerFrame );
187
- }
188
- return PFrame .Reference .EMPTY ;
189
+ return getMaterializedCallerFrame (startFrameInfo , frameAccess , selector , level );
189
190
} else if (!selector .skip (callerInfo .getRootNode ())) {
190
191
i ++;
191
192
}
192
193
currentFrame = callerInfo ;
193
194
}
194
- return currentFrame ;
195
+ return currentFrame . getPyFrame () ;
195
196
}
196
197
197
198
/**
@@ -258,7 +259,11 @@ private PFrame.Reference walkLevels(PFrame.Reference startFrameInfo, FrameInstan
258
259
* @param frameAccess - the desired {@link FrameInstance} access kind
259
260
*/
260
261
public static Frame getCurrentFrame (Node requestingNode , FrameInstance .FrameAccess frameAccess ) {
261
- return getFrame (Objects .requireNonNull (requestingNode ), null , frameAccess , AllFramesSelector .INSTANCE , 0 );
262
+ StackWalkResult result = getFrame (Objects .requireNonNull (requestingNode ), null , frameAccess , AllFramesSelector .INSTANCE , 0 );
263
+ if (result != null ) {
264
+ return result .frame ;
265
+ }
266
+ return null ;
262
267
}
263
268
264
269
/**
@@ -272,14 +277,17 @@ public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAcce
272
277
* @param selector - declares which frames should be skipped or counted
273
278
* @param level - the stack depth to go to. Ignored if {@code startFrame} is {@code null}
274
279
*/
275
- public static Frame getCallerFrame (PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
280
+ public static StackWalkResult getCallerFrame (PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
276
281
CompilerDirectives .transferToInterpreterAndInvalidate ();
277
282
return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , selector , level );
278
283
}
279
284
285
+ public record StackWalkResult (PRootNode rootNode , Frame frame ) {
286
+ }
287
+
280
288
@ TruffleBoundary
281
- private static Frame getFrame (Node requestingNode , PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
282
- Frame [] outputFrame = new Frame [1 ];
289
+ private static StackWalkResult getFrame (Node requestingNode , PFrame .Reference startFrame , FrameInstance .FrameAccess frameAccess , FrameSelector selector , int level ) {
290
+ StackWalkResult [] result = new StackWalkResult [1 ];
283
291
Truffle .getRuntime ().iterateFrames (new FrameInstanceVisitor <>() {
284
292
int i = -1 ;
285
293
@@ -288,8 +296,8 @@ private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame,
288
296
* associated with it may have been called from a different language, and thus not be
289
297
* able to pass the caller frame. That means that we cannot immediately return when we
290
298
* find the correct level frame, but instead we need to remember the frame in
291
- * {@code outputFrame } and then keep going until we find the previous Python caller on
292
- * the stack (or not). That last Python caller should have {@link IndirectCallData} that
299
+ * {@code result } and then keep going until we find the previous Python caller on the
300
+ * stack (or not). That last Python caller should have {@link IndirectCallData} that
293
301
* will be marked to pass the frame through the context.
294
302
*
295
303
* <pre>
@@ -308,13 +316,13 @@ private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame,
308
316
* ================
309
317
* </pre>
310
318
*/
311
- public Frame visitFrame (FrameInstance frameInstance ) {
319
+ public StackWalkResult visitFrame (FrameInstance frameInstance ) {
312
320
RootNode rootNode = getRootNode (frameInstance );
313
321
Node callNode = frameInstance .getCallNode ();
314
322
boolean didMark = IndirectCallData .setEncapsulatingNeedsToPassCallerFrame (callNode != null ? callNode : requestingNode );
315
323
if (rootNode instanceof PRootNode pRootNode && pRootNode .setsUpCalleeContext ()) {
316
- if (outputFrame [0 ] != null ) {
317
- return outputFrame [0 ];
324
+ if (result [0 ] != null ) {
325
+ return result [0 ];
318
326
}
319
327
boolean needsCallerFrame = true ;
320
328
if (i < 0 && startFrame != null ) {
@@ -329,7 +337,7 @@ public Frame visitFrame(FrameInstance frameInstance) {
329
337
if (i == level || startFrame == null ) {
330
338
Frame frame = getFrame (frameInstance , frameAccess );
331
339
assert PArguments .isPythonFrame (frame );
332
- outputFrame [0 ] = frame ;
340
+ result [0 ] = new StackWalkResult ( pRootNode , frame ) ;
333
341
needsCallerFrame = false ;
334
342
}
335
343
i += 1 ;
@@ -340,13 +348,13 @@ public Frame visitFrame(FrameInstance frameInstance) {
340
348
}
341
349
}
342
350
if (didMark ) {
343
- return outputFrame [0 ];
351
+ return result [0 ];
344
352
} else {
345
353
return null ;
346
354
}
347
355
}
348
356
});
349
- return outputFrame [0 ];
357
+ return result [0 ];
350
358
}
351
359
352
360
private static RootNode getRootNode (FrameInstance frameInstance ) {
0 commit comments