mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-91276: Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative (GH-32215)
This commit is contained in:
parent
5d421d7342
commit
ea2ae02607
8 changed files with 38 additions and 12 deletions
|
@ -993,21 +993,26 @@ iterations of the loop.
|
|||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: JUMP_IF_TRUE_OR_POP (target)
|
||||
.. opcode:: JUMP_IF_TRUE_OR_POP (delta)
|
||||
|
||||
If TOS is true, sets the bytecode counter to *target* and leaves TOS on the
|
||||
If TOS is true, increments the bytecode counter by *delta* and leaves TOS on the
|
||||
stack. Otherwise (TOS is false), TOS is popped.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
The oparg is now a relative delta rather than an absolute target.
|
||||
|
||||
.. opcode:: JUMP_IF_FALSE_OR_POP (target)
|
||||
.. opcode:: JUMP_IF_FALSE_OR_POP (delta)
|
||||
|
||||
If TOS is false, sets the bytecode counter to *target* and leaves TOS on the
|
||||
If TOS is false, increments the bytecode counter by *delta* and leaves TOS on the
|
||||
stack. Otherwise (TOS is true), TOS is popped.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
The oparg is now a relative delta rather than an absolute target.
|
||||
|
||||
|
||||
.. opcode:: FOR_ITER (delta)
|
||||
|
||||
|
|
|
@ -787,6 +787,9 @@ CPython bytecode changes
|
|||
:opcode:`POP_JUMP_FORWARD_IF_NONE` and :opcode:`POP_JUMP_BACKWARD_IF_NONE`
|
||||
opcodes to speed up conditional jumps.
|
||||
|
||||
* :opcode:`JUMP_IF_TRUE_OR_POP` and :opcode:`JUMP_IF_FALSE_OR_POP` are now
|
||||
relative rather than absolute.
|
||||
|
||||
|
||||
Deprecated
|
||||
==========
|
||||
|
|
2
Include/opcode.h
generated
2
Include/opcode.h
generated
|
@ -199,7 +199,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = {
|
|||
0U,
|
||||
0U,
|
||||
536870912U,
|
||||
135020544U,
|
||||
135118848U,
|
||||
4163U,
|
||||
122880U,
|
||||
0U,
|
||||
|
|
|
@ -401,6 +401,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Python 3.11a6 3491 (remove JUMP_IF_NOT_EG_MATCH, add CHECK_EG_MATCH,
|
||||
# add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual)
|
||||
# Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)
|
||||
# Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative)
|
||||
|
||||
# Python 3.12 will start with magic number 3500
|
||||
|
||||
|
@ -415,7 +416,8 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||
# in PC/launcher.c must also be updated.
|
||||
|
||||
MAGIC_NUMBER = (3492).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3493).to_bytes(2, 'little') + b'\r\n'
|
||||
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
_PYCACHE = '__pycache__'
|
||||
|
|
|
@ -131,8 +131,8 @@ hascompare.append(107)
|
|||
name_op('IMPORT_NAME', 108) # Index in name list
|
||||
name_op('IMPORT_FROM', 109) # Index in name list
|
||||
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jrel_op('JUMP_IF_FALSE_OR_POP', 111) # Number of words to skip
|
||||
jrel_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jrel_op('POP_JUMP_FORWARD_IF_FALSE', 114)
|
||||
jrel_op('POP_JUMP_FORWARD_IF_TRUE', 115)
|
||||
name_op('LOAD_GLOBAL', 116, 5) # Index in name list
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Make opcodes :opcode:`JUMP_IF_TRUE_OR_POP` and :opcode:`JUMP_IF_FALSE_OR_POP` relative rather than absolute.
|
|
@ -4081,7 +4081,7 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
if (Py_IsFalse(cond)) {
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(oparg);
|
||||
DISPATCH();
|
||||
}
|
||||
err = PyObject_IsTrue(cond);
|
||||
|
@ -4090,7 +4090,7 @@ handle_eval_breaker:
|
|||
Py_DECREF(cond);
|
||||
}
|
||||
else if (err == 0)
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(oparg);
|
||||
else
|
||||
goto error;
|
||||
DISPATCH();
|
||||
|
@ -4105,12 +4105,12 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
if (Py_IsTrue(cond)) {
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(oparg);
|
||||
DISPATCH();
|
||||
}
|
||||
err = PyObject_IsTrue(cond);
|
||||
if (err > 0) {
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else if (err == 0) {
|
||||
STACK_SHRINK(1);
|
||||
|
|
|
@ -7672,6 +7672,21 @@ normalize_jumps(struct assembler *a)
|
|||
last->i_opcode = is_forward ?
|
||||
POP_JUMP_FORWARD_IF_TRUE : POP_JUMP_BACKWARD_IF_TRUE;
|
||||
break;
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
if (!is_forward) {
|
||||
/* As far as we can tell, the compiler never emits
|
||||
* these jumps with a backwards target. If/when this
|
||||
* exception is raised, we have found a use case for
|
||||
* a backwards version of this jump (or to replace
|
||||
* it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP)
|
||||
*/
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected %s jumping backwards",
|
||||
last->i_opcode == JUMP_IF_TRUE_OR_POP ?
|
||||
"JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue