diff --git a/boa_engine/src/bytecompiler/class.rs b/boa_engine/src/bytecompiler/class.rs index 81ee0bf846d..e4bb14803cd 100644 --- a/boa_engine/src/bytecompiler/class.rs +++ b/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 = 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); diff --git a/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs b/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs index a0a34b723c8..ab8149c5c5d 100644 --- a/boa_engine/src/bytecompiler/declaration/declaration_pattern.rs +++ b/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); diff --git a/boa_engine/src/bytecompiler/declarations.rs b/boa_engine/src/bytecompiler/declarations.rs index dc4ae66241f..60cdc66169b 100644 --- a/boa_engine/src/bytecompiler/declarations.rs +++ b/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); diff --git a/boa_engine/src/bytecompiler/expression/assign.rs b/boa_engine/src/bytecompiler/expression/assign.rs index f5f103646e1..8fb8f932a73 100644 --- a/boa_engine/src/bytecompiler/expression/assign.rs +++ b/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 { diff --git a/boa_engine/src/bytecompiler/expression/binary.rs b/boa_engine/src/bytecompiler/expression/binary.rs index 0d15a3189f1..c29e23c586c 100644 --- a/boa_engine/src/bytecompiler/expression/binary.rs +++ b/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); diff --git a/boa_engine/src/bytecompiler/expression/mod.rs b/boa_engine/src/bytecompiler/expression/mod.rs index 34d072c8eb5..8189e096dd7 100644 --- a/boa_engine/src/bytecompiler/expression/mod.rs +++ b/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 { diff --git a/boa_engine/src/bytecompiler/expression/object_literal.rs b/boa_engine/src/bytecompiler/expression/object_literal.rs index fd7db7c8a06..5dcf6ed55ca 100644 --- a/boa_engine/src/bytecompiler/expression/object_literal.rs +++ b/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 { diff --git a/boa_engine/src/bytecompiler/expression/unary.rs b/boa_engine/src/bytecompiler/expression/unary.rs index ff5d6708f82..e0dcf9a9374 100644 --- a/boa_engine/src/bytecompiler/expression/unary.rs +++ b/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); } } } diff --git a/boa_engine/src/bytecompiler/expression/update.rs b/boa_engine/src/bytecompiler/expression/update.rs index 61d537b0583..94fd17dde79 100644 --- a/boa_engine/src/bytecompiler/expression/update.rs +++ b/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 { diff --git a/boa_engine/src/bytecompiler/mod.rs b/boa_engine/src/bytecompiler/mod.rs index f10e050082f..1973d3d76b8 100644 --- a/boa_engine/src/bytecompiler/mod.rs +++ b/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