Skip to content

Commit 2827eca

Browse files
authored
Simplify Intruction.deopt() (RustPython#7615)
* Simplify `Instruction.deopt()` * Adjust `scripts/generate_opcode_metadata.py`
1 parent aac2070 commit 2827eca

2 files changed

Lines changed: 55 additions & 101 deletions

File tree

crates/compiler-core/src/bytecode/instruction.rs

Lines changed: 22 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -614,23 +614,15 @@ impl Instruction {
614614
/// Map a specialized opcode back to its adaptive (base) variant.
615615
/// `_PyOpcode_Deopt`
616616
pub const fn deopt(self) -> Option<Self> {
617-
Some(match self {
618-
// RESUME specializations
619-
Self::ResumeCheck => Self::Resume {
620-
context: Arg::marker(),
621-
},
622-
// LOAD_CONST specializations
623-
Self::LoadConstMortal | Self::LoadConstImmortal => Self::LoadConst {
624-
consti: Arg::marker(),
625-
},
626-
// TO_BOOL specializations
617+
let opcode = match self {
618+
Self::ResumeCheck => Opcode::Resume,
619+
Self::LoadConstMortal | Self::LoadConstImmortal => Opcode::LoadConst,
627620
Self::ToBoolAlwaysTrue
628621
| Self::ToBoolBool
629622
| Self::ToBoolInt
630623
| Self::ToBoolList
631624
| Self::ToBoolNone
632-
| Self::ToBoolStr => Self::ToBool,
633-
// BINARY_OP specializations
625+
| Self::ToBoolStr => Opcode::ToBool,
634626
Self::BinaryOpMultiplyInt
635627
| Self::BinaryOpAddInt
636628
| Self::BinaryOpSubtractInt
@@ -645,34 +637,18 @@ impl Instruction {
645637
| Self::BinaryOpSubscrDict
646638
| Self::BinaryOpSubscrGetitem
647639
| Self::BinaryOpExtend
648-
| Self::BinaryOpInplaceAddUnicode => Self::BinaryOp { op: Arg::marker() },
649-
// STORE_SUBSCR specializations
650-
Self::StoreSubscrDict | Self::StoreSubscrListInt => Self::StoreSubscr,
651-
// SEND specializations
652-
Self::SendGen => Self::Send {
653-
delta: Arg::marker(),
654-
},
655-
// UNPACK_SEQUENCE specializations
640+
| Self::BinaryOpInplaceAddUnicode => Opcode::BinaryOp,
641+
Self::StoreSubscrDict | Self::StoreSubscrListInt => Opcode::StoreSubscr,
642+
Self::SendGen => Opcode::Send,
656643
Self::UnpackSequenceTwoTuple | Self::UnpackSequenceTuple | Self::UnpackSequenceList => {
657-
Self::UnpackSequence {
658-
count: Arg::marker(),
659-
}
644+
Opcode::UnpackSequence
660645
}
661-
// STORE_ATTR specializations
646+
662647
Self::StoreAttrInstanceValue | Self::StoreAttrSlot | Self::StoreAttrWithHint => {
663-
Self::StoreAttr {
664-
namei: Arg::marker(),
665-
}
648+
Opcode::StoreAttr
666649
}
667-
// LOAD_GLOBAL specializations
668-
Self::LoadGlobalModule | Self::LoadGlobalBuiltin => Self::LoadGlobal {
669-
namei: Arg::marker(),
670-
},
671-
// LOAD_SUPER_ATTR specializations
672-
Self::LoadSuperAttrAttr | Self::LoadSuperAttrMethod => Self::LoadSuperAttr {
673-
namei: Arg::marker(),
674-
},
675-
// LOAD_ATTR specializations
650+
Self::LoadGlobalModule | Self::LoadGlobalBuiltin => Opcode::LoadGlobal,
651+
Self::LoadSuperAttrAttr | Self::LoadSuperAttrMethod => Opcode::LoadSuperAttr,
676652
Self::LoadAttrInstanceValue
677653
| Self::LoadAttrModule
678654
| Self::LoadAttrWithHint
@@ -685,28 +661,13 @@ impl Instruction {
685661
| Self::LoadAttrMethodNoDict
686662
| Self::LoadAttrMethodLazyDict
687663
| Self::LoadAttrNondescriptorWithValues
688-
| Self::LoadAttrNondescriptorNoDict => Self::LoadAttr {
689-
namei: Arg::marker(),
690-
},
691-
// COMPARE_OP specializations
692-
Self::CompareOpFloat | Self::CompareOpInt | Self::CompareOpStr => Self::CompareOp {
693-
opname: Arg::marker(),
694-
},
695-
// CONTAINS_OP specializations
696-
Self::ContainsOpSet | Self::ContainsOpDict => Self::ContainsOp {
697-
invert: Arg::marker(),
698-
},
699-
// JUMP_BACKWARD specializations
700-
Self::JumpBackwardNoJit | Self::JumpBackwardJit => Self::JumpBackward {
701-
delta: Arg::marker(),
702-
},
703-
// FOR_ITER specializations
664+
| Self::LoadAttrNondescriptorNoDict => Opcode::LoadAttr,
665+
Self::CompareOpFloat | Self::CompareOpInt | Self::CompareOpStr => Opcode::CompareOp,
666+
Self::ContainsOpSet | Self::ContainsOpDict => Opcode::ContainsOp,
667+
Self::JumpBackwardNoJit | Self::JumpBackwardJit => Opcode::JumpBackward,
704668
Self::ForIterList | Self::ForIterTuple | Self::ForIterRange | Self::ForIterGen => {
705-
Self::ForIter {
706-
delta: Arg::marker(),
707-
}
669+
Opcode::ForIter
708670
}
709-
// CALL specializations
710671
Self::CallBoundMethodExactArgs
711672
| Self::CallPyExactArgs
712673
| Self::CallType1
@@ -726,15 +687,12 @@ impl Instruction {
726687
| Self::CallAllocAndEnterInit
727688
| Self::CallPyGeneral
728689
| Self::CallBoundMethodGeneral
729-
| Self::CallNonPyGeneral => Self::Call {
730-
argc: Arg::marker(),
731-
},
732-
// CALL_KW specializations
733-
Self::CallKwBoundMethod | Self::CallKwPy | Self::CallKwNonPy => Self::CallKw {
734-
argc: Arg::marker(),
735-
},
690+
| Self::CallNonPyGeneral => Opcode::Call,
691+
Self::CallKwBoundMethod | Self::CallKwPy | Self::CallKwNonPy => Opcode::CallKw,
736692
_ => return None,
737-
})
693+
};
694+
695+
Some(opcode.as_instruction())
738696
}
739697

740698
/// Map a specialized or instrumented opcode back to its adaptive (base) variant.

scripts/generate_opcode_metadata.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -85,48 +85,44 @@ def extract_enum_body(text: str, name: str) -> str:
8585
return text[start + 1 : i]
8686

8787

88-
def build_deopts(contents: str) -> dict[str, list[str]]:
89-
raw_body = re.search(
90-
r"fn deopt\(self\) -> Option<Self>(.*)", contents, re.DOTALL
91-
).group(1)
92-
body = "\n".join(
93-
itertools.takewhile(
94-
lambda l: not l.startswith("_ =>"), # Take until reaching fallback
95-
filter(
96-
lambda l: (
97-
not l.startswith(
98-
("//", "Some(match")
99-
) # Skip comments or start of match
100-
),
101-
map(str.strip, raw_body.splitlines()),
102-
),
103-
)
104-
).removeprefix("{")
88+
def build_deopts(text: str) -> dict[str, list[str]]:
89+
raw_body = re.search(r"fn deopt\(self\)(.*)", text, re.DOTALL).group(1)
90+
match_start = raw_body.find("match self")
91+
if match_start == -1:
92+
raise ValueError("Could not detect a match statement in deopt method")
10593

106-
depth = 0
107-
arms = []
108-
buf = []
109-
for char in body:
110-
if char == "{":
111-
depth += 1
112-
elif char == "}":
113-
depth -= 1
94+
brace_depth = 0
95+
block_start = None
96+
block_end = None
11497

115-
if depth == 0 and (char in ("}", ",")):
116-
arm = "".join(buf).strip()
117-
arms.append(arm)
118-
buf = []
119-
else:
120-
buf.append(char)
98+
for i, ch in enumerate(raw_body[match_start:], match_start):
99+
if ch == "{":
100+
brace_depth += 1
101+
if block_start is None:
102+
block_start = i + 1
103+
elif ch == "}":
104+
brace_depth -= 1
105+
if brace_depth == 0:
106+
block_end = i
107+
break
108+
109+
match_body = raw_body[block_start:block_end]
121110

122-
# last arm
123-
arms.append("".join(buf))
124-
arms = [arm for arm in arms if arm]
111+
arm_pattern = re.compile(
112+
r"((?:Self::\w+\s*\|\s*)*Self::\w+)\s*=>\s*(?:\{\s*)?Opcode::(\w+)", re.DOTALL
113+
)
114+
variants_pattern = re.compile(r"Self::(\w+)")
125115

126116
deopts = {}
127-
for arm in arms:
128-
*specialized, deopt = map(to_snake_case, re.findall(r"Self::(\w*)\b", arm))
129-
deopts[deopt] = specialized
117+
for hit in arm_pattern.finditer(match_body):
118+
raw_variants = hit.group(1)
119+
opcode = hit.group(2)
120+
121+
variants = variants_pattern.findall(raw_variants)
122+
123+
key = to_snake_case(opcode)
124+
value = [to_snake_case(variant) for variant in variants]
125+
deopts[key] = value
130126

131127
return deopts
132128

0 commit comments

Comments
 (0)