Skip to content

Commit

Permalink
gh-101632: Add the new RETURN_CONST opcode (#101633)
Browse files Browse the repository at this point in the history
  • Loading branch information
penguin-wwy authored Feb 7, 2023
1 parent 0d3d500 commit 753fc8a
Show file tree
Hide file tree
Showing 19 changed files with 186 additions and 154 deletions.
7 changes: 7 additions & 0 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,13 @@ iterations of the loop.
Returns with ``STACK[-1]`` to the caller of the function.


.. opcode:: RETURN_CONST (consti)

Returns with ``co_consts[consti]`` to the caller of the function.

.. versionadded:: 3.12


.. opcode:: YIELD_VALUE

Yields ``STACK.pop()`` from a :term:`generator`.
Expand Down
10 changes: 5 additions & 5 deletions Include/internal/pycore_opcode.h

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

16 changes: 9 additions & 7 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/dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
MAKE_FUNCTION_FLAGS = ('defaults', 'kwdefaults', 'annotations', 'closure')

LOAD_CONST = opmap['LOAD_CONST']
RETURN_CONST = opmap['RETURN_CONST']
LOAD_GLOBAL = opmap['LOAD_GLOBAL']
BINARY_OP = opmap['BINARY_OP']
JUMP_BACKWARD = opmap['JUMP_BACKWARD']
Expand Down Expand Up @@ -363,7 +364,7 @@ def _get_const_value(op, arg, co_consts):
assert op in hasconst

argval = UNKNOWN
if op == LOAD_CONST:
if op == LOAD_CONST or op == RETURN_CONST:
if co_consts is not None:
argval = co_consts[arg]
return argval
Expand Down
3 changes: 2 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a5 3515 (Embed jump mask in COMPARE_OP oparg)
# Python 3.12a5 3516 (Add COMPARE_AND_BRANCH instruction)
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
# Python 3.12a5 3518 (Add RETURN_CONST instruction)

# Python 3.13 will start with 3550

Expand All @@ -443,7 +444,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 = (3517).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3518).to_bytes(2, 'little') + b'\r\n'

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

Expand Down
2 changes: 2 additions & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ def pseudo_op(name, op, real_ops):
def_op('CONTAINS_OP', 118)
def_op('RERAISE', 119)
def_op('COPY', 120)
def_op('RETURN_CONST', 121)
hasconst.append(121)
def_op('BINARY_OP', 122)
jrel_op('SEND', 123) # Number of bytes to skip
def_op('LOAD_FAST', 124) # Local variable number, no null check
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1900,7 +1900,7 @@ def get_load_const(self, tree):
co = compile(tree, '<string>', 'exec')
consts = []
for instr in dis.get_instructions(co):
if instr.opname == 'LOAD_CONST':
if instr.opname == 'LOAD_CONST' or instr.opname == 'RETURN_CONST':
consts.append(instr.argval)
return consts

Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ def f():
pass
PY_CODE_LOCATION_INFO_NO_COLUMNS = 13
f.__code__ = f.__code__.replace(
co_stacksize=1,
co_firstlineno=42,
co_code=bytes(
[
Expand Down
18 changes: 8 additions & 10 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ def unused_code_at_end():
# RETURN_VALUE opcode. This does not always crash an interpreter.
# When you build with the clang memory sanitizer it reliably aborts.
self.assertEqual(
'RETURN_VALUE',
'RETURN_CONST',
list(dis.get_instructions(unused_code_at_end))[-1].opname)

def test_dont_merge_constants(self):
Expand Down Expand Up @@ -822,10 +822,9 @@ def unused_block_while_else():

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

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

def test_consts_in_conditionals(self):
def and_true(x):
Expand Down Expand Up @@ -1311,7 +1309,7 @@ def test_multiline_generator_expression(self):
line=1, end_line=2, column=1, end_column=8, occurrence=1)
self.assertOpcodeSourcePositionIs(compiled_code, 'JUMP_BACKWARD',
line=1, end_line=2, column=1, end_column=8, occurrence=1)
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE',
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST',
line=1, end_line=6, column=0, end_column=32, occurrence=1)

def test_multiline_async_generator_expression(self):
Expand All @@ -1328,7 +1326,7 @@ def test_multiline_async_generator_expression(self):
self.assertIsInstance(compiled_code, types.CodeType)
self.assertOpcodeSourcePositionIs(compiled_code, 'YIELD_VALUE',
line=1, end_line=2, column=1, end_column=8, occurrence=2)
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_VALUE',
self.assertOpcodeSourcePositionIs(compiled_code, 'RETURN_CONST',
line=1, end_line=6, column=0, end_column=32, occurrence=1)

def test_multiline_list_comprehension(self):
Expand Down
Loading

0 comments on commit 753fc8a

Please sign in to comment.