10000 gh-102859: Remove JUMP_IF_FALSE_OR_POP and JUMP_IF_TRUE_OR_POP (#102870) · python/cpython@3468c76 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3468c76

Browse files
authored
gh-102859: Remove JUMP_IF_FALSE_OR_POP and JUMP_IF_TRUE_OR_POP (#102870)
1 parent 04adf2d commit 3468c76

File tree

15 files changed

+235
-437
lines changed

15 files changed

+235
-437
lines changed

Doc/library/dis.rst

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,30 +1152,6 @@ iterations of the loop.
11521152
.. versionchanged:: 3.12
11531153
This is no longer a pseudo-instruction.
11541154

1155-
1156-
.. opcode:: JUMP_IF_TRUE_OR_POP (delta)
1157-
1158-
If ``STACK[-1]`` is true, increments the bytecode counter by *delta* and leaves
1159-
``STACK[-1]`` on the stack. Otherwise (``STACK[-1]`` is false), ``STACK[-1]``
1160-
is popped.
1161-
1162-
.. versionadded:: 3.1
1163-
1164-
.. versionchanged:: 3.11
1165-
The oparg is now a relative delta rather than an absolute target.
1166-
1167-
.. opcode:: JUMP_IF_FALSE_OR_POP (delta)
1168-
1169-
If ``STACK[-1]`` is false, increments the bytecode counter by *delta* and leaves
1170-
``STACK[-1]`` on the stack. Otherwise (``STACK[-1]`` is true), ``STACK[-1]`` is
1171-
popped.
1172-
1173-
.. versionadded:: 3.1
1174-
1175-
.. versionchanged:: 3.11
1176-
The oparg is now a relative delta rather than an absolute target.
1177-
1178-
11791155
.. opcode:: FOR_ITER (delta)
11801156

11811157
``STACK[-1]`` is an :term:`iterator`. Call its :meth:`~iterator.__next__` method.

Doc/whatsnew/3.12.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ CPython bytecode changes
435435
:opcode:`LOAD_METHOD` instruction if the low bit of its oparg is set.
436436
(Contributed by Ken Jin in :gh:`93429`.)
437437

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

439442
Demos and Tools
440443
===============

Include/internal/pycore_opcode.h

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/opcode.h

Lines changed: 8 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

+2Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ def _write_atomic(path, data, mode=0o666):
435435
# Python 3.12a6 3519 (Modify SEND instruction)
436436
# Python 3.12a6 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2)
437437
# Python 3.12a7 3521 (Shrink the LOAD_GLOBAL caches)
438+
# Python 3.12a7 3522 (Removed JUMP_IF_FALSE_OR_POP/JUMP_IF_TRUE_OR_POP)
438439

439440
# Python 3.13 will start with 3550
440441

@@ -451,7 +452,7 @@ def _write_atomic(path, data, mode=0o666):
451452
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
452453
# in PC/launcher.c must also be updated.
453454

454-
MAGIC_NUMBER = (3521).to_bytes(2, 'little') + b'\r\n'
455+
MAGIC_NUMBER = (3522).to_bytes(2, 'little') + b'\r\n'
455456

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

Lib/opcode.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ def pseudo_op(name, op, real_ops):
154154
name_op('IMPORT_NAME', 108) # Index in name list
155155
name_op('IMPORT_FROM', 109) # Index in name list
156156
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
157-
jrel_op('JUMP_IF_FALSE_OR_POP', 111) # Number of words to skip
158-
jrel_op('JUMP_IF_TRUE_OR_POP', 112) # ""
159157
jrel_op('POP_JUMP_IF_FALSE', 114)
160158
jrel_op('POP_JUMP_IF_TRUE', 115)
161159
name_op('LOAD_GLOBAL', 116) # Index in name list

Lib/test/test__opcode.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ def test_stack_effect(self):
3434
self.assertRaises(ValueError, stack_effect, code, 0)
3535

3636
def test_stack_effect_jump(self):
37-
JUMP_IF_TRUE_OR_POP = dis.opmap['JUMP_IF_TRUE_OR_POP']
38-
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0), 0)
39-
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=True), 0)
40-
self.assertEqual(stack_effect(JUMP_IF_TRUE_OR_POP, 0, jump=False), -1)
4137
FOR_ITER = dis.opmap['FOR_ITER']
4238
self.assertEqual(stack_effect(FOR_ITER, 0), 1)
4339
self.assertEqual(stack_effect(FOR_ITER, 0, jump=True), 1)

Lib/test/test_peepholer.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ def check_jump_targets(self, code):
5252
tgt.opname == 'RETURN_VALUE'):
5353
self.fail(f'{instr.opname} at {instr.offset} '
5454
f'jumps to {tgt.opname} at {tgt.offset}')
55-
# JUMP_IF_*_OR_POP jump to conditional jump
56-
if '_OR_POP' in instr.opname and 'JUMP_IF_' in tgt.opname:
57-
self.fail(f'{instr.opname} at {instr.offset} '
58-
f'jumps to {tgt.opname} at {tgt.offset}')
5955

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

