Skip to content

Commit

Permalink
First version of the interner
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Dec 22, 2021
1 parent 9b5e239 commit 66aa45c
Show file tree
Hide file tree
Showing 91 changed files with 2,561 additions and 1,213 deletions.
26 changes: 26 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ once_cell = "1.9.0"

# Optional Dependencies
measureme = { version = "10.0.0", optional = true }
string-interner = "0.14.0"

[target.wasm32-unknown-unknown.dependencies]
getrandom = { version = "0.2.3", features = ["js"] }
Expand Down
18 changes: 16 additions & 2 deletions boa/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
realm::Realm,
syntax::Parser,
vm::{FinallyReturn, Vm},
BoaProfiler, JsResult, JsString, JsValue,
BoaProfiler, Interner, JsResult, JsString, JsValue,
};

#[cfg(feature = "console")]
Expand Down Expand Up @@ -366,6 +366,9 @@ pub struct Context {
/// realm holds both the global object and the environment
pub(crate) realm: Realm,

/// String interner
interner: Interner,

/// console object state.
#[cfg(feature = "console")]
console: Console,
Expand Down Expand Up @@ -393,6 +396,7 @@ impl Default for Context {
let realm = Realm::create();
let mut context = Self {
realm,
interner: Interner::new(),
#[cfg(feature = "console")]
console: Console::default(),
iterator_prototypes: IteratorPrototypes::default(),
Expand Down Expand Up @@ -434,6 +438,16 @@ impl Context {
Default::default()
}

/// Gets the interner of the context.
pub fn interner(&self) -> &Interner {
&self.interner
}

/// Gets the interner of the context mutably.
pub fn interner_mut(&mut self) -> &mut Interner {
&mut self.interner
}

/// A helper function for getting an immutable reference to the `console` object.
#[cfg(feature = "console")]
pub(crate) fn console(&self) -> &Console {
Expand Down Expand Up @@ -875,7 +889,7 @@ impl Context {
let src_bytes: &[u8] = src.as_ref();

let parsing_result = Parser::new(src_bytes, false)
.parse_all()
.parse_all(&mut self.interner)
.map_err(|e| e.to_string());

let statement_list = match parsing_result {
Expand Down
39 changes: 34 additions & 5 deletions boa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ pub mod prelude {
pub use crate::{object::JsObject, Context, JsBigInt, JsResult, JsString, JsValue};
}

use std::result::Result as StdResult;

pub(crate) use crate::profiler::BoaProfiler;
use std::{num::NonZeroUsize, result::Result as StdResult};
use string_interner::{backend::BufferBackend, StringInterner, Symbol};

#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};

// Export things to root level
#[doc(inline)]
Expand All @@ -83,14 +86,40 @@ use crate::syntax::{
#[must_use]
pub type JsResult<T> = StdResult<T, JsValue>;

/// The string interner for Boa.
pub type Interner = StringInterner<BufferBackend<Sym>>;

/// The string symbol type for Boa.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "deser", serde(transparent))]
pub struct Sym {
value: NonZeroUsize,
}

impl Symbol for Sym {
#[inline]
fn try_from_usize(index: usize) -> Option<Self> {
NonZeroUsize::new(index.wrapping_add(1)).map(|value| Self { value })
}

#[inline]
fn to_usize(self) -> usize {
self.value.get() - 1
}
}

/// Parses the given source code.
///
/// It will return either the statement list AST node for the code, or a parsing error if something
/// goes wrong.
#[inline]
pub fn parse<T: AsRef<[u8]>>(src: T, strict_mode: bool) -> StdResult<StatementList, ParseError> {
let src_bytes: &[u8] = src.as_ref();
Parser::new(src_bytes, strict_mode).parse_all()
pub fn parse<T: AsRef<[u8]>>(
src: T,
strict_mode: bool,
interner: &mut Interner,
) -> StdResult<StatementList, ParseError> {
Parser::new(src.as_ref(), strict_mode).parse_all(interner)
}

/// Execute the code using an existing Context
Expand Down
5 changes: 4 additions & 1 deletion boa/src/syntax/ast/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,8 @@ unsafe impl Trace for PropertyName {
/// level.
#[cfg(test)]
fn test_formatting(source: &'static str) {
use crate::Interner;

// Remove preceding newline.
let source = &source[1..];

Expand All @@ -680,7 +682,8 @@ fn test_formatting(source: &'static str) {
.map(|l| &l[characters_to_remove..]) // Remove preceding whitespace from each line
.collect::<Vec<&'static str>>()
.join("\n");
let result = format!("{}", crate::parse(&scenario, false).unwrap());
let mut interner = Interner::new();
let result = format!("{}", crate::parse(&scenario, false, &mut interner).unwrap());
if scenario != result {
eprint!("========= Expected:\n{}", scenario);
eprint!("========= Got:\n{}", result);
Expand Down
22 changes: 19 additions & 3 deletions boa/src/syntax/lexer/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
ast::{Position, Span},
lexer::{Token, TokenKind},
},
Interner,
};
use core::convert::TryFrom;
use std::io::Read;
Expand All @@ -24,7 +25,12 @@ use std::io::Read;
pub(super) struct SingleLineComment;

impl<R> Tokenizer<R> for SingleLineComment {
fn lex(&mut self, cursor: &mut Cursor<R>, start_pos: Position) -> Result<Token, Error>
fn lex(
&mut self,
cursor: &mut Cursor<R>,
start_pos: Position,
interner: &mut Interner,
) -> Result<Token, Error>
where
R: Read,
{
Expand Down Expand Up @@ -59,7 +65,12 @@ impl<R> Tokenizer<R> for SingleLineComment {
pub(super) struct MultiLineComment;

impl<R> Tokenizer<R> for MultiLineComment {
fn lex(&mut self, cursor: &mut Cursor<R>, start_pos: Position) -> Result<Token, Error>
fn lex(
&mut self,
cursor: &mut Cursor<R>,
start_pos: Position,
_interner: &mut Interner,
) -> Result<Token, Error>
where
R: Read,
{
Expand Down Expand Up @@ -103,7 +114,12 @@ impl<R> Tokenizer<R> for MultiLineComment {
pub(super) struct HashbangComment;

impl<R> Tokenizer<R> for HashbangComment {
fn lex(&mut self, cursor: &mut Cursor<R>, start_pos: Position) -> Result<Token, Error>
fn lex(
&mut self,
cursor: &mut Cursor<R>,
start_pos: Position,
_interner: &mut Interner,
) -> Result<Token, Error>
where
R: Read,
{
Expand Down
10 changes: 8 additions & 2 deletions boa/src/syntax/lexer/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
ast::{Keyword, Position, Span},
lexer::{StringLiteral, Token, TokenKind},
},
Interner,
};
use boa_unicode::UnicodeProperties;
use core::convert::TryFrom;
Expand Down Expand Up @@ -80,7 +81,12 @@ impl Identifier {
}

impl<R> Tokenizer<R> for Identifier {
fn lex(&mut self, cursor: &mut Cursor<R>, start_pos: Position) -> Result<Token, Error>
fn lex(
&mut self,
cursor: &mut Cursor<R>,
start_pos: Position,
interner: &mut Interner,
) -> Result<Token, Error>
where
R: Read,
{
Expand Down Expand Up @@ -123,7 +129,7 @@ impl<R> Tokenizer<R> for Identifier {
start_pos,
));
}
TokenKind::identifier(identifier_name.into_boxed_str())
TokenKind::identifier(interner.get_or_intern(identifier_name))
};

Ok(Token::new(token_kind, Span::new(start_pos, cursor.pos())))
Expand Down
Loading

0 comments on commit 66aa45c

Please sign in to comment.