From 203c1961bbbe70121db1be210c29975d86c38ff0 Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Wed, 26 Oct 2022 20:50:23 +0000 Subject: [PATCH] Skip prototype field definition for arrow function (#2388) This Pull Request changes the following: - Skip prototype field definition for arrow function - Add `GetArrowFunction` opcode --- boa_engine/src/builtins/function/mod.rs | 4 ++-- boa_engine/src/bytecompiler/mod.rs | 2 ++ boa_engine/src/vm/code_block.rs | 6 ++++-- boa_engine/src/vm/mod.rs | 1 + boa_engine/src/vm/opcode/get/function.rs | 24 ++++++++++++++++++++++-- boa_engine/src/vm/opcode/mod.rs | 9 +++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) diff --git a/boa_engine/src/builtins/function/mod.rs b/boa_engine/src/builtins/function/mod.rs index f2577cb4eaa..3741d63b3d7 100644 --- a/boa_engine/src/builtins/function/mod.rs +++ b/boa_engine/src/builtins/function/mod.rs @@ -616,7 +616,7 @@ impl BuiltInFunctionObject { let function_object = if generator { crate::vm::create_generator_function_object(code, r#async, context) } else { - crate::vm::create_function_object(code, r#async, Some(prototype), context) + crate::vm::create_function_object(code, r#async, false, Some(prototype), context) }; context.realm.environments.extend(environments); @@ -647,7 +647,7 @@ impl BuiltInFunctionObject { let environments = context.realm.environments.pop_to_global(); let function_object = - crate::vm::create_function_object(code, r#async, Some(prototype), context); + crate::vm::create_function_object(code, r#async, false, Some(prototype), context); context.realm.environments.extend(environments); Ok(function_object) diff --git a/boa_engine/src/bytecompiler/mod.rs b/boa_engine/src/bytecompiler/mod.rs index 794ab9ed87a..0549587811a 100644 --- a/boa_engine/src/bytecompiler/mod.rs +++ b/boa_engine/src/bytecompiler/mod.rs @@ -2317,6 +2317,8 @@ impl<'b> ByteCompiler<'b> { self.emit(Opcode::GetGenerator, &[index]); } else if r#async { self.emit(Opcode::GetFunctionAsync, &[index]); + } else if arrow { + self.emit(Opcode::GetArrowFunction, &[index]); } else { self.emit(Opcode::GetFunction, &[index]); } diff --git a/boa_engine/src/vm/code_block.rs b/boa_engine/src/vm/code_block.rs index 3e63f15226d..f3a148bd0d3 100644 --- a/boa_engine/src/vm/code_block.rs +++ b/boa_engine/src/vm/code_block.rs @@ -223,7 +223,8 @@ impl CodeBlock { *pc += size_of::(); format!("{operand1}, {operand2}") } - Opcode::GetFunction + Opcode::GetArrowFunction + | Opcode::GetFunction | Opcode::GetFunctionAsync | Opcode::GetGenerator | Opcode::GetGeneratorAsync => { @@ -458,6 +459,7 @@ impl ToInternedString for CodeBlock { pub(crate) fn create_function_object( code: Gc, r#async: bool, + arrow: bool, prototype: Option, context: &mut Context, ) -> JsObject { @@ -551,7 +553,7 @@ pub(crate) fn create_function_object( constructor .define_property_or_throw(js_string!("name"), name_property, context) .expect("failed to define the name property of the function"); - if !r#async { + if !r#async && !arrow { constructor .define_property_or_throw(js_string!("prototype"), prototype_property, context) .expect("failed to define the prototype property of the function"); diff --git a/boa_engine/src/vm/mod.rs b/boa_engine/src/vm/mod.rs index bc22b9688fe..f90c2f0c507 100644 --- a/boa_engine/src/vm/mod.rs +++ b/boa_engine/src/vm/mod.rs @@ -250,6 +250,7 @@ impl Context { Opcode::SuperCallDerived => SuperCallDerived::execute(self)?, Opcode::Case => Case::execute(self)?, Opcode::Default => Default::execute(self)?, + Opcode::GetArrowFunction => GetArrowFunction::execute(self)?, Opcode::GetFunction => GetFunction::execute(self)?, Opcode::GetFunctionAsync => GetFunctionAsync::execute(self)?, Opcode::GetGenerator => GetGenerator::execute(self)?, diff --git a/boa_engine/src/vm/opcode/get/function.rs b/boa_engine/src/vm/opcode/get/function.rs index ce9dfe99e2e..4b3bef80007 100644 --- a/boa_engine/src/vm/opcode/get/function.rs +++ b/boa_engine/src/vm/opcode/get/function.rs @@ -3,6 +3,26 @@ use crate::{ Context, JsResult, }; +/// `GetArrowFunction` implements the Opcode Operation for `Opcode::GetArrowFunction` +/// +/// Operation: +/// - Get arrow function from the pre-compiled inner functions. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct GetArrowFunction; + +impl Operation for GetArrowFunction { + const NAME: &'static str = "GetArrowFunction"; + const INSTRUCTION: &'static str = "INST - GetArrowFunction"; + + fn execute(context: &mut Context) -> JsResult { + let index = context.vm.read::(); + let code = context.vm.frame().code.functions[index as usize].clone(); + let function = create_function_object(code, false, true, None, context); + context.vm.push(function); + Ok(ShouldExit::False) + } +} + /// `GetFunction` implements the Opcode Operation for `Opcode::GetFunction` /// /// Operation: @@ -17,7 +37,7 @@ impl Operation for GetFunction { fn execute(context: &mut Context) -> JsResult { let index = context.vm.read::(); let code = context.vm.frame().code.functions[index as usize].clone(); - let function = create_function_object(code, false, None, context); + let function = create_function_object(code, false, false, None, context); context.vm.push(function); Ok(ShouldExit::False) } @@ -37,7 +57,7 @@ impl Operation for GetFunctionAsync { fn execute(context: &mut Context) -> JsResult { let index = context.vm.read::(); let code = context.vm.frame().code.functions[index as usize].clone(); - let function = create_function_object(code, true, None, context); + let function = create_function_object(code, true, false, None, context); context.vm.push(function); Ok(ShouldExit::False) } diff --git a/boa_engine/src/vm/opcode/mod.rs b/boa_engine/src/vm/opcode/mod.rs index a944bf20f21..a8d7af62b8a 100644 --- a/boa_engine/src/vm/opcode/mod.rs +++ b/boa_engine/src/vm/opcode/mod.rs @@ -1022,6 +1022,13 @@ pub enum Opcode { /// Stack: `value` **=>** Default, + /// Get arrow function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetArrowFunction, + /// Get function from the pre-compiled inner functions. /// /// Operands: address: `u32` @@ -1441,6 +1448,7 @@ impl Opcode { Self::SuperCallDerived => SuperCallDerived::NAME, Self::Case => Case::NAME, Self::Default => Default::NAME, + Self::GetArrowFunction => GetArrowFunction::NAME, Self::GetFunction => GetFunction::NAME, Self::GetFunctionAsync => GetFunctionAsync::NAME, Self::GetGenerator => GetGenerator::NAME, @@ -1588,6 +1596,7 @@ impl Opcode { Self::SuperCallDerived => SuperCallDerived::INSTRUCTION, Self::Case => Case::INSTRUCTION, Self::Default => Default::INSTRUCTION, + Self::GetArrowFunction => GetArrowFunction::INSTRUCTION, Self::GetFunction => GetFunction::INSTRUCTION, Self::GetFunctionAsync => GetFunctionAsync::INSTRUCTION, Self::GetGenerator => GetGenerator::INSTRUCTION,