Skip to content

Commit 92ef866

Browse files
committed
LoadClosure as pseudo op
1 parent 2b8fac3 commit 92ef866

File tree

5 files changed

+31
-22
lines changed

5 files changed

+31
-22
lines changed

crates/codegen/src/compile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4074,7 +4074,7 @@ impl Compiler {
40744074
}
40754075
};
40764076

4077-
emit!(self, Instruction::LoadClosure(idx.to_u32()));
4077+
emit!(self, PseudoInstruction::LoadClosure(idx.to_u32()));
40784078
}
40794079

40804080
// Build tuple of closure variables
@@ -4297,7 +4297,7 @@ impl Compiler {
42974297
.position(|var| *var == "__class__");
42984298

42994299
if let Some(classcell_idx) = classcell_idx {
4300-
emit!(self, Instruction::LoadClosure(classcell_idx.to_u32()));
4300+
emit!(self, PseudoInstruction::LoadClosure(classcell_idx.to_u32()));
43014301
emit!(self, Instruction::Copy { index: 1_u32 });
43024302
let classcell = self.name("__classcell__");
43034303
emit!(self, Instruction::StoreName(classcell));

crates/codegen/src/ir.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ impl CodeInfo {
263263
info.arg = OpArg(encoded);
264264
info.instr = Instruction::LoadSuperAttr { arg: Arg::marker() }.into();
265265
}
266+
// LOAD_CLOSURE pseudo → LOAD_FAST (with varnames offset)
267+
PseudoInstruction::LoadClosure(idx) => {
268+
let varnames_len = varname_cache.len() as u32;
269+
let new_idx = varnames_len + idx.get(info.arg);
270+
info.arg = OpArg(new_idx);
271+
info.instr = Instruction::LoadFast(Arg::marker()).into();
272+
}
266273
PseudoInstruction::Jump { .. } => {
267274
// PseudoInstruction::Jump instructions are handled later
268275
}

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,6 @@ pub enum Instruction {
385385
InstrumentedPopJumpIfNone = 252, // Placeholder
386386
InstrumentedPopJumpIfNotNone = 253, // Placeholder
387387
InstrumentedLine = 254, // Placeholder
388-
// Pseudos (needs to be moved to `PseudoInstruction` enum.
389-
LoadClosure(Arg<NameIdx>) = 255, // TODO: Move to pseudos
390388
}
391389

392390
const _: () = assert!(mem::size_of::<Instruction>() == 1);
@@ -417,9 +415,6 @@ impl TryFrom<u8> for Instruction {
417415
let instrumented_start = u8::from(Self::InstrumentedResume);
418416
let instrumented_end = u8::from(Self::InstrumentedLine);
419417

420-
// TODO: Remove this; This instruction needs to be pseudo
421-
let load_closure = u8::from(Self::LoadClosure(Arg::marker()));
422-
423418
// RustPython-only opcodes (explicit list to avoid gaps like 125-127)
424419
let custom_ops: &[u8] = &[
425420
u8::from(Self::Break {
@@ -459,7 +454,6 @@ impl TryFrom<u8> for Instruction {
459454

460455
if (cpython_start..=cpython_end).contains(&value)
461456
|| value == resume_id
462-
|| value == load_closure
463457
|| custom_ops.contains(&value)
464458
|| (specialized_start..=specialized_end).contains(&value)
465459
|| (instrumented_start..=instrumented_end).contains(&value)
@@ -706,7 +700,6 @@ impl InstructionMetadata for Instruction {
706700
Self::StoreFastStoreFast { .. } => 0,
707701
Self::PopJumpIfNone { .. } => 0,
708702
Self::PopJumpIfNotNone { .. } => 0,
709-
Self::LoadClosure(_) => 1,
710703
Self::BinaryOpAddFloat => 0,
711704
Self::BinaryOpAddInt => 0,
712705
Self::BinaryOpAddUnicode => 0,
@@ -937,7 +930,6 @@ impl InstructionMetadata for Instruction {
937930
}
938931
Self::LoadBuildClass => w!(LOAD_BUILD_CLASS),
939932
Self::LoadFromDictOrDeref(i) => w!(LOAD_FROM_DICT_OR_DEREF, cell_name = i),
940-
Self::LoadClosure(i) => w!(LOAD_CLOSURE, cell_name = i),
941933
Self::LoadConst { idx } => fmt_const("LOAD_CONST", arg, f, idx),
942934
Self::LoadDeref(idx) => w!(LOAD_DEREF, cell_name = idx),
943935
Self::LoadFast(idx) => w!(LOAD_FAST, varname = idx),
@@ -1039,6 +1031,7 @@ pub enum PseudoInstruction {
10391031
SetupFinally = 265, // Placeholder
10401032
SetupWith = 266, // Placeholder
10411033
StoreFastMaybeNull = 267, // Placeholder
1034+
LoadClosure(Arg<NameIdx>) = 268,
10421035
}
10431036

10441037
const _: () = assert!(mem::size_of::<PseudoInstruction>() == 2);
@@ -1059,7 +1052,7 @@ impl TryFrom<u16> for PseudoInstruction {
10591052
let start = u16::from(Self::Jump {
10601053
target: Arg::marker(),
10611054
});
1062-
let end = u16::from(Self::StoreFastMaybeNull);
1055+
let end = u16::from(Self::LoadClosure(Arg::marker()));
10631056

10641057
if (start..=end).contains(&value) {
10651058
Ok(unsafe { mem::transmute::<u16, Self>(value) })
@@ -1095,6 +1088,7 @@ impl InstructionMetadata for PseudoInstruction {
10951088
Self::SetupWith => 0,
10961089
Self::StoreFastMaybeNull => 0,
10971090
Self::Reserved258 => 0,
1091+
Self::LoadClosure(_) => 1,
10981092
}
10991093
}
11001094

crates/stdlib/src/opcode.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ mod opcode {
125125
Ok(AnyInstruction::Real(
126126
Instruction::DeleteDeref(_)
127127
| Instruction::LoadFromDictOrDeref(_)
128-
| Instruction::LoadClosure(_)
129128
| Instruction::LoadDeref(_)
130129
| Instruction::StoreDeref(_)
131130
))

crates/vm/src/frame.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,24 @@ impl Frame {
115115
func_obj: Option<PyObjectRef>,
116116
vm: &VirtualMachine,
117117
) -> Self {
118-
let cells_frees = core::iter::repeat_with(|| PyCell::default().into_ref(&vm.ctx))
119-
.take(code.cellvars.len())
120-
.chain(closure.iter().cloned())
121-
.collect();
118+
let nlocals = code.varnames.len();
119+
let ncells = code.cellvars.len();
120+
let nfrees = closure.len();
121+
122+
let cells_frees: Box<[PyCellRef]> =
123+
core::iter::repeat_with(|| PyCell::default().into_ref(&vm.ctx))
124+
.take(ncells)
125+
.chain(closure.iter().cloned())
126+
.collect();
127+
128+
// Extend fastlocals to include varnames + cellvars + freevars (localsplus)
129+
let total_locals = nlocals + ncells + nfrees;
130+
let mut fastlocals_vec: Vec<Option<PyObjectRef>> = vec![None; total_locals];
131+
132+
// Store cell objects at cellvars and freevars positions
133+
for (i, cell) in cells_frees.iter().enumerate() {
134+
fastlocals_vec[nlocals + i] = Some(cell.clone().into());
135+
}
122136

123137
let state = FrameState {
124138
stack: BoxVec::new(code.max_stackdepth as usize),
@@ -127,7 +141,7 @@ impl Frame {
127141
};
128142

129143
Self {
130-
fastlocals: PyMutex::new(vec![None; code.varnames.len()].into_boxed_slice()),
144+
fastlocals: PyMutex::new(fastlocals_vec.into_boxed_slice()),
131145
cells_frees,
132146
locals: scope.locals,
133147
globals: scope.globals,
@@ -1191,11 +1205,6 @@ impl ExecutingFrame<'_> {
11911205
});
11921206
Ok(None)
11931207
}
1194-
Instruction::LoadClosure(i) => {
1195-
let value = self.cells_frees[i.get(arg) as usize].clone();
1196-
self.push_value(value.into());
1197-
Ok(None)
1198-
}
11991208
Instruction::LoadConst { idx } => {
12001209
self.push_value(self.code.constants[idx.get(arg) as usize].clone().into());
12011210
Ok(None)

0 commit comments

Comments
 (0)