mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Don't create extra JumpIfOrPop instructions.
As discussed: https://github.com/RustPython/RustPython/pull/82#discussion_r212809238
This commit is contained in:
@@ -83,15 +83,9 @@ pub enum Instruction {
|
||||
JumpIf {
|
||||
target: Label,
|
||||
},
|
||||
JumpIfOrPop {
|
||||
target: Label,
|
||||
},
|
||||
JumpIfFalse {
|
||||
target: Label,
|
||||
},
|
||||
JumpIfFalseOrPop {
|
||||
target: Label,
|
||||
},
|
||||
MakeFunction,
|
||||
CallFunction {
|
||||
count: usize,
|
||||
|
||||
@@ -545,16 +545,20 @@ impl Compiler {
|
||||
ast::BooleanOperator::And => {
|
||||
let false_label = self.new_label();
|
||||
self.compile_expression(a);
|
||||
self.emit(Instruction::JumpIfFalseOrPop {
|
||||
self.emit(Instruction::Duplicate);
|
||||
self.emit(Instruction::JumpIfFalse {
|
||||
target: false_label,
|
||||
});
|
||||
self.emit(Instruction::Pop);
|
||||
self.compile_expression(b);
|
||||
self.set_label(false_label);
|
||||
}
|
||||
ast::BooleanOperator::Or => {
|
||||
let true_label = self.new_label();
|
||||
self.compile_expression(a);
|
||||
self.emit(Instruction::JumpIfOrPop { target: true_label });
|
||||
self.emit(Instruction::Duplicate);
|
||||
self.emit(Instruction::JumpIf { target: true_label });
|
||||
self.emit(Instruction::Pop);
|
||||
self.compile_expression(b);
|
||||
self.set_label(true_label);
|
||||
}
|
||||
|
||||
50
vm/src/vm.rs
50
vm/src/vm.rs
@@ -773,22 +773,28 @@ impl VirtualMachine {
|
||||
}
|
||||
bytecode::Instruction::JumpIf { target } => {
|
||||
let obj = self.pop_value();
|
||||
self.jump_if(target, obj, true, false)
|
||||
match objbool::boolval(self, obj) {
|
||||
Ok(value) => {
|
||||
if value {
|
||||
self.jump(target);
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(value) => Some(Err(value)),
|
||||
}
|
||||
}
|
||||
|
||||
bytecode::Instruction::JumpIfFalse { target } => {
|
||||
let obj = self.pop_value();
|
||||
self.jump_if(target, obj, false, false)
|
||||
}
|
||||
|
||||
bytecode::Instruction::JumpIfOrPop { target } => {
|
||||
let obj = self.last_value();
|
||||
self.jump_if(target, obj, true, true)
|
||||
}
|
||||
|
||||
bytecode::Instruction::JumpIfFalseOrPop { target } => {
|
||||
let obj = self.last_value();
|
||||
self.jump_if(target, obj, false, true)
|
||||
match objbool::boolval(self, obj) {
|
||||
Ok(value) => {
|
||||
if !value {
|
||||
self.jump(target);
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(value) => Some(Err(value)),
|
||||
}
|
||||
}
|
||||
|
||||
bytecode::Instruction::Raise { argc } => {
|
||||
@@ -873,26 +879,6 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
fn jump_if(
|
||||
&mut self,
|
||||
label: &bytecode::Label,
|
||||
obj: PyObjectRef,
|
||||
jump_on: bool,
|
||||
or_pop: bool,
|
||||
) -> Option<PyResult> {
|
||||
match objbool::boolval(self, obj) {
|
||||
Ok(value) => {
|
||||
if value == jump_on {
|
||||
self.jump(label);
|
||||
} else if or_pop {
|
||||
self.pop_value();
|
||||
}
|
||||
None
|
||||
}
|
||||
Err(value) => Some(Err(value)),
|
||||
}
|
||||
}
|
||||
|
||||
fn jump(&mut self, label: &bytecode::Label) {
|
||||
let current_frame = self.current_frame();
|
||||
let target_pc = current_frame.code.label_map[label];
|
||||
|
||||
Reference in New Issue
Block a user