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
*/
-#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 \
return 0;
case LOAD_CONST_IMMORTAL:
return 0;
+ case LOAD_CONST_MORTAL:
+ return 0;
case LOAD_DEREF:
return 0;
case LOAD_FAST:
return 1;
case LOAD_CONST_IMMORTAL:
return 1;
+ case LOAD_CONST_MORTAL:
+ return 1;
case LOAD_DEREF:
return 1;
case LOAD_FAST:
*effect = 1;
return 0;
}
+ case LOAD_CONST_MORTAL: {
+ *effect = 1;
+ return 0;
+ }
case LOAD_DEREF: {
*effect = 1;
return 0;
[LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_COMMON_CONSTANT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
- [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_PURE_FLAG },
+ [LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[LOAD_CONST_IMMORTAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
+ [LOAD_CONST_MORTAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[LOAD_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_PURE_FLAG },
[LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_ATTR_WITH_HINT] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_WITH_HINT, 0, 0 }, { _LOAD_ATTR_WITH_HINT, 1, 3 } } },
[LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { _LOAD_BUILD_CLASS, 0, 0 } } },
[LOAD_COMMON_CONSTANT] = { .nuops = 1, .uops = { { _LOAD_COMMON_CONSTANT, 0, 0 } } },
- [LOAD_CONST] = { .nuops = 1, .uops = { { _LOAD_CONST, 0, 0 } } },
[LOAD_CONST_IMMORTAL] = { .nuops = 1, .uops = { { _LOAD_CONST_IMMORTAL, 0, 0 } } },
+ [LOAD_CONST_MORTAL] = { .nuops = 1, .uops = { { _LOAD_CONST_MORTAL, 0, 0 } } },
[LOAD_DEREF] = { .nuops = 1, .uops = { { _LOAD_DEREF, 0, 0 } } },
[LOAD_FAST] = { .nuops = 1, .uops = { { _LOAD_FAST, 0, 0 } } },
[LOAD_FAST_AND_CLEAR] = { .nuops = 1, .uops = { { _LOAD_FAST_AND_CLEAR, 0, 0 } } },
[LOAD_COMMON_CONSTANT] = "LOAD_COMMON_CONSTANT",
[LOAD_CONST] = "LOAD_CONST",
[LOAD_CONST_IMMORTAL] = "LOAD_CONST_IMMORTAL",
+ [LOAD_CONST_MORTAL] = "LOAD_CONST_MORTAL",
[LOAD_DEREF] = "LOAD_DEREF",
[LOAD_FAST] = "LOAD_FAST",
[LOAD_FAST_AND_CLEAR] = "LOAD_FAST_AND_CLEAR",
[LOAD_COMMON_CONSTANT] = LOAD_COMMON_CONSTANT,
[LOAD_CONST] = LOAD_CONST,
[LOAD_CONST_IMMORTAL] = LOAD_CONST,
+ [LOAD_CONST_MORTAL] = LOAD_CONST,
[LOAD_DEREF] = LOAD_DEREF,
[LOAD_FAST] = LOAD_FAST,
[LOAD_FAST_AND_CLEAR] = LOAD_FAST_AND_CLEAR,
case 146: \
case 147: \
case 148: \
- case 228: \
case 229: \
case 230: \
case 231: \
#define _LOAD_CONST_INLINE_BORROW 430
#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 431
#define _LOAD_CONST_INLINE_WITH_NULL 432
+#define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL
#define _LOAD_DEREF LOAD_DEREF
#define _LOAD_FAST 433
#define _LOAD_FAST_0 434
[_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_PURE_FLAG,
[_LOAD_FAST_AND_CLEAR] = HAS_ARG_FLAG | HAS_LOCAL_FLAG,
[_LOAD_FAST_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG,
- [_LOAD_CONST] = HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_PURE_FLAG,
+ [_LOAD_CONST_MORTAL] = HAS_ARG_FLAG | HAS_CONST_FLAG,
[_LOAD_CONST_IMMORTAL] = HAS_ARG_FLAG | HAS_CONST_FLAG,
[_LOAD_SMALL_INT_0] = 0,
[_LOAD_SMALL_INT_1] = 0,
[_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT",
[_LOAD_BUILD_CLASS] = "_LOAD_BUILD_CLASS",
[_LOAD_COMMON_CONSTANT] = "_LOAD_COMMON_CONSTANT",
- [_LOAD_CONST] = "_LOAD_CONST",
[_LOAD_CONST_IMMORTAL] = "_LOAD_CONST_IMMORTAL",
[_LOAD_CONST_INLINE] = "_LOAD_CONST_INLINE",
[_LOAD_CONST_INLINE_BORROW] = "_LOAD_CONST_INLINE_BORROW",
[_LOAD_CONST_INLINE_BORROW_WITH_NULL] = "_LOAD_CONST_INLINE_BORROW_WITH_NULL",
[_LOAD_CONST_INLINE_WITH_NULL] = "_LOAD_CONST_INLINE_WITH_NULL",
+ [_LOAD_CONST_MORTAL] = "_LOAD_CONST_MORTAL",
[_LOAD_DEREF] = "_LOAD_DEREF",
[_LOAD_FAST] = "_LOAD_FAST",
[_LOAD_FAST_0] = "_LOAD_FAST_0",
return 0;
case _LOAD_FAST_LOAD_FAST:
return 0;
- case _LOAD_CONST:
+ case _LOAD_CONST_MORTAL:
return 0;
case _LOAD_CONST_IMMORTAL:
return 0;
#define LOAD_ATTR_SLOT 205
#define LOAD_ATTR_WITH_HINT 206
#define LOAD_CONST_IMMORTAL 207
-#define LOAD_GLOBAL_BUILTIN 208
-#define LOAD_GLOBAL_MODULE 209
-#define LOAD_SUPER_ATTR_ATTR 210
-#define LOAD_SUPER_ATTR_METHOD 211
-#define RESUME_CHECK 212
-#define SEND_GEN 213
-#define STORE_ATTR_INSTANCE_VALUE 214
-#define STORE_ATTR_SLOT 215
-#define STORE_ATTR_WITH_HINT 216
-#define STORE_SUBSCR_DICT 217
-#define STORE_SUBSCR_LIST_INT 218
-#define TO_BOOL_ALWAYS_TRUE 219
-#define TO_BOOL_BOOL 220
-#define TO_BOOL_INT 221
-#define TO_BOOL_LIST 222
-#define TO_BOOL_NONE 223
-#define TO_BOOL_STR 224
-#define UNPACK_SEQUENCE_LIST 225
-#define UNPACK_SEQUENCE_TUPLE 226
-#define UNPACK_SEQUENCE_TWO_TUPLE 227
+#define LOAD_CONST_MORTAL 208
+#define LOAD_GLOBAL_BUILTIN 209
+#define LOAD_GLOBAL_MODULE 210
+#define LOAD_SUPER_ATTR_ATTR 211
+#define LOAD_SUPER_ATTR_METHOD 212
+#define RESUME_CHECK 213
+#define SEND_GEN 214
+#define STORE_ATTR_INSTANCE_VALUE 215
+#define STORE_ATTR_SLOT 216
+#define STORE_ATTR_WITH_HINT 217
+#define STORE_SUBSCR_DICT 218
+#define STORE_SUBSCR_LIST_INT 219
+#define TO_BOOL_ALWAYS_TRUE 220
+#define TO_BOOL_BOOL 221
+#define TO_BOOL_INT 222
+#define TO_BOOL_LIST 223
+#define TO_BOOL_NONE 224
+#define TO_BOOL_STR 225
+#define UNPACK_SEQUENCE_LIST 226
+#define UNPACK_SEQUENCE_TUPLE 227
+#define UNPACK_SEQUENCE_TWO_TUPLE 228
#define INSTRUMENTED_END_FOR 235
#define INSTRUMENTED_POP_ITER 236
#define INSTRUMENTED_END_SEND 237
"RESUME_CHECK",
],
"LOAD_CONST": [
+ "LOAD_CONST_MORTAL",
"LOAD_CONST_IMMORTAL",
],
"TO_BOOL": [
'LOAD_ATTR_SLOT': 205,
'LOAD_ATTR_WITH_HINT': 206,
'LOAD_CONST_IMMORTAL': 207,
- 'LOAD_GLOBAL_BUILTIN': 208,
- 'LOAD_GLOBAL_MODULE': 209,
- 'LOAD_SUPER_ATTR_ATTR': 210,
- 'LOAD_SUPER_ATTR_METHOD': 211,
- 'RESUME_CHECK': 212,
- 'SEND_GEN': 213,
- 'STORE_ATTR_INSTANCE_VALUE': 214,
- 'STORE_ATTR_SLOT': 215,
- 'STORE_ATTR_WITH_HINT': 216,
- 'STORE_SUBSCR_DICT': 217,
- 'STORE_SUBSCR_LIST_INT': 218,
- 'TO_BOOL_ALWAYS_TRUE': 219,
- 'TO_BOOL_BOOL': 220,
- 'TO_BOOL_INT': 221,
- 'TO_BOOL_LIST': 222,
- 'TO_BOOL_NONE': 223,
- 'TO_BOOL_STR': 224,
- 'UNPACK_SEQUENCE_LIST': 225,
- 'UNPACK_SEQUENCE_TUPLE': 226,
- 'UNPACK_SEQUENCE_TWO_TUPLE': 227,
+ 'LOAD_CONST_MORTAL': 208,
+ 'LOAD_GLOBAL_BUILTIN': 209,
+ 'LOAD_GLOBAL_MODULE': 210,
+ 'LOAD_SUPER_ATTR_ATTR': 211,
+ 'LOAD_SUPER_ATTR_METHOD': 212,
+ 'RESUME_CHECK': 213,
+ 'SEND_GEN': 214,
+ 'STORE_ATTR_INSTANCE_VALUE': 215,
+ 'STORE_ATTR_SLOT': 216,
+ 'STORE_ATTR_WITH_HINT': 217,
+ 'STORE_SUBSCR_DICT': 218,
+ 'STORE_SUBSCR_LIST_INT': 219,
+ 'TO_BOOL_ALWAYS_TRUE': 220,
+ 'TO_BOOL_BOOL': 221,
+ 'TO_BOOL_INT': 222,
+ 'TO_BOOL_LIST': 223,
+ 'TO_BOOL_NONE': 224,
+ 'TO_BOOL_STR': 225,
+ 'UNPACK_SEQUENCE_LIST': 226,
+ 'UNPACK_SEQUENCE_TUPLE': 227,
+ 'UNPACK_SEQUENCE_TWO_TUPLE': 228,
}
opmap = {
%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 (*)
expect = '''
0 RESUME 0
- 1 LOAD_CONST_IMMORTAL 0 (None)
+ 1 LOAD_CONST 0 (None)
RETURN_VALUE
'''
for flag in ['-S', '--specialized']:
}
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)) {
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());
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());
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;
&&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,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_POP_ITER,
&&TARGET_INSTRUMENTED_END_SEND,
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);
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;
}
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;
}