@@ -610,7 +610,7 @@ static PyGetSetDef frame_getsetlist[] = {
610610 f_back next item on free list, or NULL
611611*/
612612
613- static void _Py_HOT_FUNCTION
613+ static void
614614frame_dealloc (PyFrameObject * f )
615615{
616616 if (_PyObject_GC_IS_TRACKED (f )) {
@@ -621,9 +621,10 @@ frame_dealloc(PyFrameObject *f)
621621 PyCodeObject * co = NULL ;
622622
623623 /* Kill all local variables including specials, if we own them */
624- if (f -> f_own_locals_memory ) {
625- f -> f_own_locals_memory = 0 ;
626- InterpreterFrame * frame = f -> f_frame ;
624+ if (f -> f_owns_frame ) {
625+ f -> f_owns_frame = 0 ;
626+ assert (f -> f_frame == (InterpreterFrame * )f -> _f_frame_data );
627+ InterpreterFrame * frame = (InterpreterFrame * )f -> _f_frame_data ;
627628 /* Don't clear code object until the end */
628629 co = frame -> f_code ;
629630 frame -> f_code = NULL ;
@@ -633,27 +634,10 @@ frame_dealloc(PyFrameObject *f)
633634 for (int i = 0 ; i < frame -> stacktop ; i ++ ) {
634635 Py_CLEAR (locals [i ]);
635636 }
636- PyMem_Free (frame );
637637 }
638638 Py_CLEAR (f -> f_back );
639639 Py_CLEAR (f -> f_trace );
640- #if PyFrame_MAXFREELIST > 0
641- struct _Py_frame_state * state = get_frame_state ();
642- #ifdef Py_DEBUG
643- // frame_dealloc() must not be called after _PyFrame_Fini()
644- assert (state -> numfree != -1 );
645- #endif
646- if (state -> numfree < PyFrame_MAXFREELIST ) {
647- ++ state -> numfree ;
648- f -> f_back = state -> free_list ;
649- state -> free_list = f ;
650- }
651- else
652- #endif
653- {
654- PyObject_GC_Del (f );
655- }
656-
640+ PyObject_GC_Del (f );
657641 Py_XDECREF (co );
658642 Py_TRASHCAN_END ;
659643}
@@ -663,7 +647,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
663647{
664648 Py_VISIT (f -> f_back );
665649 Py_VISIT (f -> f_trace );
666- if (f -> f_own_locals_memory == 0 ) {
650+ if (f -> f_owns_frame == 0 ) {
667651 return 0 ;
668652 }
669653 assert (f -> f_frame -> frame_obj == NULL );
@@ -715,11 +699,9 @@ static PyObject *
715699frame_sizeof (PyFrameObject * f , PyObject * Py_UNUSED (ignored ))
716700{
717701 Py_ssize_t res ;
718- res = sizeof (PyFrameObject );
719- if (f -> f_own_locals_memory ) {
720- PyCodeObject * code = f -> f_frame -> f_code ;
721- res += (code -> co_nlocalsplus + code -> co_stacksize ) * sizeof (PyObject * );
722- }
702+ res = offsetof(PyFrameObject , _f_frame_data ) + offsetof(InterpreterFrame , localsplus );
703+ PyCodeObject * code = f -> f_frame -> f_code ;
704+ res += (code -> co_nlocalsplus + code -> co_stacksize ) * sizeof (PyObject * );
723705 return PyLong_FromSsize_t (res );
724706}
725707
@@ -747,7 +729,8 @@ static PyMethodDef frame_methods[] = {
747729PyTypeObject PyFrame_Type = {
748730 PyVarObject_HEAD_INIT (& PyType_Type , 0 )
749731 "frame" ,
750- sizeof (PyFrameObject ),
732+ offsetof(PyFrameObject , _f_frame_data ) +
733+ offsetof(InterpreterFrame , localsplus ),
751734 sizeof (PyObject * ),
752735 (destructor )frame_dealloc , /* tp_dealloc */
753736 0 , /* tp_vectorcall_offset */
@@ -781,67 +764,21 @@ PyTypeObject PyFrame_Type = {
781764
782765_Py_IDENTIFIER (__builtins__ );
783766
784- static InterpreterFrame *
785- allocate_heap_frame ( PyFunctionObject * func , PyObject * locals )
767+ static void
768+ init_frame ( InterpreterFrame * frame , PyFunctionObject * func , PyObject * locals )
786769{
787770 PyCodeObject * code = (PyCodeObject * )func -> func_code ;
788- int size = code -> co_nlocalsplus + code -> co_stacksize + FRAME_SPECIALS_SIZE ;
789- InterpreterFrame * frame = (InterpreterFrame * )PyMem_Malloc (sizeof (PyObject * )* size );
790- if (frame == NULL ) {
791- PyErr_NoMemory ();
792- return NULL ;
793- }
794771 _PyFrame_InitializeSpecials (frame , func , locals , code -> co_nlocalsplus );
795772 for (Py_ssize_t i = 0 ; i < code -> co_nlocalsplus ; i ++ ) {
796773 frame -> localsplus [i ] = NULL ;
797774 }
798- return frame ;
799775}
800776
801- static inline PyFrameObject *
802- frame_alloc (InterpreterFrame * frame , int owns )
803- {
804- PyFrameObject * f ;
805- #if PyFrame_MAXFREELIST > 0
806- struct _Py_frame_state * state = get_frame_state ();
807- if (state -> free_list == NULL )
808- #endif
809- {
810- f = PyObject_GC_New (PyFrameObject , & PyFrame_Type );
811- if (f == NULL ) {
812- if (owns ) {
813- Py_XDECREF (frame -> f_code );
814- Py_XDECREF (frame -> f_builtins );
815- Py_XDECREF (frame -> f_globals );
816- Py_XDECREF (frame -> f_locals );
817- PyMem_Free (frame );
818- }
819- return NULL ;
820- }
821- }
822- #if PyFrame_MAXFREELIST > 0
823- else
824- {
825- #ifdef Py_DEBUG
826- // frame_alloc() must not be called after _PyFrame_Fini()
827- assert (state -> numfree != -1 );
828- #endif
829- assert (state -> numfree > 0 );
830- -- state -> numfree ;
831- f = state -> free_list ;
832- state -> free_list = state -> free_list -> f_back ;
833- _Py_NewReference ((PyObject * )f );
834- }
835- #endif
836- f -> f_frame = frame ;
837- f -> f_own_locals_memory = owns ;
838- return f ;
839- }
840-
841- PyFrameObject * _Py_HOT_FUNCTION
842- _PyFrame_New_NoTrack (InterpreterFrame * frame , int owns )
777+ PyFrameObject *
778+ _PyFrame_New_NoTrack (PyCodeObject * code )
843779{
844- PyFrameObject * f = frame_alloc (frame , owns );
780+ int slots = code -> co_nlocalsplus + code -> co_stacksize ;
781+ PyFrameObject * f = PyObject_GC_NewVar (PyFrameObject , & PyFrame_Type , slots );
845782 if (f == NULL ) {
846783 return NULL ;
847784 }
@@ -876,15 +813,16 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
876813 if (func == NULL ) {
877814 return NULL ;
878815 }
879- InterpreterFrame * frame = allocate_heap_frame ( func , locals );
880- Py_DECREF ( func );
881- if ( frame == NULL ) {
816+ PyFrameObject * f = _PyFrame_New_NoTrack ( code );
817+ if ( f == NULL ) {
818+ Py_DECREF ( func );
882819 return NULL ;
883820 }
884- PyFrameObject * f = _PyFrame_New_NoTrack (frame , 1 );
885- if (f ) {
886- _PyObject_GC_TRACK (f );
887- }
821+ init_frame ((InterpreterFrame * )f -> _f_frame_data , func , locals );
822+ f -> f_frame = (InterpreterFrame * )f -> _f_frame_data ;
823+ f -> f_owns_frame = 1 ;
824+ Py_DECREF (func );
825+ _PyObject_GC_TRACK (f );
888826 return f ;
889827}
890828
@@ -1087,42 +1025,15 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
10871025 _PyFrame_LocalsToFast (f -> f_frame , clear );
10881026}
10891027
1090- /* Clear out the free list */
1091- void
1092- _PyFrame_ClearFreeList (PyInterpreterState * interp )
1093- {
1094- #if PyFrame_MAXFREELIST > 0
1095- struct _Py_frame_state * state = & interp -> frame ;
1096- while (state -> free_list != NULL ) {
1097- PyFrameObject * f = state -> free_list ;
1098- state -> free_list = state -> free_list -> f_back ;
1099- PyObject_GC_Del (f );
1100- -- state -> numfree ;
1101- }
1102- assert (state -> numfree == 0 );
1103- #endif
1104- }
1105-
11061028void
11071029_PyFrame_Fini (PyInterpreterState * interp )
11081030{
1109- _PyFrame_ClearFreeList (interp );
1110- #if defined(Py_DEBUG ) && PyFrame_MAXFREELIST > 0
1111- struct _Py_frame_state * state = & interp -> frame ;
1112- state -> numfree = -1 ;
1113- #endif
11141031}
11151032
11161033/* Print summary info about the state of the optimized allocator */
11171034void
11181035_PyFrame_DebugMallocStats (FILE * out )
11191036{
1120- #if PyFrame_MAXFREELIST > 0
1121- struct _Py_frame_state * state = get_frame_state ();
1122- _PyDebugAllocatorStats (out ,
1123- "free PyFrameObject" ,
1124- state -> numfree , sizeof (PyFrameObject ));
1125- #endif
11261037}
11271038
11281039
0 commit comments