Add tuple unpacking optimization

This commit is contained in:
coolreader18
2019-08-04 01:22:51 -05:00
parent b48f0c2a8b
commit 772460ea7f
3 changed files with 52 additions and 30 deletions

View File

@@ -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),
}
}
}

View File

@@ -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),
}
}

View File

@@ -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 {