@@ -101,7 +101,7 @@ static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
101
101
static InterpreterFrame *
102
102
_PyEvalFramePushAndInit (PyThreadState * tstate , PyFrameConstructor * con ,
103
103
PyObject * locals , PyObject * const * args ,
104
- size_t argcount , PyObject * kwnames , int steal_args );
104
+ size_t argcount , PyObject * kwnames );
105
105
static int
106
106
_PyEvalFrameClearAndPop (PyThreadState * tstate , InterpreterFrame * frame );
107
107
@@ -4633,7 +4633,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
4633
4633
InterpreterFrame * new_frame = _PyEvalFramePushAndInit (
4634
4634
tstate , PyFunction_AS_FRAME_CONSTRUCTOR (function ), locals ,
4635
4635
stack_pointer ,
4636
- nargs , kwnames , 1 );
4636
+ nargs , kwnames );
4637
4637
STACK_SHRINK (postcall_shrink );
4638
4638
// The frame has stolen all the arguments from the stack,
4639
4639
// so there is no need to clean them up.
@@ -4708,11 +4708,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
4708
4708
/* PEP 523 */
4709
4709
DEOPT_IF (tstate -> interp -> eval_frame != NULL , CALL_FUNCTION );
4710
4710
STAT_INC (CALL_FUNCTION , hit );
4711
- InterpreterFrame * new_frame = _PyThreadState_PushFrame (
4712
- tstate , PyFunction_AS_FRAME_CONSTRUCTOR (func ), NULL );
4711
+ PyCodeObject * code = (PyCodeObject * )func -> func_code ;
4712
+ size_t size = code -> co_nlocalsplus + code -> co_stacksize + FRAME_SPECIALS_SIZE ;
4713
+ InterpreterFrame * new_frame = _PyThreadState_BumpFramePointer (tstate , size );
4713
4714
if (new_frame == NULL ) {
4714
4715
goto error ;
4715
4716
}
4717
+ _PyFrame_InitializeSpecials (new_frame , PyFunction_AS_FRAME_CONSTRUCTOR (func ),
4718
+ NULL , code -> co_nlocalsplus );
4716
4719
STACK_SHRINK (argcount );
4717
4720
for (int i = 0 ; i < argcount ; i ++ ) {
4718
4721
new_frame -> localsplus [i ] = stack_pointer [i ];
@@ -4723,6 +4726,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
4723
4726
Py_INCREF (def );
4724
4727
new_frame -> localsplus [argcount + i ] = def ;
4725
4728
}
4729
+ for (int i = argcount + deflen ; i < code -> co_nlocalsplus ; i ++ ) {
4730
+ new_frame -> localsplus [i ] = NULL ;
4731
+ }
4726
4732
STACK_SHRINK (1 );
4727
4733
Py_DECREF (func );
4728
4734
_PyFrame_SetStackPointer (frame , stack_pointer );
@@ -5595,7 +5601,7 @@ get_exception_handler(PyCodeObject *code, int index, int *level, int *handler, i
5595
5601
static int
5596
5602
initialize_locals (PyThreadState * tstate , PyFrameConstructor * con ,
5597
5603
PyObject * * localsplus , PyObject * const * args ,
5598
- Py_ssize_t argcount , PyObject * kwnames , int steal_args )
5604
+ Py_ssize_t argcount , PyObject * kwnames )
5599
5605
{
5600
5606
PyCodeObject * co = (PyCodeObject * )con -> fc_code ;
5601
5607
const Py_ssize_t total_args = co -> co_argcount + co -> co_kwonlyargcount ;
@@ -5629,21 +5635,14 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5629
5635
}
5630
5636
for (j = 0 ; j < n ; j ++ ) {
5631
5637
PyObject * x = args [j ];
5632
- if (!steal_args ) {
5633
- Py_INCREF (x );
5634
- }
5635
5638
assert (localsplus [j ] == NULL );
5636
5639
localsplus [j ] = x ;
5637
5640
}
5638
5641
5639
5642
/* Pack other positional arguments into the *args argument */
5640
5643
if (co -> co_flags & CO_VARARGS ) {
5641
5644
PyObject * u = NULL ;
5642
- if (steal_args ) {
5643
- u = _PyTuple_FromArraySteal (args + n , argcount - n );
5644
- } else {
5645
- u = _PyTuple_FromArray (args + n , argcount - n );
5646
- }
5645
+ u = _PyTuple_FromArraySteal (args + n , argcount - n );
5647
5646
if (u == NULL ) {
5648
5647
goto fail_post_positional ;
5649
5648
}
@@ -5652,10 +5651,8 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5652
5651
}
5653
5652
else if (argcount > n ) {
5654
5653
/* Too many postional args. Error is reported later */
5655
- if (steal_args ) {
5656
- for (j = n ; j < argcount ; j ++ ) {
5657
- Py_DECREF (args [j ]);
5658
- }
5654
+ for (j = n ; j < argcount ; j ++ ) {
5655
+ Py_DECREF (args [j ]);
5659
5656
}
5660
5657
}
5661
5658
@@ -5717,19 +5714,15 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5717
5714
if (PyDict_SetItem (kwdict , keyword , value ) == -1 ) {
5718
5715
goto kw_fail ;
5719
5716
}
5720
- if (steal_args ) {
5721
- Py_DECREF (value );
5722
- }
5717
+ Py_DECREF (value );
5723
5718
continue ;
5724
5719
5725
5720
kw_fail :
5726
- if (steal_args ) {
5727
- for (;i < kwcount ; i ++ ) {
5728
- PyObject * value = args [i + argcount ];
5729
- Py_DECREF (value );
5730
- }
5721
+ for (;i < kwcount ; i ++ ) {
5722
+ PyObject * value = args [i + argcount ];
5723
+ Py_DECREF (value );
5731
5724
}
5732
- goto fail_noclean ;
5725
+ goto fail_post_args ;
5733
5726
5734
5727
kw_found :
5735
5728
if (localsplus [j ] != NULL ) {
@@ -5738,9 +5731,6 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5738
5731
con -> fc_qualname , keyword );
5739
5732
goto kw_fail ;
5740
5733
}
5741
- if (!steal_args ) {
5742
- Py_INCREF (value );
5743
- }
5744
5734
localsplus [j ] = value ;
5745
5735
}
5746
5736
}
@@ -5749,7 +5739,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5749
5739
if ((argcount > co -> co_argcount ) && !(co -> co_flags & CO_VARARGS )) {
5750
5740
too_many_positional (tstate , co , argcount , con -> fc_defaults , localsplus ,
5751
5741
con -> fc_qualname );
5752
- goto fail_noclean ;
5742
+ goto fail_post_args ;
5753
5743
}
5754
5744
5755
5745
/* Add missing positional arguments (copy default values from defs) */
@@ -5765,7 +5755,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5765
5755
if (missing ) {
5766
5756
missing_arguments (tstate , co , missing , defcount , localsplus ,
5767
5757
con -> fc_qualname );
5768
- goto fail_noclean ;
5758
+ goto fail_post_args ;
5769
5759
}
5770
5760
if (n > m )
5771
5761
i = n - m ;
@@ -5798,43 +5788,39 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
5798
5788
continue ;
5799
5789
}
5800
5790
else if (_PyErr_Occurred (tstate )) {
5801
- goto fail_noclean ;
5791
+ goto fail_post_args ;
5802
5792
}
5803
5793
}
5804
5794
missing ++ ;
5805
5795
}
5806
5796
if (missing ) {
5807
5797
missing_arguments (tstate , co , missing , -1 , localsplus ,
5808
5798
con -> fc_qualname );
5809
- goto fail_noclean ;
5799
+ goto fail_post_args ;
5810
5800
}
5811
5801
}
5812
-
5813
5802
/* Copy closure variables to free variables */
5814
5803
for (i = 0 ; i < co -> co_nfreevars ; ++ i ) {
5815
5804
PyObject * o = PyTuple_GET_ITEM (con -> fc_closure , i );
5816
5805
Py_INCREF (o );
5817
5806
localsplus [co -> co_nlocals + co -> co_nplaincellvars + i ] = o ;
5818
5807
}
5819
-
5820
5808
return 0 ;
5821
5809
5822
5810
fail_pre_positional :
5823
- if (steal_args ) {
5824
- for (j = 0 ; j < argcount ; j ++ ) {
5825
- Py_DECREF (args [j ]);
5826
- }
5811
+ for (j = 0 ; j < argcount ; j ++ ) {
5812
+ Py_DECREF (args [j ]);
5827
5813
}
5828
5814
/* fall through */
5829
5815
fail_post_positional :
5830
- if (steal_args ) {
5831
- Py_ssize_t kwcount = kwnames != NULL ? PyTuple_GET_SIZE (kwnames ) : 0 ;
5816
+ if (kwnames ) {
5817
+ Py_ssize_t kwcount = PyTuple_GET_SIZE (kwnames );
5832
5818
for (j = argcount ; j < argcount + kwcount ; j ++ ) {
5833
5819
Py_DECREF (args [j ]);
5834
5820
}
5835
5821
}
5836
5822
/* fall through */
5837
- fail_noclean :
5823
+ fail_post_args :
5838
5824
return -1 ;
5839
5825
}
5840
5826
@@ -5850,21 +5836,34 @@ make_coro_frame(PyThreadState *tstate,
5850
5836
int size = code -> co_nlocalsplus + code -> co_stacksize + FRAME_SPECIALS_SIZE ;
5851
5837
InterpreterFrame * frame = (InterpreterFrame * )PyMem_Malloc (sizeof (PyObject * )* size );
5852
5838
if (frame == NULL ) {
5853
- PyErr_NoMemory ();
5854
- return NULL ;
5839
+ goto fail_no_memory ;
5855
5840
}
5856
- for (Py_ssize_t i = 0 ; i < code -> co_nlocalsplus ; i ++ ) {
5841
+ _PyFrame_InitializeSpecials (frame , con , locals , code -> co_nlocalsplus );
5842
+ for (int i = 0 ; i < code -> co_nlocalsplus ; i ++ ) {
5857
5843
frame -> localsplus [i ] = NULL ;
5858
5844
}
5859
- _PyFrame_InitializeSpecials (frame , con , locals , code -> co_nlocalsplus );
5860
5845
assert (frame -> frame_obj == NULL );
5861
- if (initialize_locals (tstate , con , frame -> localsplus , args , argcount , kwnames , 0 )) {
5846
+ if (initialize_locals (tstate , con , frame -> localsplus , args , argcount , kwnames )) {
5862
5847
_PyFrame_Clear (frame , 1 );
5863
5848
return NULL ;
5864
5849
}
5865
5850
return frame ;
5851
+ fail_no_memory :
5852
+ /* Consume the references */
5853
+ for (Py_ssize_t i = 0 ; i < argcount ; i ++ ) {
5854
+ Py_DECREF (args [i ]);
5855
+ }
5856
+ if (kwnames ) {
5857
+ Py_ssize_t kwcount = PyTuple_GET_SIZE (kwnames );
5858
+ for (Py_ssize_t i = 0 ; i < kwcount ; i ++ ) {
5859
+ Py_DECREF (args [i + argcount ]);
5860
+ }
5861
+ }
5862
+ PyErr_NoMemory ();
5863
+ return NULL ;
5866
5864
}
5867
5865
5866
+ /* Consumes all the references to the args */
5868
5867
static PyObject *
5869
5868
make_coro (PyThreadState * tstate , PyFrameConstructor * con ,
5870
5869
PyObject * locals ,
@@ -5880,28 +5879,44 @@ make_coro(PyThreadState *tstate, PyFrameConstructor *con,
5880
5879
if (gen == NULL ) {
5881
5880
return NULL ;
5882
5881
}
5883
-
5884
5882
return gen ;
5885
5883
}
5886
5884
5887
- // If *steal_args* is set, the function will steal the references to all the arguments.
5888
- // In case of error, the function returns null and if *steal_args* is set, the caller
5889
- // will still own all the arguments.
5885
+ /* Consumes all the references to the args */
5890
5886
static InterpreterFrame *
5891
5887
_PyEvalFramePushAndInit (PyThreadState * tstate , PyFrameConstructor * con ,
5892
5888
PyObject * locals , PyObject * const * args ,
5893
- size_t argcount , PyObject * kwnames , int steal_args )
5889
+ size_t argcount , PyObject * kwnames )
5894
5890
{
5895
- InterpreterFrame * frame = _PyThreadState_PushFrame (tstate , con , locals );
5891
+ PyCodeObject * code = (PyCodeObject * )con -> fc_code ;
5892
+ size_t size = code -> co_nlocalsplus + code -> co_stacksize + FRAME_SPECIALS_SIZE ;
5893
+ InterpreterFrame * frame = _PyThreadState_BumpFramePointer (tstate , size );
5896
5894
if (frame == NULL ) {
5897
- return NULL ;
5895
+ goto fail ;
5898
5896
}
5899
- PyObject * * localsarray = _PyFrame_GetLocalsArray (frame );
5900
- if (initialize_locals (tstate , con , localsarray , args , argcount , kwnames , steal_args )) {
5897
+ _PyFrame_InitializeSpecials (frame , con , locals , code -> co_nlocalsplus );
5898
+ PyObject * * localsarray = & frame -> localsplus [0 ];
5899
+ for (int i = 0 ; i < code -> co_nlocalsplus ; i ++ ) {
5900
+ localsarray [i ] = NULL ;
5901
+ }
5902
+ if (initialize_locals (tstate , con , localsarray , args , argcount , kwnames )) {
5901
5903
_PyFrame_Clear (frame , 0 );
5902
5904
return NULL ;
5903
5905
}
5904
5906
return frame ;
5907
+ fail :
5908
+ /* Consume the references */
5909
+ for (size_t i = 0 ; i < argcount ; i ++ ) {
5910
+ Py_DECREF (args [i ]);
5911
+ }
5912
+ if (kwnames ) {
5913
+ Py_ssize_t kwcount = PyTuple_GET_SIZE (kwnames );
5914
+ for (Py_ssize_t i = 0 ; i < kwcount ; i ++ ) {
5915
+ Py_DECREF (args [i + argcount ]);
5916
+ }
5917
+ }
5918
+ PyErr_NoMemory ();
5919
+ return NULL ;
5905
5920
}
5906
5921
5907
5922
static int
@@ -5925,13 +5940,25 @@ _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con,
5925
5940
PyObject * kwnames )
5926
5941
{
5927
5942
PyCodeObject * code = (PyCodeObject * )con -> fc_code ;
5943
+ /* _PyEvalFramePushAndInit and make_coro consume
5944
+ * all the references to their arguments
5945
+ */
5946
+ for (size_t i = 0 ; i < argcount ; i ++ ) {
5947
+ Py_INCREF (args [i ]);
5948
+ }
5949
+ if (kwnames ) {
5950
+ Py_ssize_t kwcount = PyTuple_GET_SIZE (kwnames );
5951
+ for (Py_ssize_t i = 0 ; i < kwcount ; i ++ ) {
5952
+ Py_INCREF (args [i + argcount ]);
5953
+ }
5954
+ }
5928
5955
int is_coro = code -> co_flags &
5929
5956
(CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR );
5930
5957
if (is_coro ) {
5931
5958
return make_coro (tstate , con , locals , args , argcount , kwnames );
5932
5959
}
5933
5960
InterpreterFrame * frame = _PyEvalFramePushAndInit (
5934
- tstate , con , locals , args , argcount , kwnames , 0 );
5961
+ tstate , con , locals , args , argcount , kwnames );
5935
5962
if (frame == NULL ) {
5936
5963
return NULL ;
5937
5964
}
0 commit comments