Skip to content

Commit

Permalink
Merge CodeBlock constant pools (boa-dev#3413)
Browse files Browse the repository at this point in the history
* Merge `CodeBlock` constant pools

* Apply review
  • Loading branch information
HalidOdat authored and sam-finch-tezos committed Nov 29, 2023
1 parent 9f8547c commit 13bebac
Show file tree
Hide file tree
Showing 28 changed files with 264 additions and 162 deletions.
21 changes: 7 additions & 14 deletions boa_engine/src/bytecompiler/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ impl ByteCompiler<'_, '_> {
compiler.emit_opcode(Opcode::SetReturnValue);

let code = Gc::new(compiler.finish());
let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);
self.emit(
Opcode::GetFunction,
&[Operand::Varying(index), Operand::Bool(false)],
Expand Down Expand Up @@ -294,10 +293,8 @@ impl ByteCompiler<'_, '_> {

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = field_compiler.finish();
let code = Gc::new(code);
let index = self.functions.len() as u32;
self.functions.push(code);
let code = Gc::new(field_compiler.finish());
let index = self.push_function_to_constants(code);
self.emit(
Opcode::GetFunction,
&[Operand::Varying(index), Operand::Bool(false)],
Expand Down Expand Up @@ -325,10 +322,8 @@ impl ByteCompiler<'_, '_> {

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = field_compiler.finish();
let code = Gc::new(code);
let index = self.functions.len() as u32;
self.functions.push(code);
let code = Gc::new(field_compiler.finish());
let index = self.push_function_to_constants(code);
self.emit(
Opcode::GetFunction,
&[Operand::Varying(index), Operand::Bool(false)],
Expand Down Expand Up @@ -552,8 +547,7 @@ impl ByteCompiler<'_, '_> {
match element {
StaticElement::StaticBlock(code) => {
self.emit_opcode(Opcode::Dup);
let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);
self.emit(
Opcode::GetFunction,
&[Operand::Varying(index), Operand::Bool(false)],
Expand All @@ -565,8 +559,7 @@ impl ByteCompiler<'_, '_> {
StaticElement::StaticField((code, name_index)) => {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);
self.emit(
Opcode::GetFunction,
&[Operand::Varying(index), Operand::Bool(false)],
Expand Down
9 changes: 4 additions & 5 deletions boa_engine/src/bytecompiler/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl ByteCompiler<'_, '_> {
);

// Ensures global functions are printed when generating the global flowgraph.
self.functions.push(code.clone());
let _ = self.push_function_to_constants(code.clone());

// b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv.
let function = if generator {
Expand Down Expand Up @@ -733,7 +733,7 @@ impl ByteCompiler<'_, '_> {
// c. If varEnv is a Global Environment Record, then
if var_env.is_global() {
// Ensures global functions are printed when generating the global flowgraph.
self.functions.push(code.clone());
let _ = self.push_function_to_constants(code.clone());

// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
let function = if generator {
Expand All @@ -749,8 +749,7 @@ impl ByteCompiler<'_, '_> {
// d. Else,
else {
// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);
if r#async && generator {
self.emit_with_varying_operand(Opcode::GetGeneratorAsync, index);
} else if generator {
Expand Down Expand Up @@ -1034,7 +1033,7 @@ impl ByteCompiler<'_, '_> {
}

if generator {
self.emit(Opcode::Generator, &[Operand::U8(self.in_async().into())]);
self.emit(Opcode::Generator, &[Operand::Bool(self.in_async())]);
self.emit_opcode(Opcode::Pop);
}

Expand Down
5 changes: 3 additions & 2 deletions boa_engine/src/bytecompiler/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ impl ByteCompiler<'_, '_> {
function_scope,
));

let index = self.compile_environments.len() as u32;
self.compile_environments.push(env.clone());
let index = self.constants.len() as u32;
self.constants
.push(crate::vm::Constant::CompileTimeEnvironment(env.clone()));

if function_scope {
self.variable_environment = env.clone();
Expand Down
57 changes: 22 additions & 35 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use crate::{
environments::{BindingLocator, BindingLocatorError, CompileTimeEnvironment},
js_string,
vm::{
BindingOpcode, CodeBlock, CodeBlockFlags, GeneratorResumeKind, Handler, Opcode,
BindingOpcode, CodeBlock, CodeBlockFlags, Constant, GeneratorResumeKind, Handler, Opcode,
VaryingOperandKind,
},
Context, JsBigInt, JsString, JsValue,
Context, JsBigInt, JsString,
};
use boa_ast::{
declaration::{Binding, LexicalDeclaration, VarDeclaration},
Expand Down Expand Up @@ -248,21 +248,11 @@ pub struct ByteCompiler<'ctx, 'host> {
/// Bytecode
pub(crate) bytecode: Vec<u8>,

/// Literals
pub(crate) literals: Vec<JsValue>,

/// Property field names and private name `[[Description]]`s.
pub(crate) names: Vec<JsString>,
pub(crate) constants: ThinVec<Constant>,

/// Locators for all bindings in the codeblock.
pub(crate) bindings: Vec<BindingLocator>,

/// Functions inside this function
pub(crate) functions: Vec<Gc<CodeBlock>>,

/// Compile time environments in this function.
pub(crate) compile_environments: Vec<Rc<CompileTimeEnvironment>>,

/// The current variable environment.
pub(crate) variable_environment: Rc<CompileTimeEnvironment>,

Expand Down Expand Up @@ -315,13 +305,10 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
function_name: name,
length: 0,
bytecode: Vec::default(),
literals: Vec::default(),
names: Vec::default(),
constants: ThinVec::default(),
bindings: Vec::default(),
functions: Vec::default(),
this_mode: ThisMode::Global,
params: FormalParameterList::default(),
compile_environments: Vec::default(),
current_open_environments_count: 0,

// This starts at two because the first value is the `this` value, then function object.
Expand Down Expand Up @@ -372,12 +359,12 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}

let value = match literal.clone() {
Literal::String(value) => JsValue::new(value),
Literal::BigInt(value) => JsValue::new(value),
Literal::String(value) => Constant::String(value),
Literal::BigInt(value) => Constant::BigInt(value),
};

let index = self.literals.len() as u32;
self.literals.push(value);
let index = self.constants.len() as u32;
self.constants.push(value);
self.literals_map.insert(literal, index);
index
}
Expand All @@ -388,8 +375,8 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}

let string = self.interner().resolve_expect(name.sym()).utf16();
let index = self.names.len() as u32;
self.names.push(js_string!(string));
let index = self.constants.len() as u32;
self.constants.push(Constant::String(js_string!(string)));
self.names_map.insert(name, index);
index
}
Expand All @@ -411,6 +398,14 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
index
}

#[inline]
#[must_use]
pub(crate) fn push_function_to_constants(&mut self, function: Gc<CodeBlock>) -> u32 {
let index = self.constants.len() as u32;
self.constants.push(Constant::Function(function));
index
}

fn emit_binding(&mut self, opcode: BindingOpcode, name: Identifier) {
match opcode {
BindingOpcode::Var => {
Expand Down Expand Up @@ -1250,10 +1245,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.context,
);

let index = self.functions.len() as u32;
self.functions.push(code);

index
self.push_function_to_constants(code)
}

/// Compiles a function AST Node into bytecode, setting its corresponding binding or
Expand Down Expand Up @@ -1348,8 +1340,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.context,
);

let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);

if r#async && generator {
self.emit_with_varying_operand(Opcode::GetGeneratorAsync, index);
Expand Down Expand Up @@ -1412,8 +1403,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
self.context,
);

let index = self.functions.len() as u32;
self.functions.push(code);
let index = self.push_function_to_constants(code);

if r#async && generator {
self.emit_with_varying_operand(Opcode::GetGeneratorAsync, index);
Expand Down Expand Up @@ -1535,11 +1525,8 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
this_mode: self.this_mode,
params: self.params,
bytecode: self.bytecode.into_boxed_slice(),
literals: self.literals.into_boxed_slice(),
names: self.names.into_boxed_slice(),
constants: self.constants,
bindings: self.bindings.into_boxed_slice(),
functions: self.functions.into_boxed_slice(),
compile_environments: self.compile_environments.into_boxed_slice(),
handlers: self.handlers,
flags: Cell::new(self.code_block_flags),
}
Expand Down
6 changes: 5 additions & 1 deletion boa_engine/src/environments/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,11 @@ impl Context<'_> {
}
}

/// Return the environment at the given index. Panics if the index is out of range.
/// Return the environment at the given index.
///
/// # Panics
///
/// Panics if the `index` is out of range.
pub(crate) fn environment_expect(&self, index: u32) -> &Environment {
self.vm
.environments
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/module/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1657,7 +1657,7 @@ impl SourceTextModule {

// deferred initialization of function exports
for (index, locator, kind) in functions {
let code = codeblock.functions[index as usize].clone();
let code = codeblock.constant_function(index as usize);

let function = if kind.is_generator() {
create_generator_function_object(code, kind.is_async(), None, context)
Expand Down
12 changes: 6 additions & 6 deletions boa_engine/src/object/internal_methods/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub(crate) fn function_call(
let index = context
.vm
.environments
.push_lexical(code.compile_environments[last_env].clone());
.push_lexical(code.constant_compile_time_environment(last_env));
context
.vm
.environments
Expand All @@ -107,7 +107,7 @@ pub(crate) fn function_call(
}

context.vm.environments.push_function(
code.compile_environments[last_env].clone(),
code.constant_compile_time_environment(last_env),
FunctionSlots::new(this, function_object.clone(), None),
);

Expand All @@ -116,7 +116,7 @@ pub(crate) fn function_call(
context
.vm
.environments
.push_lexical(code.compile_environments[last_env].clone());
.push_lexical(code.constant_compile_time_environment(last_env));
}

// Taken from: `FunctionDeclarationInstantiation` abstract function.
Expand Down Expand Up @@ -226,7 +226,7 @@ fn function_construct(
let index = context
.vm
.environments
.push_lexical(code.compile_environments[last_env].clone());
.push_lexical(code.constant_compile_time_environment(last_env));
context
.vm
.environments
Expand All @@ -235,7 +235,7 @@ fn function_construct(
}

context.vm.environments.push_function(
code.compile_environments[last_env].clone(),
code.constant_compile_time_environment(last_env),
FunctionSlots::new(
this.clone().map_or(ThisBindingStatus::Uninitialized, |o| {
ThisBindingStatus::Initialized(o.into())
Expand All @@ -255,7 +255,7 @@ fn function_construct(
context
.vm
.environments
.push_lexical(code.compile_environments[last_env].clone());
.push_lexical(code.constant_compile_time_environment(last_env));
}

// Taken from: `FunctionDeclarationInstantiation` abstract function.
Expand Down

0 comments on commit 13bebac

Please sign in to comment.