Skip to content

Commit 32091df

Browse files
authored
bpo-47186: Replace JUMP_IF_NOT_EG_MATCH by CHECK_EG_MATCH + jump (GH-32309)
1 parent 6c6e040 commit 32091df

File tree

10 files changed

+99
-97
lines changed

10 files changed

+99
-97
lines changed

Doc/library/dis.rst

+22-23
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,28 @@ iterations of the loop.
635635

636636
.. versionadded:: 3.11
637637

638+
.. opcode:: CHECK_EG_MATCH
639+
640+
Performs exception matching for ``except*``. Applies ``split(TOS)`` on
641+
the exception group representing TOS1.
642+
643+
In case of a match, pops two items from the stack and pushes the
644+
non-matching subgroup (``None`` in case of full match) followed by the
645+
matching subgroup. When there is no match, pops one item (the match
646+
type) and pushes ``None``.
647+
648+
.. versionadded:: 3.11
649+
650+
.. opcode:: PREP_RERAISE_STAR
651+
652+
Combines the raised and reraised exceptions list from TOS, into an exception
653+
group to propagate from a try-except* block. Uses the original exception
654+
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
655+
two items from the stack and pushes the exception to reraise or ``None``
656+
if there isn't one.
657+
658+
.. versionadded:: 3.11
659+
638660
.. opcode:: WITH_EXCEPT_START
639661

640662
Calls the function in position 4 on the stack with arguments (type, val, tb)
@@ -922,18 +944,6 @@ iterations of the loop.
922944
.. versionadded:: 3.1
923945

924946

925-
.. opcode:: JUMP_IF_NOT_EG_MATCH (target)
926-
927-
Performs exception matching for ``except*``. Applies ``split(TOS)`` on
928-
the exception group representing TOS1. Jumps if no match is found.
929-
930-
Pops one item from the stack (the match type). If a match was found,
931-
next item (the exception) and pushes the non-matching part of the
932-
exception group followed by the matching part.
933-
934-
.. versionadded:: 3.11
935-
936-
937947
.. opcode:: POP_JUMP_IF_NOT_NONE (target)
938948

939949
If TOS is not none, sets the bytecode counter to *target*. TOS is popped.
@@ -948,17 +958,6 @@ iterations of the loop.
948958
.. versionadded:: 3.11
949959

950960

951-
.. opcode:: PREP_RERAISE_STAR
952-
953-
Combines the raised and reraised exceptions list from TOS, into an exception
954-
group to propagate from a try-except* block. Uses the original exception
955-
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
956-
two items from the stack and pushes the exception to reraise or ``None``
957-
if there isn't one.
958-
959-
.. versionadded:: 3.11
960-
961-
962961
.. opcode:: JUMP_IF_TRUE_OR_POP (target)
963962

964963
If TOS is true, sets the bytecode counter to *target* and leaves TOS on the

Doc/whatsnew/3.11.rst

+3
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ CPython bytecode changes
523523
* Replaced :opcode:`JUMP_IF_NOT_EXC_MATCH` by :opcode:`CHECK_EXC_MATCH` which
524524
performs the check but does not jump.
525525

