Skip to content

Commit 753fc8a

Browse files
authored
pythongh-101632: Add the new RETURN_CONST opcode (python#101633)
1 parent 0d3d500 commit 753fc8a

19 files changed

+186
-154
lines changed

Doc/library/dis.rst

+7
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,13 @@ iterations of the loop.
694694
Returns with ``STACK[-1]`` to the caller of the function.
695695

696696

697+
.. opcode:: RETURN_CONST (consti)
698+
699+
Returns with ``co_consts[consti]`` to the caller of the function.
700+
701+
.. versionadded:: 3.12
702+
703+
697704
.. opcode:: YIELD_VALUE
698705

699706
Yields ``STACK.pop()`` from a :term:`generator`.

Include/internal/pycore_opcode.h

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

Include/opcode.h

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

Lib/dis.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure')
3535

3636
LOAD_CONST = opmap['LOAD_CONST']
37+
RETURN_CONST = opmap['RETURN_CONST']
3738
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
3839
BINARY_OP = opmap['BINARY_OP']
3940
JUMP_BACKWARD = opmap['JUMP_BACKWARD']
@@ -363,7 +364,7 @@ def _get_const_value(op, arg, co_consts):
363364
assert op in hasconst
364365

365366
argval = UNKNOWN
366-
if op == LOAD_CONST:
367+
if op == LOAD_CONST or op == RETURN_CONST:
367368
if co_consts is not None:
368369
argval = co_consts[arg]
369370
return argval

Lib/importlib/_bootstrap_external.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ def _write_atomic(path, data, mode=0o666):
431431
# Python 3.12a5 3515 (Embed jump mask in COMPARE_OP oparg)
432432
# Python 3.12a5 3516 (Add COMPARE_AND_BRANCH instruction)
433433
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
434+
# Python 3.12a5 3518 (Add RETURN_CONST instruction)
434435

435436
# Python 3.13 will start with 3550
436437

@@ -443,7 +444,7 @@ def _write_atomic(path, data, mode=0o666):
443444
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
444445
# in PC/launcher.c must also be updated.
445446

446-
MAGIC_NUMBER = (3517).to_bytes(2, 'little') + b'\r\n'
447+
MAGIC_NUMBER = (3518).to_bytes(2, 'little') + b'\r\n'
447448

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

Lib/opcode.py

+2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ def pseudo_op(name, op, real_ops):
164164
def_op('CONTAINS_OP', 118)
165165
def_op('RERAISE', 119)
166166
def_op('COPY', 120)
167+
def_op('RETURN_CONST', 121)
168+
hasconst.append(121)
167169
def_op('BINARY_OP', 122)
168170
jrel_op('SEND', 123) # Number of bytes to skip
169171
def_op('LOAD_FAST', 124) # Local variable number, no null check

Lib/test/test_ast.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1900,7 +1900,7 @@ def get_load_const(self, tree):
19001900
co = compile(tree, '<string>', 'exec')
19011901
consts = []
19021902
for instr in dis.get_instructions(co):
1903-
if instr.opname == 'LOAD_CONST':
1903+
if instr.opname == 'LOAD_CONST' or instr.opname == 'RETURN_CONST':
19041904
consts.append(instr.argval)
19051905
return consts
19061906

Lib/test/test_code.py

+1
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ def f():
723723
pass
724724
PY_CODE_LOCATION_INFO_NO_COLUMNS = 13
725725
f.__code__ = f.__code__.replace(
726+
co_stacksize=1,
726727
co_firstlineno=42,
727728
co_code=bytes(
728729
[

Lib/test/test_compile.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ def unused_code_at_end():
741741
# RETURN_VALUE opcode. This does not always crash an interpreter.
742742
# When you build with the clang memory sanitizer it reliably aborts.
743743
self.assertEqual(
744-
'RETURN_VALUE',
744+
'RETURN_CONST',
745745
list(dis.get_instructions(unused_code_at_end))[-1].opname)
746746

747747
def test_dont_merge_constants(self):
@@ -822,10 +822,9 @@ def unused_block_while_else():
822822

823823
for func in funcs:
824824
opcodes = list(dis.get_instructions(func))
825-
self.assertLessEqual(len(opcodes), 4)
826-
self.assertEqual('LOAD_CONST', opcodes[-2].opname)
827-
self.assertEqual(None, opcodes[-2].argval)
828-
self.assertEqual('RETURN_VALUE', opcodes[-1].opname)
825+
self.assertLessEqual(len(opcodes), 3)
826+
self.assertEqual('RETURN_CONST', opcodes[-1].opname)
827+
self.assertEqual(None, opcodes[-1].argval)
829828

830829
def test_false_while_loop(self):
831830
def break_in_while():
@@ -841,10 +840,9 @@ def continue_in_while():
841840
# Check that we did not raise but we also don't generate bytecode
842841
for func in funcs:
843842
opcodes = list(dis.get_instructions(func))
844-
self.assertEqual(3, len(opcodes))
845-
self.assertEqual('LOAD_CONST', opcodes[1].opname)
843+
self.assertEqual(2, len(opcodes))
844+
self.assertEqual('RETURN_CONST', opcodes[1].opname)
846845
self.assertEqual(None, opcodes[1].argval)
847-
self.assertEqual('RETURN_VALUE', opcodes[2].opname)
848846

849847
def test_consts_in_conditionals(self):
850848
def and_true(x):
@@ -1311,7 +1309,7 @@ def test_multiline_generator_expression(self):
13111309
line=1, end_line=2, column=1, end_column=8, occurrence=1)
13121310
self.assertOpcodeSourcePositionIs(compiled_code, 'JUMP_BACKWARD',
13131311
line=1, end_line=2, column=1, end_column=8, occurrence=1)
1314-
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE',
1312+
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST',
13151313
line=1, end_line=6, column=0, end_column=32, occurrence=1)
13161314

13171315
def test_multiline_async_generator_expression(self):
@@ -1328,7 +1326,7 @@ def test_multiline_async_generator_expression(self):
13281326
self.assertIsInstance(compiled_code, types.CodeType)
13291327
self.assertOpcodeSourcePositionIs(compiled_code, 'YIELD_VALUE',
13301328
line=1, end_line=2, column=1, end_column=8, occurrence=2)
1331-
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE',
1329+
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST',
13321330
line=1, end_line=6, column=0, end_column=32, occurrence=1)
13331331

13341332
def test_multiline_list_comprehension(self):

0 commit comments

Comments
 (0)