From d0aa5e465dd6f1d5998a5366b9467fce6d4ff7d3 Mon Sep 17 00:00:00 2001 From: Iban Eguia Moraza Date: Sun, 23 Jan 2022 21:42:42 +0100 Subject: [PATCH 1/5] Using the interner in the AST (parser) --- Cargo.lock | 5 +- boa/Cargo.toml | 2 +- boa/benches/full.rs | 22 +- boa/src/builtins/array/tests.rs | 1 - boa/src/builtins/console/mod.rs | 8 +- boa/src/builtins/dataview/mod.rs | 2 +- boa/src/builtins/function/arguments.rs | 11 +- boa/src/builtins/function/mod.rs | 52 +-- boa/src/builtins/map/map_iterator.rs | 4 +- boa/src/builtins/set/set_iterator.rs | 6 +- boa/src/bytecompiler.rs | 277 +++++++++---- boa/src/context.rs | 14 +- .../declarative_environment_record.rs | 122 ++++-- .../environment/environment_record_trait.rs | 39 +- .../function_environment_record.rs | 28 +- .../environment/global_environment_record.rs | 139 +++++-- boa/src/environment/lexical_environment.rs | 18 +- .../environment/object_environment_record.rs | 106 +++-- boa/src/gc.rs | 4 +- boa/src/object/jsobject.rs | 14 +- boa/src/property/mod.rs | 5 +- boa/src/realm.rs | 2 +- boa/src/syntax/ast/constant.rs | 48 +-- boa/src/syntax/ast/keyword.rs | 6 + boa/src/syntax/ast/node/array/mod.rs | 10 +- boa/src/syntax/ast/node/await_expr/mod.rs | 11 +- boa/src/syntax/ast/node/block/mod.rs | 26 +- boa/src/syntax/ast/node/call/mod.rs | 14 +- .../node/conditional/conditional_op/mod.rs | 15 +- .../ast/node/conditional/if_node/mod.rs | 29 +- .../declaration/arrow_function_decl/mod.rs | 28 +- .../declaration/async_function_decl/mod.rs | 50 ++- .../declaration/async_function_expr/mod.rs | 51 ++- .../declaration/async_generator_decl/mod.rs | 49 ++- .../declaration/async_generator_expr/mod.rs | 56 ++- .../ast/node/declaration/function_decl/mod.rs | 44 +- .../ast/node/declaration/function_expr/mod.rs | 58 ++- .../node/declaration/generator_decl/mod.rs | 44 +- .../node/declaration/generator_expr/mod.rs | 60 ++- boa/src/syntax/ast/node/declaration/mod.rs | 215 ++++++---- .../ast/node/field/get_const_field/mod.rs | 23 +- .../syntax/ast/node/field/get_field/mod.rs | 12 +- boa/src/syntax/ast/node/identifier/mod.rs | 42 +- .../node/{ => iteration}/break_node/mod.rs | 38 +- .../node/{ => iteration}/break_node/tests.rs | 4 +- .../ast/node/iteration/continue_node/mod.rs | 34 +- .../ast/node/iteration/do_while_loop/mod.rs | 41 +- .../ast/node/iteration/for_in_loop/mod.rs | 41 +- .../syntax/ast/node/iteration/for_loop/mod.rs | 51 ++- .../ast/node/iteration/for_of_loop/mod.rs | 42 +- boa/src/syntax/ast/node/iteration/mod.rs | 27 +- .../ast/node/iteration/while_loop/mod.rs | 40 +- boa/src/syntax/ast/node/mod.rs | 212 +++++----- boa/src/syntax/ast/node/new/mod.rs | 8 +- boa/src/syntax/ast/node/object/mod.rs | 70 ++-- .../syntax/ast/node/operator/assign/mod.rs | 12 +- .../syntax/ast/node/operator/bin_op/mod.rs | 13 +- .../syntax/ast/node/operator/unary_op/mod.rs | 8 +- boa/src/syntax/ast/node/return_smt/mod.rs | 18 +- boa/src/syntax/ast/node/spread/mod.rs | 8 +- boa/src/syntax/ast/node/statement_list/mod.rs | 60 +-- boa/src/syntax/ast/node/switch/mod.rs | 35 +- boa/src/syntax/ast/node/template/mod.rs | 90 ++-- boa/src/syntax/ast/node/throw/mod.rs | 8 +- boa/src/syntax/ast/node/try_node/mod.rs | 55 +-- boa/src/syntax/ast/node/yield/mod.rs | 13 +- boa/src/syntax/ast/punctuator.rs | 124 +++--- boa/src/syntax/lexer/regex.rs | 101 +---- boa/src/syntax/lexer/template.rs | 6 +- boa/src/syntax/lexer/tests.rs | 140 ++++--- boa/src/syntax/lexer/token.rs | 53 ++- .../parser/cursor/buffered_lexer/tests.rs | 12 +- .../expression/assignment/arrow_function.rs | 12 +- .../parser/expression/left_hand_side/call.rs | 13 +- .../expression/left_hand_side/member.rs | 10 +- .../expression/left_hand_side/template.rs | 16 +- .../primary/array_initializer/tests.rs | 22 +- .../primary/async_function_expression/mod.rs | 16 +- .../async_function_expression/tests.rs | 26 +- .../primary/async_generator_expression/mod.rs | 18 +- .../{test.rs => tests.rs} | 26 +- .../primary/function_expression/mod.rs | 14 +- .../primary/function_expression/tests.rs | 26 +- .../primary/generator_expression/mod.rs | 14 +- .../primary/generator_expression/tests.rs | 12 +- .../syntax/parser/expression/primary/mod.rs | 33 +- .../primary/object_initializer/mod.rs | 54 +-- .../primary/object_initializer/tests.rs | 117 +++--- .../parser/expression/primary/template/mod.rs | 21 +- .../syntax/parser/expression/primary/tests.rs | 14 +- boa/src/syntax/parser/expression/tests.rs | 385 +++++++++++++----- boa/src/syntax/parser/expression/update.rs | 6 +- boa/src/syntax/parser/function/mod.rs | 7 +- boa/src/syntax/parser/function/tests.rs | 259 ++++++++---- .../syntax/parser/statement/block/tests.rs | 42 +- .../syntax/parser/statement/break_stm/mod.rs | 2 +- .../parser/statement/break_stm/tests.rs | 52 +-- .../parser/statement/continue_stm/mod.rs | 2 +- .../parser/statement/continue_stm/tests.rs | 48 ++- .../hoistable/async_function_decl/tests.rs | 12 +- .../hoistable/async_generator_decl/tests.rs | 4 +- .../hoistable/function_decl/tests.rs | 12 +- .../hoistable/generator_decl/tests.rs | 4 +- .../statement/declaration/hoistable/mod.rs | 19 +- .../parser/statement/declaration/tests.rs | 110 +++-- .../syntax/parser/statement/if_stm/tests.rs | 4 +- .../statement/iteration/for_statement.rs | 2 +- .../parser/statement/iteration/tests.rs | 58 ++- .../parser/statement/labelled_stm/mod.rs | 9 +- boa/src/syntax/parser/statement/mod.rs | 87 ++-- .../syntax/parser/statement/switch/tests.rs | 24 +- .../syntax/parser/statement/throw/tests.rs | 4 +- .../syntax/parser/statement/try_stm/catch.rs | 10 +- .../syntax/parser/statement/try_stm/tests.rs | 49 +-- boa/src/syntax/parser/tests.rs | 166 +++++--- boa/src/tests.rs | 1 - boa/src/value/mod.rs | 2 +- boa/src/vm/call_frame.rs | 3 +- boa/src/vm/code_block.rs | 114 +++--- boa/src/vm/mod.rs | 71 ++-- boa_cli/Cargo.toml | 2 +- boa_cli/src/main.rs | 2 +- boa_interner/Cargo.toml | 1 + boa_interner/src/lib.rs | 249 ++++++++++- boa_interner/src/tests.rs | 74 ++++ boa_tester/Cargo.toml | 2 +- boa_tester/src/exec/mod.rs | 4 +- boa_wasm/Cargo.toml | 2 +- yarn.lock | 6 +- 129 files changed, 3343 insertions(+), 2167 deletions(-) rename boa/src/syntax/ast/node/{ => iteration}/break_node/mod.rs (65%) rename boa/src/syntax/ast/node/{ => iteration}/break_node/tests.rs (89%) rename boa/src/syntax/parser/expression/primary/async_generator_expression/{test.rs => tests.rs} (67%) create mode 100644 boa_interner/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index c20e3a35ad9..51d726ea262 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,6 +112,7 @@ dependencies = [ name = "boa_interner" version = "0.13.0" dependencies = [ + "gc", "serde", "string-interner", ] @@ -1273,9 +1274,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79" +checksum = "edde269018d33d7146dd074e5f7da6fef9b0a957507454c867caa0852c560a9a" dependencies = [ "itoa 1.0.1", "ryu", diff --git a/boa/Cargo.toml b/boa/Cargo.toml index 0d485a506aa..686311fbf71 100644 --- a/boa/Cargo.toml +++ b/boa/Cargo.toml @@ -23,7 +23,7 @@ boa_unicode = { path = "../boa_unicode", version = "0.13.0" } boa_interner = { path = "../boa_interner", version = "0.13.0" } gc = { version = "0.4.1", features = ["derive"] } serde = { version = "1.0.134", features = ["derive", "rc"] } -serde_json = "1.0.75" +serde_json = "1.0.76" rand = "0.8.4" num-traits = "0.2.14" regress = "0.4.1" diff --git a/boa/benches/full.rs b/boa/benches/full.rs index efa7c25a159..197094c5c72 100644 --- a/boa/benches/full.rs +++ b/boa/benches/full.rs @@ -1,7 +1,6 @@ //! Benchmarks of the whole execution engine in Boa. -use boa::{realm::Realm, syntax::Parser, Context}; -use boa_interner::Interner; +use boa::{realm::Realm, Context}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; #[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))] @@ -21,9 +20,9 @@ macro_rules! full_benchmarks { $( { static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js")); - let mut interner = Interner::new(); + let mut context = Context::default(); c.bench_function(concat!($id, " (Parser)"), move |b| { - b.iter(|| Parser::new(black_box(CODE.as_bytes()), false).parse_all(&mut interner)) + b.iter(|| context.parse(black_box(CODE))) }); } )* @@ -32,11 +31,11 @@ macro_rules! full_benchmarks { $( { static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js")); - let mut interner = Interner::new(); - let statement_list = Parser::new(CODE.as_bytes(), false).parse_all( &mut interner).expect("parsing failed"); + let mut context = Context::default(); + let statement_list = context.parse(CODE).expect("parsing failed"); c.bench_function(concat!($id, " (Compiler)"), move |b| { b.iter(|| { - Context::compile(black_box(&statement_list)); + context.compile(black_box(&statement_list)) }) }); } @@ -46,13 +45,12 @@ macro_rules! full_benchmarks { $( { static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js")); - let mut interner = Interner::new(); - let statement_list = Parser::new(CODE.as_bytes(), false).parse_all(&mut interner).expect("parsing failed"); - let mut context = Context::new(interner); - let code_block = Context::compile(&statement_list); + let mut context = Context::default(); + let statement_list = context.parse(CODE).expect("parsing failed"); + let code_block = context.compile(&statement_list); c.bench_function(concat!($id, " (Execution)"), move |b| { b.iter(|| { - context.execute(black_box(code_block.clone())).unwrap(); + context.execute(black_box(code_block.clone())).unwrap() }) }); } diff --git a/boa/src/builtins/array/tests.rs b/boa/src/builtins/array/tests.rs index 9d4d683ba0a..2374fb13635 100644 --- a/boa/src/builtins/array/tests.rs +++ b/boa/src/builtins/array/tests.rs @@ -117,7 +117,6 @@ fn of() { assert_eq!(context.eval("a.length").unwrap(), JsValue::new(3)); } -#[ignore] #[test] fn concat() { let mut context = Context::default(); diff --git a/boa/src/builtins/console/mod.rs b/boa/src/builtins/console/mod.rs index 861fef63506..bbea231e94e 100644 --- a/boa/src/builtins/console/mod.rs +++ b/boa/src/builtins/console/mod.rs @@ -304,7 +304,13 @@ impl Console { let mut prev_frame = context.vm.frame.as_ref(); while let Some(frame) = prev_frame { - stack_trace.push(frame.code.name.to_string()); + stack_trace.push( + context + .interner() + .resolve(frame.code.name) + .expect("string disappeared") + .to_owned(), + ); prev_frame = frame.prev.as_ref(); } diff --git a/boa/src/builtins/dataview/mod.rs b/boa/src/builtins/dataview/mod.rs index 37207e6494f..e57d77efa43 100644 --- a/boa/src/builtins/dataview/mod.rs +++ b/boa/src/builtins/dataview/mod.rs @@ -1,6 +1,7 @@ use crate::{ builtins::{array_buffer::SharedMemoryOrder, typed_array::TypedArrayName, BuiltIn, JsArgs}, context::StandardObjects, + gc::{Finalize, Trace}, object::{ internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder, JsObject, ObjectData, @@ -10,7 +11,6 @@ use crate::{ value::JsValue, Context, JsResult, }; -use gc::{Finalize, Trace}; #[derive(Debug, Clone, Trace, Finalize)] pub struct DataView { diff --git a/boa/src/builtins/function/arguments.rs b/boa/src/builtins/function/arguments.rs index 7ef1e56c768..c74b63303ad 100644 --- a/boa/src/builtins/function/arguments.rs +++ b/boa/src/builtins/function/arguments.rs @@ -1,14 +1,13 @@ use crate::{ builtins::Array, environment::lexical_environment::Environment, + gc::{Finalize, Trace}, object::{FunctionBuilder, JsObject, ObjectData}, property::PropertyDescriptor, symbol::{self, WellKnownSymbols}, syntax::ast::node::FormalParameter, Context, JsValue, }; - -use gc::{Finalize, Trace}; use rustc_hash::FxHashSet; #[derive(Debug, Clone, Trace, Finalize)] @@ -171,9 +170,9 @@ impl Arguments { // a. Let name be parameterNames[index]. for (index, parameter_name_vec) in formals.iter().map(|fp| fp.names()).enumerate().rev() { - for parameter_name in parameter_name_vec.iter().cloned() { + for parameter_name in parameter_name_vec.iter().copied() { // b. If name is not an element of mappedNames, then - if !mapped_names.contains(parameter_name) { + if !mapped_names.contains(¶meter_name) { // i. Add name as an element of the list mappedNames. mapped_names.insert(parameter_name); // ii. If index < len, then @@ -189,7 +188,7 @@ impl Arguments { // 1. Let getterClosure be a new Abstract Closure with no parameters that captures // name and env and performs the following steps when called: |_, _, captures, context| { - captures.0.get_binding_value(&captures.1, false, context) + captures.0.get_binding_value(captures.1, false, context) }, (env.clone(), parameter_name.to_owned()), ) @@ -212,7 +211,7 @@ impl Arguments { // a. Return env.SetMutableBinding(name, value, false). captures .0 - .set_mutable_binding(&captures.1, value, false, context) + .set_mutable_binding(captures.1, value, false, context) .map(|_| JsValue::Undefined) // Ok(JsValue::Undefined) }, diff --git a/boa/src/builtins/function/mod.rs b/boa/src/builtins/function/mod.rs index ebc110bd460..255dbf14ffa 100644 --- a/boa/src/builtins/function/mod.rs +++ b/boa/src/builtins/function/mod.rs @@ -11,39 +11,29 @@ //! [spec]: https://tc39.es/ecma262/#sec-function-objects //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function -use std::{ - any::Any, - borrow::Cow, - fmt, - ops::{Deref, DerefMut}, -}; - -use dyn_clone::DynClone; -use gc::{Gc, GcCell}; - +use super::JsArgs; use crate::{ builtins::BuiltIn, context::StandardObjects, environment::lexical_environment::Environment, - gc::{Finalize, Trace}, - object::JsObject, - object::{internal_methods::get_prototype_from_constructor, NativeObject, ObjectData}, - property::Attribute, - property::PropertyDescriptor, - BoaProfiler, Context, JsResult, JsValue, -}; -use crate::{object::Object, symbol::WellKnownSymbols}; -use crate::{ - object::{ConstructorBuilder, FunctionBuilder}, - property::PropertyKey, - JsString, -}; -use crate::{ - object::{Ref, RefMut}, + gc::{self, Finalize, Gc, Trace}, + object::{ + internal_methods::get_prototype_from_constructor, JsObject, NativeObject, Object, + ObjectData, + }, + object::{ConstructorBuilder, FunctionBuilder, Ref, RefMut}, + property::{Attribute, PropertyDescriptor, PropertyKey}, + symbol::WellKnownSymbols, value::IntegerOrInfinity, + BoaProfiler, Context, JsResult, JsString, JsValue, +}; +use dyn_clone::DynClone; +use std::{ + any::Any, + borrow::Cow, + fmt, + ops::{Deref, DerefMut}, }; - -use super::JsArgs; pub(crate) mod arguments; #[cfg(test)] @@ -136,7 +126,7 @@ impl ConstructorKind { /// with `Any::downcast_ref` and `Any::downcast_mut` to recover the original /// type. #[derive(Clone, Debug, Trace, Finalize)] -pub struct Captures(Gc>>); +pub struct Captures(Gc>>); impl Captures { /// Creates a new capture context. @@ -144,7 +134,7 @@ impl Captures { where T: NativeObject, { - Self(Gc::new(GcCell::new(Box::new(captures)))) + Self(Gc::new(gc::Cell::new(Box::new(captures)))) } /// Casts `Captures` to `Any` @@ -152,7 +142,7 @@ impl Captures { /// # Panics /// /// Panics if it's already borrowed as `&mut Any` - pub fn as_any(&self) -> gc::GcCellRef<'_, dyn Any> { + pub fn as_any(&self) -> gc::Ref<'_, dyn Any> { Ref::map(self.0.borrow(), |data| data.deref().as_any()) } @@ -161,7 +151,7 @@ impl Captures { /// # Panics /// /// Panics if it's already borrowed as `&mut Any` - pub fn as_mut_any(&self) -> gc::GcCellRefMut<'_, Box, dyn Any> { + pub fn as_mut_any(&self) -> gc::RefMut<'_, Box, dyn Any> { RefMut::map(self.0.borrow_mut(), |data| data.deref_mut().as_mut_any()) } } diff --git a/boa/src/builtins/map/map_iterator.rs b/boa/src/builtins/map/map_iterator.rs index 340ff75a292..b7cbb1ab63e 100644 --- a/boa/src/builtins/map/map_iterator.rs +++ b/boa/src/builtins/map/map_iterator.rs @@ -1,13 +1,13 @@ +use super::ordered_map::MapLock; use crate::{ builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue}, + gc::{Finalize, Trace}, object::{JsObject, ObjectData}, property::{PropertyDescriptor, PropertyNameKind}, symbol::WellKnownSymbols, BoaProfiler, Context, JsResult, }; -use gc::{Finalize, Trace}; -use super::ordered_map::MapLock; /// The Map Iterator object represents an iteration over a map. It implements the iterator protocol. /// /// More information: diff --git a/boa/src/builtins/set/set_iterator.rs b/boa/src/builtins/set/set_iterator.rs index 3720423143d..c82ac608ca3 100644 --- a/boa/src/builtins/set/set_iterator.rs +++ b/boa/src/builtins/set/set_iterator.rs @@ -1,13 +1,11 @@ use crate::{ - builtins::Array, - builtins::JsValue, - builtins::{function::make_builtin_fn, iterable::create_iter_result_object}, + builtins::{function::make_builtin_fn, iterable::create_iter_result_object, Array, JsValue}, + gc::{Finalize, Trace}, object::{JsObject, ObjectData}, property::{PropertyDescriptor, PropertyNameKind}, symbol::WellKnownSymbols, BoaProfiler, Context, JsResult, }; -use gc::{Finalize, Trace}; /// The Set Iterator object represents an iteration over a set. It implements the iterator protocol. /// diff --git a/boa/src/bytecompiler.rs b/boa/src/bytecompiler.rs index 1aa6e62dfe7..5f219cbbfba 100644 --- a/boa/src/bytecompiler.rs +++ b/boa/src/bytecompiler.rs @@ -1,7 +1,6 @@ -use gc::Gc; - use crate::{ builtins::function::ThisMode, + gc::Gc, syntax::ast::{ node::{ declaration::{BindingPatternTypeArray, BindingPatternTypeObject, DeclarationPattern}, @@ -16,7 +15,9 @@ use crate::{ vm::{CodeBlock, Opcode}, JsBigInt, JsString, JsValue, }; -use std::{collections::HashMap, mem::size_of}; +use boa_interner::{Interner, Sym}; +use rustc_hash::FxHashMap; +use std::mem::size_of; #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum Literal { @@ -32,7 +33,7 @@ struct Label { #[derive(Debug, Clone)] struct JumpControlInfo { - label: Option>, + label: Option, start_address: u32, kind: JumpControlInfoKind, breaks: Vec