From 77af074012c8111a277f62251f6d1180d582ab3b Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:30:21 +0000 Subject: [PATCH] gh-98831: rewrite SEND, GET_YIELD_FROM_ITER, RETURN_GENERATOR in the instruction definition DSL (#101516) --- Python/bytecodes.c | 35 ++++++++++++++--------------------- Python/generated_cases.c.h | 35 ++++++++++++++++++++--------------- Python/opcode_metadata.h | 12 ++++++------ 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 47e46d836d5ef4b..8993567ac82206b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -663,14 +663,10 @@ dummy_func( PREDICT(LOAD_CONST); } - // error: SEND stack effect depends on jump flag - inst(SEND) { + inst(SEND, (receiver, v -- receiver if (!jump), retval)) { assert(frame != &entry_frame); - assert(STACK_LEVEL() >= 2); - PyObject *v = POP(); - PyObject *receiver = TOP(); + bool jump = false; PySendResult gen_status; - PyObject *retval; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { @@ -695,21 +691,20 @@ dummy_func( gen_status = PYGEN_NEXT; } } - Py_DECREF(v); if (gen_status == PYGEN_ERROR) { assert(retval == NULL); goto error; } + Py_DECREF(v); if (gen_status == PYGEN_RETURN) { assert(retval != NULL); Py_DECREF(receiver); - SET_TOP(retval); JUMPBY(oparg); + jump = true; } else { assert(gen_status == PYGEN_NEXT); assert(retval != NULL); - PUSH(retval); } } @@ -2043,31 +2038,30 @@ dummy_func( ERROR_IF(iter == NULL, error); } - // stack effect: ( -- ) - inst(GET_YIELD_FROM_ITER) { + inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter; if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ - Py_DECREF(iterable); - SET_TOP(NULL); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); goto error; } + iter = iterable; + } + else if (PyGen_CheckExact(iterable)) { + iter = iterable; } - else if (!PyGen_CheckExact(iterable)) { + else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) + if (iter == NULL) { goto error; + } + Py_DECREF(iterable); } PREDICT(LOAD_CONST); } @@ -3013,8 +3007,7 @@ dummy_func( func = (PyObject *)func_obj; } - // stack effect: ( -- ) - inst(RETURN_GENERATOR) { + inst(RETURN_GENERATOR, (--)) { assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 139ec633d4a7145..e524bfcb99d4700 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -865,12 +865,12 @@ } TARGET(SEND) { + PyObject *v = PEEK(1); + PyObject *receiver = PEEK(2); + PyObject *retval; assert(frame != &entry_frame); - assert(STACK_LEVEL() >= 2); - PyObject *v = POP(); - PyObject *receiver = TOP(); + bool jump = false; PySendResult gen_status; - PyObject *retval; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { @@ -895,22 +895,24 @@ gen_status = PYGEN_NEXT; } } - Py_DECREF(v); if (gen_status == PYGEN_ERROR) { assert(retval == NULL); goto error; } + Py_DECREF(v); if (gen_status == PYGEN_RETURN) { assert(retval != NULL); Py_DECREF(receiver); - SET_TOP(retval); JUMPBY(oparg); + jump = true; } else { assert(gen_status == PYGEN_NEXT); assert(retval != NULL); - PUSH(retval); } + STACK_SHRINK(1); + STACK_GROW(((!jump) ? 1 : 0)); + POKE(1, retval); DISPATCH(); } @@ -2584,30 +2586,33 @@ } TARGET(GET_YIELD_FROM_ITER) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); + PyObject *iterable = PEEK(1); PyObject *iter; + /* before: [obj]; after [getiter(obj)] */ if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ - Py_DECREF(iterable); - SET_TOP(NULL); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); goto error; } + iter = iterable; } - else if (!PyGen_CheckExact(iterable)) { + else if (PyGen_CheckExact(iterable)) { + iter = iterable; + } + else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) + if (iter == NULL) { goto error; + } + Py_DECREF(iterable); } + POKE(1, iter); PREDICT(LOAD_CONST); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 5daa958dfb442cc..857526c35aa5b65 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -99,7 +99,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case GET_AWAITABLE: return 1; case SEND: - return -1; + return 2; case YIELD_VALUE: return 1; case POP_EXCEPT: @@ -259,7 +259,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case GET_ITER: return 1; case GET_YIELD_FROM_ITER: - return -1; + return 1; case FOR_ITER: return -1; case FOR_ITER_LIST: @@ -327,7 +327,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { case MAKE_FUNCTION: return ((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0) + 1; case RETURN_GENERATOR: - return -1; + return 0; case BUILD_SLICE: return ((oparg == 3) ? 1 : 0) + 2; case FORMAT_VALUE: @@ -445,7 +445,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case GET_AWAITABLE: return 1; case SEND: - return -1; + return ((!jump) ? 1 : 0) + 1; case YIELD_VALUE: return 1; case POP_EXCEPT: @@ -605,7 +605,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case GET_ITER: return 1; case GET_YIELD_FROM_ITER: - return -1; + return 1; case FOR_ITER: return -1; case FOR_ITER_LIST: @@ -673,7 +673,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { case MAKE_FUNCTION: return 1; case RETURN_GENERATOR: - return -1; + return 0; case BUILD_SLICE: return 1; case FORMAT_VALUE: