Skip to content

gh-102859: Remove JUMP_IF_FALSE_OR_POP and JUMP_IF_TRUE_OR_POP #102870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1152,30 +1152,6 @@ iterations of the loop.
.. versionchanged:: 3.12
This is no longer a pseudo-instruction.


.. opcode:: JUMP_IF_TRUE_OR_POP (delta)

If ``STACK[-1]`` is true, increments the bytecode counter by *delta* and leaves
``STACK[-1]`` on the stack. Otherwise (``STACK[-1]`` is false), ``STACK[-1]``
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 (delta)

If ``STACK[-1]`` is false, increments the bytecode counter by *delta* and leaves
``STACK[-1]`` on the stack. Otherwise (``STACK[-1]`` is true), ``STACK[-1]`` is
popped.

.. versionadded:: 3.1

.. versionchanged:: 3.11
The oparg is now a relative delta rather than an absolute target.


.. opcode:: FOR_ITER (delta)

``STACK[-1]`` is an :term:`iterator`. Call its :meth:`~iterator.__next__` method.
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,9 @@ CPython bytecode changes
:opcode:`LOAD_METHOD` instruction if the low bit of its oparg is set.
(Contributed by Ken Jin in :gh:`93429`.)

* Removed the :opcode:`JUMP_IF_FALSE_OR_POP` and :opcode:`JUMP_IF_TRUE_OR_POP`
instructions. (Contributed by Irit Katriel in :gh:`102859`.)


Demos and Tools
===============
Expand Down
22 changes: 11 additions & 11 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 8 additions & 10 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a6 3519 (Modify SEND instruction)
# Python 3.12a6 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2)
# Python 3.12a7 3521 (Shrink the LOAD_GLOBAL caches)
# Python 3.12a7 3522 (Removed JUMP_IF_FALSE_OR_POP/JUMP_IF_TRUE_OR_POP)

# Python 3.13 will start with 3550

Expand All @@ -451,7 +452,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 = (3521).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3522).to_bytes(2, 'little') + b'\r\n'

_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

Expand Down
2 changes: 0 additions & 2 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ def pseudo_op(name, op, real_ops):
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
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_IF_FALSE', 114)
jrel_op('POP_JUMP_IF_TRUE', 115)
name_op('LOAD_GLOBAL', 116) # Index in name list
Expand Down
4 changes: 0 additions & 4 deletions Lib/test/test__opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ def test_stack_effect(self):
self.assertRaises(ValueError, stack_effect, code, 0)

def test_stack_effect_jump(self):
JUMP_IF_TRUE_OR_POP = dis.opmap['JUMP_IF_TRUE_OR_POP']
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0), 0)
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=True), 0)
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=False), -1)
FOR_ITER = dis.opmap['FOR_ITER']
self.assertEqual(stack_effect(FOR_ITER, 0), 1)
self.assertEqual(stack_effect(FOR_ITER, 0, jump=True), 1)
Expand Down
24 changes: 9 additions & 15 deletions Lib/test/test_peepholer.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ def check_jump_targets(self, code):
tgt.opname == 'RETURN_VALUE'):
self.fail(f'{instr.opname} at {instr.offset} '
f'jumps to {tgt.opname} at {tgt.offset}')
# JUMP_IF_*_OR_POP jump to conditional jump
if '_OR_POP' in instr.opname and 'JUMP_IF_' in tgt.opname:
self.fail(f'{instr.opname} at {instr.offset} '
f'jumps to {tgt.opname} at {tgt.offset}')

def check_lnotab(self, code):
"Check that the lnotab byte offsets are sensible."
Expand Down Expand Up @@ -384,38 +380,36 @@ def f():

def test_elim_jump_to_uncond_jump3(self):
# Intentionally use two-line expressions to test issue37213.
# JUMP_IF_FALSE_OR_POP to JUMP_IF_FALSE_OR_POP --> JUMP_IF_FALSE_OR_POP to non-jump
# POP_JUMP_IF_FALSE to POP_JUMP_IF_FALSE --> POP_JUMP_IF_FALSE to non-jump
def f(a, b, c):
return ((a and b)
and c)
self.check_jump_targets(f)
self.check_lnotab(f)
self.assertEqual(count_instr_recursively(f, 'JUMP_IF_FALSE_OR_POP'), 2)
# JUMP_IF_TRUE_OR_POP to JUMP_IF_TRUE_OR_POP --> JUMP_IF_TRUE_OR_POP to non-jump
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 2)
# POP_JUMP_IF_TRUE to POP_JUMP_IF_TRUE --> POP_JUMP_IF_TRUE to non-jump
def f(a, b, c):
return ((a or b)
or c)
self.check_jump_targets(f)
self.check_lnotab(f)
self.assertEqual(count_instr_recursively(f, 'JUMP_IF_TRUE_OR_POP'), 2)
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 2)
# JUMP_IF_FALSE_OR_POP to JUMP_IF_TRUE_OR_POP --> POP_JUMP_IF_FALSE to non-jump
def f(a, b, c):
return ((a and b)
or c)
self.check_jump_targets(f)
self.check_lnotab(f)
self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
self.assertInBytecode(f, 'POP_JUMP_IF_FALSE')
# JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 1)
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 1)
# POP_JUMP_IF_TRUE to POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE to non-jump
def f(a, b, c):
return ((a or b)
and c)
self.check_jump_targets(f)
self.check_lnotab(f)
self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 1)
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 1)

def test_elim_jump_to_uncond_jump4(self):
def f():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Removed :opcode:`JUMP_IF_FALSE_OR_POP` and :opcode:`JUMP_IF_TRUE_OR_POP`
instructions.
14 changes: 2 additions & 12 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,6 @@ mark_stacks(PyCodeObject *code_obj, int len)
}
opcode = code[i].op.code;
switch (opcode) {
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
{
Expand All @@ -318,16 +316,8 @@ mark_stacks(PyCodeObject *code_obj, int len)
if (stacks[j] == UNINITIALIZED && j < i) {
todo = 1;
}
if (opcode == JUMP_IF_FALSE_OR_POP ||
opcode == JUMP_IF_TRUE_OR_POP)
{
target_stack = next_stack;
next_stack = pop_value(next_stack);
}
else {
next_stack = pop_value(next_stack);
target_stack = next_stack;
}
next_stack = pop_value(next_stack);
target_stack = next_stack;
assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
stacks[j] = target_stack;
stacks[i+1] = next_stack;
Expand Down
50 changes: 0 additions & 50 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1918,56 +1918,6 @@ dummy_func(
}
}

inst(JUMP_IF_FALSE_OR_POP, (cond -- cond if (jump))) {
bool jump = false;
int err;
if (Py_IsTrue(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsFalse(cond)) {
JUMPBY(oparg);
jump = true;
}
else {
err = PyObject_IsTrue(cond);
if (err > 0) {
Py_DECREF(cond);
}
else if (err == 0) {
JUMPBY(oparg);
jump = true;
}
else {
goto error;
}
}
}

inst(JUMP_IF_TRUE_OR_POP, (cond -- cond if (jump))) {
bool jump = false;
int err;
if (Py_IsFalse(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
}
else if (Py_IsTrue(cond)) {
JUMPBY(oparg);
jump = true;
}
else {
err = PyObject_IsTrue(cond);
if (err > 0) {
JUMPBY(oparg);
jump = true;
}
else if (err == 0) {
Py_DECREF(cond);
}
else {
goto error;
}
}
}

inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
/* This bytecode is used in the `yield from` or `await` loop.
* If there is an interrupt, we want it handled in the innermost
Expand Down
Loading