@@ -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 | } |
|