@@ -610,7 +610,7 @@ static PyGetSetDef frame_getsetlist[] = {
610
610
f_back next item on free list, or NULL
611
611
*/
612
612
613
- static void _Py_HOT_FUNCTION
613
+ static void
614
614
frame_dealloc (PyFrameObject * f )
615
615
{
616
616
if (_PyObject_GC_IS_TRACKED (f )) {
@@ -621,9 +621,10 @@ frame_dealloc(PyFrameObject *f)
621
621
PyCodeObject * co = NULL ;
622
622
623
623
/* 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 ;
627
628
/* Don't clear code object until the end */
628
629
co = frame -> f_code ;
629
630
frame -> f_code = NULL ;
@@ -633,27 +634,10 @@ frame_dealloc(PyFrameObject *f)
633
634
for (int i = 0 ; i < frame -> stacktop ; i ++ ) {
634
635
Py_CLEAR (locals [i ]);
635
636
}
636
- PyMem_Free (frame );
637
637
}
638
638
Py_CLEAR (f -> f_back );
639
639
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 );
657
641
Py_XDECREF (co );
658
642
Py_TRASHCAN_END ;
659
643
}
@@ -663,7 +647,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
663
647
{
664
648
Py_VISIT (f -> f_back );
665
649
Py_VISIT (f -> f_trace );
666
- if (f -> f_own_locals_memory == 0 ) {
650
+ if (f -> f_owns_frame == 0 ) {
667
651
return 0 ;
668
652
}
669
653
assert (f -> f_frame -> frame_obj == NULL );
@@ -715,11 +699,9 @@ static PyObject *
715
699
frame_sizeof (PyFrameObject * f , PyObject * Py_UNUSED (ignored ))
716
700
{
717
701
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 * );
723
705
return PyLong_FromSsize_t (res );
724
706
}
725
707
@@ -747,7 +729,8 @@ static PyMethodDef frame_methods[] = {
747
729
PyTypeObject PyFrame_Type = {
748
730
PyVarObject_HEAD_INIT (& PyType_Type , 0 )
749
731
"frame" ,
750
- sizeof (PyFrameObject ),
732
+ offsetof(PyFrameObject , _f_frame_data ) +
733
+ offsetof(InterpreterFrame , localsplus ),
751
734
sizeof (PyObject * ),
752
735
(destructor )frame_dealloc , /* tp_dealloc */
753
736
0 , /* tp_vectorcall_offset */
@@ -781,67 +764,21 @@ PyTypeObject PyFrame_Type = {
781
764
782
765
_Py_IDENTIFIER (__builtins__ );
783
766
784
- static InterpreterFrame *
785
- allocate_heap_frame ( PyFunctionObject * func , PyObject * locals )
767
+ static void
768
+ init_frame ( InterpreterFrame * frame , PyFunctionObject * func , PyObject * locals )
786
769
{
787
770
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
- }
794
771
_PyFrame_InitializeSpecials (frame , func , locals , code -> co_nlocalsplus );
795
772
for (Py_ssize_t i = 0 ; i < code -> co_nlocalsplus ; i ++ ) {
796
773
frame -> localsplus [i ] = NULL ;
797
774
}
798
- return frame ;
799
775
}
800
776
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 )
843
779
{
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 );
845
782
if (f == NULL ) {
846
783
return NULL ;
847
784
}
@@ -876,15 +813,16 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
876
813
if (func == NULL ) {
877
814
return NULL ;
878
815
}
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 );
882
819
return NULL ;
883
820
}
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 );
888
826
return f ;
889
827
}
890
828
@@ -1087,42 +1025,15 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
1087
1025
_PyFrame_LocalsToFast (f -> f_frame , clear );
1088
1026
}
1089
1027
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
-
1106
1028
void
1107
1029
_PyFrame_Fini (PyInterpreterState * interp )
1108
1030
{
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
1114
1031
}
1115
1032
1116
1033
/* Print summary info about the state of the optimized allocator */
1117
1034
void
1118
1035
_PyFrame_DebugMallocStats (FILE * out )
1119
1036
{
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
1126
1037
}
1127
1038
1128
1039
0 commit comments