6262
6363@ NodeInfo (shortName = "read_caller_fame" )
6464public 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+
6599 @ CompilationFinal private ConditionProfile cachedCallerFrameProfile ;
66100 @ Child private MaterializeFrameNode materializeNode ;
67101
@@ -73,26 +107,30 @@ public static ReadCallerFrameNode create() {
73107 }
74108
75109 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 );
77115 }
78116
79117 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 );
81119 }
82120
83121 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 );
85123 }
86124
87125 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 );
89127 }
90128
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 );
93131 }
94132
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 ) {
96134 PFrame .Reference curFrameInfo = startFrameInfo ;
97135 if (cachedCallerFrameProfile == null ) {
98136 CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -101,28 +139,28 @@ public PFrame executeWith(VirtualFrame frame, PFrame.Reference startFrameInfo, F
101139 for (int i = 0 ; i <= level ;) {
102140 PFrame .Reference callerInfo = curFrameInfo .getCallerInfo ();
103141 if (callerInfo == null ) {
104- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , skipInternal , level );
142+ Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
105143 if (callerFrame != null ) {
106144 return ensureMaterializeNode ().execute (frame , false , true , callerFrame );
107145 }
108146 return null ;
109- } else if (!( skipInternal && ( callerInfo . getCallNode () == null || PRootNode . isPythonInternal ( callerInfo . getCallNode (). getRootNode ())) )) {
147+ } else if (!selector . skip ( callerInfo )) {
110148 i ++;
111149 }
112150 curFrameInfo = callerInfo ;
113151 }
114152 } else {
115- curFrameInfo = walkLevels (frame , curFrameInfo , frameAccess , skipInternal , level );
153+ curFrameInfo = walkLevels (frame , curFrameInfo , frameAccess , selector , level );
116154 }
117155 return curFrameInfo .getPyFrame ();
118156 }
119157
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 ) {
121159 PFrame .Reference currentFrame = startFrameInfo ;
122160 for (int i = 0 ; i <= level ;) {
123161 PFrame .Reference callerInfo = currentFrame .getCallerInfo ();
124162 if (cachedCallerFrameProfile .profile (callerInfo == null )) {
125- Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , skipInternal , level );
163+ Frame callerFrame = getCallerFrame (startFrameInfo , frameAccess , selector , level );
126164 if (callerFrame != null ) {
127165 // At this point, we must 'materialize' the frame. Actually, the Truffle frame
128166 // 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
131169 return PArguments .getCurrentFrameInfo (callerFrame );
132170 }
133171 return PFrame .Reference .EMPTY ;
134- } else if (!( skipInternal && ( callerInfo . getCallNode () == null || PRootNode . isPythonInternal ( callerInfo . getCallNode (). getRootNode ())) )) {
172+ } else if (!selector . skip ( callerInfo )) {
135173 i ++;
136174 }
137175 currentFrame = callerInfo ;
@@ -202,7 +240,7 @@ private PFrame.Reference walkLevels(VirtualFrame frame, PFrame.Reference startFr
202240 */
203241 public static Frame getCurrentFrame (Node requestingNode , FrameInstance .FrameAccess frameAccess ) {
204242 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 );
206244 }
207245
208246 /**
@@ -213,15 +251,15 @@ public static Frame getCurrentFrame(Node requestingNode, FrameInstance.FrameAcce
213251 *
214252 * @param startFrame - the frame to start counting from (must not be {@code null})
215253 * @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
217255 * @param level - the stack depth to go to. Ignored if {@code startFrame} is {@code null}
218256 */
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 ) {
220258 CompilerDirectives .transferToInterpreterAndInvalidate ();
221- return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , skipInternal , level );
259+ return getFrame (null , Objects .requireNonNull (startFrame ), frameAccess , selector , level );
222260 }
223261
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 ) {
225263 assert CompilerDirectives .inInterpreter ();
226264 final Frame [] outputFrame = new Frame [1 ];
227265 Truffle .getRuntime ().iterateFrames (new FrameInstanceVisitor <Frame >() {
@@ -272,7 +310,7 @@ public Frame visitFrame(FrameInstance frameInstance) {
272310 } else {
273311 // Skip frames of builtin functions (if requested) because these do not have
274312 // a Python frame in CPython.
275- if (!( skipInternal && pRootNode . isPythonInternal () )) {
313+ if (!selector . skip ( pRootNode )) {
276314 if (i == level || startFrame == null ) {
277315 Frame frame = frameInstance .getFrame (frameAccess );
278316 assert PArguments .isPythonFrame (frame );
0 commit comments