summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2023-02-03 11:30:21 (GMT)
committerGitHub <noreply@github.com>2023-02-03 11:30:21 (GMT)
commit04e06e20ee61f3c0d1d7a827b2feb4ed41bb198d (patch)
tree88cda5d765a9aaf51238aefe3eea308bd87aa75d
parenta52cc9853fed39b5cc90b7ffb6a64249307a990b (diff)
downloadcpython-04e06e20ee61f3c0d1d7a827b2feb4ed41bb198d.zip
cpython-04e06e20ee61f3c0d1d7a827b2feb4ed41bb198d.tar.gz
cpython-04e06e20ee61f3c0d1d7a827b2feb4ed41bb198d.tar.bz2
gh-98831: rewrite SEND, GET_YIELD_FROM_ITER, RETURN_GENERATOR in the instruction definition DSL (#101516)
-rw-r--r--Python/bytecodes.c35
-rw-r--r--Python/generated_cases.c.h35
-rw-r--r--Python/opcode_metadata.h12
3 files changed, 40 insertions, 42 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 169a264..74c53ad 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);
}
@@ -3010,8 +3004,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 9726386..6f90d9c 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 ca3dde3..256f81a 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 -1;
case RETURN_GENERATOR:
- return -1;
+ return 0;
case BUILD_SLICE:
return -1;
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: