perf(atoms): Introduce AtomStoreCell (#8232)

This commit is contained in:
David Sherret 2023-11-08 19:59:20 -05:00 committed by GitHub
parent 5472afb40e
commit a5a6eb53a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 33 deletions

View File

@ -247,3 +247,18 @@ impl AtomStore {
Atom(self.0.atom(s))
}
}
/// A fast internally mutable cell for [AtomStore].
#[derive(Default)]
pub struct AtomStoreCell(std::cell::UnsafeCell<AtomStore>);
impl AtomStoreCell {
#[inline]
pub fn atom<'a>(&self, s: impl Into<Cow<'a, str>>) -> Atom {
// SAFETY: We can skip the borrow check of RefCell because
// this API enforces a safe contract. It is slightly faster
// to use an UnsafeCell. Note the borrow here is short lived
// only to this block.
unsafe { (*self.0.get()).atom(s) }
}
}

View File

@ -47,7 +47,7 @@ impl<'a> Lexer<'a> {
});
return Ok(Some(Token::JSXText {
raw: self.atoms.borrow_mut().atom(out),
raw: self.atoms.atom(out),
}));
}
'>' => {
@ -322,10 +322,9 @@ impl<'a> Lexer<'a> {
raw.push(quote);
let mut b = self.atoms.borrow_mut();
Ok(Token::Str {
value: b.atom(out),
raw: b.atom(raw),
value: self.atoms.atom(out),
raw: self.atoms.atom(raw),
})
}
@ -351,7 +350,7 @@ impl<'a> Lexer<'a> {
});
Ok(Token::JSXName {
name: self.atoms.borrow_mut().atom(slice),
name: self.atoms.atom(slice),
})
}
}

View File

