Skip to content

Commit f93b134

Browse files
committed
Split Rotate into Rotate2 & Rotate3
1 parent f04a305 commit f93b134

File tree

4 files changed

+26
-42
lines changed

4 files changed

+26
-42
lines changed

bytecode/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,8 @@ pub enum Instruction {
265265
op: ComparisonOperator,
266266
},
267267
Pop,
268-
Rotate {
269-
amount: u32,
270-
},
268+
Rotate2,
269+
Rotate3,
271270
Duplicate,
272271
Duplicate2,
273272
GetIter,
@@ -972,7 +971,7 @@ impl Instruction {
972971
UnaryOperation { .. } => 0,
973972
BinaryOperation { .. } | BinaryOperationInplace { .. } | CompareOperation { .. } => -1,
974973
Pop => -1,
975-
Rotate { .. } => 0,
974+
Rotate2 | Rotate3 => 0,
976975
Duplicate => 1,
977976
Duplicate2 => 2,
978977
GetIter => 0,
@@ -1157,7 +1156,8 @@ impl Instruction {
11571156
LoadAttr { idx } => w!(LoadAttr, name(*idx)),
11581157
CompareOperation { op } => w!(CompareOperation, format_args!("{:?}", op)),
11591158
Pop => w!(Pop),
1160-
Rotate { amount } => w!(Rotate, amount),
1159+
Rotate2 => w!(Rotate2),
1160+
Rotate3 => w!(Rotate3),
11611161
Duplicate => w!(Duplicate),
11621162
Duplicate2 => w!(Duplicate2),
11631163
GetIter => w!(GetIter),

compiler/src/compile.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ impl Compiler {
11221122

11231123
self.emit(Instruction::Duplicate);
11241124
self.load_docstring(doc_str);
1125-
self.emit(Instruction::Rotate { amount: 2 });
1125+
self.emit(Instruction::Rotate2);
11261126
let doc = self.name("__doc__");
11271127
self.emit(Instruction::StoreAttr { idx: doc });
11281128

@@ -1498,7 +1498,7 @@ impl Compiler {
14981498
self.compile_expression(val)?;
14991499
// store rhs for the next comparison in chain
15001500
self.emit(Instruction::Duplicate);
1501-
self.emit(Instruction::Rotate { amount: 3 });
1501+
self.emit(Instruction::Rotate3);
15021502

15031503
self.emit(Instruction::CompareOperation {
15041504
op: compile_cmpop(op),
@@ -1525,7 +1525,7 @@ impl Compiler {
15251525

15261526
// early exit left us with stack: `rhs, comparison_result`. We need to clean up rhs.
15271527
self.switch_to_block(break_block);
1528-
self.emit(Instruction::Rotate { amount: 2 });
1528+
self.emit(Instruction::Rotate2);
15291529
self.emit(Instruction::Pop);
15301530

15311531
self.switch_to_block(after_block);
@@ -1692,12 +1692,12 @@ impl Compiler {
16921692
}
16931693
AugAssignKind::Subscript => {
16941694
// stack: CONTAINER SLICE RESULT
1695-
self.emit(Instruction::Rotate { amount: 3 });
1695+
self.emit(Instruction::Rotate3);
16961696
self.emit(Instruction::StoreSubscript);
16971697
}
16981698
AugAssignKind::Attr { idx } => {
16991699
// stack: CONTAINER RESULT
1700-
self.emit(Instruction::Rotate { amount: 2 });
1700+
self.emit(Instruction::Rotate2);
17011701
self.emit(Instruction::StoreAttr { idx });
17021702
}
17031703
}

jit/tests/common.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,13 @@ impl StackMachine {
132132
let value = self.stack.last().unwrap().clone();
133133
self.stack.push(value);
134134
}
135-
Instruction::Rotate { amount } => {
136-
let mut values = Vec::new();
137-
138-
// Pop all values from stack:
139-
values.extend(self.stack.drain(self.stack.len() - amount as usize..));
140-
141-
// Push top of stack back first:
142-
self.stack.push(values.pop().unwrap());
143-
144-
// Push other value back in order:
145-
self.stack.extend(values);
135+
Instruction::Rotate2 => {
136+
let i = self.stack.len() - 2;
137+
self.stack[i..].rotate_right(1);
138+
}
139+
Instruction::Rotate3 => {
140+
let i = self.stack.len() - 3;
141+
self.stack[i..].rotate_right(1);
146142
}
147143
Instruction::ReturnValue => return true,
148144
_ => unimplemented!(

vm/src/frame.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,11 @@ impl ExecutingFrame<'_> {
623623
self.push_value(top);
624624
Ok(None)
625625
}
626-
bytecode::Instruction::Rotate { amount } => self.execute_rotate(*amount),
626+
// splitting the instructions like this offloads the cost of "dynamic" dispatch (on the
627+
// amount to rotate) to the opcode dispatcher, and generates optimized code for the
628+
// concrete cases we actually have
629+
bytecode::Instruction::Rotate2 => self.execute_rotate(2),
630+
bytecode::Instruction::Rotate3 => self.execute_rotate(3),
627631
bytecode::Instruction::BuildString { size } => {
628632
let s = self
629633
.pop_multiple(*size as usize)
@@ -1248,26 +1252,10 @@ impl ExecutingFrame<'_> {
12481252
}
12491253
}
12501254

1251-
fn execute_rotate(&mut self, amount: u32) -> FrameResult {
1252-
// Shuffles top of stack amount down
1253-
if amount < 2 {
1254-
self.fatal("Can only rotate two or more values");
1255-
}
1256-
1257-
let mut values = Vec::new();
1258-
1259-
// Pop all values from stack:
1260-
for _ in 0..amount {
1261-
values.push(self.pop_value());
1262-
}
1263-
1264-
// Push top of stack back first:
1265-
self.push_value(values.remove(0));
1266-
1267-
// Push other value back in order:
1268-
for value in values.into_iter().rev() {
1269-
self.push_value(value);
1270-
}
1255+
#[inline(always)]
1256+
fn execute_rotate(&mut self, amount: usize) -> FrameResult {
1257+
let i = self.state.stack.len() - amount;
1258+
self.state.stack[i..].rotate_right(1);
12711259
Ok(None)
12721260
}
12731261

0 commit comments

Comments
 (0)