Skip to content

Commit

Permalink
GH-128685: Specialize (rather than quicken) LOAD_CONST into LOAD_CONS…
Browse files Browse the repository at this point in the history
…T_[IM]MORTAL (GH-128708)
  • Loading branch information
markshannon authored Jan 13, 2025
1 parent 29fe807 commit ddd9599
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 65 deletions.
3 changes: 2 additions & 1 deletion Include/internal/pycore_magic_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ Known values:
Python 3.14a4 3610 (Add VALUE_WITH_FAKE_GLOBALS format to annotationlib)
Python 3.14a4 3611 (Add NOT_TAKEN instruction)
Python 3.14a4 3612 (Add POP_ITER and INSTRUMENTED_POP_ITER)
Python 3.14a4 3613 (Add LOAD_CONST_MORTAL instruction)
Python 3.15 will start with 3650
Expand All @@ -277,7 +278,7 @@ PC/launcher.c must also be updated.
*/

#define PYC_MAGIC_NUMBER 3612
#define PYC_MAGIC_NUMBER 3613
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
Expand Down
16 changes: 13 additions & 3 deletions Include/internal/pycore_opcode_metadata.h

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

1 change: 1 addition & 0 deletions Include/internal/pycore_uop_ids.h

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

6 changes: 3 additions & 3 deletions Include/internal/pycore_uop_metadata.h

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

41 changes: 21 additions & 20 deletions Include/opcode_ids.h

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

42 changes: 22 additions & 20 deletions Lib/_opcode_metadata.py

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

4 changes: 2 additions & 2 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ def loop_test():
%3d RESUME_CHECK 0
%3d BUILD_LIST 0
LOAD_CONST 0 ((1, 2, 3))
LOAD_CONST_MORTAL 0 ((1, 2, 3))
LIST_EXTEND 1
LOAD_SMALL_INT 3
BINARY_OP 5 (*)
Expand Down Expand Up @@ -2548,7 +2548,7 @@ def test_specialized_code(self):
expect = '''
0 RESUME 0
1 LOAD_CONST_IMMORTAL 0 (None)
1 LOAD_CONST 0 (None)
RETURN_VALUE
'''
for flag in ['-S', '--specialized']:
Expand Down
18 changes: 16 additions & 2 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,25 @@ dummy_func(
}

family(LOAD_CONST, 0) = {
LOAD_CONST_MORTAL,
LOAD_CONST_IMMORTAL,
};

pure inst(LOAD_CONST, (-- value)) {
value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
inst(LOAD_CONST, (-- value)) {
/* We can't do this in the bytecode compiler as
* marshalling can intern strings and make them immortal. */
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
value = PyStackRef_FromPyObjectNew(obj);
#if ENABLE_SPECIALIZATION
if (this_instr->op.code == LOAD_CONST) {
this_instr->op.code = _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL;
}
#endif
}

inst(LOAD_CONST_MORTAL, (-- value)) {
PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
value = PyStackRef_FromPyObjectNew(obj);
}

inst(LOAD_CONST_IMMORTAL, (-- value)) {
Expand Down
7 changes: 5 additions & 2 deletions Python/executor_cases.c.h

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

26 changes: 25 additions & 1 deletion Python/generated_cases.c.h

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

2 changes: 1 addition & 1 deletion Python/opcode_targets.h

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

7 changes: 7 additions & 0 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,13 @@ dummy_func(void) {
value = sym_new_const(ctx, val);
}

op(_LOAD_CONST_MORTAL, (-- value)) {
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val);
value = sym_new_const(ctx, val);
}

op(_LOAD_CONST_IMMORTAL, (-- value)) {
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
Expand Down
4 changes: 3 additions & 1 deletion Python/optimizer_cases.c.h

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

9 changes: 0 additions & 9 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,15 +478,6 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, PyObject *consts,
}
i += caches;
}
else if (opcode == LOAD_CONST) {
/* We can't do this in the bytecode compiler as
* marshalling can intern strings and make them immortal. */

PyObject *obj = PyTuple_GET_ITEM(consts, oparg);
if (_Py_IsImmortal(obj)) {
instructions[i].op.code = LOAD_CONST_IMMORTAL;
}
}
if (opcode != EXTENDED_ARG) {
oparg = 0;
}
Expand Down

0 comments on commit ddd9599

Please sign in to comment.