Instruction 3.14 (#6805)

* renumber enum Instruction

* renumber magic

* Update test__opcode from 3.14.2

---------

Co-authored-by: CPython Devleopers <>
This commit is contained in:
Jeong, YunWonandCPython Devleopers authored and GitHub committed 2026-01-20 03:52:52 +09:00
1 parent b76906a8bf
commit 97167ab1cc
7 files changed
+656 -697

No files matched your search

+236 -222
View File
@@ -8,231 +8,245 @@ _specialized_opmap = {}
opmap = {
'CACHE': 0,
'BEFORE_ASYNC_WITH': 1,
'BEFORE_WITH': 2,
'BINARY_SLICE': 1,
'BUILD_TEMPLATE': 2,
'BINARY_OP_INPLACE_ADD_UNICODE': 3,
'BINARY_SLICE': 4,
'BINARY_SUBSCR': 5,
'CHECK_EG_MATCH': 6,
'CHECK_EXC_MATCH': 7,
'CLEANUP_THROW': 8,
'DELETE_SUBSCR': 9,
'END_ASYNC_FOR': 10,
'END_FOR': 11,
'END_SEND': 12,
'EXIT_INIT_CHECK': 13,
'FORMAT_SIMPLE': 14,
'FORMAT_WITH_SPEC': 15,
'GET_AITER': 16,
'CALL_FUNCTION_EX': 4,
'CHECK_EG_MATCH': 5,
'CHECK_EXC_MATCH': 6,
'CLEANUP_THROW': 7,
'DELETE_SUBSCR': 8,
'END_FOR': 9,
'END_SEND': 10,
'EXIT_INIT_CHECK': 11,
'FORMAT_SIMPLE': 12,
'FORMAT_WITH_SPEC': 13,
'GET_AITER': 14,
'GET_ANEXT': 15,
'GET_ITER': 16,
'RESERVED': 17,
'GET_ANEXT': 18,
'GET_ITER': 19,
'GET_LEN': 20,
'GET_YIELD_FROM_ITER': 21,
'INTERPRETER_EXIT': 22,
'LOAD_ASSERTION_ERROR': 23,
'LOAD_BUILD_CLASS': 24,
'LOAD_LOCALS': 25,
'MAKE_FUNCTION': 26,
'MATCH_KEYS': 27,
'MATCH_MAPPING': 28,
'MATCH_SEQUENCE': 29,
'NOP': 30,
'POP_EXCEPT': 31,
'POP_TOP': 32,
'PUSH_EXC_INFO': 33,
'PUSH_NULL': 34,
'RETURN_GENERATOR': 35,
'RETURN_VALUE': 36,
'SETUP_ANNOTATIONS': 37,
'STORE_SLICE': 38,
'STORE_SUBSCR': 39,
'TO_BOOL': 40,
'UNARY_INVERT': 41,
'UNARY_NEGATIVE': 42,
'UNARY_NOT': 43,
'WITH_EXCEPT_START': 44,
'BINARY_OP': 45,
'BUILD_CONST_KEY_MAP': 46,
'BUILD_LIST': 47,
'BUILD_MAP': 48,
'BUILD_SET': 49,
'BUILD_SLICE': 50,
'BUILD_STRING': 51,
'BUILD_TUPLE': 52,
'CALL': 53,
'CALL_FUNCTION_EX': 54,
'CALL_INTRINSIC_1': 55,
'CALL_INTRINSIC_2': 56,
'CALL_KW': 57,
'COMPARE_OP': 58,
'CONTAINS_OP': 59,
'CONVERT_VALUE': 60,
'COPY': 61,
'COPY_FREE_VARS': 62,
'DELETE_ATTR': 63,
'DELETE_DEREF': 64,
'DELETE_FAST': 65,
'DELETE_GLOBAL': 66,
'DELETE_NAME': 67,
'DICT_MERGE': 68,
'DICT_UPDATE': 69,
'ENTER_EXECUTOR': 70,
'EXTENDED_ARG': 71,
'FOR_ITER': 72,
'GET_AWAITABLE': 73,
'IMPORT_FROM': 74,
'IMPORT_NAME': 75,
'IS_OP': 76,
'JUMP_BACKWARD': 77,
'JUMP_BACKWARD_NO_INTERRUPT': 78,
'JUMP_FORWARD': 79,
'LIST_APPEND': 80,
'LIST_EXTEND': 81,
'LOAD_ATTR': 82,
'LOAD_CONST': 83,
'LOAD_DEREF': 84,
'LOAD_FAST': 85,
'LOAD_FAST_AND_CLEAR': 86,
'LOAD_FAST_CHECK': 87,
'LOAD_FAST_LOAD_FAST': 88,
'LOAD_FROM_DICT_OR_DEREF': 89,
'LOAD_FROM_DICT_OR_GLOBALS': 90,
'LOAD_GLOBAL': 91,
'LOAD_NAME': 92,
'LOAD_SUPER_ATTR': 93,
'MAKE_CELL': 94,
'MAP_ADD': 95,
'MATCH_CLASS': 96,
'POP_JUMP_IF_FALSE': 97,
'POP_JUMP_IF_NONE': 98,
'POP_JUMP_IF_NOT_NONE': 99,
'POP_JUMP_IF_TRUE': 100,
'RAISE_VARARGS': 101,
'RERAISE': 102,
'RETURN_CONST': 103,
'SEND': 104,
'SET_ADD': 105,
'SET_FUNCTION_ATTRIBUTE': 106,
'SET_UPDATE': 107,
'STORE_ATTR': 108,
'STORE_DEREF': 109,
'STORE_FAST': 110,
'STORE_FAST_LOAD_FAST': 111,
'STORE_FAST_STORE_FAST': 112,
'STORE_GLOBAL': 113,
'STORE_NAME': 114,
'SWAP': 115,
'UNPACK_EX': 116,
'UNPACK_SEQUENCE': 117,
'YIELD_VALUE': 118,
'BREAK': 119,
'BUILD_LIST_FROM_TUPLES': 120,
'BUILD_MAP_FOR_CALL': 121,
'BUILD_SET_FROM_TUPLES': 122,
'BUILD_TUPLE_FROM_ITER': 123,
'BUILD_TUPLE_FROM_TUPLES': 124,
'BUILD_TEMPLATE': 125,
'BUILD_INTERPOLATION': 126,
'CONTINUE': 128,
'JUMP_IF_FALSE_OR_POP': 129,
'JUMP_IF_TRUE_OR_POP': 130,
'JUMP_IF_NOT_EXC_MATCH': 131,
'SET_EXC_INFO': 132,
'SUBSCRIPT': 133,
'RESUME': 149,
'BINARY_OP_ADD_FLOAT': 150,
'BINARY_OP_ADD_INT': 151,
'BINARY_OP_ADD_UNICODE': 152,
'BINARY_OP_MULTIPLY_FLOAT': 153,
'BINARY_OP_MULTIPLY_INT': 154,
'BINARY_OP_SUBTRACT_FLOAT': 155,
'BINARY_OP_SUBTRACT_INT': 156,
'BINARY_SUBSCR_DICT': 157,
'BINARY_SUBSCR_GETITEM': 158,
'BINARY_SUBSCR_LIST_INT': 159,
'BINARY_SUBSCR_STR_INT': 160,
'BINARY_SUBSCR_TUPLE_INT': 161,
'CALL_ALLOC_AND_ENTER_INIT': 162,
'CALL_BOUND_METHOD_EXACT_ARGS': 163,
'CALL_BOUND_METHOD_GENERAL': 164,
'CALL_BUILTIN_CLASS': 165,
'CALL_BUILTIN_FAST': 166,
'CALL_BUILTIN_FAST_WITH_KEYWORDS': 167,
'CALL_BUILTIN_O': 168,
'CALL_ISINSTANCE': 169,
'CALL_LEN': 170,
'CALL_LIST_APPEND': 171,
'CALL_METHOD_DESCRIPTOR_FAST': 172,
'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 173,
'CALL_METHOD_DESCRIPTOR_NOARGS': 174,
'CALL_METHOD_DESCRIPTOR_O': 175,
'CALL_NON_PY_GENERAL': 176,
'CALL_PY_EXACT_ARGS': 177,
'CALL_PY_GENERAL': 178,
'CALL_STR_1': 179,
'CALL_TUPLE_1': 180,
'CALL_TYPE_1': 181,
'COMPARE_OP_FLOAT': 182,
'COMPARE_OP_INT': 183,
'COMPARE_OP_STR': 184,
'CONTAINS_OP_DICT': 185,
'CONTAINS_OP_SET': 186,
'FOR_ITER_GEN': 187,
'FOR_ITER_LIST': 188,
'FOR_ITER_RANGE': 189,
'FOR_ITER_TUPLE': 190,
'LOAD_ATTR_CLASS': 191,
'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 192,
'LOAD_ATTR_INSTANCE_VALUE': 193,
'LOAD_ATTR_METHOD_LAZY_DICT': 194,
'LOAD_ATTR_METHOD_NO_DICT': 195,
'LOAD_ATTR_METHOD_WITH_VALUES': 196,
'LOAD_ATTR_MODULE': 197,
'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 198,
'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 199,
'LOAD_ATTR_PROPERTY': 200,
'LOAD_ATTR_SLOT': 201,
'LOAD_ATTR_WITH_HINT': 202,
'LOAD_GLOBAL_BUILTIN': 203,
'LOAD_GLOBAL_MODULE': 204,
'LOAD_SUPER_ATTR_ATTR': 205,
'LOAD_SUPER_ATTR_METHOD': 206,
'RESUME_CHECK': 207,
'SEND_GEN': 208,
'STORE_ATTR_INSTANCE_VALUE': 209,
'STORE_ATTR_SLOT': 210,
'STORE_ATTR_WITH_HINT': 211,
'STORE_SUBSCR_DICT': 212,
'STORE_SUBSCR_LIST_INT': 213,
'TO_BOOL_ALWAYS_TRUE': 214,
'TO_BOOL_BOOL': 215,
'TO_BOOL_INT': 216,
'TO_BOOL_LIST': 217,
'TO_BOOL_NONE': 218,
'TO_BOOL_STR': 219,
'UNPACK_SEQUENCE_LIST': 220,
'UNPACK_SEQUENCE_TUPLE': 221,
'UNPACK_SEQUENCE_TWO_TUPLE': 222,
'INSTRUMENTED_RESUME': 236,
'INSTRUMENTED_END_FOR': 237,
'INSTRUMENTED_END_SEND': 238,
'INSTRUMENTED_RETURN_VALUE': 239,
'INSTRUMENTED_RETURN_CONST': 240,
'INSTRUMENTED_YIELD_VALUE': 241,
'INSTRUMENTED_LOAD_SUPER_ATTR': 242,
'INSTRUMENTED_FOR_ITER': 243,
'INSTRUMENTED_CALL': 244,
'INSTRUMENTED_CALL_KW': 245,
'INSTRUMENTED_CALL_FUNCTION_EX': 246,
'INSTRUMENTED_INSTRUCTION': 247,
'INSTRUMENTED_JUMP_FORWARD': 248,
'INSTRUMENTED_JUMP_BACKWARD': 249,
'INSTRUMENTED_POP_JUMP_IF_TRUE': 250,
'INSTRUMENTED_POP_JUMP_IF_FALSE': 251,
'INSTRUMENTED_POP_JUMP_IF_NONE': 252,
'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 253,
'GET_LEN': 18,
'GET_YIELD_FROM_ITER': 19,
'INTERPRETER_EXIT': 20,
'LOAD_BUILD_CLASS': 21,
'LOAD_LOCALS': 22,
'MAKE_FUNCTION': 23,
'MATCH_KEYS': 24,
'MATCH_MAPPING': 25,
'MATCH_SEQUENCE': 26,
'NOP': 27,
'NOT_TAKEN': 28,
'POP_EXCEPT': 29,
'POP_ITER': 30,
'POP_TOP': 31,
'PUSH_EXC_INFO': 32,
'PUSH_NULL': 33,
'RETURN_GENERATOR': 34,
'RETURN_VALUE': 35,
'SETUP_ANNOTATIONS': 36,
'STORE_SLICE': 37,
'STORE_SUBSCR': 38,
'TO_BOOL': 39,
'UNARY_INVERT': 40,
'UNARY_NEGATIVE': 41,
'UNARY_NOT': 42,
'WITH_EXCEPT_START': 43,
'BINARY_OP': 44,
'BUILD_INTERPOLATION': 45,
'BUILD_LIST': 46,
'BUILD_MAP': 47,
'BUILD_SET': 48,
'BUILD_SLICE': 49,
'BUILD_STRING': 50,
'BUILD_TUPLE': 51,
'CALL': 52,
'CALL_INTRINSIC_1': 53,
'CALL_INTRINSIC_2': 54,
'CALL_KW': 55,
'COMPARE_OP': 56,
'CONTAINS_OP': 57,
'CONVERT_VALUE': 58,
'COPY': 59,
'COPY_FREE_VARS': 60,
'DELETE_ATTR': 61,
'DELETE_DEREF': 62,
'DELETE_FAST': 63,
'DELETE_GLOBAL': 64,
'DELETE_NAME': 65,
'DICT_MERGE': 66,
'DICT_UPDATE': 67,
'END_ASYNC_FOR': 68,
'EXTENDED_ARG': 69,
'FOR_ITER': 70,
'GET_AWAITABLE': 71,
'IMPORT_FROM': 72,
'IMPORT_NAME': 73,
'IS_OP': 74,
'JUMP_BACKWARD': 75,
'JUMP_BACKWARD_NO_INTERRUPT': 76,
'JUMP_FORWARD': 77,
'LIST_APPEND': 78,
'LIST_EXTEND': 79,
'LOAD_ATTR': 80,
'LOAD_COMMON_CONSTANT': 81,
'LOAD_CONST': 82,
'LOAD_DEREF': 83,
'LOAD_FAST': 84,
'LOAD_FAST_AND_CLEAR': 85,
'LOAD_FAST_BORROW': 86,
'LOAD_FAST_BORROW_LOAD_FAST_BORROW': 87,
'LOAD_FAST_CHECK': 88,
'LOAD_FAST_LOAD_FAST': 89,
'LOAD_FROM_DICT_OR_DEREF': 90,
'LOAD_FROM_DICT_OR_GLOBALS': 91,
'LOAD_GLOBAL': 92,
'LOAD_NAME': 93,
'LOAD_SMALL_INT': 94,
'LOAD_SPECIAL': 95,
'LOAD_SUPER_ATTR': 96,
'MAKE_CELL': 97,
'MAP_ADD': 98,
'MATCH_CLASS': 99,
'POP_JUMP_IF_FALSE': 100,
'POP_JUMP_IF_NONE': 101,
'POP_JUMP_IF_NOT_NONE': 102,
'POP_JUMP_IF_TRUE': 103,
'RAISE_VARARGS': 104,
'RERAISE': 105,
'SEND': 106,
'SET_ADD': 107,
'SET_FUNCTION_ATTRIBUTE': 108,
'SET_UPDATE': 109,
'STORE_ATTR': 110,
'STORE_DEREF': 111,
'STORE_FAST': 112,
'STORE_FAST_LOAD_FAST': 113,
'STORE_FAST_STORE_FAST': 114,
'STORE_GLOBAL': 115,
'STORE_NAME': 116,
'SWAP': 117,
'UNPACK_EX': 118,
'UNPACK_SEQUENCE': 119,
'YIELD_VALUE': 120,
'RESUME': 128,
'BINARY_OP_ADD_FLOAT': 129,
'BINARY_OP_ADD_INT': 130,
'BINARY_OP_ADD_UNICODE': 131,
'BINARY_OP_EXTEND': 132,
'BINARY_OP_MULTIPLY_FLOAT': 133,
'BINARY_OP_MULTIPLY_INT': 134,
'BINARY_SUBSCR_DICT': 135,
'BINARY_SUBSCR_GETITEM': 136,
'BINARY_SUBSCR_LIST_INT': 137,
'BINARY_SUBSCR_LIST_SLICE': 138,
'BINARY_SUBSCR_STR_INT': 139,
'BINARY_SUBSCR_TUPLE_INT': 140,
'BINARY_OP_SUBTRACT_FLOAT': 141,
'BINARY_OP_SUBTRACT_INT': 142,
'CALL_ALLOC_AND_ENTER_INIT': 143,
'CALL_BOUND_METHOD_EXACT_ARGS': 144,
'CALL_BOUND_METHOD_GENERAL': 145,
'CALL_BUILTIN_CLASS': 146,
'CALL_BUILTIN_FAST': 147,
'CALL_BUILTIN_FAST_WITH_KEYWORDS': 148,
'CALL_BUILTIN_O': 149,
'CALL_ISINSTANCE': 150,
'CALL_KW_BOUND_METHOD': 151,
'CALL_KW_NON_PY': 152,
'CALL_KW_PY': 153,
'CALL_LEN': 154,
'CALL_LIST_APPEND': 155,
'CALL_METHOD_DESCRIPTOR_FAST': 156,
'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 157,
'CALL_METHOD_DESCRIPTOR_NOARGS': 158,
'CALL_METHOD_DESCRIPTOR_O': 159,
'CALL_NON_PY_GENERAL': 160,
'CALL_PY_EXACT_ARGS': 161,
'CALL_PY_GENERAL': 162,
'CALL_STR_1': 163,
'CALL_TUPLE_1': 164,
'CALL_TYPE_1': 165,
'COMPARE_OP_FLOAT': 166,
'COMPARE_OP_INT': 167,
'COMPARE_OP_STR': 168,
'CONTAINS_OP_DICT': 169,
'CONTAINS_OP_SET': 170,
'FOR_ITER_GEN': 171,
'FOR_ITER_LIST': 172,
'FOR_ITER_RANGE': 173,
'FOR_ITER_TUPLE': 174,
'JUMP_BACKWARD_JIT': 175,
'JUMP_BACKWARD_NO_JIT': 176,
'LOAD_ATTR_CLASS': 177,
'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 178,
'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 179,
'LOAD_ATTR_INSTANCE_VALUE': 180,
'LOAD_ATTR_METHOD_LAZY_DICT': 181,
'LOAD_ATTR_METHOD_NO_DICT': 182,
'LOAD_ATTR_METHOD_WITH_VALUES': 183,
'LOAD_ATTR_MODULE': 184,
'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 185,
'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 186,
'LOAD_ATTR_PROPERTY': 187,
'LOAD_ATTR_SLOT': 188,
'LOAD_ATTR_WITH_HINT': 189,
'LOAD_CONST_IMMORTAL': 190,
'LOAD_CONST_MORTAL': 191,
'LOAD_GLOBAL_BUILTIN': 192,
'LOAD_GLOBAL_MODULE': 193,
'LOAD_SUPER_ATTR_ATTR': 194,
'LOAD_SUPER_ATTR_METHOD': 195,
'RESUME_CHECK': 196,
'SEND_GEN': 197,
'STORE_ATTR_INSTANCE_VALUE': 198,
'STORE_ATTR_SLOT': 199,
'STORE_ATTR_WITH_HINT': 200,
'STORE_SUBSCR_DICT': 201,
'STORE_SUBSCR_LIST_INT': 202,
'TO_BOOL_ALWAYS_TRUE': 203,
'TO_BOOL_BOOL': 204,
'TO_BOOL_INT': 205,
'TO_BOOL_LIST': 206,
'TO_BOOL_NONE': 207,
'TO_BOOL_STR': 208,
'UNPACK_SEQUENCE_LIST': 209,
'UNPACK_SEQUENCE_TUPLE': 210,
'UNPACK_SEQUENCE_TWO_TUPLE': 211,
'BEFORE_ASYNC_WITH': 212,
'BEFORE_WITH': 213,
'BINARY_SUBSCR': 214,
'BUILD_CONST_KEY_MAP': 215,
'BREAK': 216,
'CONTINUE': 217,
'JUMP_IF_FALSE_OR_POP': 218,
'JUMP_IF_TRUE_OR_POP': 219,
'JUMP_IF_NOT_EXC_MATCH': 220,
'LOAD_ASSERTION_ERROR': 221,
'RETURN_CONST': 222,
'SET_EXC_INFO': 223,
'SUBSCRIPT': 224,
'INSTRUMENTED_END_FOR': 234,
'INSTRUMENTED_POP_ITER': 235,
'INSTRUMENTED_END_SEND': 236,
'INSTRUMENTED_FOR_ITER': 237,
'INSTRUMENTED_INSTRUCTION': 238,
'INSTRUMENTED_JUMP_FORWARD': 239,
'INSTRUMENTED_NOT_TAKEN': 240,
'INSTRUMENTED_POP_JUMP_IF_TRUE': 241,
'INSTRUMENTED_POP_JUMP_IF_FALSE': 242,
'INSTRUMENTED_POP_JUMP_IF_NONE': 243,
'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 244,
'INSTRUMENTED_RESUME': 245,
'INSTRUMENTED_RETURN_VALUE': 246,
'INSTRUMENTED_YIELD_VALUE': 247,
'INSTRUMENTED_END_ASYNC_FOR': 248,
'INSTRUMENTED_LOAD_SUPER_ATTR': 249,
'INSTRUMENTED_CALL': 250,
'INSTRUMENTED_CALL_KW': 251,
'INSTRUMENTED_CALL_FUNCTION_EX': 252,
'INSTRUMENTED_JUMP_BACKWARD': 253,
'INSTRUMENTED_LINE': 254,
'ENTER_EXECUTOR': 255,
'JUMP': 256,
'JUMP_NO_INTERRUPT': 257,
'RESERVED_258': 258,
+1 -1
View File
@@ -489,7 +489,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (2997).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (2996).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
+12 -5
View File
@@ -17,7 +17,7 @@ class OpListTests(unittest.TestCase):
self.assertEqual(func(op), expected)
def test_invalid_opcodes(self):
invalid = [-100, -1, 255, 512, 513, 1000]
invalid = [-100, -1, 512, 513, 1000]
self.check_bool_function_result(_opcode.is_valid, invalid, False)
self.check_bool_function_result(_opcode.has_arg, invalid, False)
self.check_bool_function_result(_opcode.has_const, invalid, False)
@@ -38,6 +38,14 @@ class OpListTests(unittest.TestCase):
opcodes = [dis.opmap[opname] for opname in names]
self.check_bool_function_result(_opcode.is_valid, opcodes, True)
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_opmaps(self):
def check_roundtrip(name, map):
return self.assertEqual(opcode.opname[map[name]], name)
check_roundtrip('BINARY_OP', opcode.opmap)
check_roundtrip('BINARY_OP_ADD_INT', opcode._specialized_opmap)
def test_oplists(self):
def check_function(self, func, expected):
for op in [-10, 520]:
@@ -58,8 +66,7 @@ class OpListTests(unittest.TestCase):
class StackEffectTests(unittest.TestCase):
def test_stack_effect(self):
self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 1), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 2), -1)
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 3), -2)
self.assertRaises(ValueError, stack_effect, 30000)
# All defined opcodes
@@ -110,7 +117,7 @@ class StackEffectTests(unittest.TestCase):
class SpecializationStatsTests(unittest.TestCase):
@unittest.expectedFailure # TODO: RUSTPYTHON - no specialization stats
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_specialization_stats(self):
stat_names = ["success", "failure", "hit", "deferred", "miss", "deopt"]
specialized_opcodes = [
@@ -119,7 +126,7 @@ class SpecializationStatsTests(unittest.TestCase):
if opcode._inline_cache_entries.get(op, 0)
]
self.assertIn('load_attr', specialized_opcodes)
self.assertIn('binary_subscr', specialized_opcodes)
self.assertIn('binary_op', specialized_opcodes)
stats = _opcode.get_specialization_stats()
if stats is not None:
+1 -1
View File
@@ -636,7 +636,7 @@ class MagicNumberTests(unittest.TestCase):
# stakeholders such as OS package maintainers must be notified
# in advance. Such exceptional releases will then require an
# adjustment to this test case.
EXPECTED_MAGIC_NUMBER = 2997
EXPECTED_MAGIC_NUMBER = 2996
actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little')
msg = (
+405 -391
View File
@@ -14,257 +14,62 @@ use crate::{
/// A Single bytecode instruction that are executed by the VM.
///
/// Currently aligned with CPython 3.13.
/// Currently aligned with CPython 3.14.
///
/// ## See also
/// - [CPython opcode IDs](https://github.com/python/cpython/blob/627894459a84be3488a1789919679c997056a03c/Include/opcode_ids.h)
/// - [CPython opcode IDs](https://github.com/python/cpython/blob/v3.14.2/Include/opcode_ids.h)
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub enum Instruction {
// ==================== No-argument instructions (opcode < 44) ====================
Cache = 0, // Placeholder
BeforeAsyncWith = 1,
BeforeWith = 2,
// No-argument instructions (opcode < HAVE_ARGUMENT=44)
Cache = 0, // Placeholder
BinarySlice = 1, // Placeholder
BuildTemplate = 2,
BinaryOpInplaceAddUnicode = 3, // Placeholder
BinarySlice = 4, // Placeholder
BinarySubscr = 5,
CheckEgMatch = 6,
CheckExcMatch = 7,
CleanupThrow = 8,
DeleteSubscr = 9,
EndAsyncFor = 10,
EndFor = 11, // Placeholder
EndSend = 12,
ExitInitCheck = 13, // Placeholder
FormatSimple = 14,
FormatWithSpec = 15,
GetAIter = 16,
CallFunctionEx = 4,
CheckEgMatch = 5,
CheckExcMatch = 6,
CleanupThrow = 7,
DeleteSubscr = 8,
EndFor = 9, // Placeholder
EndSend = 10,
ExitInitCheck = 11, // Placeholder
FormatSimple = 12,
FormatWithSpec = 13,
GetAIter = 14,
GetANext = 15,
GetIter = 16,
Reserved = 17,
GetANext = 18,
GetIter = 19,
GetLen = 20,
GetYieldFromIter = 21,
InterpreterExit = 22, // Placeholder
LoadAssertionError = 23, // Placeholder
LoadBuildClass = 24,
LoadLocals = 25, // Placeholder
MakeFunction = 26,
MatchKeys = 27,
MatchMapping = 28,
MatchSequence = 29,
Nop = 30,
PopExcept = 31,
PopTop = 32,
PushExcInfo = 33,
PushNull = 34,
ReturnGenerator = 35, // Placeholder
ReturnValue = 36,
SetupAnnotations = 37,
StoreSlice = 38, // Placeholder
StoreSubscr = 39,
ToBool = 40,
UnaryInvert = 41,
UnaryNegative = 42,
UnaryNot = 43,
WithExceptStart = 44,
// ==================== With-argument instructions (opcode > 44) ====================
GetLen = 18,
GetYieldFromIter = 19,
InterpreterExit = 20, // Placeholder
LoadBuildClass = 21,
LoadLocals = 22, // Placeholder
MakeFunction = 23,
MatchKeys = 24,
MatchMapping = 25,
MatchSequence = 26,
Nop = 27,
NotTaken = 28, // Placeholder
PopExcept = 29,
PopIter = 30, // Placeholder
PopTop = 31,
PushExcInfo = 32,
PushNull = 33,
ReturnGenerator = 34, // Placeholder
ReturnValue = 35,
SetupAnnotations = 36,
StoreSlice = 37, // Placeholder
StoreSubscr = 38,
ToBool = 39,
UnaryInvert = 40,
UnaryNegative = 41,
UnaryNot = 42,
WithExceptStart = 43,
// CPython 3.14 opcodes with arguments (44-120)
BinaryOp {
op: Arg<BinaryOperator>,
} = 45,
BuildConstKeyMap {
size: Arg<u32>,
} = 46, // Placeholder
BuildList {
size: Arg<u32>,
} = 47,
BuildMap {
size: Arg<u32>,
} = 48,
BuildSet {
size: Arg<u32>,
} = 49,
BuildSlice {
argc: Arg<BuildSliceArgCount>,
} = 50,
BuildString {
size: Arg<u32>,
} = 51,
BuildTuple {
size: Arg<u32>,
} = 52,
Call {
nargs: Arg<u32>,
} = 53,
CallFunctionEx = 54,
CallIntrinsic1 {
func: Arg<IntrinsicFunction1>,
} = 55,
CallIntrinsic2 {
func: Arg<IntrinsicFunction2>,
} = 56,
CallKw {
nargs: Arg<u32>,
} = 57,
CompareOp {
op: Arg<ComparisonOperator>,
} = 58,
ContainsOp(Arg<Invert>) = 59,
ConvertValue {
oparg: Arg<ConvertValueOparg>,
} = 60,
Copy {
index: Arg<u32>,
} = 61,
CopyFreeVars {
count: Arg<u32>,
} = 62, // Placeholder
DeleteAttr {
idx: Arg<NameIdx>,
} = 63,
DeleteDeref(Arg<NameIdx>) = 64,
DeleteFast(Arg<NameIdx>) = 65,
DeleteGlobal(Arg<NameIdx>) = 66,
DeleteName(Arg<NameIdx>) = 67,
DictMerge {
index: Arg<u32>,
} = 68, // Placeholder
DictUpdate {
index: Arg<u32>,
} = 69,
EnterExecutor = 70, // Placeholder
ExtendedArg = 71,
ForIter {
target: Arg<Label>,
} = 72,
GetAwaitable = 73, // TODO: Make this instruction to hold an oparg
ImportFrom {
idx: Arg<NameIdx>,
} = 74,
ImportName {
idx: Arg<NameIdx>,
} = 75,
IsOp(Arg<Invert>) = 76,
JumpBackward {
target: Arg<Label>,
} = 77,
JumpBackwardNoInterrupt {
target: Arg<Label>,
} = 78, // Placeholder
JumpForward {
target: Arg<Label>,
} = 79,
ListAppend {
i: Arg<u32>,
} = 80,
ListExtend {
i: Arg<u32>,
} = 81, // Placeholder
LoadAttr {
idx: Arg<NameIdx>,
} = 82,
LoadConst {
idx: Arg<u32>,
} = 83,
LoadDeref(Arg<NameIdx>) = 84,
LoadFast(Arg<NameIdx>) = 85,
LoadFastAndClear(Arg<NameIdx>) = 86,
LoadFastCheck(Arg<NameIdx>) = 87, // Placeholder
LoadFastLoadFast {
arg: Arg<u32>,
} = 88, // Placeholder
LoadFromDictOrDeref(Arg<NameIdx>) = 89,
LoadFromDictOrGlobals(Arg<NameIdx>) = 90, // Placeholder
LoadGlobal(Arg<NameIdx>) = 91,
LoadName(Arg<NameIdx>) = 92,
LoadSuperAttr {
arg: Arg<u32>,
} = 93,
MakeCell(Arg<NameIdx>) = 94, // Placeholder
MapAdd {
i: Arg<u32>,
} = 95,
MatchClass(Arg<u32>) = 96,
PopJumpIfFalse {
target: Arg<Label>,
} = 97,
PopJumpIfNone {
target: Arg<Label>,
} = 98, // Placeholder
PopJumpIfNotNone {
target: Arg<Label>,
} = 99, // Placeholder
PopJumpIfTrue {
target: Arg<Label>,
} = 100,
RaiseVarargs {
kind: Arg<RaiseKind>,
} = 101,
Reraise {
depth: Arg<u32>,
} = 102,
ReturnConst {
idx: Arg<u32>,
} = 103,
Send {
target: Arg<Label>,
} = 104,
SetAdd {
i: Arg<u32>,
} = 105,
SetFunctionAttribute {
attr: Arg<MakeFunctionFlags>,
} = 106,
SetUpdate {
i: Arg<u32>,
} = 107, // Placeholder
StoreAttr {
idx: Arg<NameIdx>,
} = 108,
StoreDeref(Arg<NameIdx>) = 109,
StoreFast(Arg<NameIdx>) = 110,
StoreFastLoadFast {
store_idx: Arg<NameIdx>,
load_idx: Arg<NameIdx>,
} = 111,
StoreFastStoreFast {
arg: Arg<u32>,
} = 112, // Placeholder
StoreGlobal(Arg<NameIdx>) = 113,
StoreName(Arg<NameIdx>) = 114,
Swap {
index: Arg<u32>,
} = 115,
UnpackEx {
args: Arg<UnpackExArgs>,
} = 116,
UnpackSequence {
size: Arg<u32>,
} = 117,
YieldValue {
arg: Arg<u32>,
} = 118,
// ==================== RustPython-only instructions (119-133) ====================
// Ideally, we want to be fully aligned with CPython opcodes, but we still have some leftovers.
// So we assign random IDs to these opcodes.
Break {
target: Arg<Label>,
} = 119,
BuildListFromTuples {
size: Arg<u32>,
} = 120,
BuildMapForCall {
size: Arg<u32>,
} = 121,
BuildSetFromTuples {
size: Arg<u32>,
} = 122,
BuildTupleFromIter = 123,
BuildTupleFromTuples {
size: Arg<u32>,
} = 124,
/// Build a Template from strings tuple and interpolations tuple on stack.
/// Stack: [strings_tuple, interpolations_tuple] -> [template]
BuildTemplate = 125,
} = 44,
/// Build an Interpolation from value, expression string, and optional format_spec on stack.
///
/// oparg encoding: (conversion << 2) | has_format_spec
@@ -274,115 +79,323 @@ pub enum Instruction {
/// Stack: [value, expression_str, format_spec?] -> [interpolation]
BuildInterpolation {
oparg: Arg<u32>,
} = 126,
} = 45,
BuildList {
size: Arg<u32>,
} = 46,
BuildMap {
size: Arg<u32>,
} = 47,
BuildSet {
size: Arg<u32>,
} = 48,
BuildSlice {
argc: Arg<BuildSliceArgCount>,
} = 49,
BuildString {
size: Arg<u32>,
} = 50,
BuildTuple {
size: Arg<u32>,
} = 51,
Call {
nargs: Arg<u32>,
} = 52,
CallIntrinsic1 {
func: Arg<IntrinsicFunction1>,
} = 53,
CallIntrinsic2 {
func: Arg<IntrinsicFunction2>,
} = 54,
CallKw {
nargs: Arg<u32>,
} = 55,
CompareOp {
op: Arg<ComparisonOperator>,
} = 56,
ContainsOp(Arg<Invert>) = 57,
ConvertValue {
oparg: Arg<ConvertValueOparg>,
} = 58,
Copy {
index: Arg<u32>,
} = 59,
CopyFreeVars {
count: Arg<u32>,
} = 60, // Placeholder
DeleteAttr {
idx: Arg<NameIdx>,
} = 61,
DeleteDeref(Arg<NameIdx>) = 62,
DeleteFast(Arg<NameIdx>) = 63,
DeleteGlobal(Arg<NameIdx>) = 64,
DeleteName(Arg<NameIdx>) = 65,
DictMerge {
index: Arg<u32>,
} = 66,
DictUpdate {
index: Arg<u32>,
} = 67,
EndAsyncFor = 68,
ExtendedArg = 69,
ForIter {
target: Arg<Label>,
} = 70,
GetAwaitable = 71, // TODO: Make this instruction to hold an oparg
ImportFrom {
idx: Arg<NameIdx>,
} = 72,
ImportName {
idx: Arg<NameIdx>,
} = 73,
IsOp(Arg<Invert>) = 74,
JumpBackward {
target: Arg<Label>,
} = 75,
JumpBackwardNoInterrupt {
target: Arg<Label>,
} = 76, // Placeholder
JumpForward {
target: Arg<Label>,
} = 77,
ListAppend {
i: Arg<u32>,
} = 78,
ListExtend {
i: Arg<u32>,
} = 79,
LoadAttr {
idx: Arg<NameIdx>,
} = 80,
LoadCommonConstant {
idx: Arg<u32>,
} = 81, // Placeholder
LoadConst {
idx: Arg<u32>,
} = 82,
LoadDeref(Arg<NameIdx>) = 83,
LoadFast(Arg<NameIdx>) = 84,
LoadFastAndClear(Arg<NameIdx>) = 85,
LoadFastBorrow(Arg<NameIdx>) = 86, // Placeholder
LoadFastBorrowLoadFastBorrow {
arg: Arg<u32>,
} = 87, // Placeholder
LoadFastCheck(Arg<NameIdx>) = 88, // Placeholder
LoadFastLoadFast {
arg: Arg<u32>,
} = 89, // Placeholder
LoadFromDictOrDeref(Arg<NameIdx>) = 90,
LoadFromDictOrGlobals(Arg<NameIdx>) = 91, // Placeholder
LoadGlobal(Arg<NameIdx>) = 92,
LoadName(Arg<NameIdx>) = 93,
LoadSmallInt {
idx: Arg<u32>,
} = 94, // Placeholder
LoadSpecial {
arg: Arg<u32>,
} = 95, // Placeholder
LoadSuperAttr {
arg: Arg<u32>,
} = 96,
MakeCell(Arg<NameIdx>) = 97, // Placeholder
MapAdd {
i: Arg<u32>,
} = 98,
MatchClass(Arg<u32>) = 99,
PopJumpIfFalse {
target: Arg<Label>,
} = 100,
PopJumpIfNone {
target: Arg<Label>,
} = 101, // Placeholder
PopJumpIfNotNone {
target: Arg<Label>,
} = 102, // Placeholder
PopJumpIfTrue {
target: Arg<Label>,
} = 103,
RaiseVarargs {
kind: Arg<RaiseKind>,
} = 104,
Reraise {
depth: Arg<u32>,
} = 105,
Send {
target: Arg<Label>,
} = 106,
SetAdd {
i: Arg<u32>,
} = 107,
SetFunctionAttribute {
attr: Arg<MakeFunctionFlags>,
} = 108,
SetUpdate {
i: Arg<u32>,
} = 109,
StoreAttr {
idx: Arg<NameIdx>,
} = 110,
StoreDeref(Arg<NameIdx>) = 111,
StoreFast(Arg<NameIdx>) = 112,
StoreFastLoadFast {
store_idx: Arg<NameIdx>,
load_idx: Arg<NameIdx>,
} = 113,
StoreFastStoreFast {
arg: Arg<u32>,
} = 114, // Placeholder
StoreGlobal(Arg<NameIdx>) = 115,
StoreName(Arg<NameIdx>) = 116,
Swap {
index: Arg<u32>,
} = 117,
UnpackEx {
args: Arg<UnpackExArgs>,
} = 118,
UnpackSequence {
size: Arg<u32>,
} = 119,
YieldValue {
arg: Arg<u32>,
} = 120,
// RustPython-only instructions (212-225)
// These either don't exist in CPython 3.14 or are RustPython-specific.
BeforeAsyncWith = 212,
BeforeWith = 213,
BinarySubscr = 214,
BuildConstKeyMap {
size: Arg<u32>,
} = 215, // Placeholder
Break {
target: Arg<Label>,
} = 216,
Continue {
target: Arg<Label>,
} = 128,
} = 217,
JumpIfFalseOrPop {
target: Arg<Label>,
} = 129,
} = 218,
JumpIfTrueOrPop {
target: Arg<Label>,
} = 130,
JumpIfNotExcMatch(Arg<Label>) = 131,
SetExcInfo = 132,
Subscript = 133,
// End of custom instructions
} = 219,
JumpIfNotExcMatch(Arg<Label>) = 220,
LoadAssertionError = 221, // Placeholder
ReturnConst {
idx: Arg<u32>,
} = 222,
SetExcInfo = 223,
Subscript = 224,
// CPython 3.14 RESUME (128)
Resume {
arg: Arg<u32>,
} = 149,
BinaryOpAddFloat = 150, // Placeholder
BinaryOpAddInt = 151, // Placeholder
BinaryOpAddUnicode = 152, // Placeholder
BinaryOpMultiplyFloat = 153, // Placeholder
BinaryOpMultiplyInt = 154, // Placeholder
BinaryOpSubtractFloat = 155, // Placeholder
BinaryOpSubtractInt = 156, // Placeholder
BinarySubscrDict = 157, // Placeholder
BinarySubscrGetitem = 158, // Placeholder
BinarySubscrListInt = 159, // Placeholder
BinarySubscrStrInt = 160, // Placeholder
BinarySubscrTupleInt = 161, // Placeholder
CallAllocAndEnterInit = 162, // Placeholder
CallBoundMethodExactArgs = 163, // Placeholder
CallBoundMethodGeneral = 164, // Placeholder
CallBuiltinClass = 165, // Placeholder
CallBuiltinFast = 166, // Placeholder
CallBuiltinFastWithKeywords = 167, // Placeholder
CallBuiltinO = 168, // Placeholder
CallIsinstance = 169, // Placeholder
CallLen = 170, // Placeholder
CallListAppend = 171, // Placeholder
CallMethodDescriptorFast = 172, // Placeholder
CallMethodDescriptorFastWithKeywords = 173, // Placeholder
CallMethodDescriptorNoargs = 174, // Placeholder
CallMethodDescriptorO = 175, // Placeholder
CallNonPyGeneral = 176, // Placeholder
CallPyExactArgs = 177, // Placeholder
CallPyGeneral = 178, // Placeholder
CallStr1 = 179, // Placeholder
CallTuple1 = 180, // Placeholder
CallType1 = 181, // Placeholder
CompareOpFloat = 182, // Placeholder
CompareOpInt = 183, // Placeholder
CompareOpStr = 184, // Placeholder
ContainsOpDict = 185, // Placeholder
ContainsOpSet = 186, // Placeholder
ForIterGen = 187, // Placeholder
ForIterList = 188, // Placeholder
ForIterRange = 189, // Placeholder
ForIterTuple = 190, // Placeholder
LoadAttrClass = 191, // Placeholder
LoadAttrGetattributeOverridden = 192, // Placeholder
LoadAttrInstanceValue = 193, // Placeholder
LoadAttrMethodLazyDict = 194, // Placeholder
LoadAttrMethodNoDict = 195, // Placeholder
LoadAttrMethodWithValues = 196, // Placeholder
LoadAttrModule = 197, // Placeholder
LoadAttrNondescriptorNoDict = 198, // Placeholder
LoadAttrNondescriptorWithValues = 199, // Placeholder
LoadAttrProperty = 200, // Placeholder
LoadAttrSlot = 201, // Placeholder
LoadAttrWithHint = 202, // Placeholder
LoadGlobalBuiltin = 203, // Placeholder
LoadGlobalModule = 204, // Placeholder
LoadSuperAttrAttr = 205, // Placeholder
LoadSuperAttrMethod = 206, // Placeholder
ResumeCheck = 207, // Placeholder
SendGen = 208, // Placeholder
StoreAttrInstanceValue = 209, // Placeholder
StoreAttrSlot = 210, // Placeholder
StoreAttrWithHint = 211, // Placeholder
StoreSubscrDict = 212, // Placeholder
StoreSubscrListInt = 213, // Placeholder
ToBoolAlwaysTrue = 214, // Placeholder
ToBoolBool = 215, // Placeholder
ToBoolInt = 216, // Placeholder
ToBoolList = 217, // Placeholder
ToBoolNone = 218, // Placeholder
ToBoolStr = 219, // Placeholder
UnpackSequenceList = 220, // Placeholder
UnpackSequenceTuple = 221, // Placeholder
UnpackSequenceTwoTuple = 222, // Placeholder
InstrumentedResume = 236, // Placeholder
InstrumentedEndFor = 237, // Placeholder
InstrumentedEndSend = 238, // Placeholder
InstrumentedReturnValue = 239, // Placeholder
InstrumentedReturnConst = 240, // Placeholder
InstrumentedYieldValue = 241, // Placeholder
InstrumentedLoadSuperAttr = 242, // Placeholder
InstrumentedForIter = 243, // Placeholder
InstrumentedCall = 244, // Placeholder
InstrumentedCallKw = 245, // Placeholder
InstrumentedCallFunctionEx = 246, // Placeholder
InstrumentedInstruction = 247, // Placeholder
InstrumentedJumpForward = 248, // Placeholder
InstrumentedJumpBackward = 249, // Placeholder
InstrumentedPopJumpIfTrue = 250, // Placeholder
InstrumentedPopJumpIfFalse = 251, // Placeholder
InstrumentedPopJumpIfNone = 252, // Placeholder
InstrumentedPopJumpIfNotNone = 253, // Placeholder
InstrumentedLine = 254, // Placeholder
} = 128,
// CPython 3.14 specialized opcodes (129-211)
BinaryOpAddFloat = 129, // Placeholder
BinaryOpAddInt = 130, // Placeholder
BinaryOpAddUnicode = 131, // Placeholder
BinaryOpExtend = 132, // Placeholder
BinaryOpMultiplyFloat = 133, // Placeholder
BinaryOpMultiplyInt = 134, // Placeholder
BinarySubscrDict = 135, // Placeholder
BinarySubscrGetitem = 136, // Placeholder
BinarySubscrListInt = 137, // Placeholder
BinarySubscrListSlice = 138, // Placeholder
BinarySubscrStrInt = 139, // Placeholder
BinarySubscrTupleInt = 140, // Placeholder
BinaryOpSubtractFloat = 141, // Placeholder
BinaryOpSubtractInt = 142, // Placeholder
CallAllocAndEnterInit = 143, // Placeholder
CallBoundMethodExactArgs = 144, // Placeholder
CallBoundMethodGeneral = 145, // Placeholder
CallBuiltinClass = 146, // Placeholder
CallBuiltinFast = 147, // Placeholder
CallBuiltinFastWithKeywords = 148, // Placeholder
CallBuiltinO = 149, // Placeholder
CallIsinstance = 150, // Placeholder
CallKwBoundMethod = 151, // Placeholder
CallKwNonPy = 152, // Placeholder
CallKwPy = 153, // Placeholder
CallLen = 154, // Placeholder
CallListAppend = 155, // Placeholder
CallMethodDescriptorFast = 156, // Placeholder
CallMethodDescriptorFastWithKeywords = 157, // Placeholder
CallMethodDescriptorNoargs = 158, // Placeholder
CallMethodDescriptorO = 159, // Placeholder
CallNonPyGeneral = 160, // Placeholder
CallPyExactArgs = 161, // Placeholder
CallPyGeneral = 162, // Placeholder
CallStr1 = 163, // Placeholder
CallTuple1 = 164, // Placeholder
CallType1 = 165, // Placeholder
CompareOpFloat = 166, // Placeholder
CompareOpInt = 167, // Placeholder
CompareOpStr = 168, // Placeholder
ContainsOpDict = 169, // Placeholder
ContainsOpSet = 170, // Placeholder
ForIterGen = 171, // Placeholder
ForIterList = 172, // Placeholder
ForIterRange = 173, // Placeholder
ForIterTuple = 174, // Placeholder
JumpBackwardJit = 175, // Placeholder
JumpBackwardNoJit = 176, // Placeholder
LoadAttrClass = 177, // Placeholder
LoadAttrClassWithMetaclassCheck = 178, // Placeholder
LoadAttrGetattributeOverridden = 179, // Placeholder
LoadAttrInstanceValue = 180, // Placeholder
LoadAttrMethodLazyDict = 181, // Placeholder
LoadAttrMethodNoDict = 182, // Placeholder
LoadAttrMethodWithValues = 183, // Placeholder
LoadAttrModule = 184, // Placeholder
LoadAttrNondescriptorNoDict = 185, // Placeholder
LoadAttrNondescriptorWithValues = 186, // Placeholder
LoadAttrProperty = 187, // Placeholder
LoadAttrSlot = 188, // Placeholder
LoadAttrWithHint = 189, // Placeholder
LoadConstImmortal = 190, // Placeholder
LoadConstMortal = 191, // Placeholder
LoadGlobalBuiltin = 192, // Placeholder
LoadGlobalModule = 193, // Placeholder
LoadSuperAttrAttr = 194, // Placeholder
LoadSuperAttrMethod = 195, // Placeholder
ResumeCheck = 196, // Placeholder
SendGen = 197, // Placeholder
StoreAttrInstanceValue = 198, // Placeholder
StoreAttrSlot = 199, // Placeholder
StoreAttrWithHint = 200, // Placeholder
StoreSubscrDict = 201, // Placeholder
StoreSubscrListInt = 202, // Placeholder
ToBoolAlwaysTrue = 203, // Placeholder
ToBoolBool = 204, // Placeholder
ToBoolInt = 205, // Placeholder
ToBoolList = 206, // Placeholder
ToBoolNone = 207, // Placeholder
ToBoolStr = 208, // Placeholder
UnpackSequenceList = 209, // Placeholder
UnpackSequenceTuple = 210, // Placeholder
UnpackSequenceTwoTuple = 211, // Placeholder
// CPython 3.14 instrumented opcodes (234-254)
InstrumentedEndFor = 234, // Placeholder
InstrumentedPopIter = 235, // Placeholder
InstrumentedEndSend = 236, // Placeholder
InstrumentedForIter = 237, // Placeholder
InstrumentedInstruction = 238, // Placeholder
InstrumentedJumpForward = 239, // Placeholder
InstrumentedNotTaken = 240, // Placeholder
InstrumentedPopJumpIfTrue = 241, // Placeholder
InstrumentedPopJumpIfFalse = 242, // Placeholder
InstrumentedPopJumpIfNone = 243, // Placeholder
InstrumentedPopJumpIfNotNone = 244, // Placeholder
InstrumentedResume = 245, // Placeholder
InstrumentedReturnValue = 246, // Placeholder
InstrumentedYieldValue = 247, // Placeholder
InstrumentedEndAsyncFor = 248, // Placeholder
InstrumentedLoadSuperAttr = 249, // Placeholder
InstrumentedCall = 250, // Placeholder
InstrumentedCallKw = 251, // Placeholder
InstrumentedCallFunctionEx = 252, // Placeholder
InstrumentedJumpBackward = 253, // Placeholder
InstrumentedLine = 254, // Placeholder
EnterExecutor = 255, // Placeholder
}
const _: () = assert!(mem::size_of::<Instruction>() == 1);
@@ -400,42 +413,31 @@ impl TryFrom<u8> for Instruction {
#[inline]
fn try_from(value: u8) -> Result<Self, MarshalError> {
// CPython-compatible opcodes (0-118)
// CPython-compatible opcodes (0-120)
let cpython_start = u8::from(Self::Cache);
let cpython_end = u8::from(Self::YieldValue { arg: Arg::marker() });
// Resume has a non-contiguous opcode (149)
// Resume has a non-contiguous opcode (128)
let resume_id = u8::from(Self::Resume { arg: Arg::marker() });
let enter_executor_id = u8::from(Self::EnterExecutor);
let specialized_start = u8::from(Self::BinaryOpAddFloat);
let specialized_end = u8::from(Self::UnpackSequenceTwoTuple);
let instrumented_start = u8::from(Self::InstrumentedResume);
let instrumented_start = u8::from(Self::InstrumentedEndFor);
let instrumented_end = u8::from(Self::InstrumentedLine);
// RustPython-only opcodes (explicit list to avoid gaps like 125-127)
// RustPython-only opcodes (explicit list to avoid gaps)
let custom_ops: &[u8] = &[
u8::from(Self::BeforeAsyncWith),
u8::from(Self::BeforeWith),
u8::from(Self::BinarySubscr),
u8::from(Self::BuildConstKeyMap {
size: Arg::marker(),
}),
u8::from(Self::Break {
target: Arg::marker(),
}),
u8::from(Self::BuildListFromTuples {
size: Arg::marker(),
}),
u8::from(Self::BuildMapForCall {
size: Arg::marker(),
}),
u8::from(Self::BuildSetFromTuples {
size: Arg::marker(),
}),
u8::from(Self::BuildTupleFromIter),
u8::from(Self::BuildTupleFromTuples {
size: Arg::marker(),
}),
u8::from(Self::BuildTemplate),
u8::from(Self::BuildInterpolation {
oparg: Arg::marker(),
}),
// 127 is unused
u8::from(Self::Continue {
target: Arg::marker(),
}),
@@ -446,12 +448,15 @@ impl TryFrom<u8> for Instruction {
target: Arg::marker(),
}),
u8::from(Self::JumpIfNotExcMatch(Arg::marker())),
u8::from(Self::LoadAssertionError),
u8::from(Self::ReturnConst { idx: Arg::marker() }),
u8::from(Self::SetExcInfo),
u8::from(Self::Subscript),
];
if (cpython_start..=cpython_end).contains(&value)
|| value == resume_id
|| value == enter_executor_id
|| custom_ops.contains(&value)
|| (specialized_start..=specialized_end).contains(&value)
|| (instrumented_start..=instrumented_end).contains(&value)
@@ -501,9 +506,11 @@ impl InstructionMetadata for Instruction {
fn stack_effect(&self, arg: OpArg, jump: bool) -> i32 {
match self {
Self::Nop => 0,
Self::NotTaken => 0,
Self::ImportName { .. } => -1,
Self::ImportFrom { .. } => 1,
Self::LoadFast(_) => 1,
Self::LoadFastBorrow(_) => 1,
Self::LoadFastAndClear(_) => 1,
Self::LoadName(_) => 1,
Self::LoadGlobal(_) => 1,
@@ -524,7 +531,10 @@ impl InstructionMetadata for Instruction {
Self::LoadAttr { .. } => 0,
Self::StoreAttr { .. } => -2,
Self::DeleteAttr { .. } => -1,
Self::LoadCommonConstant { .. } => 1,
Self::LoadConst { .. } => 1,
Self::LoadSmallInt { .. } => 1,
Self::LoadSpecial { .. } => 0,
Self::Reserved => 0,
Self::BinaryOp { .. } => -1,
Self::CompareOp { .. } => -1,
@@ -556,7 +566,7 @@ impl InstructionMetadata for Instruction {
}
}
Self::MakeFunction => {
// CPython 3.13 style: MakeFunction only pops code object
// CPython 3.14 style: MakeFunction only pops code object
-1 + 1 // pop code, push function
}
Self::SetFunctionAttribute { .. } => {
@@ -615,21 +625,14 @@ impl InstructionMetadata for Instruction {
}
Self::BuildString { size } => -(size.get(arg) as i32) + 1,
Self::BuildTuple { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildTupleFromTuples { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildList { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildListFromTuples { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildSet { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildSetFromTuples { size, .. } => -(size.get(arg) as i32) + 1,
Self::BuildTupleFromIter => 0,
Self::BuildMap { size } => {
let nargs = size.get(arg) * 2;
-(nargs as i32) + 1
}
Self::BuildMapForCall { size } => {
let nargs = size.get(arg);
-(nargs as i32) + 1
}
Self::DictUpdate { .. } => -1,
Self::DictMerge { .. } => -1,
Self::BuildSlice { argc } => {
// push 1
// pops either 2/3
@@ -641,7 +644,9 @@ impl InstructionMetadata for Instruction {
.get() as i32)
}
Self::ListAppend { .. } => -1,
Self::ListExtend { .. } => -1,
Self::SetAdd { .. } => -1,
Self::SetUpdate { .. } => -1,
Self::MapAdd { .. } => -2,
Self::LoadBuildClass => 1,
Self::UnpackSequence { size } => -1 + size.get(arg) as i32,
@@ -650,6 +655,7 @@ impl InstructionMetadata for Instruction {
-1 + before as i32 + 1 + after as i32
}
Self::PopExcept => 0,
Self::PopIter => -1,
Self::GetAwaitable => 0,
Self::BeforeAsyncWith => 1,
Self::GetAIter => 0,
@@ -682,18 +688,16 @@ impl InstructionMetadata for Instruction {
Self::LoadLocals => 0,
Self::ReturnGenerator => 0,
Self::StoreSlice => 0,
Self::DictMerge { .. } => -1,
Self::BuildConstKeyMap { .. } => 0,
Self::CopyFreeVars { .. } => 0,
Self::EnterExecutor => 0,
Self::JumpBackwardNoInterrupt { .. } => 0,
Self::JumpBackward { .. } => 0,
Self::JumpForward { .. } => 0,
Self::ListExtend { .. } => -1,
Self::LoadFastCheck(_) => 0,
Self::LoadFastLoadFast { .. } => 0,
Self::LoadFastLoadFast { .. } => 2,
Self::LoadFastBorrowLoadFastBorrow { .. } => 2,
Self::LoadFromDictOrGlobals(_) => 0,
Self::SetUpdate { .. } => -1,
Self::MakeCell(_) => 0,
Self::StoreFastStoreFast { .. } => 0,
Self::PopJumpIfNone { .. } => 0,
@@ -701,6 +705,7 @@ impl InstructionMetadata for Instruction {
Self::BinaryOpAddFloat => 0,
Self::BinaryOpAddInt => 0,
Self::BinaryOpAddUnicode => 0,
Self::BinaryOpExtend => 0,
Self::BinaryOpMultiplyFloat => 0,
Self::BinaryOpMultiplyInt => 0,
Self::BinaryOpSubtractFloat => 0,
@@ -708,6 +713,7 @@ impl InstructionMetadata for Instruction {
Self::BinarySubscrDict => 0,
Self::BinarySubscrGetitem => 0,
Self::BinarySubscrListInt => 0,
Self::BinarySubscrListSlice => 0,
Self::BinarySubscrStrInt => 0,
Self::BinarySubscrTupleInt => 0,
Self::CallAllocAndEnterInit => 0,
@@ -718,6 +724,9 @@ impl InstructionMetadata for Instruction {
Self::CallBuiltinFastWithKeywords => 0,
Self::CallBuiltinO => 0,
Self::CallIsinstance => 0,
Self::CallKwBoundMethod => 0,
Self::CallKwNonPy => 0,
Self::CallKwPy => 0,
Self::CallLen => 0,
Self::CallListAppend => 0,
Self::CallMethodDescriptorFast => 0,
@@ -739,7 +748,10 @@ impl InstructionMetadata for Instruction {
Self::ForIterList => 0,
Self::ForIterRange => 0,
Self::ForIterTuple => 0,
Self::JumpBackwardJit => 0,
Self::JumpBackwardNoJit => 0,
Self::LoadAttrClass => 0,
Self::LoadAttrClassWithMetaclassCheck => 0,
Self::LoadAttrGetattributeOverridden => 0,
Self::LoadAttrInstanceValue => 0,
Self::LoadAttrMethodLazyDict => 0,
@@ -751,6 +763,8 @@ impl InstructionMetadata for Instruction {
Self::LoadAttrProperty => 0,
Self::LoadAttrSlot => 0,
Self::LoadAttrWithHint => 0,
Self::LoadConstImmortal => 0,
Self::LoadConstMortal => 0,
Self::LoadGlobalBuiltin => 0,
Self::LoadGlobalModule => 0,
Self::LoadSuperAttrAttr => 0,
@@ -771,24 +785,26 @@ impl InstructionMetadata for Instruction {
Self::UnpackSequenceList => 0,
Self::UnpackSequenceTuple => 0,
Self::UnpackSequenceTwoTuple => 0,
Self::InstrumentedResume => 0,
Self::InstrumentedEndFor => 0,
Self::InstrumentedPopIter => -1,
Self::InstrumentedEndSend => 0,
Self::InstrumentedReturnValue => 0,
Self::InstrumentedReturnConst => 0,
Self::InstrumentedYieldValue => 0,
Self::InstrumentedLoadSuperAttr => 0,
Self::InstrumentedForIter => 0,
Self::InstrumentedCall => 0,
Self::InstrumentedCallKw => 0,
Self::InstrumentedCallFunctionEx => 0,
Self::InstrumentedInstruction => 0,
Self::InstrumentedJumpForward => 0,
Self::InstrumentedNotTaken => 0,
Self::InstrumentedJumpBackward => 0,
Self::InstrumentedPopJumpIfTrue => 0,
Self::InstrumentedPopJumpIfFalse => 0,
Self::InstrumentedPopJumpIfNone => 0,
Self::InstrumentedPopJumpIfNotNone => 0,
Self::InstrumentedResume => 0,
Self::InstrumentedReturnValue => 0,
Self::InstrumentedYieldValue => 0,
Self::InstrumentedEndAsyncFor => -2,
Self::InstrumentedLoadSuperAttr => 0,
Self::InstrumentedCall => 0,
Self::InstrumentedCallKw => 0,
Self::InstrumentedCallFunctionEx => 0,
Self::InstrumentedLine => 0,
// BuildTemplate: pops [strings_tuple, interpolations_tuple], pushes [template]
Self::BuildTemplate => -1,
@@ -860,16 +876,11 @@ impl InstructionMetadata for Instruction {
Self::BinarySubscr => w!(BINARY_SUBSCR),
Self::Break { target } => w!(BREAK, target),
Self::BuildList { size } => w!(BUILD_LIST, size),
Self::BuildListFromTuples { size } => w!(BUILD_LIST_FROM_TUPLES, size),
Self::BuildMap { size } => w!(BUILD_MAP, size),
Self::BuildMapForCall { size } => w!(BUILD_MAP_FOR_CALL, size),
Self::BuildSet { size } => w!(BUILD_SET, size),
Self::BuildSetFromTuples { size } => w!(BUILD_SET_FROM_TUPLES, size),
Self::BuildSlice { argc } => w!(BUILD_SLICE, ?argc),
Self::BuildString { size } => w!(BUILD_STRING, size),
Self::BuildTuple { size } => w!(BUILD_TUPLE, size),
Self::BuildTupleFromIter => w!(BUILD_TUPLE_FROM_ITER),
Self::BuildTupleFromTuples { size } => w!(BUILD_TUPLE_FROM_TUPLES, size),
Self::Call { nargs } => w!(CALL, nargs),
Self::CallFunctionEx => w!(CALL_FUNCTION_EX),
Self::CallKw { nargs } => w!(CALL_KW, nargs),
@@ -889,6 +900,7 @@ impl InstructionMetadata for Instruction {
Self::DeleteGlobal(idx) => w!(DELETE_GLOBAL, name = idx),
Self::DeleteName(idx) => w!(DELETE_NAME, name = idx),
Self::DeleteSubscr => w!(DELETE_SUBSCR),
Self::DictMerge { index } => w!(DICT_MERGE, index),
Self::DictUpdate { index } => w!(DICT_UPDATE, index),
Self::EndAsyncFor => w!(END_ASYNC_FOR),
Self::EndSend => w!(END_SEND),
@@ -912,6 +924,7 @@ impl InstructionMetadata for Instruction {
Self::JumpIfNotExcMatch(target) => w!(JUMP_IF_NOT_EXC_MATCH, target),
Self::JumpIfTrueOrPop { target } => w!(JUMP_IF_TRUE_OR_POP, target),
Self::ListAppend { i } => w!(LIST_APPEND, i),
Self::ListExtend { i } => w!(LIST_EXTEND, i),
Self::LoadAttr { idx } => {
let encoded = idx.get(arg);
let (name_idx, is_method) = decode_load_attr_arg(encoded);
@@ -967,6 +980,7 @@ impl InstructionMetadata for Instruction {
Self::SetExcInfo => w!(SET_EXC_INFO),
Self::SetFunctionAttribute { attr } => w!(SET_FUNCTION_ATTRIBUTE, ?attr),
Self::SetupAnnotations => w!(SETUP_ANNOTATIONS),
Self::SetUpdate { i } => w!(SET_UPDATE, i),
Self::StoreAttr { idx } => w!(STORE_ATTR, name = idx),
Self::StoreDeref(idx) => w!(STORE_DEREF, cell_name = idx),
Self::StoreFast(idx) => w!(STORE_FAST, varname = idx),
-76
View File
@@ -664,13 +664,6 @@ impl ExecutingFrame<'_> {
target: target.get(arg),
},
),
Instruction::BuildListFromTuples { size } => {
// SAFETY: compiler guarantees `size` tuples are on the stack
let elements = unsafe { self.flatten_tuples(size.get(arg) as usize) };
let list_obj = vm.ctx.new_list(elements);
self.push_value(list_obj.into());
Ok(None)
}
Instruction::BuildList { size } => {
let sz = size.get(arg) as usize;
let elements = self.pop_multiple(sz).collect();
@@ -678,22 +671,7 @@ impl ExecutingFrame<'_> {
self.push_value(list_obj.into());
Ok(None)
}
Instruction::BuildMapForCall { size } => {
self.execute_build_map_for_call(vm, size.get(arg))
}
Instruction::BuildMap { size } => self.execute_build_map(vm, size.get(arg)),
Instruction::BuildSetFromTuples { size } => {
let set = PySet::default().into_ref(&vm.ctx);
for element in self.pop_multiple(size.get(arg) as usize) {
// SAFETY: trust compiler
let tup = unsafe { element.downcast_unchecked::<PyTuple>() };
for item in tup.iter() {
set.add(item.clone(), vm)?;
}
}
self.push_value(set.into());
Ok(None)
}
Instruction::BuildSet { size } => {
let set = PySet::default().into_ref(&vm.ctx);
for element in self.pop_multiple(size.get(arg) as usize) {
@@ -721,21 +699,6 @@ impl ExecutingFrame<'_> {
self.push_value(vm.ctx.new_str(s).into());
Ok(None)
}
Instruction::BuildTupleFromIter => {
if !self.top_value().class().is(vm.ctx.types.tuple_type) {
let elements: Vec<_> = self.pop_value().try_to_value(vm)?;
let list_obj = vm.ctx.new_tuple(elements);
self.push_value(list_obj.into());
}
Ok(None)
}
Instruction::BuildTupleFromTuples { size } => {
// SAFETY: compiler guarantees `size` tuples are on the stack
let elements = unsafe { self.flatten_tuples(size.get(arg) as usize) };
let list_obj = vm.ctx.new_tuple(elements);
self.push_value(list_obj.into());
Ok(None)
}
Instruction::BuildTuple { size } => {
let elements = self.pop_multiple(size.get(arg) as usize).collect();
let list_obj = vm.ctx.new_tuple(elements);
@@ -1938,16 +1901,6 @@ impl ExecutingFrame<'_> {
})
}
unsafe fn flatten_tuples(&mut self, size: usize) -> Vec<PyObjectRef> {
let mut elements = Vec::new();
for tup in self.pop_multiple(size) {
// SAFETY: caller ensures that the elements are tuples
let tup = unsafe { tup.downcast_unchecked::<PyTuple>() };
elements.extend(tup.iter().cloned());
}
elements
}
#[cfg_attr(feature = "flame-it", flame("Frame"))]
fn import(&mut self, vm: &VirtualMachine, module_name: Option<&Py<PyStr>>) -> PyResult<()> {
let module_name = module_name.unwrap_or(vm.ctx.empty_str);
@@ -2155,35 +2108,6 @@ impl ExecutingFrame<'_> {
Ok(None)
}
fn execute_build_map_for_call(&mut self, vm: &VirtualMachine, size: u32) -> FrameResult {
let size = size as usize;
let map_obj = vm.ctx.new_dict();
for obj in self.pop_multiple(size) {
// Use keys() method for all mapping objects to preserve order
Self::iterate_mapping_keys(vm, &obj, "keyword argument", |key| {
// Check for keyword argument restrictions
if key.downcast_ref::<PyStr>().is_none() {
return Err(vm.new_type_error("keywords must be strings"));
}
if map_obj.contains_key(&*key, vm) {
let key_repr = &key.repr(vm)?;
let msg = format!(
"got multiple values for keyword argument {}",
key_repr.as_str()
);
return Err(vm.new_type_error(msg));
}
let value = obj.get_item(&*key, vm)?;
map_obj.set_item(&*key, value, vm)?;
Ok(())
})?;
}
self.push_value(map_obj.into());
Ok(None)
}
fn execute_build_slice(
&mut self,
vm: &VirtualMachine,
+1 -1
View File
@@ -129,7 +129,7 @@ pub fn get_git_datetime() -> String {
}
// Must be aligned to Lib/importlib/_bootstrap_external.py
pub const PYC_MAGIC_NUMBER: u16 = 2997;
pub const PYC_MAGIC_NUMBER: u16 = 2996;
// CPython format: magic_number | ('\r' << 16) | ('\n' << 24)
// This protects against text-mode file reads