summaryrefslogtreecommitdiffstats
path: root/Python/generated_cases.c.h
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-02-13 11:24:55 (GMT)
committerGitHub <noreply@github.com>2023-02-13 11:24:55 (GMT)
commit160f2fe2b90ed5ec7838cb4141dd35768422891f (patch)
tree2d9617e40227da45aa8e3c4452eaa0f389a0d879 /Python/generated_cases.c.h
parenta1f08f5f19753c7c9295f51b5ae1262c7a1c838f (diff)
downloadcpython-160f2fe2b90ed5ec7838cb4141dd35768422891f.zip
cpython-160f2fe2b90ed5ec7838cb4141dd35768422891f.tar.gz
cpython-160f2fe2b90ed5ec7838cb4141dd35768422891f.tar.bz2
GH-87849: Simplify stack effect of SEND and specialize it for generators and coroutines. (GH-101788)
Diffstat (limited to 'Python/generated_cases.c.h')
-rw-r--r--Python/generated_cases.c.h89
1 files changed, 52 insertions, 37 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index a224d4e..093ebff 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -882,57 +882,69 @@
}
TARGET(SEND) {
+ PREDICTED(SEND);
PyObject *v = PEEK(1);
PyObject *receiver = PEEK(2);
PyObject *retval;
+ #if ENABLE_SPECIALIZATION
+ _PySendCache *cache = (_PySendCache *)next_instr;
+ if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
+ assert(cframe.use_tracing == 0);
+ next_instr--;
+ _Py_Specialize_Send(receiver, next_instr);
+ DISPATCH_SAME_OPARG();
+ }
+ STAT_INC(SEND, deferred);
+ DECREMENT_ADAPTIVE_COUNTER(cache->counter);
+ #endif /* ENABLE_SPECIALIZATION */
assert(frame != &entry_frame);
- bool jump = false;
- PySendResult gen_status;
- if (tstate->c_tracefunc == NULL) {
- gen_status = PyIter_Send(receiver, v, &retval);
- } else {
- if (Py_IsNone(v) && PyIter_Check(receiver)) {
- retval = Py_TYPE(receiver)->tp_iternext(receiver);
- }
- else {
- retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v);
- }
- if (retval == NULL) {
- if (tstate->c_tracefunc != NULL
- && _PyErr_ExceptionMatches(tstate, PyExc_StopIteration))
- call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, frame);
- if (_PyGen_FetchStopIterationValue(&retval) == 0) {
- gen_status = PYGEN_RETURN;
- }
- else {
- gen_status = PYGEN_ERROR;
- }
+ if (Py_IsNone(v) && PyIter_Check(receiver)) {
+ retval = Py_TYPE(receiver)->tp_iternext(receiver);
+ }
+ else {
+ retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v);
+ }
+ if (retval == NULL) {
+ if (tstate->c_tracefunc != NULL
+ && _PyErr_ExceptionMatches(tstate, PyExc_StopIteration))
+ call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, frame);
+ if (_PyGen_FetchStopIterationValue(&retval) == 0) {
+ assert(retval != NULL);
+ JUMPBY(oparg);
}
else {
- gen_status = PYGEN_NEXT;
+ assert(retval == NULL);
+ goto error;
}
}
- if (gen_status == PYGEN_ERROR) {
- assert(retval == NULL);
- goto error;
- }
- Py_DECREF(v);
- if (gen_status == PYGEN_RETURN) {
- assert(retval != NULL);
- Py_DECREF(receiver);
- JUMPBY(oparg);
- jump = true;
- }
else {
- assert(gen_status == PYGEN_NEXT);
assert(retval != NULL);
}
- STACK_SHRINK(1);
- STACK_GROW(((!jump) ? 1 : 0));
POKE(1, retval);
+ JUMPBY(1);
DISPATCH();
}
+ TARGET(SEND_GEN) {
+ PyObject *v = PEEK(1);
+ PyObject *receiver = PEEK(2);
+ assert(cframe.use_tracing == 0);
+ PyGenObject *gen = (PyGenObject *)receiver;
+ DEOPT_IF(Py_TYPE(gen) != &PyGen_Type &&
+ Py_TYPE(gen) != &PyCoro_Type, SEND);
+ DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND);
+ STAT_INC(SEND, hit);
+ _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
+ frame->yield_offset = oparg;
+ STACK_SHRINK(1);
+ _PyFrame_StackPush(gen_frame, v);
+ gen->gi_frame_state = FRAME_EXECUTING;
+ gen->gi_exc_state.previous_item = tstate->exc_info;
+ tstate->exc_info = &gen->gi_exc_state;
+ JUMPBY(INLINE_CACHE_ENTRIES_SEND + oparg);
+ DISPATCH_INLINED(gen_frame);
+ }
+
TARGET(YIELD_VALUE) {
PyObject *retval = PEEK(1);
// NOTE: It's important that YIELD_VALUE never raises an exception!
@@ -1026,6 +1038,7 @@
PyObject *exc_value = PEEK(1);
PyObject *last_sent_val = PEEK(2);
PyObject *sub_iter = PEEK(3);
+ PyObject *none;
PyObject *value;
assert(throwflag);
assert(exc_value && PyExceptionInstance_Check(exc_value));
@@ -1034,13 +1047,15 @@
Py_DECREF(sub_iter);
Py_DECREF(last_sent_val);
Py_DECREF(exc_value);
+ none = Py_NewRef(Py_None);
}
else {
_PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));
goto exception_unwind;
}
- STACK_SHRINK(2);
+ STACK_SHRINK(1);
POKE(1, value);
+ POKE(2, none);
DISPATCH();
}