Skip to content

Commit 5b7db1d

Browse files
authored
Newtype LoadSuperAttr oparg (RustPython#7002)
1 parent d7c259c commit 5b7db1d

5 files changed

Lines changed: 134 additions & 38 deletions

File tree

crates/codegen/src/compile.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use rustpython_compiler_core::{
3030
bytecode::{
3131
self, AnyInstruction, Arg as OpArgMarker, BinaryOperator, BuildSliceArgCount, CodeObject,
3232
ComparisonOperator, ConstantData, ConvertValueOparg, Instruction, IntrinsicFunction1,
33-
Invert, OpArg, OpArgType, PseudoInstruction, SpecialMethod, UnpackExArgs,
34-
encode_load_attr_arg, encode_load_super_attr_arg,
33+
Invert, LoadSuperAttr, OpArg, OpArgType, PseudoInstruction, SpecialMethod, UnpackExArgs,
34+
encode_load_attr_arg,
3535
},
3636
};
3737
use rustpython_wtf8::Wtf8Buf;
@@ -7818,28 +7818,44 @@ impl Compiler {
78187818
/// Emit LOAD_SUPER_ATTR for 2-arg super().attr access.
78197819
/// Encodes: (name_idx << 2) | 0b10 (method=0, class=1)
78207820
fn emit_load_super_attr(&mut self, name_idx: u32) {
7821-
let encoded = encode_load_super_attr_arg(name_idx, false, true);
7821+
let encoded = LoadSuperAttr::builder()
7822+
.name_idx(name_idx)
7823+
.is_load_method(false)
7824+
.has_class(true)
7825+
.build();
78227826
self.emit_arg(encoded, |arg| Instruction::LoadSuperAttr { arg })
78237827
}
78247828

78257829
/// Emit LOAD_SUPER_ATTR for 2-arg super().method() call.
78267830
/// Encodes: (name_idx << 2) | 0b11 (method=1, class=1)
78277831
fn emit_load_super_method(&mut self, name_idx: u32) {
7828-
let encoded = encode_load_super_attr_arg(name_idx, true, true);
7832+
let encoded = LoadSuperAttr::builder()
7833+
.name_idx(name_idx)
7834+
.is_load_method(true)
7835+
.has_class(true)
7836+
.build();
78297837
self.emit_arg(encoded, |arg| Instruction::LoadSuperAttr { arg })
78307838
}
78317839

78327840
/// Emit LOAD_SUPER_ATTR for 0-arg super().attr access.
78337841
/// Encodes: (name_idx << 2) | 0b00 (method=0, class=0)
78347842
fn emit_load_zero_super_attr(&mut self, name_idx: u32) {
7835-
let encoded = encode_load_super_attr_arg(name_idx, false, false);
7843+
let encoded = LoadSuperAttr::builder()
7844+
.name_idx(name_idx)
7845+
.is_load_method(false)
7846+
.has_class(false)
7847+
.build();
78367848
self.emit_arg(encoded, |arg| Instruction::LoadSuperAttr { arg })
78377849
}
78387850

78397851
/// Emit LOAD_SUPER_ATTR for 0-arg super().method() call.
78407852
/// Encodes: (name_idx << 2) | 0b01 (method=1, class=0)
78417853
fn emit_load_zero_super_method(&mut self, name_idx: u32) {
7842-
let encoded = encode_load_super_attr_arg(name_idx, true, false);
7854+
let encoded = LoadSuperAttr::builder()
7855+
.name_idx(name_idx)
7856+
.is_load_method(true)
7857+
.has_class(false)
7858+
.build();
78437859
self.emit_arg(encoded, |arg| Instruction::LoadSuperAttr { arg })
78447860
}
78457861

crates/compiler-core/src/bytecode.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ use rustpython_wtf8::{Wtf8, Wtf8Buf};
1717
pub use crate::bytecode::{
1818
instruction::{
1919
AnyInstruction, Arg, Instruction, InstructionMetadata, PseudoInstruction, StackEffect,
20-
decode_load_attr_arg, decode_load_super_attr_arg, encode_load_attr_arg,
21-
encode_load_super_attr_arg,
20+
decode_load_attr_arg, encode_load_attr_arg,
2221
},
2322
oparg::{
2423
BinaryOperator, BuildSliceArgCount, CommonConstant, ComparisonOperator, ConvertValueOparg,
25-
IntrinsicFunction1, IntrinsicFunction2, Invert, Label, MakeFunctionFlags, NameIdx, OpArg,
26-
OpArgByte, OpArgState, OpArgType, RaiseKind, ResumeType, SpecialMethod, UnpackExArgs,
24+
IntrinsicFunction1, IntrinsicFunction2, Invert, Label, LoadSuperAttr, MakeFunctionFlags,
25+
NameIdx, OpArg, OpArgByte, OpArgState, OpArgType, RaiseKind, ResumeType, SpecialMethod,
26+
UnpackExArgs,
2727
},
2828
};
2929

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

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
oparg::{
77
BinaryOperator, BuildSliceArgCount, CommonConstant, ComparisonOperator,
88
ConvertValueOparg, IntrinsicFunction1, IntrinsicFunction2, Invert, Label,
9-
MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgType, RaiseKind, SpecialMethod,
10-
UnpackExArgs,
9+
LoadSuperAttr, MakeFunctionFlags, NameIdx, OpArg, OpArgByte, OpArgType, RaiseKind,
10+
SpecialMethod, UnpackExArgs,
1111
},
1212
},
1313
marshal::MarshalError,
@@ -198,7 +198,7 @@ pub enum Instruction {
198198
method: Arg<SpecialMethod>,
199199
} = 95,
200200
LoadSuperAttr {
201-
arg: Arg<u32>,
201+
arg: Arg<LoadSuperAttr>,
202202
} = 96,
203203
MakeCell(Arg<NameIdx>) = 97,
204204
MapAdd {
@@ -862,13 +862,15 @@ impl InstructionMetadata for Instruction {
862862
Self::LoadName(idx) => w!(LOAD_NAME, name = idx),
863863
Self::LoadSpecial { method } => w!(LOAD_SPECIAL, method),
864864
Self::LoadSuperAttr { arg: idx } => {
865-
let encoded = idx.get(arg);
866-
let (name_idx, load_method, has_class) = decode_load_super_attr_arg(encoded);
867-
let attr_name = name(name_idx);
865+
let oparg = idx.get(arg);
868866
write!(
869867
f,
870868
"{:pad$}({}, {}, method={}, class={})",
871-
"LOAD_SUPER_ATTR", encoded, attr_name, load_method, has_class
869+
"LOAD_SUPER_ATTR",
870+
u32::from(oparg),
871+
name(oparg.name_idx()),
872+
oparg.is_load_method(),
873+
oparg.has_class()
872874
)
873875
}
874876
Self::MakeFunction => w!(MAKE_FUNCTION),
@@ -1304,18 +1306,3 @@ pub const fn decode_load_attr_arg(oparg: u32) -> (u32, bool) {
13041306
let name_idx = oparg >> 1;
13051307
(name_idx, is_method)
13061308
}
1307-
1308-
/// Encode LOAD_SUPER_ATTR oparg: bit 0 = load_method, bit 1 = has_class, bits 2+ = name index.
1309-
#[inline]
1310-
pub const fn encode_load_super_attr_arg(name_idx: u32, load_method: bool, has_class: bool) -> u32 {
1311-
(name_idx << 2) | ((has_class as u32) << 1) | (load_method as u32)
1312-
}
1313-
1314-
/// Decode LOAD_SUPER_ATTR oparg: returns (name_idx, load_method, has_class).
1315-
#[inline]
1316-
pub const fn decode_load_super_attr_arg(oparg: u32) -> (u32, bool, bool) {
1317-
let load_method = (oparg & 1) == 1;
1318-
let has_class = (oparg & 2) == 2;
1319-
let name_idx = oparg >> 2;
1320-
(name_idx, load_method, has_class)
1321-
}

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,97 @@ impl fmt::Display for UnpackExArgs {
655655
write!(f, "before: {}, after: {}", self.before, self.after)
656656
}
657657
}
658+
659+
#[derive(Clone, Copy)]
660+
pub struct LoadSuperAttr(u32);
661+
662+
impl LoadSuperAttr {
663+
#[must_use]
664+
pub const fn new(value: u32) -> Self {
665+
Self(value)
666+
}
667+
668+
#[must_use]
669+
pub fn builder() -> LoadSuperAttrBuilder {
670+
LoadSuperAttrBuilder::default()
671+
}
672+
673+
#[must_use]
674+
pub const fn name_idx(self) -> u32 {
675+
self.0 >> 2
676+
}
677+
678+
#[must_use]
679+
pub const fn is_load_method(self) -> bool {
680+
(self.0 & 1) == 1
681+
}
682+
683+
#[must_use]
684+
pub const fn has_class(self) -> bool {
685+
(self.0 & 2) == 2
686+
}
687+
}
688+
689+
impl OpArgType for LoadSuperAttr {
690+
#[inline(always)]
691+
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
692+
Ok(x.into())
693+
}
694+
695+
#[inline(always)]
696+
fn to_op_arg(self) -> u32 {
697+
self.into()
698+
}
699+
}
700+
701+
impl From<u32> for LoadSuperAttr {
702+
fn from(value: u32) -> Self {
703+
Self::new(value)
704+
}
705+
}
706+
707+
impl From<LoadSuperAttr> for u32 {
708+
fn from(value: LoadSuperAttr) -> Self {
709+
value.0
710+
}
711+
}
712+
713+
#[derive(Clone, Copy, Default)]
714+
pub struct LoadSuperAttrBuilder {
715+
name_idx: u32,
716+
is_load_method: bool,
717+
has_class: bool,
718+
}
719+
720+
impl LoadSuperAttrBuilder {
721+
#[must_use]
722+
pub const fn build(self) -> LoadSuperAttr {
723+
let value =
724+
(self.name_idx << 2) | ((self.has_class as u32) << 1) | (self.is_load_method as u32);
725+
LoadSuperAttr::new(value)
726+
}
727+
728+
#[must_use]
729+
pub const fn name_idx(mut self, value: u32) -> Self {
730+
self.name_idx = value;
731+
self
732+
}
733+
734+
#[must_use]
735+
pub const fn is_load_method(mut self, value: bool) -> Self {
736+
self.is_load_method = value;
737+
self
738+
}
739+
740+
#[must_use]
741+
pub const fn has_class(mut self, value: bool) -> Self {
742+
self.has_class = value;
743+
self
744+
}
745+
}
746+
747+
impl From<LoadSuperAttrBuilder> for LoadSuperAttr {
748+
fn from(builder: LoadSuperAttrBuilder) -> Self {
749+
builder.build()
750+
}
751+
}

crates/vm/src/frame.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
function::{PyCell, PyCellRef, PyFunction},
1111
tuple::{PyTuple, PyTupleRef},
1212
},
13-
bytecode::{self, Instruction},
13+
bytecode::{self, Instruction, LoadSuperAttr},
1414
convert::{IntoObject, ToPyResult},
1515
coroutine::Coro,
1616
exceptions::ExceptionCtor,
@@ -2859,9 +2859,8 @@ impl ExecutingFrame<'_> {
28592859
Ok(None)
28602860
}
28612861

