/src/cpython/Python/frame.c
Line | Count | Source |
1 | | #define _PY_INTERPRETER |
2 | | |
3 | | #include "Python.h" |
4 | | #include "pycore_frame.h" // _PyFrame_New_NoTrack() |
5 | | #include "pycore_interpframe.h" // _PyFrame_GetCode() |
6 | | #include "pycore_genobject.h" // _PyGen_GetGeneratorFromFrame() |
7 | | #include "pycore_stackref.h" // _Py_VISIT_STACKREF() |
8 | | |
9 | | |
10 | | int |
11 | | _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg) |
12 | 682k | { |
13 | 682k | Py_VISIT(frame->frame_obj); |
14 | 682k | Py_VISIT(frame->f_locals); |
15 | 682k | _Py_VISIT_STACKREF(frame->f_funcobj); |
16 | 682k | _Py_VISIT_STACKREF(frame->f_executable); |
17 | 682k | return _PyGC_VisitFrameStack(frame, visit, arg); |
18 | 682k | } |
19 | | |
20 | | PyFrameObject * |
21 | | _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame) |
22 | 55.8M | { |
23 | 55.8M | PyObject *exc = PyErr_GetRaisedException(); |
24 | | |
25 | 55.8M | PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame)); |
26 | 55.8M | if (f == NULL) { |
27 | 0 | Py_XDECREF(exc); |
28 | 0 | return NULL; |
29 | 0 | } |
30 | 55.8M | PyErr_SetRaisedException(exc); |
31 | | |
32 | | // GH-97002: There was a time when a frame object could be created when we |
33 | | // are allocating the new frame object f above, so frame->frame_obj would |
34 | | // be assigned already. That path does not exist anymore. We won't call any |
35 | | // Python code in this function and garbage collection will not run. |
36 | | // Notice that _PyFrame_New_NoTrack() can potentially raise a MemoryError, |
37 | | // but it won't allocate a traceback until the frame unwinds, so we are safe |
38 | | // here. |
39 | 55.8M | assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); |
40 | 55.8M | f->f_frame = frame; |
41 | | #ifdef Py_GIL_DISABLED |
42 | | PyFrameObject *expected = NULL; |
43 | | if (!_Py_atomic_compare_exchange_ptr(&frame->frame_obj, &expected, f)) { |
44 | | Py_DECREF(f); |
45 | | return expected; |
46 | | } |
47 | | #else |
48 | 55.8M | assert(frame->frame_obj == NULL); |
49 | 55.8M | frame->frame_obj = f; |
50 | 55.8M | #endif |
51 | 55.8M | return f; |
52 | 55.8M | } |
53 | | |
54 | | static void |
55 | | take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) |
56 | 40.3M | { |
57 | 40.3M | Py_BEGIN_CRITICAL_SECTION(f); |
58 | 40.3M | assert(frame->owner < FRAME_OWNED_BY_INTERPRETER); |
59 | 40.3M | assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); |
60 | 40.3M | _PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)f->_f_frame_data; |
61 | 40.3M | _PyFrame_Copy(frame, new_frame); |
62 | | // _PyFrame_Copy takes the reference to the executable, |
63 | | // so we need to restore it. |
64 | 40.3M | new_frame->f_executable = PyStackRef_DUP(new_frame->f_executable); |
65 | 40.3M | f->f_frame = new_frame; |
66 | 40.3M | new_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT; |
67 | 40.3M | if (_PyFrame_IsIncomplete(new_frame)) { |
68 | | // This may be a newly-created generator or coroutine frame. Since it's |
69 | | // dead anyways, just pretend that the first RESUME ran: |
70 | 0 | PyCodeObject *code = _PyFrame_GetCode(new_frame); |
71 | 0 | new_frame->instr_ptr = |
72 | 0 | _PyFrame_GetBytecode(new_frame) + code->_co_firsttraceable + 1; |
73 | 0 | } |
74 | 40.3M | assert(!_PyFrame_IsIncomplete(new_frame)); |
75 | 40.3M | assert(f->f_back == NULL); |
76 | 40.3M | _PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous); |
77 | 40.3M | if (prev) { |
78 | 40.3M | assert(prev->owner < FRAME_OWNED_BY_INTERPRETER); |
79 | 40.3M | PyObject *exc = PyErr_GetRaisedException(); |
80 | | /* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */ |
81 | 40.3M | PyFrameObject *back = _PyFrame_GetFrameObject(prev); |
82 | 40.3M | if (back == NULL) { |
83 | | /* Memory error here. */ |
84 | 0 | assert(PyErr_ExceptionMatches(PyExc_MemoryError)); |
85 | | /* Nothing we can do about it */ |
86 | 0 | PyErr_Clear(); |
87 | 0 | } |
88 | 40.3M | else { |
89 | 40.3M | f->f_back = (PyFrameObject *)Py_NewRef(back); |
90 | 40.3M | } |
91 | 40.3M | PyErr_SetRaisedException(exc); |
92 | 40.3M | } |
93 | 40.3M | if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) { |
94 | 40.3M | _PyObject_GC_TRACK((PyObject *)f); |
95 | 40.3M | } |
96 | 40.3M | Py_END_CRITICAL_SECTION(); |
97 | 40.3M | } |
98 | | |
99 | | void |
100 | | _PyFrame_ClearLocals(_PyInterpreterFrame *frame) |
101 | 1.22G | { |
102 | 1.22G | assert(frame->stackpointer != NULL); |
103 | 1.22G | _PyStackRef *sp = frame->stackpointer; |
104 | 1.22G | _PyStackRef *locals = frame->localsplus; |
105 | 1.22G | frame->stackpointer = locals; |
106 | 5.02G | while (sp > locals) { |
107 | 3.80G | sp--; |
108 | 3.80G | PyStackRef_XCLOSE(*sp); |
109 | 3.80G | } |
110 | 1.22G | Py_CLEAR(frame->f_locals); |
111 | 1.22G | } |
112 | | |
113 | | void |
114 | | _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) |
115 | 1.26G | { |
116 | | /* It is the responsibility of the owning generator/coroutine |
117 | | * to have cleared the enclosing generator, if any. */ |
118 | 1.26G | assert(frame->owner != FRAME_OWNED_BY_GENERATOR || |
119 | 1.26G | FT_ATOMIC_LOAD_INT8_RELAXED(_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state) == FRAME_CLEARED); |
120 | | // GH-99729: Clearing this frame can expose the stack (via finalizers). It's |
121 | | // crucial that this frame has been unlinked, and is no longer visible: |
122 | 1.26G | assert(_PyThreadState_GET()->current_frame != frame); |
123 | 1.26G | PyFrameObject *f = FT_ATOMIC_LOAD_PTR_RELAXED(frame->frame_obj); |
124 | 1.26G | if (f != NULL) { |
125 | 55.8M | FT_ATOMIC_STORE_PTR_RELAXED(frame->frame_obj, NULL); |
126 | 55.8M | if (!_PyObject_IsUniquelyReferenced((PyObject *)f)) { |
127 | 40.3M | take_ownership(f, frame); |
128 | 40.3M | Py_DECREF(f); |
129 | 40.3M | return; |
130 | 40.3M | } |
131 | 15.4M | Py_DECREF(f); |
132 | 15.4M | } |
133 | 1.22G | _PyFrame_ClearLocals(frame); |
134 | 1.22G | PyStackRef_CLEAR(frame->f_funcobj); |
135 | 1.22G | } |
136 | | |
137 | | /* Unstable API functions */ |
138 | | |
139 | | PyObject * |
140 | | PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame) |
141 | 0 | { |
142 | 0 | return PyStackRef_AsPyObjectNew(frame->f_executable); |
143 | 0 | } |
144 | | |
145 | | // NOTE: We allow racy accesses to the instruction pointer from other threads |
146 | | // for sys._current_frames() and similar APIs. |
147 | | int _Py_NO_SANITIZE_THREAD |
148 | | PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame) |
149 | 0 | { |
150 | 0 | return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); |
151 | 0 | } |
152 | | |
153 | | int _Py_NO_SANITIZE_THREAD |
154 | | PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame) |
155 | 1.02M | { |
156 | 1.02M | int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); |
157 | 1.02M | return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr); |
158 | 1.02M | } |