Browse Source

Make environments opcodes use varying operands (#3340)

pull/3350/head
Haled Odat 1 year ago committed by GitHub
parent
commit
a51581bf94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      boa_engine/src/builtins/eval/mod.rs
  2. 37
      boa_engine/src/bytecompiler/class.rs
  3. 13
      boa_engine/src/bytecompiler/declarations.rs
  4. 17
      boa_engine/src/bytecompiler/env.rs
  5. 9
      boa_engine/src/bytecompiler/function.rs
  6. 8
      boa_engine/src/bytecompiler/statement/block.rs
  7. 74
      boa_engine/src/bytecompiler/statement/loop.rs
  8. 7
      boa_engine/src/bytecompiler/statement/switch.rs
  9. 7
      boa_engine/src/bytecompiler/statement/try.rs
  10. 3
      boa_engine/src/bytecompiler/statement/with.rs
  11. 14
      boa_engine/src/vm/code_block.rs
  12. 4
      boa_engine/src/vm/opcode/mod.rs
  13. 32
      boa_engine/src/vm/opcode/push/environment.rs

9
boa_engine/src/builtins/eval/mod.rs

@ -232,16 +232,13 @@ impl Eval {
context, context,
); );
compiler.push_compile_environment(strict); let env_index = compiler.push_compile_environment(strict);
compiler.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
let push_env = compiler.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment);
compiler.eval_declaration_instantiation(&body, strict)?; compiler.eval_declaration_instantiation(&body, strict)?;
compiler.compile_statement_list(body.statements(), true, false); compiler.compile_statement_list(body.statements(), true, false);
let env_index = compiler.pop_compile_environment(); compiler.pop_compile_environment();
compiler.patch_jump_with_target(push_env, env_index);
compiler.emit_opcode(Opcode::PopEnvironment); compiler.emit_opcode(Opcode::PopEnvironment);
let code_block = Gc::new(compiler.finish()); let code_block = Gc::new(compiler.finish());

37
boa_engine/src/bytecompiler/class.rs