@ -5,7 +5,7 @@ use std::{cell::RefCell, char, iter::FusedIterator, rc::Rc};
use either::Either::{Left, Right};
use smallvec::{smallvec, SmallVec};
use smartstring::SmartString;
use swc_atoms::{Atom, AtomStore};
use swc_atoms::{Atom, AtomStoreCell};
use swc_common::{comments::Comments, input::StringInput, BytePos, Span};
use swc_ecma_ast::{op, AssignOp, EsVersion};
@ -133,7 +133,7 @@ pub struct Lexer<'a> {
buf: Rc<RefCell<String>>,
atoms: Rc<RefCell<AtomStore>>,
atoms: Rc<AtomStoreCell>,
}
impl FusedIterator for Lexer<'_> {}
@ -767,9 +767,8 @@ impl<'a> Lexer<'a> {
fn read_ident_unknown(&mut self) -> LexResult<Token> {
debug_assert!(self.cur().is_some());
let (word, _) = self.read_word_as_str_with(|l, s, _, _| {
Word::Ident(IdentLike::Other(l.atoms.borrow_mut().atom(s)))
})?;
let (word, _) = self
.read_word_as_str_with(|l, s, _, _| Word::Ident(IdentLike::Other(l.atoms.atom(s))))?;
Ok(Word(word))
}
@ -790,7 +789,7 @@ impl<'a> Lexer<'a> {
}
}
Word::Ident(IdentLike::Other(l.atoms.borrow_mut().atom(s)))
Word::Ident(IdentLike::Other(l.atoms.atom(s)))
})?;
// Note: ctx is store in lexer because of this error.
@ -1022,10 +1021,9 @@ impl<'a> Lexer<'a> {
l.bump();
let mut b = l.atoms.borrow_mut();
return Ok(Token::Str {
value: b.atom(&*out),
raw: b.atom(raw),
value: l.atoms.atom(&*out),
raw: l.atoms.atom(raw),
});
}
'\\' => {
@ -1057,10 +1055,9 @@ impl<'a> Lexer<'a> {
l.emit_error(start, SyntaxError::UnterminatedStrLit);
let mut b = l.atoms.borrow_mut();
Ok(Token::Str {
value: b.atom(&*out),
raw: b.atom(raw),
value: l.atoms.atom(&*out),
raw: l.atoms.atom(raw),
})
})
}
@ -1108,7 +1105,7 @@ impl<'a> Lexer<'a> {
buf.push(c);
}
Ok(l.atoms.borrow_mut().atom(&**buf))
Ok(l.atoms.atom(&**buf))
})?;
// input is terminated without following `/`
@ -1129,7 +1126,7 @@ impl<'a> Lexer<'a> {
let flags = {
match self.cur() {
Some(c) if c.is_ident_start() => self
.read_word_as_str_with(|l, s, _, _| l.atoms.borrow_mut().atom(s))
.read_word_as_str_with(|l, s, _, _| l.atoms.atom(s))
.map(Some),
_ => Ok(None),
}
@ -1151,7 +1148,7 @@ impl<'a> Lexer<'a> {
self.input.bump();
}
let s = self.input.uncons_while(|c| !c.is_line_terminator());
Ok(Some(self.atoms.borrow_mut().atom(s)))
Ok(Some(self.atoms.atom(s)))
}
fn read_tmpl_token(&mut self, start_of_tpl: BytePos) -> LexResult<Token> {
@ -1176,7 +1173,7 @@ impl<'a> Lexer<'a> {
// TODO: Handle error
return Ok(Token::Template {
cooked: cooked.map(Atom::from),
raw: self.atoms.borrow_mut().atom(&*raw),
raw: self.atoms.atom(&*raw),
});
}

View File

@ -64,7 +64,7 @@ impl<'a> Lexer<'a> {
return Ok(Either::Right((
Box::new(s.into_value()),
self.atoms.borrow_mut().atom(&*raw),
self.atoms.atom(&*raw),
)));
}
@ -84,9 +84,9 @@ impl<'a> Lexer<'a> {
// e.g. `000` is octal
if start.0 != self.last_pos().0 - 1 {
// `-1` is utf 8 length of `0`
return self.make_legacy_octal(start, 0f64).map(|value| {
Either::Left((value, self.atoms.borrow_mut().atom(&*raw)))
});
return self
.make_legacy_octal(start, 0f64)
.map(|value| Either::Left((value, self.atoms.atom(&*raw))));
}
} else {
// strict mode hates non-zero decimals starting with zero.
@ -113,9 +113,9 @@ impl<'a> Lexer<'a> {
panic!("failed to parse {} into float using BigInt", val_str)
});
return self.make_legacy_octal(start, val).map(|value| {
Either::Left((value, self.atoms.borrow_mut().atom(&*raw)))
});
return self
.make_legacy_octal(start, val)
.map(|value| Either::Left((value, self.atoms.atom(&*raw))));
}
}
}
@ -227,7 +227,7 @@ impl<'a> Lexer<'a> {
self.ensure_not_ident()?;
Ok(Either::Left((val, self.atoms.borrow_mut().atom(&*raw_str))))
Ok(Either::Left((val, self.atoms.atom(&*raw_str))))
}
/// Returns `Left(value)` or `Right(BigInt)`
@ -268,13 +268,13 @@ impl<'a> Lexer<'a> {
return Ok(Either::Right((
Box::new(s.into_value()),
l.atoms.borrow_mut().atom(&**buf),
l.atoms.atom(&**buf),
)));
}
l.ensure_not_ident()?;
Ok(Either::Left((val, l.atoms.borrow_mut().atom(&**buf))))
Ok(Either::Left((val, l.atoms.atom(&**buf))))
})
}

View File

@ -257,7 +257,7 @@ impl<'a> Lexer<'a> {
let cmt = Comment {
kind: CommentKind::Line,
span: Span::new(start, end, SyntaxContext::empty()),
text: self.atoms.borrow_mut().atom(s),
text: self.atoms.atom(s),
};
if is_for_next {
@ -343,7 +343,7 @@ impl<'a> Lexer<'a> {
let cmt = Comment {
kind: CommentKind::Block,
span: Span::new(start, end, SyntaxContext::empty()),
text: self.atoms.borrow_mut().atom(s),
text: self.atoms.atom(s),
};
let _ = self.input.peek();