瀏覽代碼

Fixed optimization bug

AND and OR statements were using incorrect registers if they would exit
prematurely due to the condition being known already.

Introduce a fix that would re-use the registers, as in the original code.
Cesar Rodas 9 月之前
父節點
當前提交
5e30a03a72
共有 4 個文件被更改,包括 21 次插入13 次删除
  1. 1 1
      utxo/src/filter_expr/compiler.rs
  2. 17 9
      utxo/src/filter_expr/filter.rs
  3. 2 2
      utxo/src/filter_expr/mod.rs
  4. 1 1
      utxo/src/filter_expr/runtime.rs

+ 1 - 1
utxo/src/filter_expr/compiler.rs

@@ -62,7 +62,7 @@ impl<'a> Compiler<'a> {
                 match op {
                     ExprOp::Not => {
                         let (mut opcodes, term_return_value) =
-                            compiled_terms.pop().ok_or(Error::EmptyRegisters)?;
+                            compiled_terms.pop().ok_or(Error::UnexpectedExprState)?;
                         if !compiled_terms.is_empty() {
                             return Err(Error::UnexpectedExprState);
                         }

+ 17 - 9
utxo/src/filter_expr/filter.rs

@@ -106,10 +106,8 @@ impl Filter {
     /// LOADED and LOADED_EXTERNAL register has a unique address.
     fn assign_unique_register_addresses(&mut self) -> bool {
         let mut has_changed = false;
-        let mut counter: usize = self.opcodes.len();
-
+        let mut counter: usize = 0;
         let mut register_new_mapping = HashMap::<_, Register>::new();
-
         let mut new_mapping = |register_new_mapping: &mut HashMap<Register, Register>,
                                current: &Register|
          -> Register {
@@ -132,11 +130,16 @@ impl Filter {
             | OpCode::CPY(set, reg1)
             | OpCode::NEG(set, reg1)
             | OpCode::MOV(set, reg1) => {
-                *reg1 = register_new_mapping[reg1];
-                *set = new_mapping(&mut register_new_mapping, set);
+                *reg1 = register_new_mapping[reg1].clone();
+
+                if let Some(new_set) = register_new_mapping.get(set) {
+                    *set = new_set.clone()
+                } else {
+                    *set = new_mapping(&mut register_new_mapping, set);
+                }
             }
             OpCode::HLT(reg1) | OpCode::JEQ(reg1, _) | OpCode::JNE(reg1, _) => {
-                *reg1 = register_new_mapping[reg1];
+                *reg1 = register_new_mapping[reg1].clone();
             }
             OpCode::ADD(set, reg1, reg2)
             | OpCode::MUL(set, reg1, reg2)
@@ -152,9 +155,13 @@ impl Filter {
             | OpCode::AND(set, reg1, reg2)
             | OpCode::EQ(set, reg1, reg2)
             | OpCode::OR(set, reg1, reg2) => {
-                *reg1 = register_new_mapping[reg1];
-                *reg2 = register_new_mapping[reg2];
-                *set = new_mapping(&mut register_new_mapping, set);
+                *reg1 = register_new_mapping[reg1].clone();
+                *reg2 = register_new_mapping[reg2].clone();
+                if let Some(new_set) = register_new_mapping.get(set) {
+                    *set = new_set.clone()
+                } else {
+                    *set = new_mapping(&mut register_new_mapping, set);
+                }
             }
             OpCode::LABEL(_) | OpCode::JMP(_) => {}
         });
@@ -301,6 +308,7 @@ mod test {
             r#"
             WHERE
                 $foo = 3 + 2 * 4 / 2 * 298210 + $bar
+                AND 5 = 5
         "#,
         )
         .unwrap();

+ 2 - 2
utxo/src/filter_expr/mod.rs

@@ -65,8 +65,8 @@ pub enum Error {
     #[error("Register {0} is out of boundaries")]
     RegisterOutOfBoundaries(Register),
 
-    #[error("Empty registers")]
-    EmptyRegisters,
+    #[error("Empty registers: {0}")]
+    EmptyRegister(Register),
 
     #[error("Value is not a number")]
     NotANumber,

+ 1 - 1
utxo/src/filter_expr/runtime.rs

@@ -126,7 +126,7 @@ pub fn execute<'a>(
                 return registers
                     .remove(return_register)
                     .map(|x| x.into())
-                    .ok_or(Error::EmptyRegisters);
+                    .ok_or_else(|| Error::EmptyRegister(return_register.to_owned()));
             }
             x => println!("{:?} is not implemented", x),
         }