Browse Source

Move `RefCell` of `CompileTimeEnvironment`s to field `bindings` (#3108)

* Move `RefCell` of `CompileTimeEnvironment`s to field `bindings`

All field except the `bindings` field are mutated after `CompileTimeEnvironment`
creation. It moves the `RefCell` to `bindings` field, this cleans the methods callsites.

* cargo-clippy
pull/3122/head
Haled Odat 1 year ago committed by GitHub
parent
commit
40f33d8efb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      boa_engine/src/bytecompiler/declarations.rs
  2. 42
      boa_engine/src/bytecompiler/env.rs
  3. 2
      boa_engine/src/bytecompiler/expression/assign.rs
  4. 2
      boa_engine/src/bytecompiler/expression/update.rs
  5. 4
      boa_engine/src/bytecompiler/function.rs
  6. 13
      boa_engine/src/bytecompiler/mod.rs
  7. 95
      boa_engine/src/environments/compile.rs
  8. 13
      boa_engine/src/environments/runtime/declarative/mod.rs
  9. 1
      boa_engine/src/environments/runtime/declarative/module.rs
  10. 32
      boa_engine/src/environments/runtime/mod.rs
  11. 7
      boa_engine/src/module/source.rs
  12. 1
      boa_engine/src/object/internal_methods/module_namespace.rs
  13. 2
      boa_engine/src/realm.rs
  14. 9
      boa_engine/src/vm/code_block.rs

8
boa_engine/src/bytecompiler/declarations.rs

@ -174,7 +174,7 @@ impl ByteCompiler<'_, '_> {
// would not produce any Early Errors for script, then // would not produce any Early Errors for script, then
if !lex_names.contains(&f) { if !lex_names.contains(&f) {
// a. If env.HasLexicalDeclaration(F) is false, then // a. If env.HasLexicalDeclaration(F) is false, then
if !self.current_environment.borrow().has_lex_binding(f) { if !self.current_environment.has_lex_binding(f) {
// i. Let fnDefinable be ? env.CanDeclareGlobalVar(F). // i. Let fnDefinable be ? env.CanDeclareGlobalVar(F).
let fn_definable = self.context.can_declare_global_function(f)?; let fn_definable = self.context.can_declare_global_function(f)?;
@ -308,7 +308,7 @@ impl ByteCompiler<'_, '_> {
where where
&'a N: Into<NodeRef<'a>>, &'a N: Into<NodeRef<'a>>,
{ {
let mut env = self.current_environment.borrow_mut(); let env = &self.current_environment;
// 1. Let declarations be the LexicallyScopedDeclarations of code. // 1. Let declarations be the LexicallyScopedDeclarations of code.
let declarations = lexically_scoped_declarations(block); let declarations = lexically_scoped_declarations(block);
@ -345,8 +345,6 @@ impl ByteCompiler<'_, '_> {
} }
} }
drop(env);
// Note: Not sure if the spec is wrong here or if our implementation just differs too much, // Note: Not sure if the spec is wrong here or if our implementation just differs too much,
// but we need 3.a to be finished for all declarations before 3.b can be done. // but we need 3.a to be finished for all declarations before 3.b can be done.
@ -532,7 +530,7 @@ impl ByteCompiler<'_, '_> {
let fn_definable = if !binding_exists && var_environment_is_global { let fn_definable = if !binding_exists && var_environment_is_global {
// a. If varEnv.HasLexicalDeclaration(F) is false, then // a. If varEnv.HasLexicalDeclaration(F) is false, then
// b. Else, // b. Else,
if self.current_environment.borrow().has_lex_binding(f) { if self.current_environment.has_lex_binding(f) {
// i. Let fnDefinable be false. // i. Let fnDefinable be false.
false false
} else { } else {

42
boa_engine/src/bytecompiler/env.rs

@ -1,4 +1,4 @@
use std::{cell::RefCell, rc::Rc}; use std::rc::Rc;
use super::ByteCompiler; use super::ByteCompiler;
use crate::environments::{BindingLocator, BindingLocatorError, CompileTimeEnvironment}; use crate::environments::{BindingLocator, BindingLocatorError, CompileTimeEnvironment};
@ -7,10 +7,10 @@ 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) { pub(crate) fn push_compile_environment(&mut self, function_scope: bool) {
self.current_environment = Rc::new(RefCell::new(CompileTimeEnvironment::new( self.current_environment = Rc::new(CompileTimeEnvironment::new(
self.current_environment.clone(), self.current_environment.clone(),
function_scope, function_scope,
))); ));
} }
/// 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.
@ -20,10 +20,10 @@ impl ByteCompiler<'_, '_> {
self.compile_environments self.compile_environments
.push(self.current_environment.clone()); .push(self.current_environment.clone());
let outer = { let outer = self
let env = self.current_environment.borrow(); .current_environment
env.outer().expect("cannot pop the global environment") .outer()
}; .expect("cannot pop the global environment");
self.current_environment = outer; self.current_environment = outer;
index index
@ -31,34 +31,26 @@ impl ByteCompiler<'_, '_> {
/// Get the binding locator of the binding at bytecode compile time. /// Get the binding locator of the binding at bytecode compile time.
pub(crate) fn get_binding_value(&self, name: Identifier) -> BindingLocator { pub(crate) fn get_binding_value(&self, name: Identifier) -> BindingLocator {
self.current_environment self.current_environment.get_binding_recursive(name)
.borrow()
.get_binding_recursive(name)
} }
/// Return if a declarative binding exists at bytecode compile time. /// Return if a declarative binding exists at bytecode compile time.
/// This does not include bindings on the global object. /// This does not include bindings on the global object.
pub(crate) fn has_binding(&self, name: Identifier) -> bool { pub(crate) fn has_binding(&self, name: Identifier) -> bool {
self.current_environment self.current_environment.has_binding_recursive(name)
.borrow()
.has_binding_recursive(name)
} }
/// Check if a binding name exists in a environment. /// Check if a binding name exists in a environment.
/// If strict is `false` check until a function scope is reached. /// If strict is `false` check until a function scope is reached.
pub(crate) fn has_binding_eval(&self, name: Identifier, strict: bool) -> bool { pub(crate) fn has_binding_eval(&self, name: Identifier, strict: bool) -> bool {
self.current_environment self.current_environment.has_binding_eval(name, strict)
.borrow()
.has_binding_eval(name, strict)
} }
#[cfg(feature = "annex-b")] #[cfg(feature = "annex-b")]
/// Check if a binding name exists in a environment. /// Check if a binding name exists in a environment.
/// Stop when a function scope is reached. /// Stop when a function scope is reached.
pub(crate) fn has_binding_until_var(&self, name: Identifier) -> bool { pub(crate) fn has_binding_until_var(&self, name: Identifier) -> bool {
self.current_environment self.current_environment.has_binding_until_var(name)
.borrow()
.has_binding_until_var(name)
} }
/// Create a mutable binding at bytecode compile time. /// Create a mutable binding at bytecode compile time.
@ -70,7 +62,6 @@ impl ByteCompiler<'_, '_> {
pub(crate) fn create_mutable_binding(&mut self, name: Identifier, function_scope: bool) { pub(crate) fn create_mutable_binding(&mut self, name: Identifier, function_scope: bool) {
assert!(self assert!(self
.current_environment .current_environment
.borrow_mut()
.create_mutable_binding(name, function_scope)); .create_mutable_binding(name, function_scope));
} }
@ -81,7 +72,6 @@ impl ByteCompiler<'_, '_> {
function_scope: bool, function_scope: bool,
) -> BindingLocator { ) -> BindingLocator {
self.current_environment self.current_environment
.borrow()
.initialize_mutable_binding(name, function_scope) .initialize_mutable_binding(name, function_scope)
} }
@ -93,7 +83,6 @@ impl ByteCompiler<'_, '_> {
/// Panics if the global environment does not exist. /// Panics if the global environment does not exist.
pub(crate) fn create_immutable_binding(&mut self, name: Identifier, strict: bool) { pub(crate) fn create_immutable_binding(&mut self, name: Identifier, strict: bool) {
self.current_environment self.current_environment
.borrow_mut()
.create_immutable_binding(name, strict); .create_immutable_binding(name, strict);
} }
@ -103,9 +92,7 @@ impl ByteCompiler<'_, '_> {
/// ///
/// Panics if the global environment does not exist or a the binding was not created on the current environment. /// Panics if the global environment does not exist or a the binding was not created on the current environment.
pub(crate) fn initialize_immutable_binding(&self, name: Identifier) -> BindingLocator { pub(crate) fn initialize_immutable_binding(&self, name: Identifier) -> BindingLocator {
self.current_environment self.current_environment.initialize_immutable_binding(name)
.borrow()
.initialize_immutable_binding(name)
} }
/// Return the binding locator for a set operation on an existing binding. /// Return the binding locator for a set operation on an existing binding.
@ -113,9 +100,7 @@ impl ByteCompiler<'_, '_> {
&self, &self,
name: Identifier, name: Identifier,
) -> Result<BindingLocator, BindingLocatorError> { ) -> Result<BindingLocator, BindingLocatorError> {
self.current_environment self.current_environment.set_mutable_binding_recursive(name)
.borrow()
.set_mutable_binding_recursive(name)
} }
#[cfg(feature = "annex-b")] #[cfg(feature = "annex-b")]
@ -125,7 +110,6 @@ impl ByteCompiler<'_, '_> {
name: Identifier, name: Identifier,
) -> Result<BindingLocator, BindingLocatorError> { ) -> Result<BindingLocator, BindingLocatorError> {
self.current_environment self.current_environment
.borrow()
.set_mutable_binding_var_recursive(name) .set_mutable_binding_var_recursive(name)
} }
} }

2
boa_engine/src/bytecompiler/expression/assign.rs

@ -57,7 +57,7 @@ impl ByteCompiler<'_, '_> {
Access::Variable { name } => { Access::Variable { name } => {
let binding = self.get_binding_value(name); let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding); let index = self.get_or_insert_binding(binding);
let lex = self.current_environment.borrow().is_lex_binding(name); let lex = self.current_environment.is_lex_binding(name);
if lex { if lex {
self.emit(Opcode::GetName, &[index]); self.emit(Opcode::GetName, &[index]);

2
boa_engine/src/bytecompiler/expression/update.rs

@ -25,7 +25,7 @@ impl ByteCompiler<'_, '_> {
Access::Variable { name } => { Access::Variable { name } => {
let binding = self.get_binding_value(name); let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding); let index = self.get_or_insert_binding(binding);
let lex = self.current_environment.borrow().is_lex_binding(name); let lex = self.current_environment.is_lex_binding(name);
if lex { if lex {
self.emit(Opcode::GetName, &[index]); self.emit(Opcode::GetName, &[index]);

4
boa_engine/src/bytecompiler/function.rs

@ -1,4 +1,4 @@
use std::{cell::RefCell, rc::Rc}; use std::rc::Rc;
use crate::{ use crate::{
builtins::function::ThisMode, builtins::function::ThisMode,
@ -90,7 +90,7 @@ impl FunctionCompiler {
mut self, mut self,
parameters: &FormalParameterList, parameters: &FormalParameterList,
body: &FunctionBody, body: &FunctionBody,
outer_env: Rc<RefCell<CompileTimeEnvironment>>, outer_env: Rc<CompileTimeEnvironment>,
context: &mut Context<'_>, context: &mut Context<'_>,
) -> Gc<CodeBlock> { ) -> Gc<CodeBlock> {
self.strict = self.strict || body.strict(); self.strict = self.strict || body.strict();

13
boa_engine/src/bytecompiler/mod.rs

@ -11,10 +11,7 @@ mod module;
mod statement; mod statement;
mod utils; mod utils;
use std::{ use std::{cell::Cell, rc::Rc};
cell::{Cell, RefCell},
rc::Rc,
};
use crate::{ use crate::{
builtins::function::ThisMode, builtins::function::ThisMode,
@ -244,10 +241,10 @@ pub struct ByteCompiler<'ctx, 'host> {
pub(crate) functions: Vec<Gc<CodeBlock>>, pub(crate) functions: Vec<Gc<CodeBlock>>,
/// Compile time environments in this function. /// Compile time environments in this function.
pub(crate) compile_environments: Vec<Rc<RefCell<CompileTimeEnvironment>>>, pub(crate) compile_environments: Vec<Rc<CompileTimeEnvironment>>,
/// The environment that is currently active. /// The environment that is currently active.
pub(crate) current_environment: Rc<RefCell<CompileTimeEnvironment>>, pub(crate) current_environment: Rc<CompileTimeEnvironment>,
pub(crate) code_block_flags: CodeBlockFlags, pub(crate) code_block_flags: CodeBlockFlags,
@ -276,7 +273,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
name: Sym, name: Sym,
strict: bool, strict: bool,
json_parse: bool, json_parse: bool,
current_environment: Rc<RefCell<CompileTimeEnvironment>>, current_environment: Rc<CompileTimeEnvironment>,
// TODO: remove when we separate scripts from the context // TODO: remove when we separate scripts from the context
context: &'ctx mut Context<'host>, context: &'ctx mut Context<'host>,
) -> ByteCompiler<'ctx, 'host> { ) -> ByteCompiler<'ctx, 'host> {
@ -633,7 +630,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
Access::Variable { name } => { Access::Variable { name } => {
let binding = self.get_binding_value(name); let binding = self.get_binding_value(name);
let index = self.get_or_insert_binding(binding); let index = self.get_or_insert_binding(binding);
let lex = self.current_environment.borrow().is_lex_binding(name); let lex = self.current_environment.is_lex_binding(name);
if !lex { if !lex {
self.emit(Opcode::GetLocator, &[index]); self.emit(Opcode::GetLocator, &[index]);

95
boa_engine/src/environments/compile.rs

@ -24,9 +24,9 @@ struct CompileTimeBinding {
/// A compile time environment also indicates, if it is a function environment. /// A compile time environment also indicates, if it is a function environment.
#[derive(Debug, Finalize)] #[derive(Debug, Finalize)]
pub(crate) struct CompileTimeEnvironment { pub(crate) struct CompileTimeEnvironment {
outer: Option<Rc<RefCell<Self>>>, outer: Option<Rc<Self>>,
environment_index: u32, environment_index: u32,
bindings: FxHashMap<Identifier, CompileTimeBinding>, bindings: RefCell<FxHashMap<Identifier, CompileTimeBinding>>,
function_scope: bool, function_scope: bool,
} }
@ -41,18 +41,18 @@ impl CompileTimeEnvironment {
Self { Self {
outer: None, outer: None,
environment_index: 0, environment_index: 0,
bindings: FxHashMap::default(), bindings: RefCell::default(),
function_scope: true, function_scope: true,
} }
} }
/// Creates a new compile time environment. /// Creates a new compile time environment.
pub(crate) fn new(parent: Rc<RefCell<Self>>, function_scope: bool) -> Self { pub(crate) fn new(parent: Rc<Self>, function_scope: bool) -> Self {
let index = parent.borrow().environment_index + 1; let index = parent.environment_index + 1;
Self { Self {
outer: Some(parent), outer: Some(parent),
environment_index: index, environment_index: index,
bindings: FxHashMap::default(), bindings: RefCell::default(),
function_scope, function_scope,
} }
} }
@ -60,6 +60,7 @@ impl CompileTimeEnvironment {
/// Check if environment has a lexical binding with the given name. /// Check if environment has a lexical binding with the given name.
pub(crate) fn has_lex_binding(&self, name: Identifier) -> bool { pub(crate) fn has_lex_binding(&self, name: Identifier) -> bool {
self.bindings self.bindings
.borrow()
.get(&name) .get(&name)
.map_or(false, |binding| binding.lex) .map_or(false, |binding| binding.lex)
} }
@ -67,15 +68,15 @@ impl CompileTimeEnvironment {
#[cfg(feature = "annex-b")] #[cfg(feature = "annex-b")]
/// Check if the environment has a binding with the given name. /// Check if the environment has a binding with the given name.
pub(crate) fn has_binding(&self, name: Identifier) -> bool { pub(crate) fn has_binding(&self, name: Identifier) -> bool {
self.bindings.contains_key(&name) self.bindings.borrow().contains_key(&name)
} }
/// Checks if `name` is a lexical binding. /// Checks if `name` is a lexical binding.
pub(crate) fn is_lex_binding(&self, name: Identifier) -> bool { pub(crate) fn is_lex_binding(&self, name: Identifier) -> bool {
if let Some(binding) = self.bindings.get(&name) { if let Some(binding) = self.bindings.borrow().get(&name) {
binding.lex binding.lex
} else if let Some(outer) = &self.outer { } else if let Some(outer) = &self.outer {
outer.borrow().is_lex_binding(name) outer.is_lex_binding(name)
} else { } else {
false false
} }
@ -83,7 +84,7 @@ impl CompileTimeEnvironment {
/// Returns the number of bindings in this environment. /// Returns the number of bindings in this environment.
pub(crate) fn num_bindings(&self) -> u32 { pub(crate) fn num_bindings(&self) -> u32 {
self.bindings.len() as u32 self.bindings.borrow().len() as u32
} }
/// Check if the environment is a function environment. /// Check if the environment is a function environment.
@ -94,16 +95,17 @@ impl CompileTimeEnvironment {
/// Get the locator for a binding name. /// Get the locator for a binding name.
pub(crate) fn get_binding(&self, name: Identifier) -> Option<BindingLocator> { pub(crate) fn get_binding(&self, name: Identifier) -> Option<BindingLocator> {
self.bindings self.bindings
.borrow()
.get(&name) .get(&name)
.map(|binding| BindingLocator::declarative(name, self.environment_index, binding.index)) .map(|binding| BindingLocator::declarative(name, self.environment_index, binding.index))
} }
/// Get the locator for a binding name in this and all outer environments. /// Get the locator for a binding name in this and all outer environments.
pub(crate) fn get_binding_recursive(&self, name: Identifier) -> BindingLocator { pub(crate) fn get_binding_recursive(&self, name: Identifier) -> BindingLocator {
if let Some(binding) = self.bindings.get(&name) { if let Some(binding) = self.bindings.borrow().get(&name) {
BindingLocator::declarative(name, self.environment_index, binding.index) BindingLocator::declarative(name, self.environment_index, binding.index)
} else if let Some(outer) = &self.outer { } else if let Some(outer) = &self.outer {
outer.borrow().get_binding_recursive(name) outer.get_binding_recursive(name)
} else { } else {
BindingLocator::global(name) BindingLocator::global(name)
} }
@ -111,10 +113,10 @@ impl CompileTimeEnvironment {
/// Check if a binding name exists in this and all outer environments. /// Check if a binding name exists in this and all outer environments.
pub(crate) fn has_binding_recursive(&self, name: Identifier) -> bool { pub(crate) fn has_binding_recursive(&self, name: Identifier) -> bool {
if self.bindings.contains_key(&name) { if self.bindings.borrow().contains_key(&name) {
true true
} else if let Some(outer) = &self.outer { } else if let Some(outer) = &self.outer {
outer.borrow().has_binding_recursive(name) outer.has_binding_recursive(name)
} else { } else {
false false
} }
@ -123,7 +125,7 @@ impl CompileTimeEnvironment {
/// Check if a binding name exists in a environment. /// Check if a binding name exists in a environment.
/// If strict is `false` check until a function scope is reached. /// If strict is `false` check until a function scope is reached.
pub(crate) fn has_binding_eval(&self, name: Identifier, strict: bool) -> bool { pub(crate) fn has_binding_eval(&self, name: Identifier, strict: bool) -> bool {
let exists = self.bindings.contains_key(&name); let exists = self.bindings.borrow().contains_key(&name);
if exists || strict { if exists || strict {
return exists; return exists;
} }
@ -131,7 +133,7 @@ impl CompileTimeEnvironment {
return false; return false;
} }
if let Some(outer) = &self.outer { if let Some(outer) = &self.outer {
outer.borrow().has_binding_eval(name, false) outer.has_binding_eval(name, false)
} else { } else {
false false
} }
@ -144,11 +146,11 @@ impl CompileTimeEnvironment {
if self.function_scope { if self.function_scope {
return false; return false;
} }
if self.bindings.contains_key(&name) { if self.bindings.borrow().contains_key(&name) {
return true; return true;
} }
if let Some(outer) = &self.outer { if let Some(outer) = &self.outer {
outer.borrow().has_binding_until_var(name) outer.has_binding_until_var(name)
} else { } else {
false false
} }
@ -157,16 +159,12 @@ impl CompileTimeEnvironment {
/// Create a mutable binding. /// Create a mutable binding.
/// ///
/// If the binding is a function scope binding and this is a declarative environment, try the outer environment. /// If the binding is a function scope binding and this is a declarative environment, try the outer environment.
pub(crate) fn create_mutable_binding( pub(crate) fn create_mutable_binding(&self, name: Identifier, function_scope: bool) -> bool {
&mut self,
name: Identifier,
function_scope: bool,
) -> bool {
if let Some(outer) = &self.outer { if let Some(outer) = &self.outer {
if !function_scope || self.function_scope { if !function_scope || self.function_scope {
if !self.bindings.contains_key(&name) { if !self.bindings.borrow().contains_key(&name) {
let binding_index = self.bindings.len() as u32; let binding_index = self.bindings.borrow().len() as u32;
self.bindings.insert( self.bindings.borrow_mut().insert(
name, name,
CompileTimeBinding { CompileTimeBinding {
index: binding_index, index: binding_index,
@ -178,16 +176,14 @@ impl CompileTimeEnvironment {
} }
true true
} else { } else {
return outer outer.create_mutable_binding(name, function_scope)
.borrow_mut()
.create_mutable_binding(name, function_scope);
} }
} else if function_scope { } else if function_scope {
false false
} else { } else {
if !self.bindings.contains_key(&name) { if !self.bindings.borrow().contains_key(&name) {
let binding_index = self.bindings.len() as u32; let binding_index = self.bindings.borrow().len() as u32;
self.bindings.insert( self.bindings.borrow_mut().insert(
name, name,
CompileTimeBinding { CompileTimeBinding {
index: binding_index, index: binding_index,
@ -202,9 +198,9 @@ impl CompileTimeEnvironment {
} }
/// Crate an immutable binding. /// Crate an immutable binding.
pub(crate) fn create_immutable_binding(&mut self, name: Identifier, strict: bool) { pub(crate) fn create_immutable_binding(&self, name: Identifier, strict: bool) {
let binding_index = self.bindings.len() as u32; let binding_index = self.bindings.borrow().len() as u32;
self.bindings.insert( self.bindings.borrow_mut().insert(
name, name,
CompileTimeBinding { CompileTimeBinding {
index: binding_index, index: binding_index,
@ -223,19 +219,13 @@ impl CompileTimeEnvironment {
) -> BindingLocator { ) -> BindingLocator {
if let Some(outer) = &self.outer { if let Some(outer) = &self.outer {
if function_scope && !self.function_scope { if function_scope && !self.function_scope {
return outer return outer.initialize_mutable_binding(name, function_scope);
.borrow()
.initialize_mutable_binding(name, function_scope);
} }
self.bindings.get(&name).map_or_else( self.bindings.borrow().get(&name).map_or_else(
|| { || outer.initialize_mutable_binding(name, function_scope),
outer
.borrow()
.initialize_mutable_binding(name, function_scope)
},
|binding| BindingLocator::declarative(name, self.environment_index, binding.index), |binding| BindingLocator::declarative(name, self.environment_index, binding.index),
) )
} else if let Some(binding) = self.bindings.get(&name) { } else if let Some(binding) = self.bindings.borrow().get(&name) {
BindingLocator::declarative(name, self.environment_index, binding.index) BindingLocator::declarative(name, self.environment_index, binding.index)
} else { } else {
BindingLocator::global(name) BindingLocator::global(name)
@ -248,7 +238,8 @@ impl CompileTimeEnvironment {
/// ///
/// Panics if the binding is not in the current environment. /// Panics if the binding is not in the current environment.
pub(crate) fn initialize_immutable_binding(&self, name: Identifier) -> BindingLocator { pub(crate) fn initialize_immutable_binding(&self, name: Identifier) -> BindingLocator {
let binding = self.bindings.get(&name).expect("binding must exist"); let bindings = self.bindings.borrow();
let binding = bindings.get(&name).expect("binding must exist");
BindingLocator::declarative(name, self.environment_index, binding.index) BindingLocator::declarative(name, self.environment_index, binding.index)
} }
@ -257,7 +248,7 @@ impl CompileTimeEnvironment {
&self, &self,
name: Identifier, name: Identifier,
) -> Result<BindingLocator, BindingLocatorError> { ) -> Result<BindingLocator, BindingLocatorError> {
Ok(match self.bindings.get(&name) { Ok(match self.bindings.borrow().get(&name) {
Some(binding) if binding.mutable => { Some(binding) if binding.mutable => {
BindingLocator::declarative(name, self.environment_index, binding.index) BindingLocator::declarative(name, self.environment_index, binding.index)
} }
@ -265,7 +256,7 @@ impl CompileTimeEnvironment {
Some(_) => return Err(BindingLocatorError::Silent), Some(_) => return Err(BindingLocatorError::Silent),
None => self.outer.as_ref().map_or_else( None => self.outer.as_ref().map_or_else(
|| Ok(BindingLocator::global(name)), || Ok(BindingLocator::global(name)),
|outer| outer.borrow().set_mutable_binding_recursive(name), |outer| outer.set_mutable_binding_recursive(name),
)?, )?,
}) })
} }
@ -279,11 +270,11 @@ impl CompileTimeEnvironment {
if !self.is_function() { if !self.is_function() {
return self.outer.as_ref().map_or_else( return self.outer.as_ref().map_or_else(
|| Ok(BindingLocator::global(name)), || Ok(BindingLocator::global(name)),
|outer| outer.borrow().set_mutable_binding_var_recursive(name), |outer| outer.set_mutable_binding_var_recursive(name),
); );
} }
Ok(match self.bindings.get(&name) { Ok(match self.bindings.borrow().get(&name) {
Some(binding) if binding.mutable => { Some(binding) if binding.mutable => {
BindingLocator::declarative(name, self.environment_index, binding.index) BindingLocator::declarative(name, self.environment_index, binding.index)
} }
@ -291,13 +282,13 @@ impl CompileTimeEnvironment {
Some(_) => return Err(BindingLocatorError::Silent), Some(_) => return Err(BindingLocatorError::Silent),
None => self.outer.as_ref().map_or_else( None => self.outer.as_ref().map_or_else(
|| Ok(BindingLocator::global(name)), || Ok(BindingLocator::global(name)),
|outer| outer.borrow().set_mutable_binding_var_recursive(name), |outer| outer.set_mutable_binding_var_recursive(name),
)?, )?,
}) })
} }
/// Gets the outer environment of this environment. /// Gets the outer environment of this environment.
pub(crate) fn outer(&self) -> Option<Rc<RefCell<Self>>> { pub(crate) fn outer(&self) -> Option<Rc<Self>> {
self.outer.clone() self.outer.clone()
} }

13
boa_engine/src/environments/runtime/declarative/mod.rs

@ -3,10 +3,7 @@ mod global;
mod lexical; mod lexical;
mod module; mod module;
use std::{ use std::{cell::Cell, rc::Rc};
cell::{Cell, RefCell},
rc::Rc,
};
use boa_gc::{Finalize, GcRefCell, Trace}; use boa_gc::{Finalize, GcRefCell, Trace};
pub(crate) use function::{FunctionEnvironment, FunctionSlots, ThisBindingStatus}; pub(crate) use function::{FunctionEnvironment, FunctionSlots, ThisBindingStatus};
@ -42,7 +39,7 @@ pub(crate) struct DeclarativeEnvironment {
// Safety: Nothing in CompileTimeEnvironment needs tracing. // Safety: Nothing in CompileTimeEnvironment needs tracing.
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
compile: Rc<RefCell<CompileTimeEnvironment>>, compile: Rc<CompileTimeEnvironment>,
} }
impl DeclarativeEnvironment { impl DeclarativeEnvironment {
@ -50,20 +47,20 @@ impl DeclarativeEnvironment {
pub(crate) fn global(global_this: JsObject) -> Self { pub(crate) fn global(global_this: JsObject) -> Self {
Self { Self {
kind: DeclarativeEnvironmentKind::Global(GlobalEnvironment::new(global_this)), kind: DeclarativeEnvironmentKind::Global(GlobalEnvironment::new(global_this)),
compile: Rc::new(RefCell::new(CompileTimeEnvironment::new_global())), compile: Rc::new(CompileTimeEnvironment::new_global()),
} }
} }
/// Creates a new `DeclarativeEnvironment` from its kind and compile environment. /// Creates a new `DeclarativeEnvironment` from its kind and compile environment.
pub(crate) fn new( pub(crate) fn new(
kind: DeclarativeEnvironmentKind, kind: DeclarativeEnvironmentKind,
compile: Rc<RefCell<CompileTimeEnvironment>>, compile: Rc<CompileTimeEnvironment>,
) -> Self { ) -> Self {
Self { kind, compile } Self { kind, compile }
} }
/// Gets the compile time environment of this environment. /// Gets the compile time environment of this environment.
pub(crate) fn compile_env(&self) -> Rc<RefCell<CompileTimeEnvironment>> { pub(crate) fn compile_env(&self) -> Rc<CompileTimeEnvironment> {
self.compile.clone() self.compile.clone()
} }

1
boa_engine/src/environments/runtime/declarative/module.rs

@ -65,7 +65,6 @@ impl ModuleEnvironment {
BindingAccessor::Identifier(name) => { BindingAccessor::Identifier(name) => {
let index = env let index = env
.compile_env() .compile_env()
.borrow()
.get_binding(name) .get_binding(name)
.expect("linking must ensure the binding exists"); .expect("linking must ensure the binding exists");

32
boa_engine/src/environments/runtime/mod.rs

@ -1,4 +1,4 @@
use std::{cell::RefCell, rc::Rc}; use std::rc::Rc;
use crate::{ use crate::{
environments::CompileTimeEnvironment, environments::CompileTimeEnvironment,
@ -89,7 +89,7 @@ impl EnvironmentStack {
.rev() .rev()
{ {
if let DeclarativeEnvironmentKind::Function(fun) = &env.kind() { if let DeclarativeEnvironmentKind::Function(fun) = &env.kind() {
let compile_bindings_number = env.compile_env().borrow().num_bindings() as usize; let compile_bindings_number = env.compile_env().num_bindings() as usize;
let mut bindings = fun.poisonable_environment().bindings().borrow_mut(); let mut bindings = fun.poisonable_environment().bindings().borrow_mut();
if compile_bindings_number > bindings.len() { if compile_bindings_number > bindings.len() {
@ -115,7 +115,6 @@ impl EnvironmentStack {
.rev() .rev()
{ {
let compile = env.compile_env(); let compile = env.compile_env();
let compile = compile.borrow();
for name in names { for name in names {
if compile.has_lex_binding(*name) { if compile.has_lex_binding(*name) {
return Some(*name); return Some(*name);
@ -137,7 +136,6 @@ impl EnvironmentStack {
.filter_map(Environment::as_declarative) .filter_map(Environment::as_declarative)
{ {
let compile = env.compile_env(); let compile = env.compile_env();
let compile = compile.borrow();
if compile.is_function() { if compile.is_function() {
return compile.outer().is_none(); return compile.outer().is_none();
} }
@ -220,11 +218,8 @@ impl EnvironmentStack {
/// ///
/// Panics if no environment exists on the stack. /// Panics if no environment exists on the stack.
#[track_caller] #[track_caller]
pub(crate) fn push_lexical( pub(crate) fn push_lexical(&mut self, compile_environment: Rc<CompileTimeEnvironment>) -> u32 {
&mut self, let num_bindings = compile_environment.num_bindings();
compile_environment: Rc<RefCell<CompileTimeEnvironment>>,
) -> u32 {
let num_bindings = compile_environment.borrow().num_bindings();
let (poisoned, with) = { let (poisoned, with) = {
let with = self let with = self
@ -267,10 +262,10 @@ impl EnvironmentStack {
#[track_caller] #[track_caller]
pub(crate) fn push_function( pub(crate) fn push_function(
&mut self, &mut self,
compile_environment: Rc<RefCell<CompileTimeEnvironment>>, compile_environment: Rc<CompileTimeEnvironment>,
function_slots: FunctionSlots, function_slots: FunctionSlots,
) { ) {
let num_bindings = compile_environment.borrow().num_bindings(); let num_bindings = compile_environment.num_bindings();
let (poisoned, with) = { let (poisoned, with) = {
let with = self let with = self
@ -311,12 +306,12 @@ impl EnvironmentStack {
#[track_caller] #[track_caller]
pub(crate) fn push_function_inherit( pub(crate) fn push_function_inherit(
&mut self, &mut self,
compile_environment: Rc<RefCell<CompileTimeEnvironment>>, compile_environment: Rc<CompileTimeEnvironment>,
) { ) {
let num_bindings = compile_environment.borrow().num_bindings(); let num_bindings = compile_environment.num_bindings();
debug_assert!( debug_assert!(
self.stack.len() as u32 == compile_environment.borrow().environment_index(), self.stack.len() as u32 == compile_environment.environment_index(),
"tried to push an invalid compile environment" "tried to push an invalid compile environment"
); );
@ -363,8 +358,8 @@ impl EnvironmentStack {
/// ///
/// Panics if no environment exists on the stack. /// Panics if no environment exists on the stack.
#[track_caller] #[track_caller]
pub(crate) fn push_module(&mut self, compile_environment: Rc<RefCell<CompileTimeEnvironment>>) { pub(crate) fn push_module(&mut self, compile_environment: Rc<CompileTimeEnvironment>) {
let num_bindings = compile_environment.borrow().num_bindings(); let num_bindings = compile_environment.num_bindings();
self.stack.push(Environment::Declarative(Gc::new( self.stack.push(Environment::Declarative(Gc::new(
DeclarativeEnvironment::new( DeclarativeEnvironment::new(
DeclarativeEnvironmentKind::Module(ModuleEnvironment::new(num_bindings)), DeclarativeEnvironmentKind::Module(ModuleEnvironment::new(num_bindings)),
@ -400,7 +395,7 @@ impl EnvironmentStack {
/// # Panics /// # Panics
/// ///
/// Panics if no environment exists on the stack. /// Panics if no environment exists on the stack.
pub(crate) fn current_compile_environment(&self) -> Rc<RefCell<CompileTimeEnvironment>> { pub(crate) fn current_compile_environment(&self) -> Rc<CompileTimeEnvironment> {
self.stack self.stack
.iter() .iter()
.filter_map(Environment::as_declarative) .filter_map(Environment::as_declarative)
@ -419,7 +414,7 @@ impl EnvironmentStack {
.filter_map(Environment::as_declarative) .filter_map(Environment::as_declarative)
{ {
env.poison(); env.poison();
if env.compile_env().borrow().is_function() { if env.compile_env().is_function() {
return; return;
} }
} }
@ -607,7 +602,6 @@ impl Context<'_> {
Environment::Declarative(env) => { Environment::Declarative(env) => {
if env.poisoned() { if env.poisoned() {
let compile = env.compile_env(); let compile = env.compile_env();
let compile = compile.borrow();
if compile.is_function() { if compile.is_function() {
if let Some(b) = compile.get_binding(locator.name) { if let Some(b) = compile.get_binding(locator.name) {
locator.environment_index = b.environment_index; locator.environment_index = b.environment_index;

7
boa_engine/src/module/source.rs

@ -1,5 +1,5 @@
use std::{ use std::{
cell::{Cell, RefCell}, cell::Cell,
collections::HashSet, collections::HashSet,
hash::{BuildHasherDefault, Hash}, hash::{BuildHasherDefault, Hash},
rc::Rc, rc::Rc,
@ -1410,10 +1410,7 @@ impl SourceTextModule {
// 6. Set module.[[Environment]] to env. // 6. Set module.[[Environment]] to env.
let global_env = realm.environment().clone(); let global_env = realm.environment().clone();
let global_compile_env = global_env.compile_env(); let global_compile_env = global_env.compile_env();
let module_compile_env = Rc::new(RefCell::new(CompileTimeEnvironment::new( let module_compile_env = Rc::new(CompileTimeEnvironment::new(global_compile_env, true));
global_compile_env,
true,
)));
let mut compiler = let mut compiler =
ByteCompiler::new(Sym::MAIN, true, false, module_compile_env.clone(), context); ByteCompiler::new(Sym::MAIN, true, false, module_compile_env.clone(), context);

1
boa_engine/src/object/internal_methods/module_namespace.rs

@ -242,7 +242,6 @@ fn module_namespace_exotic_get(
let locator = env let locator = env
.compile_env() .compile_env()
.borrow()
.get_binding(name) .get_binding(name)
.expect("checked before that the name was reachable"); .expect("checked before that the name was reachable");

2
boa_engine/src/realm.rs

@ -106,7 +106,7 @@ impl Realm {
/// Resizes the number of bindings on the global environment. /// Resizes the number of bindings on the global environment.
pub(crate) fn resize_global_env(&self) { pub(crate) fn resize_global_env(&self) {
let binding_number = self.environment().compile_env().borrow().num_bindings(); let binding_number = self.environment().compile_env().num_bindings();
let env = self let env = self
.environment() .environment()
.kind() .kind()

9
boa_engine/src/vm/code_block.rs

@ -23,12 +23,7 @@ use boa_ast::function::FormalParameterList;
use boa_gc::{empty_trace, Finalize, Gc, Trace}; use boa_gc::{empty_trace, Finalize, Gc, Trace};
use boa_interner::Sym; use boa_interner::Sym;
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::{ use std::{cell::Cell, collections::VecDeque, mem::size_of, rc::Rc};
cell::{Cell, RefCell},
collections::VecDeque,
mem::size_of,
rc::Rc,
};
use thin_vec::ThinVec; use thin_vec::ThinVec;
#[cfg(any(feature = "trace", feature = "flowgraph"))] #[cfg(any(feature = "trace", feature = "flowgraph"))]
@ -139,7 +134,7 @@ pub struct CodeBlock {
// //
// TODO(#3034): Maybe changing this to Gc after garbage collection would be better than Rc. // TODO(#3034): Maybe changing this to Gc after garbage collection would be better than Rc.
#[unsafe_ignore_trace] #[unsafe_ignore_trace]
pub(crate) compile_environments: Box<[Rc<RefCell<CompileTimeEnvironment>>]>, pub(crate) compile_environments: Box<[Rc<CompileTimeEnvironment>]>,
} }
/// ---- `CodeBlock` public API ---- /// ---- `CodeBlock` public API ----

Loading…
Cancel
Save