@@ -17,9 +17,37 @@ extern "C" {
1717#define _PyInterpreterFrame_LASTI (IF ) \
1818 ((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF))))
1919
20+ PyAPI_DATA (PyTypeObject ) PyUnstable_ExternalExecutable_Type ;
21+
22+ #define PyUnstable_ExternalExecutable_Check (op ) Py_IS_TYPE((op), &PyUnstable_ExternalExecutable_Type)
23+
24+ // Initialize a potentially external frame and make it safe to access the
25+ // all of the members of the returned _PyInterpreterFrame. The returned
26+ // value will be the same address as the passed in pointer.
27+ PyAPI_FUNC (void ) _PyFrame_InitializeExternalFrame (_PyInterpreterFrame * frame );
28+
29+ PyAPI_FUNC (PyObject * ) PyUnstable_MakeExternalExecutable (_PyFrame_Reifier reifier , PyCodeObject * code , PyObject * state );
30+
31+ static bool _PyFrame_IsExternalFrame (_PyInterpreterFrame * frame )
32+ {
33+ return frame -> owner & FRAME_OWNED_EXTERNALLY ;
34+ }
35+
36+ static inline void
37+ _PyFrame_EnsureFrameFullyInitialized (_PyInterpreterFrame * frame )
38+ {
39+ if (_PyFrame_IsExternalFrame (frame )) {
40+ _PyFrame_InitializeExternalFrame (frame );
41+ }
42+ }
43+
2044static inline PyCodeObject * _PyFrame_GetCode (_PyInterpreterFrame * f ) {
2145 assert (!PyStackRef_IsNull (f -> f_executable ));
2246 PyObject * executable = PyStackRef_AsPyObjectBorrow (f -> f_executable );
47+ if (f -> owner & FRAME_OWNED_EXTERNALLY ) {
48+ assert (PyUnstable_ExternalExecutable_Check (executable ));
49+ return ((PyUnstable_PyExternalExecutable * )executable )-> ef_code ;
50+ }
2351 assert (PyCode_Check (executable ));
2452 return (PyCodeObject * )executable ;
2553}
@@ -30,12 +58,6 @@ static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
3058static inline PyCodeObject * _Py_NO_SANITIZE_THREAD
3159_PyFrame_SafeGetCode (_PyInterpreterFrame * f )
3260{
33- // globals and builtins may be NULL on a legit frame, but it's unlikely.
34- // It's more likely that it's a sign of an invalid frame.
35- if (f -> f_globals == NULL || f -> f_builtins == NULL ) {
36- return NULL ;
37- }
38-
3961 if (PyStackRef_IsNull (f -> f_executable )) {
4062 return NULL ;
4163 }
@@ -48,6 +70,18 @@ _PyFrame_SafeGetCode(_PyInterpreterFrame *f)
4870 if (_PyObject_IsFreed (executable )) {
4971 return NULL ;
5072 }
73+ if (_PyFrame_IsExternalFrame (f )) {
74+ executable = (PyObject * )((PyUnstable_PyExternalExecutable * )executable )-> ef_code ;
75+ if (_PyObject_IsFreed (executable )) {
76+ return NULL ;
77+ }
78+ } else {
79+ // globals and builtins may be NULL on a legit frame, but it's unlikely.
80+ // It's more likely that it's a sign of an invalid frame.
81+ if (f -> f_globals == NULL || f -> f_builtins == NULL ) {
82+ return NULL ;
83+ }
84+ }
5185 if (!PyCode_Check (executable )) {
5286 return NULL ;
5387 }
@@ -59,6 +93,7 @@ _PyFrame_GetBytecode(_PyInterpreterFrame *f)
5993{
6094#ifdef Py_GIL_DISABLED
6195 PyCodeObject * co = _PyFrame_GetCode (f );
96+ _PyFrame_EnsureFrameFullyInitialized (f );
6297 _PyCodeArray * tlbc = _PyCode_GetTLBCArray (co );
6398 assert (f -> tlbc_index >= 0 && f -> tlbc_index < tlbc -> size );
6499 return (_Py_CODEUNIT * )tlbc -> entries [f -> tlbc_index ];
@@ -81,6 +116,7 @@ _PyFrame_SafeGetLasti(struct _PyInterpreterFrame *f)
81116 }
82117
83118 _Py_CODEUNIT * bytecode ;
119+ _PyFrame_EnsureFrameFullyInitialized (f );
84120#ifdef Py_GIL_DISABLED
85121 _PyCodeArray * tlbc = _PyCode_GetTLBCArray (co );
86122 assert (f -> tlbc_index >= 0 && f -> tlbc_index < tlbc -> size );
@@ -261,10 +297,11 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
261297{
262298 if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER ) {
263299 return true;
300+ } else if (frame -> owner & (FRAME_OWNED_BY_GENERATOR |FRAME_OWNED_EXTERNALLY )) {
301+ return false;
264302 }
265- return frame -> owner != FRAME_OWNED_BY_GENERATOR &&
266- frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
267- _PyFrame_GetCode (frame )-> _co_firsttraceable ;
303+ return frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
304+ _PyFrame_GetCode (frame )-> _co_firsttraceable ;
268305}
269306
270307static inline _PyInterpreterFrame *
@@ -276,12 +313,66 @@ _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
276313 return frame ;
277314}
278315
316+ #if Py_DEBUG
317+
318+ static inline bool _Py_NO_SANITIZE_THREAD
319+ _PyFrame_IsIncompleteOrUninitialized (_PyInterpreterFrame * frame )
320+ {
321+ if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER || _PyFrame_IsExternalFrame (frame )) {
322+ return true;
323+ }
324+ return !(frame -> owner & FRAME_OWNED_BY_GENERATOR ) &&
325+ frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
326+ _PyFrame_GetCode (frame )-> _co_firsttraceable ;
327+ }
328+
329+ static inline _PyInterpreterFrame *
330+ _PyFrame_GetFirstCompleteInitialized (_PyInterpreterFrame * frame )
331+ {
332+ while (frame && _PyFrame_IsIncompleteOrUninitialized (frame )) {
333+ frame = frame -> previous ;
334+ }
335+ return frame ;
336+ }
337+
338+ #endif
339+
340+ static inline bool
341+ _PyFrame_StackpointerSaved (void )
342+ {
343+ #if Py_DEBUG
344+ PyThreadState * tstate = PyThreadState_GET ();
345+ return _PyFrame_GetFirstCompleteInitialized (tstate -> current_frame ) == NULL ||
346+ _PyFrame_GetFirstCompleteInitialized (tstate -> current_frame )-> stackpointer != NULL ;
347+ #else
348+ return true;
349+ #endif
350+ }
351+
352+
353+
279354static inline _PyInterpreterFrame *
280355_PyThreadState_GetFrame (PyThreadState * tstate )
281356{
282357 return _PyFrame_GetFirstComplete (tstate -> current_frame );
283358}
284359
360+ static inline PyObject *
361+ _PyFrame_GetGlobals (_PyInterpreterFrame * frame ) {
362+ if (frame -> f_globals == NULL ) {
363+ frame -> f_globals = _PyFrame_GetFunction (frame )-> func_globals ;
364+ }
365+ return frame -> f_globals ;
366+ }
367+
368+ static inline PyObject *
369+ _PyFrame_GetBuiltins (_PyInterpreterFrame * frame ) {
370+ if (frame -> f_builtins == NULL ) {
371+ frame -> f_builtins = _PyFrame_GetFunction (frame )-> func_builtins ;
372+ }
373+ return frame -> f_builtins ;
374+ }
375+
285376/* For use by _PyFrame_GetFrameObject
286377 Do not call directly. */
287378PyAPI_FUNC (PyFrameObject * )
@@ -293,9 +384,9 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
293384static inline PyFrameObject *
294385_PyFrame_GetFrameObject (_PyInterpreterFrame * frame )
295386{
296-
387+ _PyFrame_EnsureFrameFullyInitialized ( frame );
297388 assert (!_PyFrame_IsIncomplete (frame ));
298- PyFrameObject * res = frame -> frame_obj ;
389+ PyFrameObject * res = frame -> frame_obj ;
299390 if (res != NULL ) {
300391 return res ;
301392 }
@@ -314,7 +405,7 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
314405 * take should be set to 1 for heap allocated
315406 * frames like the ones in generators and coroutines.
316407 */
317- void
408+ PyAPI_FUNC ( void )
318409_PyFrame_ClearExceptCode (_PyInterpreterFrame * frame );
319410
320411int
@@ -363,7 +454,7 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, _PyStackRef func, int null_locals_
363454/* Pushes a trampoline frame without checking for space.
364455 * Must be guarded by _PyThreadState_HasStackSpace() */
365456static inline _PyInterpreterFrame *
366- _PyFrame_PushTrampolineUnchecked (PyThreadState * tstate , PyCodeObject * code , int stackdepth , _PyInterpreterFrame * previous )
457+ _PyFrame_PushTrampolineUnchecked (PyThreadState * tstate , PyCodeObject * code , int stackdepth , _PyInterpreterFrame * previous )
367458{
368459 CALL_STAT_INC (frames_pushed );
369460 _PyInterpreterFrame * frame = (_PyInterpreterFrame * )tstate -> datastack_top ;
0 commit comments