]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-45256: Don't track the exact depth of each `InterpreterFrame` (GH-30372)
authorBrandt Bucher <brandt@python.org>
Wed, 5 Jan 2022 11:30:26 +0000 (03:30 -0800)
committerGitHub <noreply@github.com>
Wed, 5 Jan 2022 11:30:26 +0000 (11:30 +0000)
Include/internal/pycore_frame.h
Lib/test/test_sys.py
Python/ceval.c
Tools/gdb/libpython.py

index 8eca39d1ab2503215b1293005251e0537bb7a24b..42df51f635615da74584eafaf2af289880182e0c 100644 (file)
@@ -4,6 +4,8 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
+
 
 /* runtime lifecycle */
 
@@ -44,7 +46,7 @@ typedef struct _interpreter_frame {
     int f_lasti;       /* Last instruction if called */
     int stacktop;     /* Offset of TOS from localsplus  */
     PyFrameState f_state;  /* What state the frame is in */
-    int depth; /* Depth of the frame in a ceval loop */
+    bool is_entry;  // Whether this is the "root" frame for the current CFrame.
     PyObject *localsplus[1];
 } InterpreterFrame;
 
@@ -101,7 +103,7 @@ _PyFrame_InitializeSpecials(
     frame->generator = NULL;
     frame->f_lasti = -1;
     frame->f_state = FRAME_CREATED;
-    frame->depth = 0;
+    frame->is_entry = false;
 }
 
 /* Gets the pointer to the locals array
index 96075cf3b3473c593876fa5e1859dc81bda3782b..38771d427da7b18d43ac231bb17051d5f058d677 100644 (file)
@@ -1323,7 +1323,7 @@ class SizeofTest(unittest.TestCase):
         def func():
             return sys._getframe()
         x = func()
-        check(x, size('3Pi3c8P2iciP'))
+        check(x, size('3Pi3c8P2ic?P'))
         # function
         def func(): pass
         check(func, size('14Pi'))
@@ -1340,7 +1340,7 @@ class SizeofTest(unittest.TestCase):
             check(bar, size('PP'))
         # generator
         def get_gen(): yield 1
-        check(get_gen(), size('P2P4P4c8P2iciP'))
+        check(get_gen(), size('P2P4P4c8P2ic?P'))
         # iterator
         check(iter('abc'), size('lP'))
         # callable-iterator
index 953876f6226b95fc06c94ac1011afb6ec0d08f52..b4ac9ec848f773f0bfa012e8e20ccb9d62e15b36 100644 (file)
@@ -1683,7 +1683,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
     cframe.previous = prev_cframe;
     tstate->cframe = &cframe;
 
-    assert(frame->depth == 0);
+    frame->is_entry = true;
     /* Push frame */
     frame->previous = prev_cframe->current_frame;
     cframe.current_frame = frame;
@@ -2310,7 +2310,6 @@ check_eval_breaker:
             _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
             frame = cframe.current_frame = new_frame;
-            new_frame->depth = frame->depth + 1;
             goto start_frame;
         }
 
@@ -2475,7 +2474,7 @@ check_eval_breaker:
             TRACE_FUNCTION_EXIT();
             DTRACE_FUNCTION_EXIT();
             _Py_LeaveRecursiveCall(tstate);
-            if (frame->depth) {
+            if (!frame->is_entry) {
                 frame = cframe.current_frame = pop_frame(tstate, frame);
                 _PyFrame_StackPush(frame, retval);
                 goto resume_frame;
@@ -2625,7 +2624,7 @@ check_eval_breaker:
         }
 
         TARGET(SEND) {
-            assert(frame->depth == 0);
+            assert(frame->is_entry);
             assert(STACK_LEVEL() >= 2);
             PyObject *v = POP();
             PyObject *receiver = TOP();
@@ -2684,7 +2683,7 @@ check_eval_breaker:
         }
 
         TARGET(YIELD_VALUE) {
-            assert(frame->depth == 0);
+            assert(frame->is_entry);
             PyObject *retval = POP();
 
             if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) {
@@ -4612,7 +4611,6 @@ check_eval_breaker:
                     _PyFrame_SetStackPointer(frame, stack_pointer);
                     new_frame->previous = frame;
                     cframe.current_frame = frame = new_frame;
-                    new_frame->depth = frame->depth + 1;
                     goto start_frame;
                 }
             }
@@ -4706,7 +4704,6 @@ check_eval_breaker:
             _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
             frame = cframe.current_frame = new_frame;
-            new_frame->depth = frame->depth + 1;
             goto start_frame;
         }
 
@@ -5382,7 +5379,7 @@ exception_unwind:
 exit_unwind:
     assert(_PyErr_Occurred(tstate));
     _Py_LeaveRecursiveCall(tstate);
-    if (frame->depth == 0) {
+    if (frame->is_entry) {
         /* Restore previous cframe and exit */
         tstate->cframe = cframe.previous;
         tstate->cframe->use_tracing = cframe.use_tracing;
index a0a95e3fc63cba27763433c56ca608d6acb4bf56..e3d73bce6cfe5a60b04f9f7035d40875fa5fd72f 100755 (executable)
@@ -1044,8 +1044,8 @@ class PyFramePtr:
     def _f_lasti(self):
         return self._f_special("f_lasti", int_from_int)
 
-    def depth(self):
-        return self._f_special("depth", int_from_int)
+    def is_entry(self):
+        return self._f_special("is_entry", bool)
 
     def previous(self):
         return self._f_special("previous", PyFramePtr)
@@ -1860,7 +1860,7 @@ class Frame(object):
                         line = interp_frame.current_line()
                         if line is not None:
                             sys.stdout.write('    %s\n' % line.strip())
-                    if interp_frame.depth() == 0:
+                    if interp_frame.is_entry():
                         break
                 else:
                     sys.stdout.write('#%i (unable to read python frame information)\n' % self.get_index())
@@ -1883,7 +1883,7 @@ class Frame(object):
                         line = interp_frame.current_line()
                         if line is not None:
                             sys.stdout.write('    %s\n' % line.strip())
-                    if interp_frame.depth() == 0:
+                    if interp_frame.is_entry():
                         break
                 else:
                     sys.stdout.write('  (unable to read python frame information)\n')
@@ -2147,7 +2147,7 @@ class PyLocals(gdb.Command):
                     % (pyop_name.proxyval(set()),
                         pyop_value.get_truncated_repr(MAX_OUTPUT_LEN)))
 
-            if pyop_frame.depth() == 0:
+            if pyop_frame.is_entry():
                 break
 
             pyop_frame = pyop_frame.previous()