4545import com .oracle .graal .python .builtins .objects .frame .PFrame ;
4646import com .oracle .graal .python .builtins .objects .function .PArguments ;
4747import com .oracle .graal .python .nodes .PRootNode ;
48+ import com .oracle .graal .python .nodes .bytecode_dsl .PBytecodeDSLRootNode ;
4849import com .oracle .graal .python .runtime .IndirectCallData ;
4950import com .oracle .truffle .api .CompilerDirectives ;
5051import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
@@ -156,42 +157,42 @@ public PFrame executeWith(PFrame.Reference startFrameInfo, FrameInstance.FrameAc
156157 for (int i = 0 ; i <= level ;) {
157158 PFrame .Reference callerInfo = curFrameInfo .getCallerInfo ();
158159 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 );
164161 } else if (!selector .skip (callerInfo .getRootNode ())) {
165162 i ++;
166163 }
167164 curFrameInfo = callerInfo ;
168165 }
166+ return curFrameInfo .getPyFrame ();
169167 } 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 );
171180 }
172- return curFrameInfo . getPyFrame () ;
181+ return null ;
173182 }
174183
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 ) {
176185 PFrame .Reference currentFrame = startFrameInfo ;
177186 for (int i = 0 ; i <= level ;) {
178187 PFrame .Reference callerInfo = currentFrame .getCallerInfo ();
179188 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 );
189190 } else if (!selector .skip (callerInfo .getRootNode ())) {
190191 i ++;
191192 }
192193 currentFrame = callerInfo ;
193194 }
194- return currentFrame ;
195+ return currentFrame . getPyFrame () ;
195196 }
196197
197198 /**
@@ -258,7 +259,11 @@ private PFrame.Reference walkLevels(PFrame.Reference startFrameInfo, FrameInstan
258259 * @param frameAccess - the desired {@link FrameInstance} access kind
259260 */
260261 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 ;
262267 }
263268
264269 /**
@@ -272,14 +277,17 @@ public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAcce
272277 * @param selector - declares which frames should be skipped or counted
273278 * @param level - the stack depth to go to. Ignored if {@code startFrame} is {@code null}
274279 */
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 ) {
276281 CompilerDirectives .transferToInterpreterAndInvalidate ();
277282 return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , selector , level );
278283 }
279284
285+ public record StackWalkResult (PRootNode rootNode , Frame frame ) {
286+ }
287+
280288 @ 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 ];
283291 Truffle .getRuntime ().iterateFrames (new FrameInstanceVisitor <>() {
284292 int i = -1 ;
285293
@@ -288,8 +296,8 @@ private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame,
288296 * associated with it may have been called from a different language, and thus not be
289297 * able to pass the caller frame. That means that we cannot immediately return when we
290298 * 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
293301 * will be marked to pass the frame through the context.
294302 *
295303 * <pre>
@@ -308,13 +316,13 @@ private static Frame getFrame(Node requestingNode, PFrame.Reference startFrame,
308316 * ================
309317 * </pre>
310318 */
311- public Frame visitFrame (FrameInstance frameInstance ) {
319+ public StackWalkResult visitFrame (FrameInstance frameInstance ) {
312320 RootNode rootNode = getRootNode (frameInstance );
313321 Node callNode = frameInstance .getCallNode ();
314322 boolean didMark = IndirectCallData .setEncapsulatingNeedsToPassCallerFrame (callNode != null ? callNode : requestingNode );
315323 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 ];
318326 }
319327 boolean needsCallerFrame = true ;
320328 if (i < 0 && startFrame != null ) {
@@ -329,7 +337,7 @@ public Frame visitFrame(FrameInstance frameInstance) {
329337 if (i == level || startFrame == null ) {
330338 Frame frame = getFrame (frameInstance , frameAccess );
331339 assert PArguments .isPythonFrame (frame );
332- outputFrame [0 ] = frame ;
340+ result [0 ] = new StackWalkResult ( pRootNode , frame ) ;
333341 needsCallerFrame = false ;
334342 }
335343 i += 1 ;
@@ -340,13 +348,13 @@ public Frame visitFrame(FrameInstance frameInstance) {
340348 }
341349 }
342350 if (didMark ) {
343- return outputFrame [0 ];
351+ return result [0 ];
344352 } else {
345353 return null ;
346354 }
347355 }
348356 });
349- return outputFrame [0 ];
357+ return result [0 ];
350358 }
351359
352360 private static RootNode getRootNode (FrameInstance frameInstance ) {
0 commit comments