aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2025-01-13 10:30:28 +0000
committerGitHub <noreply@github.com>2025-01-13 10:30:28 +0000
commitddd959987c557beaf823b681bf5e5e573ad657ac (patch)
treee59574d3eb62f94e497f7aecd585bf656ebc984e /Python
parent29fe8072cf404b891dde9c1d415095edddbe19de (diff)
downloadcpython-ddd959987c557beaf823b681bf5e5e573ad657ac.tar.gz
cpython-ddd959987c557beaf823b681bf5e5e573ad657ac.zip
GH-128685: Specialize (rather than quicken) LOAD_CONST into LOAD_CONST_[IM]MORTAL (GH-128708)
Diffstat (limited to 'Python')
-rw-r--r--Python/bytecodes.c18
-rw-r--r--Python/executor_cases.c.h7
-rw-r--r--Python/generated_cases.c.h26
-rw-r--r--Python/opcode_targets.h2
-rw-r--r--Python/optimizer_bytecodes.c7
-rw-r--r--Python/optimizer_cases.c.h4
-rw-r--r--Python/specialize.c9
7 files changed, 57 insertions, 16 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 8bab4ea16b6..657e2fb4e1c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -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)) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index e40fa88be89..e90d6b5ec10 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -209,10 +209,13 @@
break;
}
- case _LOAD_CONST: {
+ /* _LOAD_CONST is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
+
+ case _LOAD_CONST_MORTAL: {
_PyStackRef value;
oparg = CURRENT_OPARG();
- value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
+ PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
+ value = PyStackRef_FromPyObjectNew(obj);
stack_pointer[0] = value;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 7028ba52faa..70d0814d682 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -5913,8 +5913,18 @@
next_instr += 1;
INSTRUCTION_STATS(LOAD_CONST);
PREDICTED(LOAD_CONST);
+ _Py_CODEUNIT* const this_instr = next_instr - 1;
+ (void)this_instr;
_PyStackRef value;
- value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
+ /* 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
stack_pointer[0] = value;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@@ -5936,6 +5946,20 @@
DISPATCH();
}
+ TARGET(LOAD_CONST_MORTAL) {
+ frame->instr_ptr = next_instr;
+ next_instr += 1;
+ INSTRUCTION_STATS(LOAD_CONST_MORTAL);
+ static_assert(0 == 0, "incorrect cache size");
+ _PyStackRef value;
+ PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg);
+ value = PyStackRef_FromPyObjectNew(obj);
+ stack_pointer[0] = value;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ DISPATCH();
+ }
+
TARGET(LOAD_DEREF) {
frame->instr_ptr = next_instr;
next_instr += 1;
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 00d55d3a82e..c5c008fcbe5 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -207,6 +207,7 @@ static void *opcode_targets[256] = {
&&TARGET_LOAD_ATTR_SLOT,
&&TARGET_LOAD_ATTR_WITH_HINT,
&&TARGET_LOAD_CONST_IMMORTAL,
+ &&TARGET_LOAD_CONST_MORTAL,
&&TARGET_LOAD_GLOBAL_BUILTIN,
&&TARGET_LOAD_GLOBAL_MODULE,
&&TARGET_LOAD_SUPER_ATTR_ATTR,
@@ -233,7 +234,6 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_POP_ITER,
&&TARGET_INSTRUMENTED_END_SEND,
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 86394480f76..788adecca8a 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -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);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index c72ae7b6281..a64dd465467 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -58,7 +58,9 @@
break;
}
- case _LOAD_CONST: {
+ /* _LOAD_CONST is not a viable micro-op for tier 2 */
+
+ case _LOAD_CONST_MORTAL: {
_Py_UopsSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
diff --git a/Python/specialize.c b/Python/specialize.c
index c9325c39210..897005c4f10 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -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;
}