Bytecode instrumented placeholder (#6741)

* Add all other bytecodes

* Mark passing/failing tests
This commit is contained in:
Shahar Naveh
2026-01-16 16:08:06 +02:00
committed by GitHub
parent 4cb3b9d8f0
commit 380fa39eba
3 changed files with 296 additions and 11 deletions

View File

@@ -136,10 +136,102 @@ opmap = {
'JUMP_IF_FALSE_OR_POP': 129,
'JUMP_IF_TRUE_OR_POP': 130,
'JUMP_IF_NOT_EXC_MATCH': 131,
'SET_EXC_INFO': 134,
'SUBSCRIPT': 135,
'SET_EXC_INFO': 132,
'SUBSCRIPT': 133,
'RESUME': 149,
'LOAD_CLOSURE': 253,
'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,
'INSTRUMENTED_LINE': 254,
'LOAD_CLOSURE': 255,
'JUMP': 256,
'JUMP_NO_INTERRUPT': 257,
'RESERVED_258': 258,

View File

@@ -16,6 +16,7 @@ class OpListTests(unittest.TestCase):
self.assertIsInstance(func(op), bool)
self.assertEqual(func(op), expected)
@unittest.expectedFailure # TODO: RUSTPYTHON; Move LoadClosure to psudoes
def test_invalid_opcodes(self):
invalid = [-100, -1, 255, 512, 513, 1000]
self.check_bool_function_result(_opcode.is_valid, invalid, False)
@@ -27,7 +28,6 @@ class OpListTests(unittest.TestCase):
self.check_bool_function_result(_opcode.has_local, invalid, False)
self.check_bool_function_result(_opcode.has_exc, invalid, False)
@unittest.expectedFailure # TODO: RUSTPYTHON - no instrumented opcodes
def test_is_valid(self):
names = [
'CACHE',

View File

@@ -245,10 +245,7 @@ pub enum Instruction {
YieldValue {
arg: Arg<u32>,
} = 118,
Resume {
arg: Arg<u32>,
} = 149,
// ==================== RustPython-only instructions (119-135) ====================
// ==================== 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 {
@@ -277,10 +274,106 @@ pub enum Instruction {
target: Arg<Label>,
} = 130,
JumpIfNotExcMatch(Arg<Label>) = 131,
SetExcInfo = 134,
Subscript = 135,
SetExcInfo = 132,
Subscript = 133,
// End of custom instructions
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
// Pseudos (needs to be moved to `PseudoInstruction` enum.
LoadClosure(Arg<NameIdx>) = 253, // TODO: Move to pseudos
LoadClosure(Arg<NameIdx>) = 255, // TODO: Move to pseudos
}
const _: () = assert!(mem::size_of::<Instruction>() == 1);
@@ -305,6 +398,12 @@ impl TryFrom<u8> for Instruction {
// Resume has a non-contiguous opcode (149)
let resume_id = u8::from(Self::Resume { arg: Arg::marker() });
let specialized_start = u8::from(Self::BinaryOpAddFloat);
let specialized_end = u8::from(Self::UnpackSequenceTwoTuple);
let instrumented_start = u8::from(Self::InstrumentedResume);
let instrumented_end = u8::from(Self::InstrumentedLine);
// TODO: Remove this; This instruction needs to be pseudo
let load_closure = u8::from(Self::LoadClosure(Arg::marker()));
@@ -345,6 +444,8 @@ impl TryFrom<u8> for Instruction {
|| value == resume_id
|| value == load_closure
|| custom_ops.contains(&value)
|| (specialized_start..=specialized_end).contains(&value)
|| (instrumented_start..=instrumented_end).contains(&value)
{
Ok(unsafe { mem::transmute::<u8, Self>(value) })
} else {
@@ -589,6 +690,98 @@ impl InstructionMetadata for Instruction {
Self::PopJumpIfNone { .. } => 0,
Self::PopJumpIfNotNone { .. } => 0,
Self::LoadClosure(_) => 1,
Self::BinaryOpAddFloat => 0,
Self::BinaryOpAddInt => 0,
Self::BinaryOpAddUnicode => 0,
Self::BinaryOpMultiplyFloat => 0,
Self::BinaryOpMultiplyInt => 0,
Self::BinaryOpSubtractFloat => 0,
Self::BinaryOpSubtractInt => 0,
Self::BinarySubscrDict => 0,
Self::BinarySubscrGetitem => 0,
Self::BinarySubscrListInt => 0,
Self::BinarySubscrStrInt => 0,
Self::BinarySubscrTupleInt => 0,
Self::CallAllocAndEnterInit => 0,
Self::CallBoundMethodExactArgs => 0,
Self::CallBoundMethodGeneral => 0,
Self::CallBuiltinClass => 0,
Self::CallBuiltinFast => 0,
Self::CallBuiltinFastWithKeywords => 0,
Self::CallBuiltinO => 0,
Self::CallIsinstance => 0,
Self::CallLen => 0,
Self::CallListAppend => 0,
Self::CallMethodDescriptorFast => 0,
Self::CallMethodDescriptorFastWithKeywords => 0,
Self::CallMethodDescriptorNoargs => 0,
Self::CallMethodDescriptorO => 0,
Self::CallNonPyGeneral => 0,
Self::CallPyExactArgs => 0,
Self::CallPyGeneral => 0,
Self::CallStr1 => 0,
Self::CallTuple1 => 0,
Self::CallType1 => 0,
Self::CompareOpFloat => 0,
Self::CompareOpInt => 0,
Self::CompareOpStr => 0,
Self::ContainsOpDict => 0,
Self::ContainsOpSet => 0,
Self::ForIterGen => 0,
Self::ForIterList => 0,
Self::ForIterRange => 0,
Self::ForIterTuple => 0,
Self::LoadAttrClass => 0,
Self::LoadAttrGetattributeOverridden => 0,
Self::LoadAttrInstanceValue => 0,
Self::LoadAttrMethodLazyDict => 0,
Self::LoadAttrMethodNoDict => 0,
Self::LoadAttrMethodWithValues => 0,
Self::LoadAttrModule => 0,
Self::LoadAttrNondescriptorNoDict => 0,
Self::LoadAttrNondescriptorWithValues => 0,
Self::LoadAttrProperty => 0,
Self::LoadAttrSlot => 0,
Self::LoadAttrWithHint => 0,
Self::LoadGlobalBuiltin => 0,
Self::LoadGlobalModule => 0,
Self::LoadSuperAttrAttr => 0,
Self::LoadSuperAttrMethod => 0,
Self::ResumeCheck => 0,
Self::SendGen => 0,
Self::StoreAttrInstanceValue => 0,
Self::StoreAttrSlot => 0,
Self::StoreAttrWithHint => 0,
Self::StoreSubscrDict => 0,
Self::StoreSubscrListInt => 0,
Self::ToBoolAlwaysTrue => 0,
Self::ToBoolBool => 0,
Self::ToBoolInt => 0,
Self::ToBoolList => 0,
Self::ToBoolNone => 0,
Self::ToBoolStr => 0,
Self::UnpackSequenceList => 0,
Self::UnpackSequenceTuple => 0,
Self::UnpackSequenceTwoTuple => 0,
Self::InstrumentedResume => 0,
Self::InstrumentedEndFor => 0,
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::InstrumentedJumpBackward => 0,
Self::InstrumentedPopJumpIfTrue => 0,
Self::InstrumentedPopJumpIfFalse => 0,
Self::InstrumentedPopJumpIfNone => 0,
Self::InstrumentedPopJumpIfNotNone => 0,
Self::InstrumentedLine => 0,
}
}