Browse Source

Removed duplicated code in vm.run using macros. (#1044)

pull/1162/head
Stéphane Magnenat 4 years ago committed by GitHub
parent
commit
f3f39490ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 174
      boa/src/vm/mod.rs

174
boa/src/vm/mod.rs

@ -78,162 +78,93 @@ impl<'a> VM<'a> {
let _timer =
BoaProfiler::global().start_event(&self.instructions[self.idx].to_string(), "vm");
match self.instructions[self.idx] {
Instruction::Undefined => self.push(Value::undefined()),
Instruction::Null => self.push(Value::null()),
Instruction::True => self.push(Value::boolean(true)),
Instruction::False => self.push(Value::boolean(false)),
Instruction::Zero => self.push(Value::integer(0)),
Instruction::One => self.push(Value::integer(1)),
Instruction::Int32(i) => self.push(Value::integer(i)),
Instruction::Rational(r) => self.push(Value::rational(r)),
Instruction::String(index) => {
let value = self.pool[index].clone();
self.push(value)
}
Instruction::BigInt(index) => {
let value = self.pool[index].clone();
self.push(value)
}
Instruction::Add => {
macro_rules! bin_op {
($op:ident) => {{
let r = self.pop();
let l = self.pop();
let val = l.add(&r, self.ctx)?;
self.push(val);
let val = l.$op(&r, self.ctx)?;
Some(val.into())
}};
}
let result = match self.instructions[self.idx] {
Instruction::Undefined => Some(Value::undefined()),
Instruction::Null => Some(Value::null()),
Instruction::True => Some(Value::boolean(true)),
Instruction::False => Some(Value::boolean(false)),
Instruction::Zero => Some(Value::integer(0)),
Instruction::One => Some(Value::integer(1)),
Instruction::Int32(i) => Some(Value::integer(i)),
Instruction::Rational(r) => Some(Value::rational(r)),
Instruction::String(index) => Some(self.pool[index].clone()),
Instruction::BigInt(index) => Some(self.pool[index].clone()),
Instruction::Add => {
bin_op!(add)
}
Instruction::Sub => {
let r = self.pop();
let l = self.pop();
let val = l.sub(&r, self.ctx)?;
self.push(val);
bin_op!(sub)
}
Instruction::Mul => {
let r = self.pop();
let l = self.pop();
let val = l.mul(&r, self.ctx)?;
self.push(val);
bin_op!(mul)
}
Instruction::Div => {
let r = self.pop();
let l = self.pop();
let val = l.div(&r, self.ctx)?;
self.push(val);
bin_op!(div)
}
Instruction::Pow => {
let r = self.pop();
let l = self.pop();
let val = l.pow(&r, self.ctx)?;
self.push(val);
bin_op!(pow)
}
Instruction::Mod => {
let r = self.pop();
let l = self.pop();
let val = l.rem(&r, self.ctx)?;
self.push(val);
bin_op!(rem)
}
Instruction::BitAnd => {
let r = self.pop();
let l = self.pop();
let val = l.bitand(&r, self.ctx)?;
self.push(val);
bin_op!(bitand)
}
Instruction::BitOr => {
let r = self.pop();
let l = self.pop();
let val = l.bitor(&r, self.ctx)?;
self.push(val);
bin_op!(bitor)
}
Instruction::BitXor => {
let r = self.pop();
let l = self.pop();
let val = l.bitxor(&r, self.ctx)?;
self.push(val);
bin_op!(bitxor)
}
Instruction::Shl => {
let r = self.pop();
let l = self.pop();
let val = l.shl(&r, self.ctx)?;
self.push(val);
bin_op!(shl)
}
Instruction::Shr => {
let r = self.pop();
let l = self.pop();
let val = l.shr(&r, self.ctx)?;
self.push(val);
bin_op!(shr)
}
Instruction::UShr => {
let r = self.pop();
let l = self.pop();
let val = l.ushr(&r, self.ctx)?;
self.push(val);
bin_op!(ushr)
}
Instruction::Eq => {
let r = self.pop();
let l = self.pop();
let val = l.equals(&r, self.ctx)?;
self.push(val.into());
Some((l.equals(&r, self.ctx)?).into())
}
Instruction::NotEq => {
let r = self.pop();
let l = self.pop();
let val = !l.equals(&r, self.ctx)?;
self.push(val.into());
Some((!l.equals(&r, self.ctx)?).into())
}
Instruction::StrictEq => {
let r = self.pop();
let l = self.pop();
let val = l.strict_equals(&r);
self.push(val.into());
Some((l.strict_equals(&r)).into())
}
Instruction::StrictNotEq => {
let r = self.pop();
let l = self.pop();
let val = !l.strict_equals(&r);
self.push(val.into());
Some((!l.strict_equals(&r)).into())
}
Instruction::Gt => {
let r = self.pop();
let l = self.pop();
let val = l.ge(&r, self.ctx)?;
self.push(val.into());
bin_op!(gt)
}
Instruction::Ge => {
let r = self.pop();
let l = self.pop();
let val = l.ge(&r, self.ctx)?;
self.push(val.into());
bin_op!(ge)
}
Instruction::Lt => {
let r = self.pop();
let l = self.pop();
let val = l.lt(&r, self.ctx)?;
self.push(val.into());
bin_op!(lt)
}
Instruction::Le => {
let r = self.pop();
let l = self.pop();
let val = l.le(&r, self.ctx)?;
self.push(val.into());
bin_op!(le)
}
Instruction::In => {
let r = self.pop();
@ -246,9 +177,7 @@ impl<'a> VM<'a> {
));
}
let key = l.to_property_key(self.ctx)?;
let val = self.ctx.has_property(&r, &key);
self.push(val.into());
Some(self.ctx.has_property(&r, &key).into())
}
Instruction::InstanceOf => {
let r = self.pop();
@ -265,24 +194,24 @@ impl<'a> VM<'a> {
}
Instruction::Void => {
let _value = self.pop();
self.push(Value::undefined());
Some(Value::undefined())
}
Instruction::TypeOf => {
let value = self.pop();
self.push(value.get_type().as_str().into());
Some(value.get_type().as_str().into())
}
Instruction::Pos => {
let value = self.pop();
let value = value.to_number(self.ctx)?;
self.push(value.into());
Some(value.into())
}
Instruction::Neg => {
let value = self.pop();
self.push(Value::from(!value.to_boolean()));
Some(Value::from(!value.to_boolean()))
}
Instruction::Not => {
let value = self.pop();
self.push((!value.to_boolean()).into());
Some((!value.to_boolean()).into())
}
Instruction::BitNot => {
let target = self.pop();
@ -293,7 +222,7 @@ impl<'a> VM<'a> {
// TODO: this is not spec compliant.
!(num as i32)
};
self.push(value.into());
Some(value.into())
}
Instruction::DefVar(name_index) => {
let name: String = self.pool[name_index].to_string(self.ctx)?.to_string();
@ -303,6 +232,8 @@ impl<'a> VM<'a> {
.environment
.create_mutable_binding(name.to_string(), false, VariableScope::Function)
.map_err(|e| e.to_error(self.ctx))?;
None
}
Instruction::DefLet(name_index) => {
let name = self.pool[name_index].to_string(self.ctx)?;
@ -312,6 +243,8 @@ impl<'a> VM<'a> {
.environment
.create_mutable_binding(name.to_string(), false, VariableScope::Block)
.map_err(|e| e.to_error(self.ctx))?;
None
}
Instruction::DefConst(name_index) => {
let name = self.pool[name_index].to_string(self.ctx)?;
@ -321,6 +254,8 @@ impl<'a> VM<'a> {
.environment
.create_immutable_binding(name.to_string(), false, VariableScope::Block)
.map_err(|e| e.to_error(self.ctx))?;
None
}
Instruction::InitLexical(name_index) => {
let name = self.pool[name_index].to_string(self.ctx)?;
@ -331,8 +266,11 @@ impl<'a> VM<'a> {
.initialize_binding(&name, value.clone())
.map_err(|e| e.to_error(self.ctx))?;
self.push(value);
Some(value)
}
};
if let Some(value) = result {
self.push(value);
}
self.idx += 1;

Loading…
Cancel
Save