2862-
fn load_super_attr(&mut self, vm: &VirtualMachine, oparg: u32) -> FrameResult {
2863-
let (name_idx, load_method, has_class) = bytecode::decode_load_super_attr_arg(oparg);
2864-
let attr_name = self.code.names[name_idx as usize];
2862+
fn load_super_attr(&mut self, vm: &VirtualMachine, oparg: LoadSuperAttr) -> FrameResult {
2863+
let attr_name = self.code.names[oparg.name_idx() as usize];
28652864

28662865
// Stack layout (bottom to top): [super, class, self]
28672866
// Pop in LIFO order: self, class, super
@@ -2871,13 +2870,13 @@ impl ExecutingFrame<'_> {
28712870

28722871
// Create super object - pass args based on has_class flag
28732872
// When super is shadowed, has_class=false means call with 0 args
2874-
let super_obj = if has_class {
2873+
let super_obj = if oparg.has_class() {
28752874
global_super.call((class.clone(), self_obj.clone()), vm)?
28762875
} else {
28772876
global_super.call((), vm)?
28782877
};
28792878

2880-
if load_method {
2879+
if oparg.is_load_method() {
28812880
// Method load: push [method, self_or_null]
28822881
let method = PyMethod::get(super_obj, attr_name, vm)?;
28832882
match method {

0 commit comments

Comments
 (0)