From e6e9c4b3fb0fa97c1dcaa486ac3d8fb809d4916d Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 2 Feb 2023 11:11:23 +0000 Subject: [PATCH 1/4] iterator --- Python/bytecodes.c | 20 +++++++++----------- Python/generated_cases.c.h | 17 ++++++++++------- Python/opcode_metadata.h | 8 ++++---- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 169a2647866b31..484d162dc45a7f 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2043,31 +2043,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; + } } PREDICT(LOAD_CONST); } @@ -3010,8 +3009,7 @@ dummy_func( PUSH((PyObject *)func); } - // 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 97263866fe9158..8b6242f4477d2c 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2584,30 +2584,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)) { + 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; + } } + POKE(1, iter); PREDICT(LOAD_CONST); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index ca3dde363bfd85..120e5512e12e47 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -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 -1; case RETURN_GENERATOR: - return -1; + return 0; case BUILD_SLICE: return -1; case FORMAT_VALUE: @@ -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: From a664a74ace1773b1dda90503f24c66c0f0afa0ad Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 2 Feb 2023 11:43:05 +0000 Subject: [PATCH 2/4] SEND --- Python/bytecodes.c | 13 ++++--------- Python/generated_cases.c.h | 16 +++++++++------- Python/opcode_metadata.h | 4 ++-- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 484d162dc45a7f..5290320bb0ddfb 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); } } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 8b6242f4477d2c..d21fc9ffe554a4 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(); PySendResult gen_status; - PyObject *retval; + bool jump = false; 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(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 120e5512e12e47..256f81a89fcd36 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: @@ -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: From 3ba9aae95dda64209926ab429757f51b14a8ca78 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 2 Feb 2023 14:57:13 +0000 Subject: [PATCH 3/4] regen-cases --- Python/generated_cases.c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d21fc9ffe554a4..9b6a723296bbb2 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -869,8 +869,8 @@ PyObject *receiver = PEEK(2); PyObject *retval; assert(frame != &entry_frame); - PySendResult gen_status; bool jump = false; + PySendResult gen_status; if (tstate->c_tracefunc == NULL) { gen_status = PyIter_Send(receiver, v, &retval); } else { From 99c34ca665ca3b551f5fbca3415240c6fe66bc47 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 2 Feb 2023 23:39:13 +0000 Subject: [PATCH 4/4] keep ref to iterable until after 'goto error' --- Python/bytecodes.c | 2 +- Python/generated_cases.c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 5290320bb0ddfb..74c53ad1579f6c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2058,10 +2058,10 @@ dummy_func( else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); if (iter == NULL) { goto error; } + Py_DECREF(iterable); } PREDICT(LOAD_CONST); } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 9b6a723296bbb2..6f90d9ca4a59ef 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2607,10 +2607,10 @@ else { /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); if (iter == NULL) { goto error; } + Py_DECREF(iterable); } POKE(1, iter); PREDICT(LOAD_CONST);