Browse Source

Improve bytecompiler bytecode generation. (#3188)

* Improve bytecompiler bytecode generation

* Implement push f32 value (#3198)
pull/3202/head
Haled Odat 1 year ago committed by GitHub
parent
commit
c2df31b781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 108
      boa_engine/src/bytecompiler/class.rs
  2. 18
      boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
  3. 42
      boa_engine/src/bytecompiler/declarations.rs
  4. 27
      boa_engine/src/bytecompiler/expression/assign.rs
  5. 19
      boa_engine/src/bytecompiler/expression/binary.rs
  6. 32
      boa_engine/src/bytecompiler/expression/mod.rs
  7. 46
      boa_engine/src/bytecompiler/expression/object_literal.rs
  8. 6
      boa_engine/src/bytecompiler/expression/unary.rs
  9. 42
      boa_engine/src/bytecompiler/expression/update.rs
  10. 270
      boa_engine/src/bytecompiler/mod.rs
  11. 5
      boa_engine/src/bytecompiler/module.rs
  12. 22
      boa_engine/src/bytecompiler/statement/loop.rs
  13. 11
      boa_engine/src/bytecompiler/utils.rs
  14. 4
      boa_engine/src/module/source.rs
  15. 10
      boa_engine/src/vm/code_block.rs
  16. 11
      boa_engine/src/vm/flowgraph/mod.rs
  17. 13
      boa_engine/src/vm/opcode/mod.rs
  18. 3
      boa_engine/src/vm/opcode/push/numbers.rs

108
boa_engine/src/bytecompiler/class.rs

@ -1,4 +1,4 @@
use super::{ByteCompiler, Literal};
use super::{ByteCompiler, Literal, Operand};
use crate::vm::{BindingOpcode, CodeBlockFlags, Opcode};
use boa_ast::{
expression::Identifier,
@ -78,8 +78,10 @@ impl ByteCompiler<'_, '_> {
let code = Gc::new(compiler.finish());
let index = self.functions.len() as u32;
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
let class_env: Option<super::Label> = match class.name() {
Some(name) if class.has_binding_identifier() => {
@ -127,7 +129,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticGetterByName, &[index]);
self.emit(
Opcode::DefineClassStaticGetterByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -140,7 +145,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticSetterByName, &[index]);
self.emit(
Opcode::DefineClassStaticSetterByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -153,7 +161,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticMethodByName, &[index]);
self.emit(
Opcode::DefineClassStaticMethodByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -166,7 +177,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticMethodByName, &[index]);
self.emit(
Opcode::DefineClassStaticMethodByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -179,7 +193,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticMethodByName, &[index]);
self.emit(
Opcode::DefineClassStaticMethodByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -192,7 +209,10 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassStaticMethodByName, &[index]);
self.emit(
Opcode::DefineClassStaticMethodByName,
&[Operand::U32(index)],
);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -210,32 +230,32 @@ impl ByteCompiler<'_, '_> {
MethodDefinition::Get(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateGetter, &[index]);
self.emit(Opcode::SetPrivateGetter, &[Operand::U32(index)]);
}
MethodDefinition::Set(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateSetter, &[index]);
self.emit(Opcode::SetPrivateSetter, &[Operand::U32(index)]);
}
MethodDefinition::Ordinary(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateMethod, &[index]);
self.emit(Opcode::SetPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::Async(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateMethod, &[index]);
self.emit(Opcode::SetPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::Generator(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateMethod, &[index]);
self.emit(Opcode::SetPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::AsyncGenerator(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::SetPrivateMethod, &[index]);
self.emit(Opcode::SetPrivateMethod, &[Operand::U32(index)]);
}
}
}
@ -277,8 +297,10 @@ impl ByteCompiler<'_, '_> {
let code = Gc::new(code);
let index = self.functions.len() as u32;
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
self.emit_opcode(Opcode::PushClassField);
}
ClassElement::PrivateFieldDefinition(name, field) => {
@ -310,9 +332,11 @@ impl ByteCompiler<'_, '_> {
let code = Gc::new(code);
let index = self.functions.len() as u32;
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit(Opcode::PushClassFieldPrivate, &[name_index]);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
self.emit(Opcode::PushClassFieldPrivate, &[Operand::U32(name_index)]);
}
ClassElement::StaticFieldDefinition(name, field) => {
self.emit_opcode(Opcode::Dup);
@ -353,12 +377,14 @@ impl ByteCompiler<'_, '_> {
let code = Gc::new(code);
let index = self.functions.len() as u32;
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
self.emit_opcode(Opcode::SetHomeObjectClass);
self.emit(Opcode::Call, &[0]);
self.emit(Opcode::Call, &[Operand::U32(0)]);
if let Some(name_index) = name_index {
self.emit(Opcode::DefineOwnPropertyByName, &[name_index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(name_index)]);
} else {
self.emit_opcode(Opcode::DefineOwnPropertyByValue);
}
@ -371,7 +397,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::PushUndefined);
}
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::DefinePrivateField, &[index]);
self.emit(Opcode::DefinePrivateField, &[Operand::U32(index)]);
}
ClassElement::StaticBlock(body) => {
self.emit_opcode(Opcode::Dup);
@ -401,10 +427,12 @@ impl ByteCompiler<'_, '_> {
let code = Gc::new(compiler.finish());
let index = self.functions.len() as u32;
self.functions.push(code);
self.emit(Opcode::GetFunction, &[index]);
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
self.emit_opcode(Opcode::SetHomeObjectClass);
self.emit(Opcode::Call, &[0]);
self.emit(Opcode::Call, &[Operand::U32(0)]);
self.emit_opcode(Opcode::Pop);
}
// TODO: set names for private methods
@ -414,32 +442,32 @@ impl ByteCompiler<'_, '_> {
MethodDefinition::Get(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateGetter, &[index]);
self.emit(Opcode::PushClassPrivateGetter, &[Operand::U32(index)]);
}
MethodDefinition::Set(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateSetter, &[index]);
self.emit(Opcode::PushClassPrivateSetter, &[Operand::U32(index)]);
}
MethodDefinition::Ordinary(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateMethod, &[index]);
self.emit(Opcode::PushClassPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::Async(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateMethod, &[index]);
self.emit(Opcode::PushClassPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::Generator(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateMethod, &[index]);
self.emit(Opcode::PushClassPrivateMethod, &[Operand::U32(index)]);
}
MethodDefinition::AsyncGenerator(expr) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_private_name(*name);
self.emit(Opcode::PushClassPrivateMethod, &[index]);
self.emit(Opcode::PushClassPrivateMethod, &[Operand::U32(index)]);
}
}
}
@ -459,7 +487,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassGetterByName, &[index]);
self.emit(Opcode::DefineClassGetterByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -472,7 +500,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassSetterByName, &[index]);
self.emit(Opcode::DefineClassSetterByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -485,7 +513,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassMethodByName, &[index]);
self.emit(Opcode::DefineClassMethodByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -498,7 +526,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassMethodByName, &[index]);
self.emit(Opcode::DefineClassMethodByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -511,7 +539,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassMethodByName, &[index]);
self.emit(Opcode::DefineClassMethodByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);
@ -524,7 +552,7 @@ impl ByteCompiler<'_, '_> {
PropertyName::Literal(name) => {
self.method(expr.into(), class_name);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineClassMethodByName, &[index]);
self.emit(Opcode::DefineClassMethodByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_expr(name_node, true);

18
boa_engine/src/bytecompiler/declaration/declaration_pattern.rs

@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler, Literal},
bytecompiler::{Access, ByteCompiler, Literal, Operand},
vm::{BindingOpcode, Opcode},
};
use boa_ast::{
@ -40,7 +40,7 @@ impl ByteCompiler<'_, '_> {
match name {
PropertyName::Literal(name) => {
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(node) => {
self.compile_expr(node, true);
@ -80,7 +80,10 @@ impl ByteCompiler<'_, '_> {
self.emit(
Opcode::CopyDataProperties,
&[excluded_keys.len() as u32, additional_excluded_keys_count],
&[
Operand::U32(excluded_keys.len() as u32),
Operand::U32(additional_excluded_keys_count),
],
);
self.emit_binding(def, *ident);
}
@ -95,7 +98,10 @@ impl ByteCompiler<'_, '_> {
self.interner().resolve_expect(key.sym()).into_common(false),
));
}
self.emit(Opcode::CopyDataProperties, &[excluded_keys.len() as u32, 0]);
self.emit(
Opcode::CopyDataProperties,
&[Operand::U32(excluded_keys.len() as u32), Operand::U32(0)],
);
self.access_set(
Access::Property { access },
false,
@ -112,7 +118,7 @@ impl ByteCompiler<'_, '_> {
match name {
PropertyName::Literal(name) => {
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(node) => {
self.compile_expr(node, true);
@ -152,7 +158,7 @@ impl ByteCompiler<'_, '_> {
match name {
PropertyName::Literal(name) => {
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(node) => {
self.compile_expr(node, true);

42
boa_engine/src/bytecompiler/declarations.rs

@ -23,6 +23,8 @@ use boa_interner::Sym;
#[cfg(feature = "annex-b")]
use boa_ast::operations::annex_b_function_declarations_names;
use super::Operand;
impl ByteCompiler<'_, '_> {
/// `GlobalDeclarationInstantiation ( script, env )`
///
@ -570,7 +572,7 @@ impl ByteCompiler<'_, '_> {
let binding = self.initialize_mutable_binding(f, true);
let index = self.get_or_insert_binding(binding);
self.emit_opcode(Opcode::PushUndefined);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
}
@ -717,16 +719,19 @@ impl ByteCompiler<'_, '_> {
let index = self.functions.len() as u32;
self.functions.push(code);
if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
self.emit(Opcode::GetGeneratorAsync, &[Operand::U32(index)]);
} else if generator {
self.emit(Opcode::GetGenerator, &[index]);
self.emit(Opcode::GetGenerator, &[Operand::U32(index)]);
} else if r#async {
self.emit(Opcode::GetFunctionAsync, &[index]);
self.emit(
Opcode::GetFunctionAsync,
&[Operand::U32(index), Operand::Bool(false)],
);
} else {
self.emit(Opcode::GetFunction, &[index]);
}
if !generator {
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
}
// i. Let bindingExists be ! varEnv.HasBinding(fn).
@ -739,14 +744,14 @@ impl ByteCompiler<'_, '_> {
match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
} else {
@ -756,7 +761,7 @@ impl ByteCompiler<'_, '_> {
self.create_mutable_binding(name, !strict);
let binding = self.initialize_mutable_binding(name, !strict);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
}
}
@ -782,7 +787,7 @@ impl ByteCompiler<'_, '_> {
let binding = self.initialize_mutable_binding(name, !strict);
let index = self.get_or_insert_binding(binding);
self.emit_opcode(Opcode::PushUndefined);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
}
}
@ -1012,8 +1017,7 @@ impl ByteCompiler<'_, '_> {
}
if generator {
self.emit_opcode(Opcode::Generator);
self.emit_u8(self.in_async().into());
self.emit(Opcode::Generator, &[Operand::U8(self.in_async().into())]);
self.emit_opcode(Opcode::Pop);
}
@ -1052,14 +1056,14 @@ impl ByteCompiler<'_, '_> {
// a. Let initialValue be ! env.GetBindingValue(n, false).
let binding = self.get_binding_value(n);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::GetName, &[index]);
self.emit(Opcode::GetName, &[Operand::U32(index)]);
}
// 5. Perform ! varEnv.InitializeBinding(n, initialValue).
let binding = self.initialize_mutable_binding(n, true);
let index = self.get_or_insert_binding(binding);
self.emit_opcode(Opcode::PushUndefined);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
// 6. NOTE: A var with the same name as a formal parameter initially has
// the same value as the corresponding initialized parameter.
@ -1086,7 +1090,7 @@ impl ByteCompiler<'_, '_> {
let binding = self.initialize_mutable_binding(n, true);
let index = self.get_or_insert_binding(binding);
self.emit_opcode(Opcode::PushUndefined);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
}
@ -1118,7 +1122,7 @@ impl ByteCompiler<'_, '_> {
let binding = self.initialize_mutable_binding(f, true);
let index = self.get_or_insert_binding(binding);
self.emit_opcode(Opcode::PushUndefined);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
// c. Append F to instantiatedVarNames.
instantiated_var_names.push(f);

27
boa_engine/src/bytecompiler/expression/assign.rs

@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler},
bytecompiler::{Access, ByteCompiler, Operand},
environments::BindingLocatorError,
vm::{BindingOpcode, Opcode},
};
@ -60,9 +60,9 @@ impl ByteCompiler<'_, '_> {
let lex = self.current_environment.is_lex_binding(name);
if lex {
self.emit(Opcode::GetName, &[index]);
self.emit(Opcode::GetName, &[Operand::U32(index)]);
} else {
self.emit(Opcode::GetNameAndLocator, &[index]);
self.emit(Opcode::GetNameAndLocator, &[Operand::U32(index)]);
}
if short_circuit {
@ -79,14 +79,14 @@ impl ByteCompiler<'_, '_> {
match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
} else {
@ -102,7 +102,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
if short_circuit {
pop_count = 2;
early_exit = Some(self.emit_opcode_with_operand(opcode));
@ -112,7 +112,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(opcode);
}
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if !use_expr {
self.emit_opcode(Opcode::Pop);
}
@ -145,7 +145,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPrivateField, &[index]);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
if short_circuit {
pop_count = 1;
early_exit = Some(self.emit_opcode_with_operand(opcode));
@ -155,7 +155,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(opcode);
}
self.emit(Opcode::SetPrivateField, &[index]);
self.emit(Opcode::SetPrivateField, &[Operand::U32(index)]);
if !use_expr {
self.emit_opcode(Opcode::Pop);
}
@ -169,7 +169,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
if short_circuit {
pop_count = 2;
early_exit = Some(self.emit_opcode_with_operand(opcode));
@ -179,7 +179,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(opcode);
}
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if !use_expr {
self.emit_opcode(Opcode::Pop);
}
@ -201,8 +201,7 @@ impl ByteCompiler<'_, '_> {
}
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(2);
self.emit(Opcode::RotateRight, &[Operand::U8(2)]);
self.emit_opcode(Opcode::SetPropertyByValue);
if !use_expr {

19
boa_engine/src/bytecompiler/expression/binary.rs

@ -3,7 +3,10 @@ use boa_ast::expression::operator::{
Binary, BinaryInPrivate,
};
use crate::{bytecompiler::ByteCompiler, vm::Opcode};
use crate::{
bytecompiler::{ByteCompiler, Operand},
vm::Opcode,
};
impl ByteCompiler<'_, '_> {
pub(crate) fn compile_binary(&mut self, binary: &Binary, use_expr: bool) {
@ -21,7 +24,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
BinaryOp::Bitwise(op) => {
@ -36,7 +39,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
BinaryOp::Relational(op) => {
@ -57,7 +60,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
BinaryOp::Logical(op) => {
@ -80,15 +83,15 @@ impl ByteCompiler<'_, '_> {
};
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
BinaryOp::Comma => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
self.compile_expr(binary.rhs(), true);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
};
@ -97,7 +100,7 @@ impl ByteCompiler<'_, '_> {
pub(crate) fn compile_binary_in_private(&mut self, binary: &BinaryInPrivate, use_expr: bool) {
let index = self.get_or_insert_private_name(*binary.lhs());
self.compile_expr(binary.rhs(), true);
self.emit(Opcode::InPrivate, &[index]);
self.emit(Opcode::InPrivate, &[Operand::U32(index)]);
if !use_expr {
self.emit_opcode(Opcode::Pop);

32
boa_engine/src/bytecompiler/expression/mod.rs

@ -4,7 +4,7 @@ mod object_literal;
mod unary;
mod update;
use super::{Access, Callable, NodeKind};
use super::{Access, Callable, NodeKind, Operand};
use crate::{
bytecompiler::{ByteCompiler, Literal},
vm::{GeneratorResumeKind, Opcode},
@ -36,7 +36,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
@ -50,7 +50,7 @@ impl ByteCompiler<'_, '_> {
self.patch_jump(exit);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
};
}
@ -68,11 +68,11 @@ impl ByteCompiler<'_, '_> {
self.emit(
Opcode::ConcatToString,
&[template_literal.elements().len() as u32],
&[Operand::U32(template_literal.elements().len() as u32)],
);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
@ -114,7 +114,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
Expression::This => {
@ -173,7 +173,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::PushUndefined);
// stack: undefined
self.emit_push_integer(GeneratorResumeKind::Normal as i32);
self.emit_resume_kind(GeneratorResumeKind::Normal);
// stack: resume_kind, undefined
let start_address = self.next_opcode_location();
@ -194,7 +194,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::IteratorResult);
self.emit_opcode(Opcode::GeneratorYield);
}
self.emit(Opcode::Jump, &[start_address]);
self.emit(Opcode::Jump, &[Operand::U32(start_address)]);
self.patch_jump(return_gen);
self.patch_jump(return_method_undefined);
@ -229,7 +229,7 @@ impl ByteCompiler<'_, '_> {
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(field) => {
self.compile_expr(field, true);
@ -241,7 +241,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(access.target(), true);
self.emit(Opcode::Dup, &[]);
let index = self.get_or_insert_private_name(access.field());
self.emit(Opcode::GetPrivateField, &[index]);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
}
expr => {
self.compile_expr(expr, true);
@ -269,7 +269,7 @@ impl ByteCompiler<'_, '_> {
));
}
self.emit(Opcode::TemplateCreate, &[count]);
self.emit(Opcode::TemplateCreate, &[Operand::U32(count)]);
self.emit_u64(site);
self.patch_jump(jump_label);
@ -278,7 +278,10 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(expr, true);
}
self.emit(Opcode::Call, &[(template.exprs().len() + 1) as u32]);
self.emit(
Opcode::Call,
&[Operand::U32(template.exprs().len() as u32 + 1)],
);
}
Expression::Class(class) => self.class(class, true),
Expression::SuperCall(super_call) => {
@ -309,7 +312,10 @@ impl ByteCompiler<'_, '_> {
if contains_spread {
self.emit_opcode(Opcode::SuperCallSpread);
} else {
self.emit(Opcode::SuperCall, &[super_call.arguments().len() as u32]);
self.emit(
Opcode::SuperCall,
&[Operand::U32(super_call.arguments().len() as u32)],
);
}
if !use_expr {

46
boa_engine/src/bytecompiler/expression/object_literal.rs

@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler, FunctionSpec},
bytecompiler::{Access, ByteCompiler, FunctionSpec, Operand},
vm::Opcode,
};
use boa_ast::{
@ -18,7 +18,7 @@ impl ByteCompiler<'_, '_> {
PropertyDefinition::IdentifierReference(ident) => {
let index = self.get_or_insert_name(*ident);
self.access_get(Access::Variable { name: *ident }, true);
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
PropertyDefinition::Property(name, expr) => match name {
PropertyName::Literal(name) => {
@ -27,7 +27,7 @@ impl ByteCompiler<'_, '_> {
if *name == Sym::__PROTO__ && !self.json_parse {
self.emit_opcode(Opcode::SetPrototype);
} else {
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
}
PropertyName::Computed(name_node) => {
@ -36,8 +36,7 @@ impl ByteCompiler<'_, '_> {
if expr.is_anonymous_function_definition() {
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit(Opcode::SetFunctionName, &[Operand::U8(0)]);
} else {
self.compile_expr(expr, true);
}
@ -50,7 +49,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertyGetterByName, &[index]);
self.emit(Opcode::SetPropertyGetterByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -65,7 +64,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertySetterByName, &[index]);
self.emit(Opcode::SetPropertySetterByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -80,7 +79,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -95,7 +94,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -110,7 +109,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -125,7 +124,7 @@ impl ByteCompiler<'_, '_> {
self.object_method(expr.into());
self.emit_opcode(Opcode::SetHomeObject);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::DefineOwnPropertyByName, &[index]);
self.emit(Opcode::DefineOwnPropertyByName, &[Operand::U32(index)]);
}
PropertyName::Computed(name_node) => {
self.compile_object_literal_computed_method(
@ -139,7 +138,10 @@ impl ByteCompiler<'_, '_> {
PropertyDefinition::SpreadObject(expr) => {
self.compile_expr(expr, true);
self.emit_opcode(Opcode::Swap);
self.emit(Opcode::CopyDataProperties, &[0, 0]);
self.emit(
Opcode::CopyDataProperties,
&[Operand::U32(0), Operand::U32(0)],
);
self.emit_opcode(Opcode::Pop);
}
PropertyDefinition::CoverInitializedName(_, _) => {
@ -149,7 +151,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
@ -172,16 +174,15 @@ impl ByteCompiler<'_, '_> {
self.object_method(function);
// stack: object, object, ToPropertyKey(name), ToPropertyKey(name), method
self.emit_opcode(Opcode::SetFunctionName);
match kind {
MethodKind::Get => self.emit_u8(1),
MethodKind::Set => self.emit_u8(2),
MethodKind::Ordinary => self.emit_u8(0),
}
let value = match kind {
MethodKind::Get => 1,
MethodKind::Set => 2,
MethodKind::Ordinary => 0,
};
self.emit(Opcode::SetFunctionName, &[Operand::U8(value)]);
// stack: object, object, ToPropertyKey(name), method
self.emit_opcode(Opcode::RotateLeft);
self.emit_u8(3);
self.emit(Opcode::RotateLeft, &[Operand::U8(3)]);
// stack: object, ToPropertyKey(name), method, object
self.emit_opcode(Opcode::Swap);
@ -193,8 +194,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Swap);
// stack: object, ToPropertyKey(name), method, object
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(3);
self.emit(Opcode::RotateRight, &[Operand::U8(3)]);
// stack: object, object, ToPropertyKey(name), method
match kind {

6
boa_engine/src/bytecompiler/expression/unary.rs

@ -4,7 +4,7 @@ use boa_ast::{
};
use crate::{
bytecompiler::{Access, ByteCompiler},
bytecompiler::{Access, ByteCompiler, Operand},
vm::Opcode,
};
@ -29,7 +29,7 @@ impl ByteCompiler<'_, '_> {
Expression::Identifier(identifier) => {
let binding = self.get_binding_value(*identifier);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::GetNameOrUndefined, &[index]);
self.emit(Opcode::GetNameOrUndefined, &[Operand::U32(index)]);
}
expr => self.compile_expr(expr, true),
}
@ -45,7 +45,7 @@ impl ByteCompiler<'_, '_> {
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
}

42
boa_engine/src/bytecompiler/expression/update.rs

@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler},
bytecompiler::{Access, ByteCompiler, Operand},
environments::BindingLocatorError,
vm::Opcode,
};
@ -28,9 +28,9 @@ impl ByteCompiler<'_, '_> {
let lex = self.current_environment.is_lex_binding(name);
if lex {
self.emit(Opcode::GetName, &[index]);
self.emit(Opcode::GetName, &[Operand::U32(index)]);
} else {
self.emit(Opcode::GetNameAndLocator, &[index]);
self.emit(Opcode::GetNameAndLocator, &[Operand::U32(index)]);
}
self.emit_opcode(opcode);
@ -44,14 +44,14 @@ impl ByteCompiler<'_, '_> {
match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
} else {
@ -67,14 +67,13 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(4);
self.emit(Opcode::RotateRight, &[Operand::U8(4)]);
}
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if post {
self.emit_opcode(Opcode::Pop);
}
@ -89,8 +88,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::GetPropertyByValuePush);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(5);
self.emit(Opcode::RotateRight, &[Operand::U8(5)]);
}
self.emit_opcode(Opcode::SetPropertyByValue);
@ -104,14 +102,13 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPrivateField, &[index]);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(3);
self.emit(Opcode::RotateRight, &[Operand::U8(3)]);
}
self.emit(Opcode::SetPrivateField, &[index]);
self.emit(Opcode::SetPrivateField, &[Operand::U32(index)]);
if post {
self.emit_opcode(Opcode::Pop);
}
@ -125,14 +122,13 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(3);
self.emit(Opcode::RotateRight, &[Operand::U8(3)]);
}
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if post {
self.emit_opcode(Opcode::Pop);
}
@ -146,13 +142,11 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::GetPropertyByValuePush);
self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(2);
self.emit(Opcode::RotateRight, &[Operand::U8(2)]);
}
self.emit_opcode(Opcode::This);
self.emit_opcode(Opcode::RotateRight);
self.emit_u8(2);
self.emit(Opcode::RotateRight, &[Operand::U8(2)]);
self.emit_opcode(Opcode::SetPropertyByValue);
if post {

270
boa_engine/src/bytecompiler/mod.rs

@ -210,6 +210,21 @@ impl Access<'_> {
}
}
/// An opcode operand.
#[derive(Debug, Clone, Copy)]
#[allow(unused)]
pub(crate) enum Operand {
Bool(bool),
I8(i8),
U8(u8),
I16(i16),
U16(u16),
I32(i32),
U32(u32),
I64(i64),
U64(u64),
}
/// The [`ByteCompiler`] is used to compile ECMAScript AST from [`boa_ast`] to bytecode.
#[derive(Debug)]
#[allow(clippy::struct_excessive_bools)]
@ -390,50 +405,50 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
BindingOpcode::Var => {
let binding = self.initialize_mutable_binding(name, true);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefVar, &[index]);
self.emit(Opcode::DefVar, &[Operand::U32(index)]);
}
BindingOpcode::InitVar => {
if self.has_binding(name) {
match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
} else {
let binding = self.initialize_mutable_binding(name, true);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
};
}
BindingOpcode::InitLet => {
let binding = self.initialize_mutable_binding(name, false);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::PutLexicalValue, &[index]);
self.emit(Opcode::PutLexicalValue, &[Operand::U32(index)]);
}
BindingOpcode::InitConst => {
let binding = self.initialize_immutable_binding(name);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::PutLexicalValue, &[index]);
self.emit(Opcode::PutLexicalValue, &[Operand::U32(index)]);
}
BindingOpcode::SetName => match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
},
}
@ -444,52 +459,80 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.bytecode.len() as u32
}
pub(crate) fn emit(&mut self, opcode: Opcode, operands: &[u32]) {
pub(crate) fn emit(&mut self, opcode: Opcode, operands: &[Operand]) {
self.emit_opcode(opcode);
for operand in operands {
self.emit_u32(*operand);
self.emit_operand(*operand);
}
}
pub(crate) fn emit_operand(&mut self, operand: Operand) {
match operand {
Operand::Bool(v) => self.emit_u8(v.into()),
Operand::I8(v) => self.emit_i8(v),
Operand::U8(v) => self.emit_u8(v),
Operand::I16(v) => self.emit_i16(v),
Operand::U16(v) => self.emit_u16(v),
Operand::I32(v) => self.emit_i32(v),
Operand::U32(v) => self.emit_u32(v),
Operand::I64(v) => self.emit_i64(v),
Operand::U64(v) => self.emit_u64(v),
}
}
fn emit_i64(&mut self, value: i64) {
self.emit_u64(value as u64);
}
fn emit_u64(&mut self, value: u64) {
self.bytecode.extend(value.to_ne_bytes());
}
fn emit_i32(&mut self, value: i32) {
self.emit_u32(value as u32);
}
fn emit_u32(&mut self, value: u32) {
self.bytecode.extend(value.to_ne_bytes());
}
fn emit_i16(&mut self, value: i16) {
self.emit_u16(value as u16);
}
fn emit_u16(&mut self, value: u16) {
self.bytecode.extend(value.to_ne_bytes());
}
pub(crate) fn emit_opcode(&mut self, opcode: Opcode) {
self.emit_u8(opcode as u8);
fn emit_i8(&mut self, value: i8) {
self.emit_u8(value as u8);
}
fn emit_u8(&mut self, value: u8) {
self.bytecode.push(value);
}
pub(crate) fn emit_opcode(&mut self, opcode: Opcode) {
self.emit_u8(opcode as u8);
}
fn emit_push_integer(&mut self, value: i32) {
match value {
0 => self.emit_opcode(Opcode::PushZero),
1 => self.emit_opcode(Opcode::PushOne),
x if i32::from(x as i8) == x => {
self.emit_opcode(Opcode::PushInt8);
self.emit_u8(x as i8 as u8);
self.emit(Opcode::PushInt8, &[Operand::I8(x as i8)]);
}
x if i32::from(x as i16) == x => {
self.emit_opcode(Opcode::PushInt16);
self.emit_u16(x as i16 as u16);
self.emit(Opcode::PushInt16, &[Operand::I16(x as i16)]);
}
x => self.emit(Opcode::PushInt32, &[x as _]),
x => self.emit(Opcode::PushInt32, &[Operand::I32(x)]),
}
}
fn emit_push_literal(&mut self, literal: Literal) {
let index = self.get_or_insert_literal(literal);
self.emit(Opcode::PushLiteral, &[index]);
self.emit(Opcode::PushLiteral, &[Operand::U32(index)]);
}
fn emit_push_rational(&mut self, value: f64) {
@ -508,8 +551,14 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
if f64::from(value as i32).to_bits() == value.to_bits() {
self.emit_push_integer(value as i32);
} else {
self.emit_opcode(Opcode::PushRational);
self.emit_u64(value.to_bits());
let f32_value = value as f32;
#[allow(clippy::float_cmp)]
if f64::from(f32_value) == value {
self.emit(Opcode::PushFloat, &[Operand::U32(f32_value.to_bits())]);
} else {
self.emit(Opcode::PushDouble, &[Operand::U64(value.to_bits())]);
}
}
}
@ -529,6 +578,10 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.emit_opcode_with_operand(Opcode::JumpIfNullOrUndefined)
}
fn emit_resume_kind(&mut self, resume_kind: GeneratorResumeKind) {
self.emit_push_integer(resume_kind as i32);
}
fn jump_if_not_resume_kind(&mut self, resume_kind: GeneratorResumeKind) -> Label {
let label = self.emit_opcode_with_operand(Opcode::JumpIfNotResumeKind);
self.emit_u8(resume_kind as u8);
@ -540,7 +593,10 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
/// Returns the jump label entries and the default label.
fn jump_table(&mut self, count: u32) -> (Vec<Label>, Label) {
let index = self.next_opcode_location();
self.emit(Opcode::JumpTable, &[count, Self::DUMMY_ADDRESS]);
self.emit(
Opcode::JumpTable,
&[Operand::U32(count), Operand::U32(Self::DUMMY_ADDRESS)],
);
let default = Label { index: index + 4 };
let mut labels = Vec::with_capacity(count as usize);
for i in 0..count {
@ -557,7 +613,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
/// Return the `Label` of the operand.
pub(crate) fn emit_opcode_with_operand(&mut self, opcode: Opcode) -> Label {
let index = self.next_opcode_location();
self.emit(opcode, &[Self::DUMMY_ADDRESS]);
self.emit(opcode, &[Operand::U32(Self::DUMMY_ADDRESS)]);
Label { index }
}
@ -565,7 +621,13 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
/// Return the `Label`s of the two operands.
pub(crate) fn emit_opcode_with_two_operands(&mut self, opcode: Opcode) -> (Label, Label) {
let index = self.next_opcode_location();
self.emit(opcode, &[Self::DUMMY_ADDRESS, Self::DUMMY_ADDRESS]);
self.emit(
opcode,
&[
Operand::U32(Self::DUMMY_ADDRESS),
Operand::U32(Self::DUMMY_ADDRESS),
],
);
(Label { index }, Label { index: index + 4 })
}
@ -592,7 +654,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
Access::Variable { name } => {
let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::GetName, &[index]);
self.emit(Opcode::GetName, &[Operand::U32(index)]);
}
Access::Property { access } => match access {
PropertyAccess::Simple(access) => match access.field() {
@ -600,7 +662,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
let index = self.get_or_insert_name((*name).into());
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
@ -612,14 +674,14 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccess::Private(access) => {
let index = self.get_or_insert_private_name(access.field());
self.compile_expr(access.target(), true);
self.emit(Opcode::GetPrivateField, &[index]);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
}
PropertyAccess::Super(access) => match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
self.emit_opcode(Opcode::Super);
self.emit_opcode(Opcode::This);
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(expr) => {
self.emit_opcode(Opcode::Super);
@ -630,12 +692,12 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
},
},
Access::This => {
self.emit(Opcode::This, &[]);
self.emit_opcode(Opcode::This);
}
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
@ -644,8 +706,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
0 => {}
1 => compiler.emit_opcode(Opcode::Swap),
_ => {
compiler.emit_opcode(Opcode::RotateLeft);
compiler.emit_u8(level + 1);
compiler.emit(Opcode::RotateLeft, &[Operand::U8(level + 1)]);
}
}
}
@ -661,7 +722,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
let lex = self.current_environment.is_lex_binding(name);
if !lex {
self.emit(Opcode::GetLocator, &[index]);
self.emit(Opcode::GetLocator, &[Operand::U32(index)]);
}
expr_fn(self, 0);
@ -673,14 +734,14 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
match self.set_mutable_binding(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
} else {
@ -695,9 +756,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
expr_fn(self, 2);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
PropertyAccessField::Expr(expr) => {
@ -715,9 +776,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.compile_expr(access.target(), true);
expr_fn(self, 1);
let index = self.get_or_insert_private_name(access.field());
self.emit(Opcode::SetPrivateField, &[index]);
self.emit(Opcode::SetPrivateField, &[Operand::U32(index)]);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
PropertyAccess::Super(access) => match access.field() {
@ -726,9 +787,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.emit_opcode(Opcode::This);
expr_fn(self, 1);
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::SetPropertyByName, &[index]);
self.emit(Opcode::SetPropertyByName, &[Operand::U32(index)]);
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
PropertyAccessField::Expr(expr) => {
@ -754,7 +815,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
PropertyAccessField::Const(name) => {
let index = self.get_or_insert_name((*name).into());
self.compile_expr(access.target(), true);
self.emit(Opcode::DeletePropertyByName, &[index]);
self.emit(Opcode::DeletePropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
@ -771,7 +832,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
Access::Variable { name } => {
let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DeleteName, &[index]);
self.emit(Opcode::DeleteName, &[Operand::U32(index)]);
}
Access::This => {
self.emit_opcode(Opcode::PushTrue);
@ -844,7 +905,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(field) => {
self.compile_expr(field, true);
@ -856,7 +917,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
let index = self.get_or_insert_private_name(access.field());
self.emit(Opcode::GetPrivateField, &[index]);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
}
PropertyAccess::Super(access) => {
self.emit_opcode(Opcode::This);
@ -865,7 +926,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
match access.field() {
PropertyAccessField::Const(field) => {
let index = self.get_or_insert_name((*field).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(expr, true);
@ -951,23 +1012,21 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
match field {
PropertyAccessField::Const(name) => {
let index = self.get_or_insert_name((*name).into());
self.emit(Opcode::GetPropertyByName, &[index]);
self.emit(Opcode::GetPropertyByName, &[Operand::U32(index)]);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(expr, true);
self.emit_opcode(Opcode::GetPropertyByValue);
}
}
self.emit_opcode(Opcode::RotateLeft);
self.emit_u8(3);
self.emit(Opcode::RotateLeft, &[Operand::U8(3)]);
self.emit_opcode(Opcode::Pop);
}
OptionalOperationKind::PrivatePropertyAccess { field } => {
self.emit_opcode(Opcode::Dup);
let index = self.get_or_insert_private_name(*field);
self.emit(Opcode::GetPrivateField, &[index]);
self.emit_opcode(Opcode::RotateLeft);
self.emit_u8(3);
self.emit(Opcode::GetPrivateField, &[Operand::U32(index)]);
self.emit(Opcode::RotateLeft, &[Operand::U8(3)]);
self.emit_opcode(Opcode::Pop);
}
OptionalOperationKind::Call { args } => {
@ -990,7 +1049,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
for arg in args {
self.compile_expr(arg, true);
}
self.emit(Opcode::Call, &[args.len() as u32]);
self.emit(Opcode::Call, &[Operand::U32(args.len() as u32)]);
}
self.emit_opcode(Opcode::PushUndefined);
@ -1099,19 +1158,19 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
if self.annex_b_function_names.contains(&name) {
let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::GetName, &[index]);
self.emit(Opcode::GetName, &[Operand::U32(index)]);
match self.set_mutable_binding_var(name) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::SetName, &[index]);
self.emit(Opcode::SetName, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(name);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
}
@ -1186,20 +1245,29 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
let index = self.function(function);
if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
self.emit(Opcode::GetGeneratorAsync, &[Operand::U32(index)]);
} else if generator {
self.emit(Opcode::GetGenerator, &[index]);
self.emit(Opcode::GetGenerator, &[Operand::U32(index)]);
} else if r#async && arrow {
self.emit(Opcode::GetAsyncArrowFunction, &[index]);
self.emit(
Opcode::GetAsyncArrowFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
} else if r#async {
self.emit(Opcode::GetFunctionAsync, &[index]);
self.emit(
Opcode::GetFunctionAsync,
&[Operand::U32(index), Operand::Bool(false)],
);
} else if arrow {
self.emit(Opcode::GetArrowFunction, &[index]);
self.emit(
Opcode::GetArrowFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
} else {
self.emit(Opcode::GetFunction, &[index]);
}
if !generator {
self.emit_u8(0);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(false)],
);
}
match node_kind {
@ -1211,7 +1279,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}
NodeKind::Expression => {
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
}
@ -1260,20 +1328,29 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.functions.push(code);
if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
self.emit(Opcode::GetGeneratorAsync, &[Operand::U32(index)]);
} else if generator {
self.emit(Opcode::GetGenerator, &[index]);
self.emit(Opcode::GetGenerator, &[Operand::U32(index)]);
} else if r#async && arrow {
self.emit(Opcode::GetAsyncArrowFunction, &[index]);
self.emit(
Opcode::GetAsyncArrowFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
} else if r#async {
self.emit(Opcode::GetFunctionAsync, &[index]);
self.emit(
Opcode::GetFunctionAsync,
&[Operand::U32(index), Operand::Bool(true)],
);
} else if arrow {
self.emit(Opcode::GetArrowFunction, &[index]);
self.emit(
Opcode::GetArrowFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
} else {
self.emit(Opcode::GetFunction, &[index]);
}
if !generator {
self.emit_u8(1);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
}
}
@ -1321,20 +1398,29 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.functions.push(code);
if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
self.emit(Opcode::GetGeneratorAsync, &[Operand::U32(index)]);
} else if generator {
self.emit(Opcode::GetGenerator, &[index]);
self.emit(Opcode::GetGenerator, &[Operand::U32(index)]);
} else if r#async && arrow {
self.emit(Opcode::GetAsyncArrowFunction, &[index]);
self.emit(
Opcode::GetAsyncArrowFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
} else if r#async {
self.emit(Opcode::GetFunctionAsync, &[index]);
self.emit(
Opcode::GetFunctionAsync,
&[Operand::U32(index), Operand::Bool(true)],
);
} else if arrow {
self.emit(Opcode::GetArrowFunction, &[index]);
self.emit(
Opcode::GetArrowFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
} else {
self.emit(Opcode::GetFunction, &[index]);
}
if !generator {
self.emit_u8(1);
self.emit(
Opcode::GetFunction,
&[Operand::U32(index), Operand::Bool(true)],
);
}
}
@ -1398,15 +1484,17 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
match kind {
CallKind::CallEval if contains_spread => self.emit_opcode(Opcode::CallEvalSpread),
CallKind::CallEval => self.emit(Opcode::CallEval, &[call.args().len() as u32]),
CallKind::CallEval => {
self.emit(Opcode::CallEval, &[Operand::U32(call.args().len() as u32)]);
}
CallKind::Call if contains_spread => self.emit_opcode(Opcode::CallSpread),
CallKind::Call => self.emit(Opcode::Call, &[call.args().len() as u32]),
CallKind::Call => self.emit(Opcode::Call, &[Operand::U32(call.args().len() as u32)]),
CallKind::New if contains_spread => self.emit_opcode(Opcode::NewSpread),
CallKind::New => self.emit(Opcode::New, &[call.args().len() as u32]),
CallKind::New => self.emit(Opcode::New, &[Operand::U32(call.args().len() as u32)]),
}
if !use_expr {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}

5
boa_engine/src/bytecompiler/module.rs

@ -1,6 +1,6 @@
use crate::vm::{BindingOpcode, Opcode};
use super::{ByteCompiler, Literal};
use super::{ByteCompiler, Literal, Operand};
use boa_ast::{declaration::ExportDeclaration, expression::Identifier, ModuleItem, ModuleItemList};
use boa_interner::Sym;
@ -63,8 +63,7 @@ impl ByteCompiler<'_, '_> {
.into_common(false);
self.emit_push_literal(Literal::String(default));
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
self.emit(Opcode::SetFunctionName, &[Operand::U8(0)]);
}
self.emit_binding(BindingOpcode::InitLet, name);

22
boa_engine/src/bytecompiler/statement/loop.rs

@ -9,7 +9,7 @@ use boa_ast::{
use boa_interner::Sym;
use crate::{
bytecompiler::{Access, ByteCompiler},
bytecompiler::{Access, ByteCompiler, Operand},
environments::BindingLocatorError,
vm::{BindingOpcode, Opcode},
};
@ -69,13 +69,13 @@ impl ByteCompiler<'_, '_> {
if let Some(let_binding_indices) = let_binding_indices {
for index in &let_binding_indices {
self.emit(Opcode::GetName, &[*index]);
self.emit(Opcode::GetName, &[Operand::U32(*index)]);
}
self.emit_opcode(Opcode::PopEnvironment);
iteration_env_labels =
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment));
for index in let_binding_indices.iter().rev() {
self.emit(Opcode::PutLexicalValue, &[*index]);
self.emit(Opcode::PutLexicalValue, &[Operand::U32(*index)]);
}
}
@ -96,7 +96,7 @@ impl ByteCompiler<'_, '_> {
self.compile_stmt(for_loop.body(), use_expr, true);
self.emit(Opcode::Jump, &[start_address]);
self.emit(Opcode::Jump, &[Operand::U32(start_address)]);
self.patch_jump(exit);
self.pop_loop_control_info();
@ -225,7 +225,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::PopEnvironment);
}
self.emit(Opcode::Jump, &[start_address]);
self.emit(Opcode::Jump, &[Operand::U32(start_address)]);
self.patch_jump(exit);
self.pop_loop_control_info();
@ -303,14 +303,14 @@ impl ByteCompiler<'_, '_> {
match self.set_mutable_binding(*ident) {
Ok(binding) => {
let index = self.get_or_insert_binding(binding);
self.emit(Opcode::DefInitVar, &[index]);
self.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
}
Err(BindingLocatorError::MutateImmutable) => {
let index = self.get_or_insert_name(*ident);
self.emit(Opcode::ThrowMutateImmutable, &[index]);
self.emit(Opcode::ThrowMutateImmutable, &[Operand::U32(index)]);
}
Err(BindingLocatorError::Silent) => {
self.emit(Opcode::Pop, &[]);
self.emit_opcode(Opcode::Pop);
}
}
}
@ -394,7 +394,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::PopEnvironment);
}
self.emit(Opcode::Jump, &[start_address]);
self.emit(Opcode::Jump, &[Operand::U32(start_address)]);
self.patch_jump(exit);
self.pop_loop_control_info();
@ -417,7 +417,7 @@ impl ByteCompiler<'_, '_> {
self.compile_stmt(while_loop.body(), use_expr, true);
self.emit(Opcode::Jump, &[start_address]);
self.emit(Opcode::Jump, &[Operand::U32(start_address)]);
self.patch_jump(exit);
self.pop_loop_control_info();
@ -444,7 +444,7 @@ impl ByteCompiler<'_, '_> {
self.compile_stmt(do_while_loop.body(), use_expr, true);
self.emit(Opcode::Jump, &[condition_label_address]);
self.emit(Opcode::Jump, &[Operand::U32(condition_label_address)]);
self.patch_jump(exit);
self.pop_loop_control_info();

11
boa_engine/src/bytecompiler/utils.rs

@ -3,7 +3,7 @@ use crate::{
vm::{GeneratorResumeKind, Opcode},
};
use super::{ByteCompiler, Literal};
use super::{ByteCompiler, Literal, Operand};
impl ByteCompiler<'_, '_> {
/// Closes an iterator
@ -36,7 +36,7 @@ impl ByteCompiler<'_, '_> {
let error_msg = self.get_or_insert_literal(Literal::String(js_string!(
"inner result was not an object"
)));
self.emit(Opcode::ThrowNewTypeError, &[error_msg]);
self.emit(Opcode::ThrowNewTypeError, &[Operand::U32(error_msg)]);
self.patch_jump(skip_return);
self.emit_opcode(Opcode::IteratorPop);
@ -51,7 +51,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::IteratorStackEmpty);
let empty = self.jump_if_true();
self.iterator_close(self.in_async_generator());
self.emit(Opcode::Jump, &[start]);
self.emit(Opcode::Jump, &[Operand::U32(start)]);
self.patch_jump(empty);
}
@ -72,8 +72,7 @@ impl ByteCompiler<'_, '_> {
self.async_generator_yield();
} else {
// 3. Otherwise, return ? GeneratorYield(CreateIterResultObject(value, false)).
self.emit_opcode(Opcode::CreateIteratorResult);
self.emit_u8(u8::from(false));
self.emit(Opcode::CreateIteratorResult, &[Operand::Bool(false)]);
self.emit_opcode(Opcode::GeneratorYield);
}
@ -108,7 +107,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Pop);
// Stack: received
self.emit_push_integer(GeneratorResumeKind::Return as i32);
self.emit_resume_kind(GeneratorResumeKind::Return);
// Stack: resume_kind(Return) received
self.patch_jump(non_normal_resume);

4
boa_engine/src/module/source.rs

@ -22,7 +22,7 @@ use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
use crate::{
builtins::{promise::PromiseCapability, Promise},
bytecompiler::{ByteCompiler, FunctionSpec},
bytecompiler::{ByteCompiler, FunctionSpec, Operand},
environments::{BindingLocator, CompileTimeEnvironment, EnvironmentStack},
module::ModuleKind,
object::{FunctionObjectBuilder, JsPromise, RecursionLimiter},
@ -1501,7 +1501,7 @@ impl SourceTextModule {
let binding = compiler.initialize_mutable_binding(name, false);
let index = compiler.get_or_insert_binding(binding);
compiler.emit_opcode(Opcode::PushUndefined);
compiler.emit(Opcode::DefInitVar, &[index]);
compiler.emit(Opcode::DefInitVar, &[Operand::U32(index)]);
// 3. Append dn to declaredVarNames.
declared_var_names.push(name);
}

10
boa_engine/src/vm/code_block.rs

@ -340,7 +340,12 @@ impl CodeBlock {
*pc += size_of::<i32>();
result
}
Opcode::PushRational => {
Opcode::PushFloat => {
let operand = self.read::<f32>(*pc);
*pc += size_of::<f32>();
ryu_js::Buffer::new().format(operand).to_string()
}
Opcode::PushDouble => {
let operand = self.read::<f64>(*pc);
*pc += size_of::<f64>();
ryu_js::Buffer::new().format(operand).to_string()
@ -676,8 +681,7 @@ impl CodeBlock {
| Opcode::Reserved55
| Opcode::Reserved56
| Opcode::Reserved57
| Opcode::Reserved58
| Opcode::Reserved59 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved58 => unreachable!("Reserved opcodes are unrechable"),
}
}
}

11
boa_engine/src/vm/flowgraph/mod.rs

@ -84,7 +84,13 @@ impl CodeBlock {
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
}
Opcode::PushRational => {
Opcode::PushFloat => {
pc += size_of::<f32>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
graph.add_edge(previous_pc, pc, None, Color::None, EdgeStyle::Line);
}
Opcode::PushDouble => {
pc += size_of::<f64>();
graph.add_node(previous_pc, NodeShape::None, label.into(), Color::None);
@ -611,8 +617,7 @@ impl CodeBlock {
| Opcode::Reserved55
| Opcode::Reserved56
| Opcode::Reserved57
| Opcode::Reserved58
| Opcode::Reserved59 => unreachable!("Reserved opcodes are unrechable"),
| Opcode::Reserved58 => unreachable!("Reserved opcodes are unrechable"),
}
}

13
boa_engine/src/vm/opcode/mod.rs

@ -249,12 +249,19 @@ generate_impl! {
/// Stack: **=>** value
PushInt32,
/// Push `f32` value on the stack.
///
/// Operands: value: `f32`
///
/// Stack: **=>** value
PushFloat,
/// Push `f64` value on the stack.
///
/// Operands: value: `f64`
///
/// Stack: **=>** value
PushRational,
PushDouble,
/// Push `NaN` integer on the stack.
///
@ -1255,7 +1262,7 @@ generate_impl! {
/// Get function from the pre-compiled inner functions.
///
/// Operands: address: `u32`, method: `u8`
/// Operands: address: `u32`, is_method: `u8`
///
/// Stack: **=>** func
GetFunction,
@ -1788,8 +1795,6 @@ generate_impl! {
Reserved57 => Reserved,
/// Reserved [`Opcode`].
Reserved58 => Reserved,
/// Reserved [`Opcode`].
Reserved59 => Reserved,
}
}

3
boa_engine/src/vm/opcode/push/numbers.rs

@ -51,4 +51,5 @@ implement_push_numbers_with_conversion!(PushInt8, i8, "Push `i8` value on the st
implement_push_numbers_with_conversion!(PushInt16, i16, "Push `i16` value on the stack");
implement_push_numbers_no_conversion!(PushInt32, i32, "Push `i32` value on the stack");
implement_push_numbers_no_conversion!(PushRational, f64, "Push `f64` value on the stack");
implement_push_numbers_no_conversion!(PushFloat, f32, "Push `f64` value on the stack");
implement_push_numbers_no_conversion!(PushDouble, f64, "Push `f64` value on the stack");

Loading…
Cancel
Save