385381
def test_elim_jump_to_uncond_jump3(self):
386382
# Intentionally use two-line expressions to test issue37213.
387-
# JUMP_IF_FALSE_OR_POP to JUMP_IF_FALSE_OR_POP --> JUMP_IF_FALSE_OR_POP to non-jump
383+
# POP_JUMP_IF_FALSE to POP_JUMP_IF_FALSE --> POP_JUMP_IF_FALSE to non-jump
388384
def f(a, b, c):
389385
return ((a and b)
390386
and c)
391387
self.check_jump_targets(f)
392388
self.check_lnotab(f)
393-
self.assertEqual(count_instr_recursively(f, 'JUMP_IF_FALSE_OR_POP'), 2)
394-
# JUMP_IF_TRUE_OR_POP to JUMP_IF_TRUE_OR_POP --> JUMP_IF_TRUE_OR_POP to non-jump
389+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 2)
390+
# POP_JUMP_IF_TRUE to POP_JUMP_IF_TRUE --> POP_JUMP_IF_TRUE to non-jump
395391
def f(a, b, c):
396392
return ((a or b)
397393
or c)
398394
self.check_jump_targets(f)
399395
self.check_lnotab(f)
400-
self.assertEqual(count_instr_recursively(f, 'JUMP_IF_TRUE_OR_POP'), 2)
396+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 2)
401397
# JUMP_IF_FALSE_OR_POP to JUMP_IF_TRUE_OR_POP --> POP_JUMP_IF_FALSE to non-jump
402398
def f(a, b, c):
403399
return ((a and b)
404400
or c)
405401
self.check_jump_targets(f)
406402
self.check_lnotab(f)
407-
self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
408-
self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
409-
self.assertInBytecode(f, 'POP_JUMP_IF_FALSE')
410-
# JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump
403+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 1)
404+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 1)
405+
# POP_JUMP_IF_TRUE to POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE to non-jump
411406
def f(a, b, c):
412407
return ((a or b)
413408
and c)
414409
self.check_jump_targets(f)
415410
self.check_lnotab(f)
416-
self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
417-
self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
418-
self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
411+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_FALSE'), 1)
412+
self.assertEqual(count_instr_recursively(f, 'POP_JUMP_IF_TRUE'), 1)
419413

420414
def test_elim_jump_to_uncond_jump4(self):
421415
def f():
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removed :opcode:`JUMP_IF_FALSE_OR_POP` and :opcode:`JUMP_IF_TRUE_OR_POP`
2+
instructions.

Objects/frameobject.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ mark_stacks(PyCodeObject *code_obj, int len)
306306
}
307307
opcode = code[i].op.code;
308308
switch (opcode) {
309-
case JUMP_IF_FALSE_OR_POP:
310-
case JUMP_IF_TRUE_OR_POP:
311309
case POP_JUMP_IF_FALSE:
312310
case POP_JUMP_IF_TRUE:
313311
{
@@ -318,16 +316,8 @@ mark_stacks(PyCodeObject *code_obj, int len)
318316
if (stacks[j] == UNINITIALIZED && j < i) {
319317
todo = 1;
320318
}
321-
if (opcode == JUMP_IF_FALSE_OR_POP ||
322-
opcode == JUMP_IF_TRUE_OR_POP)
323-
{
324-
target_stack = next_stack;
325-
next_stack = pop_value(next_stack);
326-
}
327-
else {
328-
next_stack = pop_value(next_stack);
329-
target_stack = next_stack;
330-
}
319+
next_stack = pop_value(next_stack);
320+
target_stack = next_stack;
331321
assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
332322
stacks[j] = target_stack;
333323
stacks[i+1] = next_stack;

Python/bytecodes.c

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,56 +1918,6 @@ dummy_func(
19181918
}
19191919
}
19201920

1921-
inst(JUMP_IF_FALSE_OR_POP, (cond -- cond if (jump))) {
1922-
bool jump = false;
1923-
int err;
1924-
if (Py_IsTrue(cond)) {
1925-
_Py_DECREF_NO_DEALLOC(cond);
1926-
}
1927-
else if (Py_IsFalse(cond)) {
1928-
JUMPBY(oparg);
1929-
jump = true;
1930-
}
1931-
else {
1932-
err = PyObject_IsTrue(cond);
1933-
if (err > 0) {
1934-
Py_DECREF(cond);
1935-
}
1936-
else if (err == 0) {
1937-
JUMPBY(oparg);
1938-
jump = true;
1939-
}
1940-
else {
1941-
goto error;
1942-
}
1943-
}
1944-
}
1945-
1946-
inst(JUMP_IF_TRUE_OR_POP, (cond -- cond if (jump))) {
1947-
bool jump = false;
1948-
int err;
1949-
if (Py_IsFalse(cond)) {
1950-
_Py_DECREF_NO_DEALLOC(cond);
1951-
}
1952-
else if (Py_IsTrue(cond)) {
1953-
JUMPBY(oparg);
1954-
jump = true;
1955-
}
1956-
else {
1957-
err = PyObject_IsTrue(cond);
1958-
if (err > 0) {
1959-
JUMPBY(oparg);
1960-
jump = true;
1961-
}
1962-
else if (err == 0) {
1963-
Py_DECREF(cond);
1964-
}
1965-
else {
1966-
goto error;
1967-
}
1968-
}
1969-
}
1970-
19711921
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
19721922
/* This bytecode is used in the `yield from` or `await` loop.
19731923
* If there is an interrupt, we want it handled in the innermost

0 commit comments

Comments
 (0)
0