526+
* Replaced :opcode:`JUMP_IF_NOT_EG_MATCH` by :opcode:`CHECK_EG_MATCH` which
527+
performs the check but does not jump.
528+
526529
* Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`.
527530

528531
Deprecated

Include/opcode.h

+36-36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ def _write_atomic(path, data, mode=0o666):
398398
# Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL)
399399
# Python 3.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE)
400400
# Python 3.11a6 3490 (remove JUMP_IF_NOT_EXC_MATCH, add CHECK_EXC_MATCH)
401+
# Python 3.11a6 3491 (remove JUMP_IF_NOT_EG_MATCH, add CHECK_EG_MATCH)
401402

402403
# Python 3.12 will start with magic number 3500
403404

@@ -412,7 +413,7 @@ def _write_atomic(path, data, mode=0o666):
412413
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
413414
# in PC/launcher.c must also be updated.
414415

415-
MAGIC_NUMBER = (3490).to_bytes(2, 'little') + b'\r\n'
416+
MAGIC_NUMBER = (3491).to_bytes(2, 'little') + b'\r\n'
416417
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
417418

418419
_PYCACHE = '__pycache__'

Lib/opcode.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def jabs_op(name, op, entries=0):
7777

7878
def_op('PUSH_EXC_INFO', 35)
7979
def_op('CHECK_EXC_MATCH', 36)
80+
def_op('CHECK_EG_MATCH', 37)
8081

8182
def_op('WITH_EXCEPT_START', 49)
8283
def_op('GET_AITER', 50)
@@ -147,7 +148,6 @@ def jabs_op(name, op, entries=0):
147148
haslocal.append(125)
148149
def_op('DELETE_FAST', 126) # Local variable number
149150
haslocal.append(126)
150-
jabs_op('JUMP_IF_NOT_EG_MATCH', 127)
151151
jabs_op('POP_JUMP_IF_NOT_NONE', 128)
152152
jabs_op('POP_JUMP_IF_NONE', 129)
153153
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Replace :opcode:`JUMP_IF_NOT_EG_MATCH` by :opcode:`CHECK_EG_MATCH` + jump.

Objects/frameobject.c

+2-8
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,15 @@ mark_stacks(PyCodeObject *code_obj, int len)
207207
case JUMP_IF_TRUE_OR_POP:
208208
case POP_JUMP_IF_FALSE:
209209
case POP_JUMP_IF_TRUE:
210-
case JUMP_IF_NOT_EG_MATCH:
211210
{
212211
int64_t target_stack;
213212
int j = get_arg(code, i);
214213
assert(j < len);
215214
if (stacks[j] == UNINITIALIZED && j < i) {
216215
todo = 1;
217216
}
218-
if (opcode == JUMP_IF_NOT_EG_MATCH)
219-
{
220-
next_stack = pop_value(pop_value(next_stack));
221-
target_stack = next_stack;
222-
}
223-
else if (opcode == JUMP_IF_FALSE_OR_POP ||
224-
opcode == JUMP_IF_TRUE_OR_POP)
217+
if (opcode == JUMP_IF_FALSE_OR_POP ||
218+
opcode == JUMP_IF_TRUE_OR_POP)
225219
{
226220
target_stack = next_stack;
227221
next_stack = pop_value(next_stack);

Python/ceval.c

+3-13
Original file line numberDiff line numberDiff line change
@@ -3804,7 +3804,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
38043804
DISPATCH();
38053805
}
38063806

3807-
TARGET(JUMP_IF_NOT_EG_MATCH) {
3807+
TARGET(CHECK_EG_MATCH) {
38083808
PyObject *match_type = POP();
38093809
if (check_except_star_type_valid(tstate, match_type) < 0) {
38103810
Py_DECREF(match_type);
@@ -3825,33 +3825,23 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
38253825
assert(rest == NULL);
38263826
goto error;
38273827
}
3828-
38293828
if (Py_IsNone(match)) {
3830-
Py_DECREF(match);
3829+
PUSH(match);
38313830
Py_XDECREF(rest);
3832-
/* no match - jump to target */
3833-
JUMPTO(oparg);
38343831
}
38353832
else {
3836-
38373833
/* Total or partial match - update the stack from
38383834
* [val]
38393835
* to
38403836
* [rest, match]
38413837
* (rest can be Py_None)
38423838
*/
38433839

3844-
PyObject *exc = TOP();
3845-
38463840
SET_TOP(rest);
38473841
PUSH(match);
3848-
38493842
PyErr_SetExcInfo(NULL, Py_NewRef(match), NULL);
3850-
3851-
Py_DECREF(exc);
3852-
3843+
Py_DECREF(exc_value);
38533844
}
3854-
38553845
DISPATCH();
38563846
}
38573847

Python/compile.c

+21-7
Original file line numberDiff line numberDiff line change
@@ -1000,8 +1000,8 @@ stack_effect(int opcode, int oparg, int jump)
10001000
return -1;
10011001
case CHECK_EXC_MATCH:
10021002
return 0;
1003-
case JUMP_IF_NOT_EG_MATCH:
1004-
return jump > 0 ? -1 : 0;
1003+
case CHECK_EG_MATCH:
1004+
return 0;
10051005
case IMPORT_NAME:
10061006
return -1;
10071007
case IMPORT_FROM:
@@ -3533,14 +3533,18 @@ compiler_try_except(struct compiler *c, stmt_ty s)
35333533
[] POP_BLOCK
35343534
[] JUMP L0
35353535
3536-
[exc] L1: COPY 1 ) save copy of the original exception
3536+
[exc] L1: COPY 1 ) save copy of the original exception
35373537
[orig, exc] BUILD_LIST ) list for raised/reraised excs ("result")
35383538
[orig, exc, res] SWAP 2
35393539
35403540
[orig, res, exc] <evaluate E1>
3541-
[orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2
3541+
[orig, res, exc, E1] CHECK_EG_MATCH
3542+
[orig, red, rest/exc, match?] COPY 1
3543+
[orig, red, rest/exc, match?, match?] POP_JUMP_IF_NOT_NONE H1
3544+
[orig, red, exc, None] POP_TOP
3545+
[orig, red, exc] JUMP L2
35423546
3543-
[orig, res, rest, match] <assign to V1> (or POP if no V1)
3547+
[orig, res, rest, match] H1: <assign to V1> (or POP if no V1)
35443548
35453549
[orig, res, rest] SETUP_FINALLY R1
35463550
[orig, res, rest] <code for S1>
@@ -3622,6 +3626,10 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
36223626
if (except == NULL) {
36233627
return 0;
36243628
}
3629+
basicblock *handle_match = compiler_new_block(c);
3630+
if (handle_match == NULL) {
3631+
return 0;
3632+
}
36253633
if (i == 0) {
36263634
/* Push the original EG into the stack */
36273635
/*
@@ -3641,9 +3649,15 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
36413649
}
36423650
if (handler->v.ExceptHandler.type) {
36433651
VISIT(c, expr, handler->v.ExceptHandler.type);
3644-
ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except);
3652+
ADDOP(c, CHECK_EG_MATCH);
3653+
ADDOP_I(c, COPY, 1);
3654+
ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, handle_match);
3655+
ADDOP(c, POP_TOP); // match
3656+
ADDOP_JUMP(c, JUMP, except);
36453657
}
36463658

3659+
compiler_use_next_block(c, handle_match);
3660+
36473661
basicblock *cleanup_end = compiler_new_block(c);
36483662
if (cleanup_end == NULL) {
36493663
return 0;
@@ -3657,7 +3671,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
36573671
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
36583672
}
36593673
else {
3660-
ADDOP(c, POP_TOP); // exc
3674+
ADDOP(c, POP_TOP); // match
36613675
}
36623676

36633677
/*

0 commit comments

Comments
 (0)