@ -26,13 +26,14 @@ impl ByteCompiler<'_, '_> {
pub(crate) fn compile_class(&mut self, class: &Class, expression: bool) { pub(crate) fn compile_class(&mut self, class: &Class, expression: bool) {
let class_name = class.name().map_or(Sym::EMPTY_STRING, Identifier::sym); let class_name = class.name().map_or(Sym::EMPTY_STRING, Identifier::sym);
let class_env: Option<super::Label> = match class.name() { let class_env = match class.name() {
Some(name) if class.has_binding_identifier() => { Some(name) if class.has_binding_identifier() => {
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
self.create_immutable_binding(name, true); self.create_immutable_binding(name, true);
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment)) self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
true
} }
_ => None, _ => false,
}; };
let mut compiler = ByteCompiler::new( let mut compiler = ByteCompiler::new(
@ -43,7 +44,8 @@ impl ByteCompiler<'_, '_> {
self.context, self.context,
); );
compiler.push_compile_environment(true); // Function environment
let _ = compiler.push_compile_environment(true);
if let Some(expr) = class.constructor() { if let Some(expr) = class.constructor() {
compiler.length = expr.parameters().length(); compiler.length = expr.parameters().length();
@ -59,15 +61,11 @@ impl ByteCompiler<'_, '_> {
compiler.compile_statement_list(expr.body().statements(), false, false); compiler.compile_statement_list(expr.body().statements(), false, false);
let env_index = compiler.pop_compile_environment(); if env_label {
if let Some(env_label) = env_label {
compiler.patch_jump_with_target(env_label, env_index);
compiler.pop_compile_environment(); compiler.pop_compile_environment();
} else { } else {
compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR; compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR;
} }
compiler.emit_opcode(Opcode::PushUndefined); compiler.emit_opcode(Opcode::PushUndefined);
} else { } else {
if class.super_ref().is_some() { if class.super_ref().is_some() {
@ -76,10 +74,10 @@ impl ByteCompiler<'_, '_> {
compiler.emit_opcode(Opcode::RestParameterPop); compiler.emit_opcode(Opcode::RestParameterPop);
compiler.emit_opcode(Opcode::PushUndefined); compiler.emit_opcode(Opcode::PushUndefined);
} }
compiler.pop_compile_environment();
compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR; compiler.code_block_flags |= CodeBlockFlags::IS_CLASS_CONSTRUCTOR;
} }
compiler.emit_opcode(Opcode::SetReturnValue); compiler.emit_opcode(Opcode::SetReturnValue);
compiler.pop_compile_environment();
let code = Gc::new(compiler.finish()); let code = Gc::new(compiler.finish());
let index = self.functions.len() as u32; let index = self.functions.len() as u32;
@ -119,7 +117,7 @@ impl ByteCompiler<'_, '_> {
let mut static_elements = Vec::new(); let mut static_elements = Vec::new();
let mut static_field_name_count = 0; let mut static_field_name_count = 0;
if class_env.is_some() { if class_env {
self.emit_opcode(Opcode::Dup); self.emit_opcode(Opcode::Dup);
self.emit_binding(BindingOpcode::InitConst, class_name.into()); self.emit_binding(BindingOpcode::InitConst, class_name.into());
} }
@ -282,7 +280,9 @@ impl ByteCompiler<'_, '_> {
self.current_environment.clone(), self.current_environment.clone(),
self.context, self.context,
); );
field_compiler.push_compile_environment(true);
// Function environment
let _ = field_compiler.push_compile_environment(true);
if let Some(node) = field { if let Some(node) = field {
field_compiler.compile_expr(node, true); field_compiler.compile_expr(node, true);
} else { } else {
@ -314,7 +314,7 @@ impl ByteCompiler<'_, '_> {
self.current_environment.clone(), self.current_environment.clone(),
self.context, self.context,
); );
field_compiler.push_compile_environment(true); let _ = field_compiler.push_compile_environment(true);
if let Some(node) = field { if let Some(node) = field {
field_compiler.compile_expr(node, true); field_compiler.compile_expr(node, true);
} else { } else {
@ -358,7 +358,7 @@ impl ByteCompiler<'_, '_> {
self.current_environment.clone(), self.current_environment.clone(),
self.context, self.context,
); );
field_compiler.push_compile_environment(true); let _ = field_compiler.push_compile_environment(true);
if let Some(node) = field { if let Some(node) = field {
field_compiler.compile_expr(node, true); field_compiler.compile_expr(node, true);
} else { } else {
@ -393,7 +393,7 @@ impl ByteCompiler<'_, '_> {
self.current_environment.clone(), self.current_environment.clone(),
self.context, self.context,
); );
compiler.push_compile_environment(true); let _ = compiler.push_compile_environment(true);
compiler.function_declaration_instantiation( compiler.function_declaration_instantiation(
body, body,
@ -589,9 +589,8 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::Swap); self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::Pop); self.emit_opcode(Opcode::Pop);
if let Some(class_env) = class_env { if class_env {
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(class_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }

13
boa_engine/src/bytecompiler/declarations.rs

@ -1,5 +1,5 @@
use crate::{ use crate::{
bytecompiler::{ByteCompiler, FunctionCompiler, FunctionSpec, Label, NodeKind}, bytecompiler::{ByteCompiler, FunctionCompiler, FunctionSpec, NodeKind},
environments::BindingLocatorError, environments::BindingLocatorError,
vm::{ vm::{
create_function_object_fast, create_generator_function_object, BindingOpcode, create_function_object_fast, create_generator_function_object, BindingOpcode,
@ -809,8 +809,8 @@ impl ByteCompiler<'_, '_> {
arrow: bool, arrow: bool,
strict: bool, strict: bool,
generator: bool, generator: bool,
) -> (Option<Label>, bool) { ) -> (bool, bool) {
let mut env_label = None; let mut env_label = false;
let mut additional_env = false; let mut additional_env = false;
// 1. Let calleeContext be the running execution context. // 1. Let calleeContext be the running execution context.
@ -910,7 +910,7 @@ impl ByteCompiler<'_, '_> {
// c. Let env be NewDeclarativeEnvironment(calleeEnv). // c. Let env be NewDeclarativeEnvironment(calleeEnv).
// d. Assert: The VariableEnvironment of calleeContext is calleeEnv. // d. Assert: The VariableEnvironment of calleeContext is calleeEnv.
// e. Set the LexicalEnvironment of calleeContext to env. // e. Set the LexicalEnvironment of calleeContext to env.
self.push_compile_environment(false); let _ = self.push_compile_environment(false);
additional_env = true; additional_env = true;
} }
@ -1030,8 +1030,9 @@ impl ByteCompiler<'_, '_> {
// visibility of declarations in the function body. // visibility of declarations in the function body.
// b. Let varEnv be NewDeclarativeEnvironment(env). // b. Let varEnv be NewDeclarativeEnvironment(env).
// c. Set the VariableEnvironment of calleeContext to varEnv. // c. Set the VariableEnvironment of calleeContext to varEnv.
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
env_label = Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment)); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
env_label = true;
// d. Let instantiatedVarNames be a new empty List. // d. Let instantiatedVarNames be a new empty List.
let mut instantiated_var_names = Vec::new(); let mut instantiated_var_names = Vec::new();

17
boa_engine/src/bytecompiler/env.rs

@ -6,29 +6,32 @@ use boa_ast::expression::Identifier;
impl ByteCompiler<'_, '_> { impl ByteCompiler<'_, '_> {
/// Push either a new declarative or function environment on the compile time environment stack. /// Push either a new declarative or function environment on the compile time environment stack.
pub(crate) fn push_compile_environment(&mut self, function_scope: bool) { #[must_use]
pub(crate) fn push_compile_environment(&mut self, function_scope: bool) -> u32 {
self.current_open_environments_count += 1; self.current_open_environments_count += 1;
self.current_environment = Rc::new(CompileTimeEnvironment::new( self.current_environment = Rc::new(CompileTimeEnvironment::new(
self.current_environment.clone(), self.current_environment.clone(),
function_scope, function_scope,
)); ));
let index = self.compile_environments.len() as u32;
self.compile_environments
.push(self.current_environment.clone());
index
} }
/// Pops the top compile time environment and returns its index in the compile time environments array. /// Pops the top compile time environment and returns its index in the compile time environments array.
#[track_caller] #[track_caller]
pub(crate) fn pop_compile_environment(&mut self) -> u32 { pub(crate) fn pop_compile_environment(&mut self) {
self.current_open_environments_count -= 1; self.current_open_environments_count -= 1;
let index = self.compile_environments.len() as u32;
self.compile_environments
.push(self.current_environment.clone());
let outer = self let outer = self
.current_environment .current_environment
.outer() .outer()
.expect("cannot pop the global environment"); .expect("cannot pop the global environment");
self.current_environment = outer; self.current_environment = outer;
index
} }
/// Get the binding locator of the binding at bytecode compile time. /// Get the binding locator of the binding at bytecode compile time.

9
boa_engine/src/bytecompiler/function.rs

@ -100,12 +100,12 @@ impl FunctionCompiler {
if let Some(binding_identifier) = self.binding_identifier { if let Some(binding_identifier) = self.binding_identifier {
compiler.code_block_flags |= CodeBlockFlags::HAS_BINDING_IDENTIFIER; compiler.code_block_flags |= CodeBlockFlags::HAS_BINDING_IDENTIFIER;
compiler.push_compile_environment(false); let _ = compiler.push_compile_environment(false);
compiler.create_immutable_binding(binding_identifier.into(), self.strict); compiler.create_immutable_binding(binding_identifier.into(), self.strict);
} }
// Function environment // Function environment
compiler.push_compile_environment(true); let _ = compiler.push_compile_environment(true);
// Taken from: // Taken from:
// - 15.9.3 Runtime Semantics: EvaluateAsyncConciseBody: <https://tc39.es/ecma262/#sec-runtime-semantics-evaluateasyncconcisebody> // - 15.9.3 Runtime Semantics: EvaluateAsyncConciseBody: <https://tc39.es/ecma262/#sec-runtime-semantics-evaluateasyncconcisebody>
@ -155,9 +155,8 @@ impl FunctionCompiler {
compiler.compile_statement_list(body.statements(), false, false); compiler.compile_statement_list(body.statements(), false, false);
if let Some(env_labels) = env_label { if env_label {
let env_index = compiler.pop_compile_environment(); compiler.pop_compile_environment();
compiler.patch_jump_with_target(env_labels, env_index);
} }
if additional_env { if additional_env {

8
boa_engine/src/bytecompiler/statement/block.rs

@ -4,15 +4,13 @@ use boa_ast::statement::Block;
impl ByteCompiler<'_, '_> { impl ByteCompiler<'_, '_> {
/// Compile a [`Block`] `boa_ast` node /// Compile a [`Block`] `boa_ast` node
pub(crate) fn compile_block(&mut self, block: &Block, use_expr: bool) { pub(crate) fn compile_block(&mut self, block: &Block, use_expr: bool) {
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
let push_env = self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.block_declaration_instantiation(block); self.block_declaration_instantiation(block);
self.compile_statement_list(block.statement_list(), use_expr, true); self.compile_statement_list(block.statement_list(), use_expr, true);
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(push_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }
} }

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

@ -22,8 +22,7 @@ impl ByteCompiler<'_, '_> {
use_expr: bool, use_expr: bool,
) { ) {
let mut let_binding_indices = None; let mut let_binding_indices = None;
let mut env_labels = None; let mut has_lexical_environment_binding = false;
let mut iteration_env_labels = None;
if let Some(init) = for_loop.init() { if let Some(init) = for_loop.init() {
match init { match init {
@ -32,9 +31,9 @@ impl ByteCompiler<'_, '_> {
self.compile_var_decl(decl); self.compile_var_decl(decl);
} }
ForLoopInitializer::Lexical(decl) => { ForLoopInitializer::Lexical(decl) => {
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
env_labels = self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment)); has_lexical_environment_binding = true;
let names = bound_names(decl); let names = bound_names(decl);
if decl.is_const() { if decl.is_const() {
@ -49,7 +48,7 @@ impl ByteCompiler<'_, '_> {
let index = self.get_or_insert_binding(binding); let index = self.get_or_insert_binding(binding);
indices.push(index); indices.push(index);
} }
let_binding_indices = Some(indices); let_binding_indices = Some((indices, env_index));
} }
self.compile_lexical_decl(decl); self.compile_lexical_decl(decl);
} }
@ -67,13 +66,14 @@ impl ByteCompiler<'_, '_> {
.expect("jump_control must exist as it was just pushed") .expect("jump_control must exist as it was just pushed")
.set_start_address(start_address); .set_start_address(start_address);
if let Some(let_binding_indices) = let_binding_indices { if let Some((let_binding_indices, env_index)) = &let_binding_indices {
for index in &let_binding_indices { for index in let_binding_indices {
self.emit_with_varying_operand(Opcode::GetName, *index); self.emit_with_varying_operand(Opcode::GetName, *index);
} }
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
iteration_env_labels = self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, *env_index);
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment));
for index in let_binding_indices.iter().rev() { for index in let_binding_indices.iter().rev() {
self.emit_with_varying_operand(Opcode::PutLexicalValue, *index); self.emit_with_varying_operand(Opcode::PutLexicalValue, *index);
} }
@ -100,16 +100,10 @@ impl ByteCompiler<'_, '_> {
self.patch_jump(exit); self.patch_jump(exit);
self.pop_loop_control_info(); self.pop_loop_control_info();
if env_labels.is_some() {
self.emit_opcode(Opcode::PopEnvironment);
}
if let Some(env_labels) = env_labels { if has_lexical_environment_binding {
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(env_labels, env_index); self.emit_opcode(Opcode::PopEnvironment);
if let Some(iteration_env_labels) = iteration_env_labels {
self.patch_jump_with_target(iteration_env_labels, env_index);
}
} }
} }
@ -136,16 +130,15 @@ impl ByteCompiler<'_, '_> {
if initializer_bound_names.is_empty() { if initializer_bound_names.is_empty() {
self.compile_expr(for_in_loop.target(), true); self.compile_expr(for_in_loop.target(), true);
} else { } else {
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
let push_env = self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
for name in &initializer_bound_names { for name in &initializer_bound_names {
self.create_mutable_binding(*name, false); self.create_mutable_binding(*name, false);
} }
self.compile_expr(for_in_loop.target(), true); self.compile_expr(for_in_loop.target(), true);
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(push_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }
@ -162,12 +155,10 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::IteratorValue); self.emit_opcode(Opcode::IteratorValue);
let iteration_environment = if initializer_bound_names.is_empty() { if !initializer_bound_names.is_empty() {
None let env_index = self.push_compile_environment(false);
} else { self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.push_compile_environment(false); }
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment))
};
match for_in_loop.initializer() { match for_in_loop.initializer() {
IterableLoopInitializer::Identifier(ident) => { IterableLoopInitializer::Identifier(ident) => {
@ -219,9 +210,8 @@ impl ByteCompiler<'_, '_> {
self.compile_stmt(for_in_loop.body(), use_expr, true); self.compile_stmt(for_in_loop.body(), use_expr, true);
if let Some(iteration_environment) = iteration_environment { if !initializer_bound_names.is_empty() {
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(iteration_environment, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }
@ -252,16 +242,15 @@ impl ByteCompiler<'_, '_> {
if initializer_bound_names.is_empty() { if initializer_bound_names.is_empty() {
self.compile_expr(for_of_loop.iterable(), true); self.compile_expr(for_of_loop.iterable(), true);
} else { } else {
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
let push_env = self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
for name in &initializer_bound_names { for name in &initializer_bound_names {
self.create_mutable_binding(*name, false); self.create_mutable_binding(*name, false);
} }
self.compile_expr(for_of_loop.iterable(), true); self.compile_expr(for_of_loop.iterable(), true);
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(push_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }
@ -290,11 +279,9 @@ impl ByteCompiler<'_, '_> {
let exit = self.jump_if_true(); let exit = self.jump_if_true();
self.emit_opcode(Opcode::IteratorValue); self.emit_opcode(Opcode::IteratorValue);
let iteration_environment = if initializer_bound_names.is_empty() { if !initializer_bound_names.is_empty() {
None let env_index = self.push_compile_environment(false);
} else { self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.push_compile_environment(false);
Some(self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment))
}; };
let mut handler_index = None; let mut handler_index = None;
@ -388,9 +375,8 @@ impl ByteCompiler<'_, '_> {
self.compile_stmt(for_of_loop.body(), use_expr, true); self.compile_stmt(for_of_loop.body(), use_expr, true);
if let Some(iteration_environment) = iteration_environment { if !initializer_bound_names.is_empty() {
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(iteration_environment, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }

7
boa_engine/src/bytecompiler/statement/switch.rs

@ -6,8 +6,8 @@ impl ByteCompiler<'_, '_> {
pub(crate) fn compile_switch(&mut self, switch: &Switch, use_expr: bool) { pub(crate) fn compile_switch(&mut self, switch: &Switch, use_expr: bool) {
self.compile_expr(switch.val(), true); self.compile_expr(switch.val(), true);
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
let push_env = self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.block_declaration_instantiation(switch); self.block_declaration_instantiation(switch);
@ -50,8 +50,7 @@ impl ByteCompiler<'_, '_> {
self.pop_switch_control_info(); self.pop_switch_control_info();
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(push_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }
} }

7
boa_engine/src/bytecompiler/statement/try.rs

@ -111,8 +111,8 @@ impl ByteCompiler<'_, '_> {
pub(crate) fn compile_catch_stmt(&mut self, catch: &Catch, _has_finally: bool, use_expr: bool) { pub(crate) fn compile_catch_stmt(&mut self, catch: &Catch, _has_finally: bool, use_expr: bool) {
// stack: exception // stack: exception
self.push_compile_environment(false); let env_index = self.push_compile_environment(false);
let push_env = self.emit_opcode_with_operand(Opcode::PushDeclarativeEnvironment); self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
if let Some(binding) = catch.parameter() { if let Some(binding) = catch.parameter() {
match binding { match binding {
@ -133,8 +133,7 @@ impl ByteCompiler<'_, '_> {
self.compile_catch_finally_block(catch.block(), use_expr); self.compile_catch_finally_block(catch.block(), use_expr);
let env_index = self.pop_compile_environment(); self.pop_compile_environment();
self.patch_jump_with_target(push_env, env_index);
self.emit_opcode(Opcode::PopEnvironment); self.emit_opcode(Opcode::PopEnvironment);
} }

3
boa_engine/src/bytecompiler/statement/with.rs

@ -5,7 +5,8 @@ impl ByteCompiler<'_, '_> {
/// Compile a [`With`] `boa_ast` node /// Compile a [`With`] `boa_ast` node
pub(crate) fn compile_with(&mut self, with: &With, use_expr: bool) { pub(crate) fn compile_with(&mut self, with: &With, use_expr: bool) {
self.compile_expr(with.expression(), true); self.compile_expr(with.expression(), true);
self.push_compile_environment(false);
let _ = self.push_compile_environment(false);
self.emit_opcode(Opcode::PushObjectEnvironment); self.emit_opcode(Opcode::PushObjectEnvironment);
self.compile_stmt(with.statement(), use_expr, true); self.compile_stmt(with.statement(), use_expr, true);

14
boa_engine/src/vm/code_block.rs

@ -363,7 +363,7 @@ impl CodeBlock {
| Instruction::ConcatToString { value_count: value } => value.value().to_string(), | Instruction::ConcatToString { value_count: value } => value.value().to_string(),
Instruction::PushDeclarativeEnvironment { Instruction::PushDeclarativeEnvironment {
compile_environments_index, compile_environments_index,
} => compile_environments_index.to_string(), } => compile_environments_index.value().to_string(),
Instruction::CopyDataProperties { Instruction::CopyDataProperties {
excluded_key_count: value1, excluded_key_count: value1,
excluded_key_count_computed: value2, excluded_key_count_computed: value2,
@ -1062,7 +1062,7 @@ impl JsObject {
let env_fp = context.vm.environments.len() as u32; let env_fp = context.vm.environments.len() as u32;
let mut last_env = code.compile_environments.len() - 1; let mut last_env = 0;
if code.has_binding_identifier() { if code.has_binding_identifier() {
let index = context let index = context
@ -1073,7 +1073,7 @@ impl JsObject {
.vm .vm
.environments .environments
.put_lexical_value(index, 0, self.clone().into()); .put_lexical_value(index, 0, self.clone().into());
last_env -= 1; last_env += 1;
} }
context.vm.environments.push_function( context.vm.environments.push_function(
@ -1082,7 +1082,7 @@ impl JsObject {
); );
if code.has_parameters_env_bindings() { if code.has_parameters_env_bindings() {
last_env -= 1; last_env += 1;
context context
.vm .vm
.environments .environments
@ -1204,7 +1204,7 @@ impl JsObject {
let new_target = this_target.as_object().expect("must be object"); let new_target = this_target.as_object().expect("must be object");
let mut last_env = code.compile_environments.len() - 1; let mut last_env = 0;
if code.has_binding_identifier() { if code.has_binding_identifier() {
let index = context let index = context
@ -1215,7 +1215,7 @@ impl JsObject {
.vm .vm
.environments .environments
.put_lexical_value(index, 0, self.clone().into()); .put_lexical_value(index, 0, self.clone().into());
last_env -= 1; last_env += 1;
} }
context.vm.environments.push_function( context.vm.environments.push_function(
@ -1232,7 +1232,7 @@ impl JsObject {
let environment = context.vm.environments.current(); let environment = context.vm.environments.current();
if code.has_parameters_env_bindings() { if code.has_parameters_env_bindings() {
last_env -= 1; last_env += 1;
context context
.vm .vm
.environments .environments

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

@ -1738,10 +1738,10 @@ generate_opcodes! {
/// Push a declarative environment. /// Push a declarative environment.
/// ///
/// Operands: compile_environments_index: `u32` /// Operands: compile_environments_index: `VaryingOperand`
/// ///
/// Stack: **=>** /// Stack: **=>**
PushDeclarativeEnvironment { compile_environments_index: u32 }, PushDeclarativeEnvironment { compile_environments_index: VaryingOperand },
/// Push an object environment. /// Push an object environment.
/// ///

32
boa_engine/src/vm/opcode/push/environment.rs

@ -12,17 +12,36 @@ use boa_gc::Gc;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub(crate) struct PushDeclarativeEnvironment; pub(crate) struct PushDeclarativeEnvironment;
impl PushDeclarativeEnvironment {
#[allow(clippy::unnecessary_wraps)]
fn operation(
context: &mut Context<'_>,
compile_environments_index: usize,
) -> JsResult<CompletionType> {
let compile_environment =
context.vm.frame().code_block.compile_environments[compile_environments_index].clone();
context.vm.environments.push_lexical(compile_environment);
Ok(CompletionType::Normal)
}
}
impl Operation for PushDeclarativeEnvironment { impl Operation for PushDeclarativeEnvironment {
const NAME: &'static str = "PushDeclarativeEnvironment"; const NAME: &'static str = "PushDeclarativeEnvironment";
const INSTRUCTION: &'static str = "INST - PushDeclarativeEnvironment"; const INSTRUCTION: &'static str = "INST - PushDeclarativeEnvironment";
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
let compile_environments_index = context.vm.read::<u32>(); let compile_environments_index = context.vm.read::<u8>() as usize;
let compile_environment = context.vm.frame().code_block.compile_environments Self::operation(context, compile_environments_index)
[compile_environments_index as usize] }
.clone();
context.vm.environments.push_lexical(compile_environment); fn execute_with_u16_operands(context: &mut Context<'_>) -> JsResult<CompletionType> {
Ok(CompletionType::Normal) let compile_environments_index = context.vm.read::<u16>() as usize;
Self::operation(context, compile_environments_index)
}
fn execute_with_u32_operands(context: &mut Context<'_>) -> JsResult<CompletionType> {
let compile_environments_index = context.vm.read::<u32>() as usize;
Self::operation(context, compile_environments_index)
} }
} }
@ -98,7 +117,6 @@ impl Operation for PopPrivateEnvironment {
fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> { fn execute(context: &mut Context<'_>) -> JsResult<CompletionType> {
context.vm.environments.pop_private(); context.vm.environments.pop_private();
Ok(CompletionType::Normal) Ok(CompletionType::Normal)
} }
} }

Loading…
Cancel
Save