Skip to content

Commit

Permalink
Remove compile time environments from every runtime DeclarativeEnviro…
Browse files Browse the repository at this point in the history
…nment
  • Loading branch information
raskad committed Sep 7, 2024
1 parent 9643c37 commit c1b05f4
Show file tree
Hide file tree
Showing 18 changed files with 236 additions and 134 deletions.
18 changes: 13 additions & 5 deletions core/engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Eval {
/// [spec]: https://tc39.es/ecma262/#sec-eval-x
fn eval(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Return ? PerformEval(x, false, false).
Self::perform_eval(args.get_or_undefined(0), false, false, context)
Self::perform_eval(args.get_or_undefined(0), false, None, false, context)
}

/// `19.2.1.1 PerformEval ( x, strictCaller, direct )`
Expand All @@ -74,6 +74,7 @@ impl Eval {
pub(crate) fn perform_eval(
x: &JsValue,
direct: bool,
lex_env: Option<Rc<CompileTimeEnvironment>>,
mut strict: bool,
context: &mut Context,
) -> JsResult<JsValue> {
Expand Down Expand Up @@ -229,10 +230,17 @@ impl Eval {
}
});

let var_environment = context.vm.environments.outer_function_environment().clone();
let mut var_env = var_environment.compile_env();

let lex_env = context.vm.environments.current_compile_environment();
let (var_environment, mut var_env) =
if let Some(e) = context.vm.environments.outer_function_environment() {
(e.0, e.1)
} else {
(
context.realm().environment().clone(),
context.realm().compile_environment(),
)
};

let lex_env = lex_env.unwrap_or(context.realm().compile_environment());
let lex_env = Rc::new(CompileTimeEnvironment::new(lex_env, strict));

let mut annex_b_function_names = Vec::new();
Expand Down
20 changes: 10 additions & 10 deletions core/engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,8 @@ impl BuiltInFunctionObject {
.compile(
&parameters,
&body,
context.realm().environment().compile_env(),
context.realm().environment().compile_env(),
context.realm().compile_environment(),
context.realm().compile_environment(),
context.interner_mut(),
);

Expand Down Expand Up @@ -1008,10 +1008,10 @@ pub(crate) fn function_call(
let mut last_env = 0;

if code.has_binding_identifier() {
let index = context
.vm
.environments
.push_lexical(code.constant_compile_time_environment(last_env));
let index = context.vm.environments.push_lexical(
code.constant_compile_time_environment(last_env)
.num_bindings(),
);
context.vm.environments.put_lexical_value(
BindingLocatorEnvironment::Stack(index),
0,
Expand Down Expand Up @@ -1101,10 +1101,10 @@ fn function_construct(
let mut last_env = 0;

if code.has_binding_identifier() {
let index = context
.vm
.environments
.push_lexical(code.constant_compile_time_environment(last_env));
let index = context.vm.environments.push_lexical(
code.constant_compile_time_environment(last_env)
.num_bindings(),
);
context.vm.environments.put_lexical_value(
BindingLocatorEnvironment::Stack(index),
0,
Expand Down
4 changes: 2 additions & 2 deletions core/engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ impl Json {
js_string!("<main>"),
script.strict(),
true,
context.realm().environment().compile_env(),
context.realm().environment().compile_env(),
context.realm().compile_environment(),
context.realm().compile_environment(),
false,
false,
context.interner_mut(),
Expand Down
17 changes: 15 additions & 2 deletions core/engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1709,9 +1709,22 @@ impl<'ctx> ByteCompiler<'ctx> {
}

match kind {
CallKind::CallEval if contains_spread => self.emit_opcode(Opcode::CallEvalSpread),
CallKind::CallEval => {
self.emit_with_varying_operand(Opcode::CallEval, call.args().len() as u32);
let env_index = self.constants.len() as u32;
self.constants.push(Constant::CompileTimeEnvironment(
self.lexical_environment.clone(),
));
if contains_spread {
self.emit_with_varying_operand(Opcode::CallEvalSpread, env_index);
} else {
self.emit(
Opcode::CallEval,
&[
Operand::Varying(call.args().len() as u32),
Operand::Varying(env_index),
],
);
}
}
CallKind::Call if contains_spread => self.emit_opcode(Opcode::CallSpread),
CallKind::Call => {
Expand Down
25 changes: 23 additions & 2 deletions core/engine/src/environments/runtime/declarative/function.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
use std::rc::Rc;

use boa_gc::{custom_trace, Finalize, GcRefCell, Trace};

use crate::{builtins::function::OrdinaryFunction, JsNativeError, JsObject, JsResult, JsValue};
use crate::{
builtins::function::OrdinaryFunction, environments::CompileTimeEnvironment, JsNativeError,
JsObject, JsResult, JsValue,
};

use super::PoisonableEnvironment;

#[derive(Debug, Trace, Finalize)]
pub(crate) struct FunctionEnvironment {
inner: PoisonableEnvironment,
slots: Box<FunctionSlots>,

// Safety: Nothing in CompileTimeEnvironment needs tracing.
#[unsafe_ignore_trace]
compile: Rc<CompileTimeEnvironment>,
}

impl FunctionEnvironment {
/// Creates a new `FunctionEnvironment`.
pub(crate) fn new(bindings: u32, poisoned: bool, with: bool, slots: FunctionSlots) -> Self {
pub(crate) fn new(
bindings: u32,
poisoned: bool,
with: bool,
slots: FunctionSlots,
compile: Rc<CompileTimeEnvironment>,
) -> Self {
Self {
inner: PoisonableEnvironment::new(bindings, poisoned, with),
slots: Box::new(slots),
compile,
}
}

Expand All @@ -24,6 +40,11 @@ impl FunctionEnvironment {
&self.slots
}

/// Gets the compile time environment of this function environment.
pub(crate) const fn compile(&self) -> &Rc<CompileTimeEnvironment> {
&self.compile
}

/// Gets the `poisonable_environment` of this function environment.
pub(crate) const fn poisonable_environment(&self) -> &PoisonableEnvironment {
&self.inner
Expand Down
29 changes: 6 additions & 23 deletions core/engine/src/environments/runtime/declarative/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ pub(crate) use global::GlobalEnvironment;
pub(crate) use lexical::LexicalEnvironment;
pub(crate) use module::ModuleEnvironment;

use crate::{environments::CompileTimeEnvironment, JsResult, JsValue};
use crate::{JsResult, JsValue};
use boa_gc::{Finalize, GcRefCell, Trace};
use std::{cell::Cell, rc::Rc};
use std::cell::Cell;

/// A declarative environment holds binding values at runtime.
///
Expand All @@ -35,32 +35,19 @@ use std::{cell::Cell, rc::Rc};
#[derive(Debug, Trace, Finalize)]
pub(crate) struct DeclarativeEnvironment {
kind: DeclarativeEnvironmentKind,

// Safety: Nothing in CompileTimeEnvironment needs tracing.
#[unsafe_ignore_trace]
compile: Rc<CompileTimeEnvironment>,
}

impl DeclarativeEnvironment {
/// Creates a new global `DeclarativeEnvironment`.
pub(crate) fn global() -> Self {
Self {
kind: DeclarativeEnvironmentKind::Global(GlobalEnvironment::new()),
compile: Rc::new(CompileTimeEnvironment::new_global()),
}
}

/// Creates a new `DeclarativeEnvironment` from its kind and compile environment.
pub(crate) fn new(
kind: DeclarativeEnvironmentKind,
compile: Rc<CompileTimeEnvironment>,
) -> Self {
Self { kind, compile }
}

/// Gets the compile time environment of this environment.
pub(crate) fn compile_env(&self) -> Rc<CompileTimeEnvironment> {
self.compile.clone()
pub(crate) fn new(kind: DeclarativeEnvironmentKind) -> Self {
Self { kind }
}

/// Returns a reference to the the kind of the environment.
Expand All @@ -70,11 +57,7 @@ impl DeclarativeEnvironment {

/// Returns whether this environment is a function environment.
pub(crate) fn is_function(&self) -> bool {
if let DeclarativeEnvironmentKind::Function(_) = self.kind() {
true
} else {
false
}
matches!(self.kind(), DeclarativeEnvironmentKind::Function(_))
}

/// Gets the binding value from the environment by index.
Expand Down Expand Up @@ -139,7 +122,7 @@ impl DeclarativeEnvironment {
/// Extends the environment with the bindings from the compile time environment.
pub(crate) fn extend_from_compile(&self) {
if let Some(env) = self.kind().as_function() {
let compile_bindings_number = self.compile_env().num_bindings() as usize;
let compile_bindings_number = env.compile().num_bindings() as usize;
let mut bindings = env.poisonable_environment().bindings().borrow_mut();
if compile_bindings_number > bindings.len() {
bindings.resize(compile_bindings_number, None);
Expand Down
21 changes: 17 additions & 4 deletions core/engine/src/environments/runtime/declarative/module.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::cell::RefCell;
use std::{cell::RefCell, rc::Rc};

use boa_gc::{Finalize, GcRefCell, Trace};

use crate::{module::Module, JsString, JsValue};
use crate::{environments::CompileTimeEnvironment, module::Module, JsString, JsValue};

/// Type of accessor used to access an indirect binding.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -36,16 +36,26 @@ enum BindingType {
#[derive(Debug, Trace, Finalize)]
pub(crate) struct ModuleEnvironment {
bindings: GcRefCell<Vec<BindingType>>,

// Safety: Nothing in CompileTimeEnvironment needs tracing.
#[unsafe_ignore_trace]
compile: Rc<CompileTimeEnvironment>,
}

impl ModuleEnvironment {
/// Creates a new `LexicalEnvironment`.
pub(crate) fn new(bindings: u32) -> Self {
pub(crate) fn new(bindings: u32, compile: Rc<CompileTimeEnvironment>) -> Self {
Self {
bindings: GcRefCell::new(vec![BindingType::Direct(None); bindings as usize]),
compile,
}
}

/// Gets the compile time environment of this module environment.
pub(crate) const fn compile(&self) -> &Rc<CompileTimeEnvironment> {
&self.compile
}

/// Get the binding value from the environment by it's index.
///
/// # Panics
Expand All @@ -63,7 +73,10 @@ impl ModuleEnvironment {
match &*accessor.clone().borrow() {
BindingAccessor::Identifier(name) => {
let index = env
.compile_env()
.kind()
.as_module()
.expect("must be module environment")
.compile()
.get_binding(name)
.expect("linking must ensure the binding exists");

Expand Down
Loading

0 comments on commit c1b05f4

Please sign in to comment.