mirror of
https://github.com/python/cpython.git
synced 2026-04-13 23:31:02 +00:00
GH-145667: Merge GET_ITER and GET_YIELD_FROM_ITER (GH-146120)
* Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER
This commit is contained in:
parent
b5e4c46be2
commit
879c85f6e4
30 changed files with 944 additions and 989 deletions
|
|
@ -425,13 +425,15 @@ dummy_func(
|
|||
PyStackRef_CLOSE(iter);
|
||||
}
|
||||
|
||||
pure inst(END_SEND, (receiver, value -- val)) {
|
||||
pure inst(END_SEND, (receiver, index_or_null, value -- val)) {
|
||||
val = value;
|
||||
(void)index_or_null;
|
||||
DEAD(value);
|
||||
DEAD(index_or_null);
|
||||
PyStackRef_CLOSE(receiver);
|
||||
}
|
||||
|
||||
tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- val)) {
|
||||
tier1 inst(INSTRUMENTED_END_SEND, (receiver, index_or_null, value -- val)) {
|
||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||
if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) {
|
||||
int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value));
|
||||
|
|
@ -440,6 +442,8 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
val = value;
|
||||
(void)index_or_null;
|
||||
DEAD(index_or_null);
|
||||
DEAD(value);
|
||||
PyStackRef_CLOSE(receiver);
|
||||
}
|
||||
|
|
@ -1410,7 +1414,7 @@ dummy_func(
|
|||
SEND_GEN,
|
||||
};
|
||||
|
||||
specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused -- receiver, unused)) {
|
||||
specializing op(_SPECIALIZE_SEND, (counter/1, receiver, unused, unused -- receiver, unused, unused)) {
|
||||
#if ENABLE_SPECIALIZATION
|
||||
if (ADAPTIVE_COUNTER_TRIGGERS(counter)) {
|
||||
next_instr = this_instr;
|
||||
|
|
@ -1422,7 +1426,7 @@ dummy_func(
|
|||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
op(_SEND, (receiver, v -- receiver, retval)) {
|
||||
op(_SEND, (receiver, null_or_index, v -- receiver, null_or_index, retval)) {
|
||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||
PyObject *retval_o;
|
||||
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||
|
|
@ -1443,36 +1447,49 @@ dummy_func(
|
|||
gen_frame->previous = frame;
|
||||
DISPATCH_INLINED(gen_frame);
|
||||
}
|
||||
if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) {
|
||||
retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o);
|
||||
if (!PyStackRef_IsNull(null_or_index)) {
|
||||
_PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index);
|
||||
if (!PyStackRef_IsValid(item)) {
|
||||
if (PyStackRef_IsError(item)) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
JUMPBY(oparg);
|
||||
DISPATCH();
|
||||
}
|
||||
retval = item;
|
||||
}
|
||||
else {
|
||||
retval_o = PyObject_CallMethodOneArg(receiver_o,
|
||||
&_Py_ID(send),
|
||||
PyStackRef_AsPyObjectBorrow(v));
|
||||
}
|
||||
if (retval_o == NULL) {
|
||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||
if (matches) {
|
||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||
}
|
||||
int err = _PyGen_FetchStopIterationValue(&retval_o);
|
||||
if (err == 0) {
|
||||
assert(retval_o != NULL);
|
||||
JUMPBY(oparg);
|
||||
if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) {
|
||||
retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o);
|
||||
}
|
||||
else {
|
||||
PyStackRef_CLOSE(v);
|
||||
ERROR_IF(true);
|
||||
retval_o = PyObject_CallMethodOneArg(receiver_o,
|
||||
&_Py_ID(send),
|
||||
PyStackRef_AsPyObjectBorrow(v));
|
||||
}
|
||||
if (retval_o == NULL) {
|
||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||
if (matches) {
|
||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||
}
|
||||
int err = _PyGen_FetchStopIterationValue(&retval_o);
|
||||
if (err == 0) {
|
||||
assert(retval_o != NULL);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else {
|
||||
PyStackRef_CLOSE(v);
|
||||
ERROR_IF(true);
|
||||
}
|
||||
}
|
||||
retval = PyStackRef_FromPyObjectSteal(retval_o);
|
||||
}
|
||||
PyStackRef_CLOSE(v);
|
||||
retval = PyStackRef_FromPyObjectSteal(retval_o);
|
||||
}
|
||||
|
||||
macro(SEND) = _SPECIALIZE_SEND + _SEND;
|
||||
|
||||
op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) {
|
||||
op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) {
|
||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver);
|
||||
EXIT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type);
|
||||
EXIT_IF(!gen_try_set_executing((PyGenObject *)gen));
|
||||
|
|
@ -1490,7 +1507,7 @@ dummy_func(
|
|||
|
||||
macro(SEND_GEN) =
|
||||
unused/1 +
|
||||
_RECORD_NOS_GEN_FUNC +
|
||||
_RECORD_3OS_GEN_FUNC +
|
||||
_CHECK_PEP_523 +
|
||||
_SEND_GEN_FRAME +
|
||||
_PUSH_FRAME;
|
||||
|
|
@ -1602,17 +1619,17 @@ dummy_func(
|
|||
|
||||
macro(END_ASYNC_FOR) = _END_ASYNC_FOR;
|
||||
|
||||
tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- none, value)) {
|
||||
tier1 inst(CLEANUP_THROW, (sub_iter, null_in, last_sent_val, exc_value_st -- none, null_out, value)) {
|
||||
PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
|
||||
#if !_Py_TAIL_CALL_INTERP
|
||||
assert(throwflag);
|
||||
#endif
|
||||
assert(exc_value && PyExceptionInstance_Check(exc_value));
|
||||
|
||||
int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration);
|
||||
if (matches) {
|
||||
value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value);
|
||||
DECREF_INPUTS();
|
||||
null_out = null_in;
|
||||
none = PyStackRef_None;
|
||||
}
|
||||
else {
|
||||
|
|
@ -3335,52 +3352,10 @@ dummy_func(
|
|||
#ifdef Py_STATS
|
||||
_Py_GatherStats_GetIter(iterable);
|
||||
#endif
|
||||
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||
/* Leave iterable on stack and pushed tagged 0 */
|
||||
iter = iterable;
|
||||
DEAD(iterable);
|
||||
index_or_null = PyStackRef_TagInt(0);
|
||||
}
|
||||
else {
|
||||
/* Pop iterable, and push iterator then NULL */
|
||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||
PyStackRef_CLOSE(iterable);
|
||||
ERROR_IF(iter_o == NULL);
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
index_or_null = PyStackRef_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable);
|
||||
if (PyCoro_CheckExact(iterable_o)) {
|
||||
/* `iterable` is a coroutine */
|
||||
if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||
/* and it is used in a 'yield from' expression of a
|
||||
regular generator. */
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
iter = iterable;
|
||||
DEAD(iterable);
|
||||
}
|
||||
else if (PyGen_CheckExact(iterable_o)) {
|
||||
iter = iterable;
|
||||
DEAD(iterable);
|
||||
}
|
||||
else {
|
||||
/* `iterable` is not a generator. */
|
||||
PyObject *iter_o = PyObject_GetIter(iterable_o);
|
||||
if (iter_o == NULL) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
DECREF_INPUTS();
|
||||
}
|
||||
_PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg);
|
||||
DEAD(iterable);
|
||||
ERROR_IF(PyStackRef_IsError(result));
|
||||
iter = result;
|
||||
}
|
||||
|
||||
// Most members of this family are "secretly" super-instructions.
|
||||
|
|
@ -5857,6 +5832,17 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
tier2 op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) {
|
||||
PyObject *obj = PyStackRef_AsPyObjectBorrow(gen);
|
||||
if (PyGen_Check(obj)) {
|
||||
PyGenObject *gen_obj = (PyGenObject *)obj;
|
||||
_PyStackRef func = gen_obj->gi_iframe.f_funcobj;
|
||||
if (!PyStackRef_IsNull(func)) {
|
||||
RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tier2 op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) {
|
||||
RECORD_VALUE(PyStackRef_AsPyObjectBorrow(value));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1165,6 +1165,42 @@ stop_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
|
|||
#include "generated_cases.c.h"
|
||||
#endif
|
||||
|
||||
|
||||
_PyStackRef
|
||||
_PyEval_GetIter(_PyStackRef iterable, _PyStackRef *index_or_null, int yield_from)
|
||||
{
|
||||
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||
/* Leave iterable on stack and pushed tagged 0 */
|
||||
*index_or_null = PyStackRef_TagInt(0);
|
||||
return iterable;
|
||||
}
|
||||
*index_or_null = PyStackRef_NULL;
|
||||
if (tp->tp_iter == PyObject_SelfIter) {
|
||||
return iterable;
|
||||
}
|
||||
if (yield_from && tp == &PyCoro_Type) {
|
||||
assert(yield_from != GET_ITER_YIELD_FROM);
|
||||
if (yield_from == GET_ITER_YIELD_FROM_CORO_CHECK) {
|
||||
/* `iterable` is a coroutine and it is used in a 'yield from'
|
||||
* expression of a regular generator. */
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
PyStackRef_CLOSE(iterable);
|
||||
return PyStackRef_ERROR;
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
/* Pop iterable, and push iterator then NULL */
|
||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||
PyStackRef_CLOSE(iterable);
|
||||
if (iter_o == NULL) {
|
||||
return PyStackRef_ERROR;
|
||||
}
|
||||
return PyStackRef_FromPyObjectSteal(iter_o);
|
||||
}
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ >= 10 && !defined(__clang__)) && defined(__x86_64__)
|
||||
/*
|
||||
* gh-129987: The SLP autovectorizer can cause poor code generation for
|
||||
|
|
|
|||
|
|
@ -606,6 +606,7 @@ codegen_unwind_fblock(compiler *c, location *ploc,
|
|||
RETURN_IF_ERROR(codegen_call_exit_with_nones(c, *ploc));
|
||||
if (info->fb_type == COMPILE_FBLOCK_ASYNC_WITH) {
|
||||
ADDOP_I(c, *ploc, GET_AWAITABLE, 2);
|
||||
ADDOP(c, *ploc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, *ploc, Py_None);
|
||||
ADD_YIELD_FROM(c, *ploc, 1);
|
||||
}
|
||||
|
|
@ -2124,7 +2125,7 @@ codegen_for(compiler *c, stmt_ty s)
|
|||
VISIT(c, expr, s->v.For.iter);
|
||||
|
||||
loc = LOC(s->v.For.iter);
|
||||
ADDOP(c, loc, GET_ITER);
|
||||
ADDOP_I(c, loc, GET_ITER, 0);
|
||||
|
||||
USE_LABEL(c, start);
|
||||
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
|
||||
|
|
@ -2175,6 +2176,7 @@ codegen_async_for(compiler *c, stmt_ty s)
|
|||
/* SETUP_FINALLY to guard the __anext__ call */
|
||||
ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
|
||||
ADDOP(c, loc, GET_ANEXT);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
USE_LABEL(c, send);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
|
|
@ -4540,7 +4542,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
|
|||
|
||||
if (IS_JUMP_TARGET_LABEL(start)) {
|
||||
if (iter_pos != ITERATOR_ON_STACK) {
|
||||
ADDOP(c, LOC(gen->iter), GET_ITER);
|
||||
ADDOP_I(c, LOC(gen->iter), GET_ITER, 0);
|
||||
depth += 1;
|
||||
}
|
||||
USE_LABEL(c, start);
|
||||
|
|
@ -4574,7 +4576,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
|
|||
NEW_JUMP_TARGET_LABEL(c, unpack_start);
|
||||
NEW_JUMP_TARGET_LABEL(c, unpack_end);
|
||||
VISIT(c, expr, elt->v.Starred.value);
|
||||
ADDOP(c, elt_loc, GET_ITER);
|
||||
ADDOP_I(c, elt_loc, GET_ITER, 0);
|
||||
USE_LABEL(c, unpack_start);
|
||||
ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
|
||||
ADDOP_YIELD(c, elt_loc);
|
||||
|
|
@ -4686,6 +4688,7 @@ codegen_async_comprehension_generator(compiler *c, location loc,
|
|||
|
||||
ADDOP_JUMP(c, loc, SETUP_FINALLY, except);
|
||||
ADDOP(c, loc, GET_ANEXT);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
USE_LABEL(c, send);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
|
|
@ -4716,7 +4719,7 @@ codegen_async_comprehension_generator(compiler *c, location loc,
|
|||
NEW_JUMP_TARGET_LABEL(c, unpack_start);
|
||||
NEW_JUMP_TARGET_LABEL(c, unpack_end);
|
||||
VISIT(c, expr, elt->v.Starred.value);
|
||||
ADDOP(c, elt_loc, GET_ITER);
|
||||
ADDOP_I(c, elt_loc, GET_ITER, 0);
|
||||
USE_LABEL(c, unpack_start);
|
||||
ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
|
||||
ADDOP_YIELD(c, elt_loc);
|
||||
|
|
@ -5039,6 +5042,7 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
|
|||
|
||||
if (is_async_comprehension && type != COMP_GENEXP) {
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 0);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
}
|
||||
|
|
@ -5178,6 +5182,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos)
|
|||
ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___AENTER__);
|
||||
ADDOP_I(c, loc, CALL, 0);
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 1);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
|
||||
|
|
@ -5214,6 +5219,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos)
|
|||
*/
|
||||
RETURN_IF_ERROR(codegen_call_exit_with_nones(c, loc));
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 2);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
|
||||
|
|
@ -5228,6 +5234,7 @@ codegen_async_with_inner(compiler *c, stmt_ty s, int pos)
|
|||
ADDOP(c, loc, PUSH_EXC_INFO);
|
||||
ADDOP(c, loc, WITH_EXCEPT_START);
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 2);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
RETURN_IF_ERROR(codegen_with_except_finish(c, cleanup));
|
||||
|
|
@ -5408,13 +5415,14 @@ codegen_visit_expr(compiler *c, expr_ty e)
|
|||
return _PyCompile_Error(c, loc, "'yield from' inside async function");
|
||||
}
|
||||
VISIT(c, expr, e->v.YieldFrom.value);
|
||||
ADDOP(c, loc, GET_YIELD_FROM_ITER);
|
||||
ADDOP_I(c, loc, GET_ITER, GET_ITER_YIELD_FROM);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 0);
|
||||
break;
|
||||
case Await_kind:
|
||||
VISIT(c, expr, e->v.Await.value);
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 0);
|
||||
ADDOP(c, loc, PUSH_NULL);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
break;
|
||||
|
|
|
|||
121
Python/executor_cases.c.h
generated
121
Python/executor_cases.c.h
generated
|
|
@ -2602,17 +2602,21 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _END_SEND_r21: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
case _END_SEND_r31: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef value;
|
||||
_PyStackRef index_or_null;
|
||||
_PyStackRef receiver;
|
||||
_PyStackRef val;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
value = _stack_item_1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
value = _stack_item_2;
|
||||
index_or_null = _stack_item_1;
|
||||
receiver = _stack_item_0;
|
||||
val = value;
|
||||
(void)index_or_null;
|
||||
stack_pointer[0] = val;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
|
|
@ -7132,30 +7136,33 @@
|
|||
|
||||
/* _SEND is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
|
||||
|
||||
case _SEND_GEN_FRAME_r22: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
case _SEND_GEN_FRAME_r33: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef v;
|
||||
_PyStackRef receiver;
|
||||
_PyStackRef gen_frame;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
oparg = CURRENT_OPARG();
|
||||
v = _stack_item_1;
|
||||
v = _stack_item_2;
|
||||
receiver = _stack_item_0;
|
||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver);
|
||||
if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = v;
|
||||
_tos_cache2 = v;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = receiver;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
if (!gen_try_set_executing((PyGenObject *)gen)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = v;
|
||||
_tos_cache2 = v;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = receiver;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
STAT_INC(SEND, hit);
|
||||
|
|
@ -7167,10 +7174,10 @@
|
|||
frame->return_offset = (uint16_t)( 2u + oparg);
|
||||
pushed_frame->previous = frame;
|
||||
gen_frame = PyStackRef_Wrap(pushed_frame);
|
||||
_tos_cache1 = gen_frame;
|
||||
_tos_cache2 = gen_frame;
|
||||
_tos_cache1 = _stack_item_1;
|
||||
_tos_cache0 = receiver;
|
||||
_tos_cache2 = PyStackRef_ZERO_BITS;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
|
@ -11493,98 +11500,30 @@
|
|||
_PyStackRef iter;
|
||||
_PyStackRef index_or_null;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
oparg = CURRENT_OPARG();
|
||||
iterable = _stack_item_0;
|
||||
#ifdef Py_STATS
|
||||
_Py_GatherStats_GetIter(iterable);
|
||||
#endif
|
||||
stack_pointer[0] = iterable;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_Py_GatherStats_GetIter(iterable);
|
||||
_PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -1;
|
||||
#endif
|
||||
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||
iter = iterable;
|
||||
index_or_null = PyStackRef_TagInt(0);
|
||||
}
|
||||
else {
|
||||
stack_pointer[0] = iterable;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (PyStackRef_IsError(result)) {
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(iterable);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (iter_o == NULL) {
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
index_or_null = PyStackRef_NULL;
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
iter = result;
|
||||
_tos_cache1 = index_or_null;
|
||||
_tos_cache0 = iter;
|
||||
_tos_cache2 = PyStackRef_ZERO_BITS;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _GET_YIELD_FROM_ITER_r11: {
|
||||
CHECK_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef iterable;
|
||||
_PyStackRef iter;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
iterable = _stack_item_0;
|
||||
PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable);
|
||||
if (PyCoro_CheckExact(iterable_o)) {
|
||||
if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||
stack_pointer[0] = iterable;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
iter = iterable;
|
||||
}
|
||||
else if (PyGen_CheckExact(iterable_o)) {
|
||||
iter = iterable;
|
||||
}
|
||||
else {
|
||||
stack_pointer[0] = iterable;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *iter_o = PyObject_GetIter(iterable_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (iter_o == NULL) {
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = iterable;
|
||||
iterable = iter;
|
||||
stack_pointer[-1] = iterable;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -1;
|
||||
}
|
||||
_tos_cache0 = iter;
|
||||
_tos_cache1 = PyStackRef_ZERO_BITS;
|
||||
_tos_cache2 = PyStackRef_ZERO_BITS;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2884,7 +2884,6 @@ optimize_load_fast(cfg_builder *g)
|
|||
case GET_ANEXT:
|
||||
case GET_ITER:
|
||||
case GET_LEN:
|
||||
case GET_YIELD_FROM_ITER:
|
||||
case IMPORT_FROM:
|
||||
case MATCH_KEYS:
|
||||
case MATCH_MAPPING:
|
||||
|
|
@ -2919,7 +2918,16 @@ optimize_load_fast(cfg_builder *g)
|
|||
break;
|
||||
}
|
||||
|
||||
case END_SEND:
|
||||
case END_SEND: {
|
||||
assert(_PyOpcode_num_popped(opcode, oparg) == 3);
|
||||
assert(_PyOpcode_num_pushed(opcode, oparg) == 1);
|
||||
ref tos = ref_stack_pop(&refs);
|
||||
ref_stack_pop(&refs);
|
||||
ref_stack_pop(&refs);
|
||||
PUSH_REF(tos.instr, tos.local);
|
||||
break;
|
||||
}
|
||||
|
||||
case SET_FUNCTION_ATTRIBUTE: {
|
||||
assert(_PyOpcode_num_popped(opcode, oparg) == 2);
|
||||
assert(_PyOpcode_num_pushed(opcode, oparg) == 1);
|
||||
|
|
|
|||
191
Python/generated_cases.c.h
generated
191
Python/generated_cases.c.h
generated
|
|
@ -4740,13 +4740,16 @@
|
|||
next_instr += 1;
|
||||
INSTRUCTION_STATS(CLEANUP_THROW);
|
||||
_PyStackRef sub_iter;
|
||||
_PyStackRef null_in;
|
||||
_PyStackRef last_sent_val;
|
||||
_PyStackRef exc_value_st;
|
||||
_PyStackRef none;
|
||||
_PyStackRef null_out;
|
||||
_PyStackRef value;
|
||||
exc_value_st = stack_pointer[-1];
|
||||
last_sent_val = stack_pointer[-2];
|
||||
sub_iter = stack_pointer[-3];
|
||||
null_in = stack_pointer[-3];
|
||||
sub_iter = stack_pointer[-4];
|
||||
PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
|
||||
#if !_Py_TAIL_CALL_INTERP
|
||||
assert(throwflag);
|
||||
|
|
@ -4760,7 +4763,7 @@
|
|||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = sub_iter;
|
||||
sub_iter = value;
|
||||
stack_pointer[-3] = sub_iter;
|
||||
stack_pointer[-4] = sub_iter;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = exc_value_st;
|
||||
exc_value_st = PyStackRef_NULL;
|
||||
|
|
@ -4770,9 +4773,14 @@
|
|||
last_sent_val = PyStackRef_NULL;
|
||||
stack_pointer[-2] = last_sent_val;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
tmp = null_in;
|
||||
null_in = PyStackRef_NULL;
|
||||
stack_pointer[-3] = null_in;
|
||||
PyStackRef_XCLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -3;
|
||||
stack_pointer += -4;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
null_out = null_in;
|
||||
none = PyStackRef_None;
|
||||
}
|
||||
else {
|
||||
|
|
@ -4782,8 +4790,9 @@
|
|||
JUMP_TO_LABEL(exception_unwind);
|
||||
}
|
||||
stack_pointer[0] = none;
|
||||
stack_pointer[1] = value;
|
||||
stack_pointer += 2;
|
||||
stack_pointer[1] = null_out;
|
||||
stack_pointer[2] = value;
|
||||
stack_pointer += 3;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
DISPATCH();
|
||||
}
|
||||
|
|
@ -5668,13 +5677,16 @@
|
|||
next_instr += 1;
|
||||
INSTRUCTION_STATS(END_SEND);
|
||||
_PyStackRef receiver;
|
||||
_PyStackRef index_or_null;
|
||||
_PyStackRef value;
|
||||
_PyStackRef val;
|
||||
value = stack_pointer[-1];
|
||||
receiver = stack_pointer[-2];
|
||||
index_or_null = stack_pointer[-2];
|
||||
receiver = stack_pointer[-3];
|
||||
val = value;
|
||||
stack_pointer[-2] = val;
|
||||
stack_pointer += -1;
|
||||
(void)index_or_null;
|
||||
stack_pointer[-3] = val;
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(receiver);
|
||||
|
|
@ -6294,31 +6306,15 @@
|
|||
_PyStackRef index_or_null;
|
||||
iterable = stack_pointer[-1];
|
||||
#ifdef Py_STATS
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_Py_GatherStats_GetIter(iterable);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
#endif
|
||||
PyTypeObject *tp = PyStackRef_TYPE(iterable);
|
||||
if (tp == &PyTuple_Type || tp == &PyList_Type) {
|
||||
iter = iterable;
|
||||
index_or_null = PyStackRef_TagInt(0);
|
||||
}
|
||||
else {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(iterable);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (iter_o == NULL) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
index_or_null = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef result = _PyEval_GetIter(iterable, &index_or_null, oparg);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (PyStackRef_IsError(result)) {
|
||||
JUMP_TO_LABEL(pop_1_error);
|
||||
}
|
||||
iter = result;
|
||||
stack_pointer[-1] = iter;
|
||||
stack_pointer[0] = index_or_null;
|
||||
stack_pointer += 1;
|
||||
|
|
@ -6354,51 +6350,6 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(GET_YIELD_FROM_ITER) {
|
||||
#if _Py_TAIL_CALL_INTERP
|
||||
int opcode = GET_YIELD_FROM_ITER;
|
||||
(void)(opcode);
|
||||
#endif
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(GET_YIELD_FROM_ITER);
|
||||
_PyStackRef iterable;
|
||||
_PyStackRef iter;
|
||||
iterable = stack_pointer[-1];
|
||||
PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable);
|
||||
if (PyCoro_CheckExact(iterable_o)) {
|
||||
if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
iter = iterable;
|
||||
}
|
||||
else if (PyGen_CheckExact(iterable_o)) {
|
||||
iter = iterable;
|
||||
}
|
||||
else {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *iter_o = PyObject_GetIter(iterable_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (iter_o == NULL) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
iter = PyStackRef_FromPyObjectSteal(iter_o);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyStackRef tmp = iterable;
|
||||
iterable = iter;
|
||||
stack_pointer[-1] = iterable;
|
||||
PyStackRef_CLOSE(tmp);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
stack_pointer[-1] = iter;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(IMPORT_FROM) {
|
||||
#if _Py_TAIL_CALL_INTERP
|
||||
int opcode = IMPORT_FROM;
|
||||
|
|
@ -7002,10 +6953,12 @@
|
|||
next_instr += 1;
|
||||
INSTRUCTION_STATS(INSTRUMENTED_END_SEND);
|
||||
_PyStackRef receiver;
|
||||
_PyStackRef index_or_null;
|
||||
_PyStackRef value;
|
||||
_PyStackRef val;
|
||||
value = stack_pointer[-1];
|
||||
receiver = stack_pointer[-2];
|
||||
index_or_null = stack_pointer[-2];
|
||||
receiver = stack_pointer[-3];
|
||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||
if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
|
|
@ -7016,8 +6969,9 @@
|
|||
}
|
||||
}
|
||||
val = value;
|
||||
stack_pointer[-2] = val;
|
||||
stack_pointer += -1;
|
||||
(void)index_or_null;
|
||||
stack_pointer[-3] = val;
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(receiver);
|
||||
|
|
@ -10733,11 +10687,12 @@
|
|||
_Py_CODEUNIT* const this_instr = next_instr - 2;
|
||||
(void)this_instr;
|
||||
_PyStackRef receiver;
|
||||
_PyStackRef null_or_index;
|
||||
_PyStackRef v;
|
||||
_PyStackRef retval;
|
||||
// _SPECIALIZE_SEND
|
||||
{
|
||||
receiver = stack_pointer[-2];
|
||||
receiver = stack_pointer[-3];
|
||||
uint16_t counter = read_u16(&this_instr[1].cache);
|
||||
(void)counter;
|
||||
#if ENABLE_SPECIALIZATION
|
||||
|
|
@ -10755,6 +10710,7 @@
|
|||
// _SEND
|
||||
{
|
||||
v = stack_pointer[-1];
|
||||
null_or_index = stack_pointer[-2];
|
||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||
PyObject *retval_o;
|
||||
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||
|
|
@ -10775,53 +10731,66 @@
|
|||
gen_frame->previous = frame;
|
||||
DISPATCH_INLINED(gen_frame);
|
||||
}
|
||||
if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) {
|
||||
if (!PyStackRef_IsNull(null_or_index)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o);
|
||||
_PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, receiver, &null_or_index);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (!PyStackRef_IsValid(item)) {
|
||||
if (PyStackRef_IsError(item)) {
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
JUMPBY(oparg);
|
||||
stack_pointer[-2] = null_or_index;
|
||||
DISPATCH();
|
||||
}
|
||||
retval = item;
|
||||
}
|
||||
else {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
retval_o = PyObject_CallMethodOneArg(receiver_o,
|
||||
&_Py_ID(send),
|
||||
PyStackRef_AsPyObjectBorrow(v));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
if (retval_o == NULL) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (matches) {
|
||||
if (PyStackRef_IsNone(v) && PyIter_Check(receiver_o)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||
retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int err = _PyGen_FetchStopIterationValue(&retval_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (err == 0) {
|
||||
assert(retval_o != NULL);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(v);
|
||||
retval_o = PyObject_CallMethodOneArg(receiver_o,
|
||||
&_Py_ID(send),
|
||||
PyStackRef_AsPyObjectBorrow(v));
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
if (retval_o == NULL) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (matches) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyEval_MonitorRaise(tstate, frame, this_instr);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int err = _PyGen_FetchStopIterationValue(&retval_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (err == 0) {
|
||||
assert(retval_o != NULL);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else {
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(v);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
}
|
||||
retval = PyStackRef_FromPyObjectSteal(retval_o);
|
||||
}
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
stack_pointer[-2] = null_or_index;
|
||||
stack_pointer[-1] = retval;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyStackRef_CLOSE(v);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
retval = PyStackRef_FromPyObjectSteal(retval_o);
|
||||
}
|
||||
stack_pointer[0] = retval;
|
||||
stack_pointer += 1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
@ -10852,7 +10821,7 @@
|
|||
// _SEND_GEN_FRAME
|
||||
{
|
||||
v = stack_pointer[-1];
|
||||
receiver = stack_pointer[-2];
|
||||
receiver = stack_pointer[-3];
|
||||
PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver);
|
||||
if (Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type) {
|
||||
UPDATE_MISS_STATS(SEND);
|
||||
|
|
|
|||
13
Python/opcode_targets.h
generated
13
Python/opcode_targets.h
generated
|
|
@ -16,10 +16,8 @@ static void *opcode_targets_table[256] = {
|
|||
&&TARGET_FORMAT_WITH_SPEC,
|
||||
&&TARGET_GET_AITER,
|
||||
&&TARGET_GET_ANEXT,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_GET_YIELD_FROM_ITER,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_INTERPRETER_EXIT,
|
||||
&&TARGET_LOAD_BUILD_CLASS,
|
||||
&&TARGET_LOAD_LOCALS,
|
||||
|
|
@ -72,6 +70,7 @@ static void *opcode_targets_table[256] = {
|
|||
&&TARGET_EXTENDED_ARG,
|
||||
&&TARGET_FOR_ITER,
|
||||
&&TARGET_GET_AWAITABLE,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_IMPORT_FROM,
|
||||
&&TARGET_IMPORT_NAME,
|
||||
&&TARGET_IS_OP,
|
||||
|
|
@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RESUME,
|
||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
|
|
@ -379,7 +379,7 @@ static void *opcode_tracing_targets_table[256] = {
|
|||
&&TARGET_TRACE_RECORD,
|
||||
&&TARGET_TRACE_RECORD,
|
||||
&&TARGET_TRACE_RECORD,
|
||||
&&TARGET_TRACE_RECORD,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
|
|
@ -626,7 +626,6 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS);
|
|||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_IMPORT_NAME(TAIL_CALL_PARAMS);
|
||||
static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_INSTRUMENTED_CALL(TAIL_CALL_PARAMS);
|
||||
|
|
@ -868,7 +867,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = {
|
|||
[GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE,
|
||||
[GET_ITER] = _TAIL_CALL_GET_ITER,
|
||||
[GET_LEN] = _TAIL_CALL_GET_LEN,
|
||||
[GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER,
|
||||
[IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM,
|
||||
[IMPORT_NAME] = _TAIL_CALL_IMPORT_NAME,
|
||||
[INSTRUMENTED_CALL] = _TAIL_CALL_INSTRUMENTED_CALL,
|
||||
|
|
@ -1002,6 +1000,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = {
|
|||
[UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
[WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START,
|
||||
[YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE,
|
||||
[120] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[121] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[122] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[123] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
|
|
@ -1126,7 +1125,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = {
|
|||
[GET_AWAITABLE] = _TAIL_CALL_TRACE_RECORD,
|
||||
[GET_ITER] = _TAIL_CALL_TRACE_RECORD,
|
||||
[GET_LEN] = _TAIL_CALL_TRACE_RECORD,
|
||||
[GET_YIELD_FROM_ITER] = _TAIL_CALL_TRACE_RECORD,
|
||||
[IMPORT_FROM] = _TAIL_CALL_TRACE_RECORD,
|
||||
[IMPORT_NAME] = _TAIL_CALL_TRACE_RECORD,
|
||||
[INSTRUMENTED_CALL] = _TAIL_CALL_TRACE_RECORD,
|
||||
|
|
@ -1260,6 +1258,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = {
|
|||
[UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD,
|
||||
[WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD,
|
||||
[YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD,
|
||||
[120] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[121] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[122] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
[123] = _TAIL_CALL_UNKNOWN_OPCODE,
|
||||
|
|
|
|||
|
|
@ -1038,7 +1038,7 @@ dummy_func(void) {
|
|||
gen_frame = PyJitRef_WrapInvalid(new_frame);
|
||||
}
|
||||
|
||||
op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) {
|
||||
op(_SEND_GEN_FRAME, (receiver, null, v -- receiver, null, gen_frame)) {
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0);
|
||||
if (new_frame == NULL) {
|
||||
ctx->done = true;
|
||||
|
|
@ -1779,6 +1779,12 @@ dummy_func(void) {
|
|||
sym_set_recorded_gen_func(nos, func);
|
||||
}
|
||||
|
||||
op(_RECORD_3OS_GEN_FUNC, (gen, nos, tos -- gen, nos, tos)) {
|
||||
PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0;
|
||||
assert(func == NULL || PyFunction_Check(func));
|
||||
sym_set_recorded_gen_func(gen, func);
|
||||
}
|
||||
|
||||
op(_GUARD_CODE_VERSION__PUSH_FRAME, (version/2 -- )) {
|
||||
PyCodeObject *co = get_current_code_object(ctx);
|
||||
if (co->co_version == version) {
|
||||
|
|
|
|||
24
Python/optimizer_cases.c.h
generated
24
Python/optimizer_cases.c.h
generated
|
|
@ -209,9 +209,9 @@
|
|||
case _END_SEND: {
|
||||
JitOptRef val;
|
||||
val = sym_new_not_null(ctx);
|
||||
CHECK_STACK_BOUNDS(-1);
|
||||
stack_pointer[-2] = val;
|
||||
stack_pointer += -1;
|
||||
CHECK_STACK_BOUNDS(-2);
|
||||
stack_pointer[-3] = val;
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1385,7 +1385,7 @@
|
|||
JitOptRef receiver;
|
||||
JitOptRef gen_frame;
|
||||
v = stack_pointer[-1];
|
||||
receiver = stack_pointer[-2];
|
||||
receiver = stack_pointer[-3];
|
||||
_Py_UOpsAbstractFrame *new_frame = frame_new_from_symbol(ctx, receiver, NULL, 0);
|
||||
if (new_frame == NULL) {
|
||||
ctx->done = true;
|
||||
|
|
@ -2738,13 +2738,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _GET_YIELD_FROM_ITER: {
|
||||
JitOptRef iter;
|
||||
iter = sym_new_not_null(ctx);
|
||||
stack_pointer[-1] = iter;
|
||||
break;
|
||||
}
|
||||
|
||||
/* _FOR_ITER is not a viable micro-op for tier 2 */
|
||||
|
||||
case _FOR_ITER_TIER_TWO: {
|
||||
|
|
@ -4420,6 +4413,15 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _RECORD_3OS_GEN_FUNC: {
|
||||
JitOptRef gen;
|
||||
gen = stack_pointer[-3];
|
||||
PyFunctionObject *func = (PyFunctionObject *)this_instr->operand0;
|
||||
assert(func == NULL || PyFunction_Check(func));
|
||||
sym_set_recorded_gen_func(gen, func);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_4OS: {
|
||||
JitOptRef value;
|
||||
value = stack_pointer[-4];
|
||||
|
|
|
|||
28
Python/record_functions.c.h
generated
28
Python/record_functions.c.h
generated
|
|
@ -41,6 +41,20 @@ void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackR
|
|||
}
|
||||
}
|
||||
|
||||
void _PyOpcode_RecordFunction_3OS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) {
|
||||
_PyStackRef gen;
|
||||
gen = stack_pointer[-3];
|
||||
PyObject *obj = PyStackRef_AsPyObjectBorrow(gen);
|
||||
if (PyGen_Check(obj)) {
|
||||
PyGenObject *gen_obj = (PyGenObject *)obj;
|
||||
_PyStackRef func = gen_obj->gi_iframe.f_funcobj;
|
||||
if (!PyStackRef_IsNull(func)) {
|
||||
*recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func);
|
||||
Py_INCREF(*recorded_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _PyOpcode_RecordFunction_4OS(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) {
|
||||
_PyStackRef value;
|
||||
value = stack_pointer[-4];
|
||||
|
|
@ -73,14 +87,15 @@ void _PyOpcode_RecordFunction_CODE(_PyInterpreterFrame *frame, _PyStackRef *stac
|
|||
|
||||
#define _RECORD_TOS_TYPE_INDEX 1
|
||||
#define _RECORD_NOS_INDEX 2
|
||||
#define _RECORD_NOS_GEN_FUNC_INDEX 3
|
||||
#define _RECORD_CALLABLE_INDEX 4
|
||||
#define _RECORD_BOUND_METHOD_INDEX 5
|
||||
#define _RECORD_4OS_INDEX 6
|
||||
#define _RECORD_3OS_GEN_FUNC_INDEX 3
|
||||
#define _RECORD_NOS_GEN_FUNC_INDEX 4
|
||||
#define _RECORD_CALLABLE_INDEX 5
|
||||
#define _RECORD_BOUND_METHOD_INDEX 6
|
||||
#define _RECORD_4OS_INDEX 7
|
||||
const uint8_t _PyOpcode_RecordFunctionIndices[256] = {
|
||||
[TO_BOOL_ALWAYS_TRUE] = _RECORD_TOS_TYPE_INDEX,
|
||||
[BINARY_OP_SUBSCR_GETITEM] = _RECORD_NOS_INDEX,
|
||||
[SEND_GEN] = _RECORD_NOS_GEN_FUNC_INDEX,
|
||||
[SEND_GEN] = _RECORD_3OS_GEN_FUNC_INDEX,
|
||||
[LOAD_ATTR_INSTANCE_VALUE] = _RECORD_TOS_TYPE_INDEX,
|
||||
[LOAD_ATTR_WITH_HINT] = _RECORD_TOS_TYPE_INDEX,
|
||||
[LOAD_ATTR_SLOT] = _RECORD_TOS_TYPE_INDEX,
|
||||
|
|
@ -110,10 +125,11 @@ const uint8_t _PyOpcode_RecordFunctionIndices[256] = {
|
|||
[CALL_EX_PY] = _RECORD_4OS_INDEX,
|
||||
};
|
||||
|
||||
const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[7] = {
|
||||
const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[8] = {
|
||||
[0] = NULL,
|
||||
[_RECORD_TOS_TYPE_INDEX] = _PyOpcode_RecordFunction_TOS_TYPE,
|
||||
[_RECORD_NOS_INDEX] = _PyOpcode_RecordFunction_NOS,
|
||||
[_RECORD_3OS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_3OS_GEN_FUNC,
|
||||
[_RECORD_NOS_GEN_FUNC_INDEX] = _PyOpcode_RecordFunction_NOS_GEN_FUNC,
|
||||
[_RECORD_CALLABLE_INDEX] = _PyOpcode_RecordFunction_CALLABLE,
|
||||
[_RECORD_BOUND_METHOD_INDEX] = _PyOpcode_RecordFunction_BOUND_METHOD,
|
||||
|
|
|
|||
|
|
@ -41,9 +41,24 @@ do { \
|
|||
# define SPECIALIZATION_FAIL(opcode, kind) ((void)0)
|
||||
#endif // Py_STATS
|
||||
|
||||
static void
|
||||
fixup_getiter(_Py_CODEUNIT *instruction, int flags)
|
||||
{
|
||||
// Compiler can't know if types.coroutine() will be called,
|
||||
// so fix up here
|
||||
if (instruction->op.arg) {
|
||||
if (flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) {
|
||||
instruction->op.arg = GET_ITER_YIELD_FROM_NO_CHECK;
|
||||
}
|
||||
else {
|
||||
instruction->op.arg = GET_ITER_YIELD_FROM_CORO_CHECK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize warmup counters and optimize instructions. This cannot fail.
|
||||
void
|
||||
_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters)
|
||||
_PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters, int flags)
|
||||
{
|
||||
#if ENABLE_SPECIALIZATION
|
||||
_Py_BackoffCounter jump_counter, adaptive_counter, resume_counter;
|
||||
|
|
@ -66,6 +81,9 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
|
|||
opcode = instructions[i].op.code;
|
||||
int caches = _PyOpcode_Caches[opcode];
|
||||
oparg = (oparg << 8) | instructions[i].op.arg;
|
||||
if (opcode == GET_ITER) {
|
||||
fixup_getiter(&instructions[i], flags);
|
||||
}
|
||||
if (caches) {
|
||||
// The initial value depends on the opcode
|
||||
switch (opcode) {
|
||||
|
|
@ -91,6 +109,13 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
|
|||
oparg = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (Py_ssize_t i = 0; i < size-1; i++) {
|
||||
if (instructions[i].op.code == GET_ITER) {
|
||||
fixup_getiter(&instructions[i], flags);
|
||||
}
|
||||
i += _PyOpcode_Caches[opcode];
|
||||
}
|
||||
#endif /* ENABLE_SPECIALIZATION */
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue