@@ -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 );
@@ -256,10 +292,11 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
256292{
257293 if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER ) {
258294 return true;
295+ } else if (frame -> owner & (FRAME_OWNED_BY_GENERATOR |FRAME_OWNED_EXTERNALLY )) {
296+ return false;
259297 }
260- return frame -> owner != FRAME_OWNED_BY_GENERATOR &&
261- frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
262- _PyFrame_GetCode (frame )-> _co_firsttraceable ;
298+ return frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
299+ _PyFrame_GetCode (frame )-> _co_firsttraceable ;
263300}
264301
265302static inline _PyInterpreterFrame *
@@ -271,12 +308,66 @@ _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
271308 return frame ;
272309}
273310
311+ #if Py_DEBUG
312+
313+ static inline bool _Py_NO_SANITIZE_THREAD
314+ _PyFrame_IsIncompleteOrUninitialized (_PyInterpreterFrame * frame )
315+ {
316+ if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER || _PyFrame_IsExternalFrame (frame )) {
317+ return true;
318+ }
319+ return !(frame -> owner & FRAME_OWNED_BY_GENERATOR ) &&
320+ frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
321+ _PyFrame_GetCode (frame )-> _co_firsttraceable ;
322+ }
323+
324+ static inline _PyInterpreterFrame *
325+ _PyFrame_GetFirstCompleteInitialized (_PyInterpreterFrame * frame )
326+ {
327+ while (frame && _PyFrame_IsIncompleteOrUninitialized (frame )) {
328+ frame = frame -> previous ;
329+ }
330+ return frame ;
331+ }
332+
333+ #endif
334+
335+ static inline bool
336+ _PyFrame_StackpointerSaved (void )
337+ {
338+ #if Py_DEBUG
339+ PyThreadState * tstate = PyThreadState_GET ();
340+ return _PyFrame_GetFirstCompleteInitialized (tstate -> current_frame ) == NULL ||
341+ _PyFrame_GetFirstCompleteInitialized (tstate -> current_frame )-> stackpointer != NULL ;
342+ #else
343+ return true;
344+ #endif
345+ }
346+
347+
348+
274349static inline _PyInterpreterFrame *
275350_PyThreadState_GetFrame (PyThreadState * tstate )
276351{
277352 return _PyFrame_GetFirstComplete (tstate -> current_frame );
278353}
279354
355+ static inline PyObject *
356+ _PyFrame_GetGlobals (_PyInterpreterFrame * frame ) {
357+ if (frame -> f_globals == NULL ) {
358+ frame -> f_globals = _PyFrame_GetFunction (frame )-> func_globals ;
359+ }
360+ return frame -> f_globals ;
361+ }
362+
363+ static inline PyObject *
364+ _PyFrame_GetBuiltins (_PyInterpreterFrame * frame ) {
365+ if (frame -> f_builtins == NULL ) {
366+ frame -> f_builtins = _PyFrame_GetFunction (frame )-> func_builtins ;
367+ }
368+ return frame -> f_builtins ;
369+ }
370+
280371/* For use by _PyFrame_GetFrameObject
281372 Do not call directly. */
282373PyAPI_FUNC (PyFrameObject * )
@@ -288,9 +379,9 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
288379static inline PyFrameObject *
289380_PyFrame_GetFrameObject (_PyInterpreterFrame * frame )
290381{
291-
382+ _PyFrame_EnsureFrameFullyInitialized ( frame );
292383 assert (!_PyFrame_IsIncomplete (frame ));
293- PyFrameObject * res = frame -> frame_obj ;
384+ PyFrameObject * res = frame -> frame_obj ;
294385 if (res != NULL ) {
295386 return res ;
296387 }
@@ -309,7 +400,7 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
309400 * take should be set to 1 for heap allocated
310401 * frames like the ones in generators and coroutines.
311402 */
312- void
403+ PyAPI_FUNC ( void )
313404_PyFrame_ClearExceptCode (_PyInterpreterFrame * frame );
314405
315406int
@@ -358,7 +449,7 @@ _PyFrame_PushUnchecked(PyThreadState *tstate, _PyStackRef func, int null_locals_
358449/* Pushes a trampoline frame without checking for space.
359450 * Must be guarded by _PyThreadState_HasStackSpace() */
360451static inline _PyInterpreterFrame *
361- _PyFrame_PushTrampolineUnchecked (PyThreadState * tstate , PyCodeObject * code , int stackdepth , _PyInterpreterFrame * previous )
452+ _PyFrame_PushTrampolineUnchecked (PyThreadState * tstate , PyCodeObject * code , int stackdepth , _PyInterpreterFrame * previous )
362453{
363454 CALL_STAT_INC (frames_pushed );
364455 _PyInterpreterFrame * frame = (_PyInterpreterFrame * )tstate -> datastack_top ;
0 commit comments