diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 90bf5bbd1baa02..006628257b01c3 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -22,22 +22,22 @@ static const uint32_t _PyOpcode_RelativeJump[9] = { 0U, 536870912U, 135118848U, - 4163U, + 100667459U, 122880U, 0U, 0U, - 1008U, + 3056U, }; static const uint32_t _PyOpcode_Jump[9] = { 0U, 0U, 536870912U, 135118848U, - 4163U, + 100667459U, 122880U, 0U, 0U, - 1008U, + 3056U, }; const uint8_t _PyOpcode_Caches[256] = { @@ -225,6 +225,8 @@ const uint8_t _PyOpcode_Deopt[256] = { [STORE_SUBSCR_DICT] = STORE_SUBSCR, [STORE_SUBSCR_LIST_INT] = STORE_SUBSCR, [SWAP] = SWAP, + [THROW_BACKWARD] = THROW_BACKWARD, + [THROW_FORWARD] = THROW_FORWARD, [UNARY_INVERT] = UNARY_INVERT, [UNARY_NEGATIVE] = UNARY_NEGATIVE, [UNARY_NOT] = UNARY_NOT, @@ -241,7 +243,7 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_TABLES #ifdef Py_DEBUG -static const char *const _PyOpcode_OpName[267] = { +static const char *const _PyOpcode_OpName[268] = { [CACHE] = "CACHE", [POP_TOP] = "POP_TOP", [PUSH_NULL] = "PUSH_NULL", @@ -395,38 +397,38 @@ static const char *const _PyOpcode_OpName[267] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [THROW_FORWARD] = "THROW_FORWARD", + [THROW_BACKWARD] = "THROW_BACKWARD", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [RESUME_QUICK] = "RESUME_QUICK", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", - [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", - [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", + [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", - [183] = "<183>", - [184] = "<184>", [185] = "<185>", [186] = "<186>", [187] = "<187>", @@ -509,12 +511,11 @@ static const char *const _PyOpcode_OpName[267] = { [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE", [POP_JUMP_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE", [LOAD_METHOD] = "LOAD_METHOD", + [THROW] = "THROW", }; #endif #define EXTRA_CASES \ - case 183: \ - case 184: \ case 185: \ case 186: \ case 187: \ diff --git a/Include/opcode.h b/Include/opcode.h index f90ebb1d6e01cb..fcb5cb466e2213 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -107,6 +107,8 @@ extern "C" { #define YIELD_VALUE 150 #define RESUME 151 #define MATCH_CLASS 152 +#define THROW_FORWARD 153 +#define THROW_BACKWARD 154 #define FORMAT_VALUE 155 #define BUILD_CONST_KEY_MAP 156 #define BUILD_STRING 157 @@ -132,7 +134,8 @@ extern "C" { #define POP_JUMP_IF_NONE 264 #define POP_JUMP_IF_NOT_NONE 265 #define LOAD_METHOD 266 -#define MAX_PSEUDO_OPCODE 266 +#define THROW 267 +#define MAX_PSEUDO_OPCODE 267 #define BINARY_OP_ADAPTIVE 3 #define BINARY_OP_ADD_FLOAT 4 #define BINARY_OP_ADD_INT 5 @@ -188,23 +191,23 @@ extern "C" { #define LOAD_CONST__LOAD_FAST 121 #define LOAD_FAST__LOAD_CONST 141 #define LOAD_FAST__LOAD_FAST 143 -#define LOAD_GLOBAL_ADAPTIVE 153 -#define LOAD_GLOBAL_BUILTIN 154 -#define LOAD_GLOBAL_MODULE 158 -#define RESUME_QUICK 159 -#define STORE_ATTR_ADAPTIVE 160 -#define STORE_ATTR_INSTANCE_VALUE 161 -#define STORE_ATTR_SLOT 166 -#define STORE_ATTR_WITH_HINT 167 -#define STORE_FAST__LOAD_FAST 168 -#define STORE_FAST__STORE_FAST 169 -#define STORE_SUBSCR_ADAPTIVE 170 -#define STORE_SUBSCR_DICT 177 -#define STORE_SUBSCR_LIST_INT 178 -#define UNPACK_SEQUENCE_ADAPTIVE 179 -#define UNPACK_SEQUENCE_LIST 180 -#define UNPACK_SEQUENCE_TUPLE 181 -#define UNPACK_SEQUENCE_TWO_TUPLE 182 +#define LOAD_GLOBAL_ADAPTIVE 158 +#define LOAD_GLOBAL_BUILTIN 159 +#define LOAD_GLOBAL_MODULE 160 +#define RESUME_QUICK 161 +#define STORE_ATTR_ADAPTIVE 166 +#define STORE_ATTR_INSTANCE_VALUE 167 +#define STORE_ATTR_SLOT 168 +#define STORE_ATTR_WITH_HINT 169 +#define STORE_FAST__LOAD_FAST 170 +#define STORE_FAST__STORE_FAST 177 +#define STORE_SUBSCR_ADAPTIVE 178 +#define STORE_SUBSCR_DICT 179 +#define STORE_SUBSCR_LIST_INT 180 +#define UNPACK_SEQUENCE_ADAPTIVE 181 +#define UNPACK_SEQUENCE_LIST 182 +#define UNPACK_SEQUENCE_TUPLE 183 +#define UNPACK_SEQUENCE_TWO_TUPLE 184 #define DO_TRACING 255 #define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\ @@ -215,6 +218,7 @@ extern "C" { || ((op) == POP_JUMP_IF_NONE) \ || ((op) == POP_JUMP_IF_NOT_NONE) \ || ((op) == LOAD_METHOD) \ + || ((op) == THROW) \ ) #define HAS_CONST(op) (false\ diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 82d204257ed7a3..42f4f321c36071 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -411,10 +411,10 @@ def _write_atomic(path, data, mode=0o666): # Python 3.12a1 3505 (Specialization/Cache for FOR_ITER) # Python 3.12a1 3506 (Add BINARY_SLICE and STORE_SLICE instructions) # Python 3.12a1 3507 (Set lineno of module's RESUME to 0) +# Python 3.12a1 3508 (Add THROW_FORWARD/THROW_BACKWARD) # Python 3.13 will start with 3550 -# # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). @@ -424,7 +424,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3507).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3508).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/opcode.py b/Lib/opcode.py index 8a07fb75b2e97c..945c33f20a3fca 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -201,7 +201,8 @@ def pseudo_op(name, op, real_ops): def_op('YIELD_VALUE', 150) def_op('RESUME', 151) # This must be kept in sync with deepfreeze.py def_op('MATCH_CLASS', 152) - +jrel_op('THROW_FORWARD', 153) +jrel_op('THROW_BACKWARD', 154) def_op('FORMAT_VALUE', 155) def_op('BUILD_CONST_KEY_MAP', 156) def_op('BUILD_STRING', 157) @@ -239,6 +240,7 @@ def pseudo_op(name, op, real_ops): pseudo_op('POP_JUMP_IF_NONE', 264, ['POP_JUMP_FORWARD_IF_NONE', 'POP_JUMP_BACKWARD_IF_NONE']) pseudo_op('POP_JUMP_IF_NOT_NONE', 265, ['POP_JUMP_FORWARD_IF_NOT_NONE', 'POP_JUMP_BACKWARD_IF_NOT_NONE']) pseudo_op('LOAD_METHOD', 266, ['LOAD_ATTR']) +pseudo_op('THROW', 267, ['THROW_FORWARD', 'THROW_BACKWARD']) MAX_PSEUDO_OPCODE = MIN_PSEUDO_OPCODE + len(_pseudo_ops) - 1 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index f07e7c86054782..7d6ef5621e3cf4 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -482,7 +482,7 @@ async def _asyncwith(c): GET_AWAITABLE 1 LOAD_CONST 0 (None) >> SEND 3 (to 22) - YIELD_VALUE 3 + >> YIELD_VALUE 3 RESUME 3 JUMP_BACKWARD_NO_INTERRUPT 4 (to 14) >> POP_TOP @@ -497,7 +497,7 @@ async def _asyncwith(c): GET_AWAITABLE 2 LOAD_CONST 0 (None) >> SEND 3 (to 56) - YIELD_VALUE 2 + >> YIELD_VALUE 2 RESUME 3 JUMP_BACKWARD_NO_INTERRUPT 4 (to 48) >> POP_TOP @@ -507,26 +507,32 @@ async def _asyncwith(c): LOAD_CONST 0 (None) RETURN_VALUE -%3d >> PUSH_EXC_INFO +%3d >> THROW_BACKWARD 23 (to 114) + JUMP_BACKWARD_NO_INTERRUPT 27 (to 16) + >> THROW_BACKWARD 8 (to 88) + JUMP_BACKWARD_NO_INTERRUPT 12 (to 50) + >> PUSH_EXC_INFO WITH_EXCEPT_START GET_AWAITABLE 2 LOAD_CONST 0 (None) - >> SEND 3 (to 82) - YIELD_VALUE 6 + >> SEND 5 (to 94) + >> YIELD_VALUE 6 RESUME 3 - JUMP_BACKWARD_NO_INTERRUPT 4 (to 74) - >> POP_JUMP_FORWARD_IF_TRUE 1 (to 86) + >> JUMP_BACKWARD_NO_INTERRUPT 4 (to 82) + >> THROW_FORWARD 1 (to 94) + JUMP_BACKWARD_NO_INTERRUPT 5 (to 84) + >> POP_JUMP_FORWARD_IF_TRUE 1 (to 98) RERAISE 2 >> POP_TOP POP_EXCEPT POP_TOP POP_TOP - JUMP_BACKWARD 19 (to 58) + JUMP_BACKWARD 25 (to 58) >> COPY 3 POP_EXCEPT RERAISE 1 ExceptionTable: -2 rows +6 rows """ % (_asyncwith.__code__.co_firstlineno, _asyncwith.__code__.co_firstlineno + 1, _asyncwith.__code__.co_firstlineno + 2, diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 26b38bae780c70..cf1ee29fe1bae9 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -356,6 +356,23 @@ mark_stacks(PyCodeObject *code_obj, int len) stacks[j] = pop_value(next_stack); stacks[i+1] = next_stack; break; + case THROW_FORWARD: + j = get_arg(code, i) + i + 1; + assert(j < len); + next_stack = pop_value(next_stack); + assert(stacks[j] == UNINITIALIZED || stacks[j] == pop_value(next_stack)); + stacks[j] = pop_value(next_stack); + stacks[i+1] = next_stack; + break; + case THROW_BACKWARD: + j = i + 1 - get_arg(code, i); + assert(j >= 0); + assert(j < len); + next_stack = pop_value(next_stack); + assert(stacks[j] == UNINITIALIZED || stacks[j] == pop_value(next_stack)); + stacks[j] = pop_value(next_stack); + stacks[i+1] = next_stack; + break; case JUMP_FORWARD: j = get_arg(code, i) + i + 1; assert(j < len); diff --git a/Objects/genobject.c b/Objects/genobject.c index 2b45e28cbf16df..e7025cb8f76fb4 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -425,91 +425,27 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, PyObject *typ, PyObject *val, PyObject *tb) { PyObject *yf = _PyGen_yf(gen); - if (yf) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - PyObject *ret; - int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && - close_on_genexit - ) { + close_on_genexit) + { /* Asynchronous generators *should not* be closed right away. We have to allow some awaits to work it through, hence the `close_on_genexit` parameter here. */ PyFrameState state = gen->gi_frame_state; gen->gi_frame_state = FRAME_EXECUTING; - err = gen_close_iter(yf); + int err = gen_close_iter(yf); gen->gi_frame_state = state; Py_DECREF(yf); - if (err < 0) + if (err < 0) { return gen_send_ex(gen, Py_None, 1, 0); - goto throw_here; - } - if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) { - /* `yf` is a generator or a coroutine. */ - PyThreadState *tstate = _PyThreadState_GET(); - /* Since we are fast-tracking things by skipping the eval loop, - we need to update the current frame so the stack trace - will be reported correctly to the user. */ - /* XXX We should probably be updating the current frame - somewhere in ceval.c. */ - _PyInterpreterFrame *prev = tstate->cframe->current_frame; - frame->previous = prev; - tstate->cframe->current_frame = frame; - /* Close the generator that we are currently iterating with - 'yield from' or awaiting on with 'await'. */ - PyFrameState state = gen->gi_frame_state; - gen->gi_frame_state = FRAME_EXECUTING; - ret = _gen_throw((PyGenObject *)yf, close_on_genexit, - typ, val, tb); - gen->gi_frame_state = state; - tstate->cframe->current_frame = prev; - frame->previous = NULL; - } else { - /* `yf` is an iterator or a coroutine-like object. */ - PyObject *meth; - if (_PyObject_LookupAttr(yf, &_Py_ID(throw), &meth) < 0) { - Py_DECREF(yf); - return NULL; - } - if (meth == NULL) { - Py_DECREF(yf); - goto throw_here; } - PyFrameState state = gen->gi_frame_state; - gen->gi_frame_state = FRAME_EXECUTING; - ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); - gen->gi_frame_state = state; - Py_DECREF(meth); } - Py_DECREF(yf); - if (!ret) { - PyObject *val; - /* Pop subiterator from stack */ - assert(gen->gi_frame_state < FRAME_CLEARED); - ret = _PyFrame_StackPop((_PyInterpreterFrame *)gen->gi_iframe); - assert(ret == yf); - Py_DECREF(ret); - // XXX: Performing this jump ourselves is awkward and problematic. - // See https://github.com/python/cpython/pull/31968. - /* Termination repetition of SEND loop */ - assert(_PyInterpreterFrame_LASTI(frame) >= 0); - /* Backup to SEND */ - assert(_Py_OPCODE(frame->prev_instr[-1]) == SEND); - int jump = _Py_OPARG(frame->prev_instr[-1]); - frame->prev_instr += jump - 1; - if (_PyGen_FetchStopIterationValue(&val) == 0) { - ret = gen_send(gen, val); - Py_DECREF(val); - } else { - ret = gen_send_ex(gen, Py_None, 1, 0); - } + else { + Py_DECREF(yf); } - return ret; } - -throw_here: /* First, check the traceback argument, replacing None with NULL. */ if (tb == Py_None) { diff --git a/Python/ceval.c b/Python/ceval.c index abb934d494f3e9..a0a532ce83b903 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2655,6 +2655,61 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } + TARGET(THROW_FORWARD) { + PREDICTED(THROW_FORWARD); + assert(frame->is_entry); + assert(throwflag); + PyObject *exc_value = POP(); + PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value)); + PyObject *exc_traceback = PyException_GetTraceback(exc_value); + PyErr_NormalizeException(&exc_type, &exc_value, &exc_traceback); + PyObject *last_send = POP(); + Py_DECREF(last_send); + PyObject *yieldfrom = TOP(); + PyObject *throw; + int found = _PyObject_LookupAttr(yieldfrom, &_Py_ID(throw), &throw); + if (found < 0) { + if (PyErr_GivenExceptionMatches(exc_value, PyExc_GeneratorExit)) + { + _PyErr_Clear(tstate); + _PyErr_Restore(tstate, exc_type, exc_value, exc_traceback); + } + goto exception_unwind; + } + if (found == 0) { + _PyErr_Restore(tstate, exc_type, exc_value, exc_traceback); + goto exception_unwind; + } + PyObject *retval = PyObject_CallFunctionObjArgs( + throw, exc_type, exc_value, exc_traceback, NULL); + Py_DECREF(throw); + Py_DECREF(exc_type); + Py_DECREF(exc_value); + Py_XDECREF(exc_traceback); + if (retval) { + PUSH(retval); + DISPATCH(); + } + if (tstate->c_tracefunc && + _PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) + { + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, + frame); + } + if (_PyGen_FetchStopIterationValue(&TOP())) { + goto exception_unwind; + } + Py_DECREF(yieldfrom); + JUMPBY(oparg); + DISPATCH(); + } + + TARGET(THROW_BACKWARD) { + // No interrupts! + oparg = -oparg; + JUMP_TO_INSTRUCTION(THROW_FORWARD); + } + TARGET(ASYNC_GEN_WRAP) { PyObject *v = TOP(); assert(frame->f_code->co_flags & CO_ASYNC_GENERATOR); @@ -2668,6 +2723,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(YIELD_VALUE) { + // NOTE: It's important that YIELD_VALUE never raises an exception! + // The compiler treats *anything* raised here as a throw() call. assert(oparg == STACK_LEVEL()); assert(frame->is_entry); PyObject *retval = POP(); diff --git a/Python/compile.c b/Python/compile.c index 3c4dd56b05926a..cd7be2e885cbd7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -101,7 +101,9 @@ (opcode) == POP_JUMP_FORWARD_IF_TRUE || \ (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \ (opcode) == POP_JUMP_FORWARD_IF_FALSE || \ - (opcode) == POP_JUMP_BACKWARD_IF_FALSE) + (opcode) == POP_JUMP_BACKWARD_IF_FALSE || \ + (opcode) == THROW_FORWARD || \ + (opcode) == THROW_BACKWARD) #define IS_BACKWARDS_JUMP_OPCODE(opcode) \ ((opcode) == JUMP_BACKWARD || \ @@ -109,7 +111,8 @@ (opcode) == POP_JUMP_BACKWARD_IF_NONE || \ (opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \ (opcode) == POP_JUMP_BACKWARD_IF_TRUE || \ - (opcode) == POP_JUMP_BACKWARD_IF_FALSE) + (opcode) == POP_JUMP_BACKWARD_IF_FALSE || \ + (opcode) == THROW_BACKWARD) #define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \ ((opcode) == JUMP || \ @@ -1081,6 +1084,10 @@ stack_effect(int opcode, int oparg, int jump) return jump > 0 ? -1 : 1; case SEND: return jump > 0 ? -1 : 0; + case THROW: + case THROW_FORWARD: + case THROW_BACKWARD: + return jump > 0 ? -2 : -1; case STORE_ATTR: return -2; case DELETE_ATTR: @@ -1957,19 +1964,29 @@ compiler_call_exit_with_nones(struct compiler *c) { static int compiler_add_yield_from(struct compiler *c, int await) { - NEW_JUMP_TARGET_LABEL(c, start); - NEW_JUMP_TARGET_LABEL(c, resume); - NEW_JUMP_TARGET_LABEL(c, exit); + NEW_JUMP_TARGET_LABEL(c, send); + NEW_JUMP_TARGET_LABEL(c, yield); + NEW_JUMP_TARGET_LABEL(c, thrown); + NEW_JUMP_TARGET_LABEL(c, stop); - USE_LABEL(c, start); - ADDOP_JUMP(c, SEND, exit); + USE_LABEL(c, send); + ADDOP_JUMP(c, SEND, stop); - USE_LABEL(c, resume); + USE_LABEL(c, yield); + ADDOP_JUMP(c, SETUP_FINALLY, thrown); + RETURN_IF_FALSE(compiler_push_fblock(c, TRY_EXCEPT, yield, NO_LABEL, NULL)); + // The only way YIELD_VALUE can raise is if throw() is called: ADDOP_I(c, YIELD_VALUE, 0); + compiler_pop_fblock(c, TRY_EXCEPT, yield); + ADDOP_NOLINE(c, POP_BLOCK); ADDOP_I(c, RESUME, await ? 3 : 2); - ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); + ADDOP_JUMP(c, JUMP_NO_INTERRUPT, send); - USE_LABEL(c, exit); + USE_LABEL(c, thrown); + ADDOP_JUMP(c, THROW, stop); + ADDOP_JUMP(c, JUMP_NO_INTERRUPT, yield); + + USE_LABEL(c, stop); return 1; } @@ -7790,6 +7807,9 @@ normalize_jumps(basicblock *entryblock) "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP"); } break; + case THROW: + last->i_opcode = is_forward ? THROW_FORWARD : THROW_BACKWARD; + break; } } } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index c9f65edfad1bdc..4550563fed2a9b 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -152,30 +152,32 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, - &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_THROW_FORWARD, + &&TARGET_THROW_BACKWARD, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_RESUME_QUICK, - &&TARGET_STORE_ATTR_ADAPTIVE, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__STORE_FAST, - &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, + &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, @@ -252,7 +254,5 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_DO_TRACING };