Browse Source

Skip prototype field definition for arrow function (#2388)

This Pull Request changes the following:

- Skip prototype field definition for arrow function
- Add `GetArrowFunction` opcode
pull/2391/head
raskad 2 years ago
parent
commit
203c1961bb
  1. 4
      boa_engine/src/builtins/function/mod.rs
  2. 2
      boa_engine/src/bytecompiler/mod.rs
  3. 6
      boa_engine/src/vm/code_block.rs
  4. 1
      boa_engine/src/vm/mod.rs
  5. 24
      boa_engine/src/vm/opcode/get/function.rs
  6. 9
      boa_engine/src/vm/opcode/mod.rs

4
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)

2
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]);
}

6
boa_engine/src/vm/code_block.rs

@ -223,7 +223,8 @@ impl CodeBlock {
*pc += size_of::<u32>();
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<CodeBlock>,
r#async: bool,
arrow: bool,
prototype: Option<JsObject>,
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");

1
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)?,

24
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<ShouldExit> {
let index = context.vm.read::<u32>();
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<ShouldExit> {
let index = context.vm.read::<u32>();
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<ShouldExit> {
let index = context.vm.read::<u32>();
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)
}

9
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,

Loading…
Cancel
Save