mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Add tuple unpacking optimization
This commit is contained in:
@@ -219,6 +219,9 @@ pub enum Instruction {
|
||||
spec: String,
|
||||
},
|
||||
PopException,
|
||||
Reverse {
|
||||
amount: usize,
|
||||
},
|
||||
}
|
||||
|
||||
use self::Instruction::*;
|
||||
@@ -438,6 +441,7 @@ impl Instruction {
|
||||
Unpack => w!(Unpack),
|
||||
FormatValue { spec, .. } => w!(FormatValue, spec), // TODO: write conversion
|
||||
PopException => w!(PopException),
|
||||
Reverse { amount } => w!(Reverse, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ struct InstructionMetadata {
|
||||
labels: Vec<Label>,
|
||||
}
|
||||
|
||||
impl InstructionMetadata {
|
||||
fn from_multiple(metas: Vec<Self>) -> Self {
|
||||
impl From<Vec<InstructionMetadata>> for InstructionMetadata {
|
||||
fn from(metas: Vec<Self>) -> Self {
|
||||
debug_assert!(!metas.is_empty(), "`metas` must not be empty");
|
||||
InstructionMetadata {
|
||||
loc: metas[0].loc.clone(),
|
||||
@@ -69,28 +69,28 @@ impl<O: OutputStream> PeepholeOptimizer<O> {
|
||||
}
|
||||
|
||||
fn optimize(&mut self, instruction: Instruction, meta: InstructionMetadata) {
|
||||
macro_rules! lc {
|
||||
($name:ident {$($field:tt)*}) => {
|
||||
Instruction::LoadConst {
|
||||
value: bytecode::Constant::$name {$($field)*},
|
||||
}
|
||||
};
|
||||
($name:ident, $($value:tt)*) => {
|
||||
lc!($name { value: $($value)* })
|
||||
};
|
||||
}
|
||||
macro_rules! emitconst {
|
||||
([$($metas:expr),*], $($arg:tt)*) => {
|
||||
self.emit(
|
||||
lc!($($arg)*),
|
||||
InstructionMetadata::from(vec![$($metas),*]),
|
||||
)
|
||||
};
|
||||
}
|
||||
match instruction {
|
||||
Instruction::BinaryOperation { op, inplace } => {
|
||||
let (rhs, rhs_meta) = self.pop();
|
||||
let (lhs, lhs_meta) = self.pop();
|
||||
macro_rules! lc {
|
||||
($name:ident {$($field:tt)*}) => {
|
||||
Instruction::LoadConst {
|
||||
value: bytecode::Constant::$name {$($field)*},
|
||||
}
|
||||
};
|
||||
($name:ident, $($value:tt)*) => {
|
||||
lc!($name { value: $($value)* })
|
||||
};
|
||||
}
|
||||
macro_rules! emitconst {
|
||||
([$($metas:expr),*], $($arg:tt)*) => {
|
||||
self.emit(
|
||||
lc!($($arg)*),
|
||||
InstructionMetadata::from_multiple(vec![$($metas),*]),
|
||||
)
|
||||
};
|
||||
}
|
||||
macro_rules! op {
|
||||
($op:ident) => {
|
||||
bytecode::BinaryOperator::$op
|
||||
@@ -129,6 +129,24 @@ impl<O: OutputStream> PeepholeOptimizer<O> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Instruction::UnpackSequence { size } => {
|
||||
let (arg, arg_meta) = self.pop();
|
||||
match arg {
|
||||
Instruction::BuildTuple {
|
||||
size: tup_size,
|
||||
unpack,
|
||||
} if !unpack && tup_size == size => {
|
||||
self.emit(
|
||||
Instruction::Reverse { amount: size },
|
||||
vec![arg_meta, meta].into(),
|
||||
);
|
||||
}
|
||||
arg => {
|
||||
self.emit(arg, arg_meta);
|
||||
self.emit(instruction, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
other => self.emit(other, meta),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,6 +662,12 @@ impl Frame {
|
||||
panic!("Block type must be ExceptHandler here.")
|
||||
}
|
||||
}
|
||||
bytecode::Instruction::Reverse { amount } => {
|
||||
let mut stack = self.stack.borrow_mut();
|
||||
let stack_len = stack.len();
|
||||
stack[stack_len - amount..stack_len].reverse();
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -676,10 +682,7 @@ impl Frame {
|
||||
if unpack {
|
||||
let mut result: Vec<PyObjectRef> = vec![];
|
||||
for element in elements {
|
||||
let expanded = vm.extract_elements(&element)?;
|
||||
for inner in expanded {
|
||||
result.push(inner);
|
||||
}
|
||||
result.extend(vm.extract_elements(&element)?);
|
||||
}
|
||||
Ok(result)
|
||||
} else {
|
||||
@@ -1170,12 +1173,9 @@ impl Frame {
|
||||
}
|
||||
|
||||
fn pop_multiple(&self, count: usize) -> Vec<PyObjectRef> {
|
||||
let mut objs: Vec<PyObjectRef> = Vec::new();
|
||||
for _x in 0..count {
|
||||
objs.push(self.pop_value());
|
||||
}
|
||||
objs.reverse();
|
||||
objs
|
||||
let mut stack = self.stack.borrow_mut();
|
||||
let stack_len = stack.len();
|
||||
stack.drain(stack_len - count..stack_len).collect()
|
||||
}
|
||||
|
||||
fn last_value(&self) -> PyObjectRef {
|
||||
|
||||
Reference in New Issue
Block a user