Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(es/ast): Use Atom in some places #5271

Merged
merged 63 commits into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c980d7e
Atom
kdy1 Jul 22, 2022
efdf719
Change types
kdy1 Jul 22, 2022
6ee0a58
fixup
kdy1 Jul 22, 2022
9ceb85f
impl `Default` for `Atom`
kdy1 Jul 22, 2022
c17c5ee
More ast work
kdy1 Jul 22, 2022
a68e9fc
Fix
kdy1 Jul 22, 2022
d101240
Fix
kdy1 Jul 22, 2022
8f21f28
Doc
kdy1 Jul 22, 2022
e959730
Fix
kdy1 Jul 22, 2022
a4b1576
Doc
kdy1 Jul 22, 2022
a4a5237
`Comment`
kdy1 Jul 22, 2022
3aa4fe0
fixup
kdy1 Jul 22, 2022
e670ce2
Fix
kdy1 Jul 22, 2022
523881f
Fix
kdy1 Jul 22, 2022
443674a
More fix
kdy1 Jul 22, 2022
34cb111
fixup
kdy1 Jul 22, 2022
f6dac24
More fix
kdy1 Jul 22, 2022
358a09b
fixup
kdy1 Jul 22, 2022
647094c
fixup
kdy1 Jul 22, 2022
b822869
Fix
kdy1 Jul 22, 2022
a058d37
Fix
kdy1 Jul 22, 2022
2f7227c
Rename
kdy1 Jul 22, 2022
b8da028
fixup
kdy1 Jul 22, 2022
b4e8e69
More
kdy1 Jul 22, 2022
ca4d336
Fix more
kdy1 Jul 22, 2022
7095be1
fixup
kdy1 Jul 22, 2022
3d2f007
fixup
kdy1 Jul 22, 2022
8b0962d
Revert
kdy1 Jul 22, 2022
1c048d1
API
kdy1 Jul 22, 2022
915d6a3
fix
kdy1 Jul 22, 2022
3f75269
FIx?
kdy1 Jul 22, 2022
7bdd730
impl_from
kdy1 Jul 22, 2022
44c3994
fixup
kdy1 Jul 22, 2022
e56d8ce
Fix
kdy1 Jul 22, 2022
400fc12
clippy
kdy1 Jul 22, 2022
2af3c4d
FIx parser
kdy1 Jul 22, 2022
25c7333
fixup
kdy1 Jul 22, 2022
838dd84
Remove
kdy1 Jul 22, 2022
68e8738
Fix quoter
kdy1 Jul 22, 2022
bb36d17
More fix
kdy1 Jul 22, 2022
770fc89
Fix
kdy1 Jul 22, 2022
7403250
Fix ast api
kdy1 Jul 22, 2022
0b9bd2b
fixup
kdy1 Jul 22, 2022
4948f07
Fix
kdy1 Jul 22, 2022
0de029f
Doc
kdy1 Jul 22, 2022
21a489a
More fix
kdy1 Jul 22, 2022
0411e5a
More fix
kdy1 Jul 22, 2022
4e7919e
fixup
kdy1 Jul 22, 2022
d5ef2a1
Rename
kdy1 Jul 22, 2022
5aeb35e
fixup
kdy1 Jul 22, 2022
d6a8c6c
fix
kdy1 Jul 22, 2022
a6b28c7
fixup
kdy1 Jul 22, 2022
5c5d065
FIx
kdy1 Jul 22, 2022
1481ac5
Fix
kdy1 Jul 22, 2022
5be2445
Merge branch 'main' into atom
kdy1 Jul 22, 2022
bec8b44
Feature
kdy1 Jul 22, 2022
38ad15e
Fix
kdy1 Jul 22, 2022
54378cc
Clone
kdy1 Jul 22, 2022
5d6d373
Doc
kdy1 Jul 22, 2022
041d4f2
Fix CI
kdy1 Jul 22, 2022
3334d91
Fix
kdy1 Jul 22, 2022
cd881e7
Ttry
kdy1 Jul 22, 2022
475a073
Hmm
kdy1 Jul 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

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

74 changes: 64 additions & 10 deletions crates/swc_atoms/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,27 @@ use serde::Serializer;

include!(concat!(env!("OUT_DIR"), "/js_word.rs"));

/// An interned string.
/// An (optionally) interned string.
///
/// Use [AtomGenerator] to create [Atom]s.
/// Use [AtomGenerator], [`Atom::new`] or `.into()` to create [Atom]s.
/// If you think the same value will be used multiple time, use [AtomGenerator].
/// Othrwise, create an [Atom] using `.into()`.
///
/// # Comparison with [JsWord][]
///
/// [JsWord][] is a globally interned string with phf support, while [Atom] is a
/// locally interened string. Global interning results in a less memory usage,
/// but global means a mutex. Because of the mutex, [Atom] performs better in
/// multi-thread environments. But due to lack of phf or global interning,
/// comparison and hashing of [Atom] is slower than them of [JsWord].
///
/// # Usages
///
/// This should be used instead of [JsWord] for
///
/// - Long texts, which is **not likely to be duplicated**. This does not mean
/// "longer than xx" as this is a type.
/// - Raw values.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(
feature = "rkyv",
Expand All @@ -43,7 +61,15 @@ impl Atom {
/// Creates a bad [Atom] from a string.
///
/// This [Atom] is bad because it doesn't help reducing memory usage.
pub fn new_bad<S>(s: S) -> Self
///
/// # Note
///
/// Although this is called `bad`, it's fine to use this if a string is
/// unlikely to be duplicated.
///
/// e.g. Texts in template literals or comments are unlikely to benefit from
/// interning.
pub fn new<S>(s: S) -> Self
where
Arc<str>: From<S>,
{
Expand All @@ -70,6 +96,16 @@ macro_rules! impl_eq {
};
}

macro_rules! impl_from {
($T:ty) => {
impl From<$T> for Atom {
fn from(s: $T) -> Self {
Atom::new(s)
}
}
};
}

impl PartialEq<str> for Atom {
fn eq(&self, other: &str) -> bool {
&*self.0 == other
Expand All @@ -84,6 +120,18 @@ impl_eq!(Cow<'_, str>);
impl_eq!(String);
impl_eq!(JsWord);

impl_from!(&'_ str);
impl_from!(Box<str>);
impl_from!(Arc<str>);
impl_from!(Cow<'_, str>);
impl_from!(String);

impl From<JsWord> for Atom {
fn from(v: JsWord) -> Self {
Self::new(&*v)
}
}

impl AsRef<str> for Atom {
fn as_ref(&self) -> &str {
&self.0
Expand All @@ -108,16 +156,22 @@ impl Display for Atom {
}
}

impl Default for Atom {
fn default() -> Self {
atom!("")
}
}

/// Generator for an interned strings.
///
/// A lexer is expected to store this in it.
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct AtomGenerator {
inner: FxHashSet<Atom>,
}

impl AtomGenerator {
pub fn gen<S>(&mut self, s: S) -> Atom
pub fn intern<S>(&mut self, s: S) -> Atom
where
Arc<str>: From<S>,
S: Eq + Hash,
Expand All @@ -127,7 +181,7 @@ impl AtomGenerator {
return v;
}

let new = Atom::new_bad(s);
let new = Atom::new(s);

self.inner.insert(new.clone());
new
Expand All @@ -148,7 +202,7 @@ impl<'de> serde::de::Deserialize<'de> for Atom {
where
D: serde::Deserializer<'de>,
{
String::deserialize(deserializer).map(Self::new_bad)
String::deserialize(deserializer).map(Self::new)
}
}

Expand All @@ -157,7 +211,7 @@ impl<'de> serde::de::Deserialize<'de> for Atom {
macro_rules! atom {
($s:literal) => {{
static CACHE: $crate::once_cell::sync::Lazy<$crate::Atom> =
$crate::once_cell::sync::Lazy::new(|| $crate::Atom::new_bad($s));
$crate::once_cell::sync::Lazy::new(|| $crate::Atom::new($s));

$crate::Atom::clone(&*CACHE)
}};
Expand All @@ -167,8 +221,8 @@ macro_rules! atom {
fn _assert() {
let mut g = AtomGenerator::default();

g.gen("str");
g.gen(String::new());
g.intern("str");
g.intern(String::new());
}

impl PartialEq<Atom> for str {
Expand Down
4 changes: 2 additions & 2 deletions crates/swc_common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ perf = ["parking_lot"]
plugin-base = ["anyhow", "rkyv-impl", "diagnostic-serde"]
plugin-mode = ["plugin-base"]
plugin-rt = ["plugin-base"]
rkyv-impl = ["rkyv", "bytecheck"]
tty-emitter = ["atty", "termcolor"]
plugin_transform_schema_v1 = []
plugin_transform_schema_vtest = []
rkyv-impl = ["rkyv", "bytecheck", "swc_atoms/rkyv-impl"]
tty-emitter = ["atty", "termcolor"]

[dependencies]
ahash = "0.7.4"
Expand Down
6 changes: 4 additions & 2 deletions crates/swc_common/src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{
};

use rustc_hash::FxHashMap;
use swc_atoms::{atom, Atom};

use crate::{
pos::Spanned,
Expand Down Expand Up @@ -439,7 +440,7 @@ impl Comments for SingleThreadedComments {
let pure_comment = Comment {
kind: CommentKind::Block,
span: DUMMY_SP,
text: "#__PURE__".into(),
text: atom!("#__PURE__"),
};

if !leading.iter().any(|c| c.text == pure_comment.text) {
Expand Down Expand Up @@ -545,7 +546,8 @@ impl SingleThreadedComments {
pub struct Comment {
pub kind: CommentKind,
pub span: Span,
pub text: String,
/// [`Atom::new_bad`][] is perfectly fine for this value.
pub text: Atom,
}

impl Spanned for Comment {
Expand Down
11 changes: 4 additions & 7 deletions crates/swc_ecma_ast/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use is_macro::Is;
use serde::{self, Deserialize, Serialize};
use string_enum::StringEnum;
use swc_atoms::JsWord;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanned, DUMMY_SP};

use crate::{
Expand Down Expand Up @@ -793,12 +793,9 @@ pub struct TplElement {
///
/// If you are going to use codegen right after creating a [TplElement], you
/// don't have to worry about this value.
pub cooked: Option<Atom>,

#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub cooked: Option<JsWord>,

#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: JsWord,
pub raw: Atom,
}

impl Take for TplElement {
Expand All @@ -807,7 +804,7 @@ impl Take for TplElement {
span: DUMMY_SP,
tail: Default::default(),
cooked: None,
raw: "".into(),
raw: Default::default(),
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions crates/swc_ecma_ast/src/jsx.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use is_macro::Is;
use swc_atoms::JsWord;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};

use crate::{
Expand Down Expand Up @@ -197,10 +197,8 @@ pub enum JSXAttrValue {
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct JSXText {
pub span: Span,
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub value: JsWord,
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: JsWord,
pub value: Atom,
pub raw: Atom,
}

#[cfg(feature = "arbitrary")]
Expand Down
29 changes: 18 additions & 11 deletions crates/swc_ecma_ast/src/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
};

use num_bigint::BigInt as BigIntValue;
use swc_atoms::{js_word, JsWord};
use swc_atoms::{js_word, Atom, JsWord};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};

use crate::jsx::JSXText;
Expand Down Expand Up @@ -54,6 +54,7 @@ bridge_expr_from!(Lit, JSXText);

bridge_lit_from!(Str, &'_ str);
bridge_lit_from!(Str, JsWord);
bridge_lit_from!(Str, Atom);
bridge_lit_from!(Str, Cow<'_, str>);
bridge_lit_from!(Str, String);
bridge_lit_from!(Bool, bool);
Expand All @@ -70,8 +71,7 @@ pub struct BigInt {

/// Use `None` value only for transformations to avoid recalculate
/// characters in big integer
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: Option<JsWord>,
pub raw: Option<Atom>,
}

impl EqIgnoreSpan for BigInt {
Expand Down Expand Up @@ -164,8 +164,7 @@ pub struct Str {

/// Use `None` value only for transformations to avoid recalculate escaped
/// characters in strings
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: Option<JsWord>,
pub raw: Option<Atom>,
}

impl Take for Str {
Expand Down Expand Up @@ -214,6 +213,17 @@ impl From<JsWord> for Str {
}
}

impl From<Atom> for Str {
#[inline]
fn from(value: Atom) -> Self {
Str {
span: DUMMY_SP,
value: JsWord::from(&*value),
raw: None,
}
}
}

bridge_from!(Str, JsWord, &'_ str);
bridge_from!(Str, JsWord, String);
bridge_from!(Str, JsWord, Cow<'_, str>);
Expand Down Expand Up @@ -273,12 +283,10 @@ pub struct Regex {
pub span: Span,

#[serde(rename = "pattern")]
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub exp: JsWord,
pub exp: Atom,

#[serde(default)]
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub flags: JsWord,
pub flags: Atom,
}

impl Take for Regex {
Expand Down Expand Up @@ -324,8 +332,7 @@ pub struct Number {

/// Use `None` value only for transformations to avoid recalculate
/// characters in number literal
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: Option<JsWord>,
pub raw: Option<Atom>,
}

impl Eq for Number {}
Expand Down
8 changes: 3 additions & 5 deletions crates/swc_ecma_ast/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use is_macro::Is;
use swc_atoms::JsWord;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};

use crate::{module_decl::ModuleDecl, stmt::Stmt};
Expand Down Expand Up @@ -44,8 +44,7 @@ pub struct Module {
pub body: Vec<ModuleItem>,

#[serde(default, rename = "interpreter")]
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub shebang: Option<JsWord>,
pub shebang: Option<Atom>,
}

#[cfg(feature = "arbitrary")]
Expand Down Expand Up @@ -80,8 +79,7 @@ pub struct Script {
pub body: Vec<Stmt>,

#[serde(default, rename = "interpreter")]
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub shebang: Option<JsWord>,
pub shebang: Option<Atom>,
}

#[cfg(feature = "arbitrary")]
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_codegen/src/jsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ where

#[emitter]
fn emit_jsx_text(&mut self, node: &JSXText) -> Result {
self.emit_js_word(node.span(), &node.value)?;
self.emit_atom(node.span(), &node.value)?;
}

#[emitter]
Expand Down
4 changes: 2 additions & 2 deletions crates/swc_ecma_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{borrow::Cow, fmt::Write, io};

use memchr::memmem::Finder;
use once_cell::sync::Lazy;
use swc_atoms::JsWord;
use swc_atoms::Atom;
use swc_common::{
comments::{CommentKind, Comments},
sync::Lrc,
Expand Down Expand Up @@ -513,7 +513,7 @@ where
}
}

fn emit_js_word(&mut self, span: Span, value: &JsWord) -> Result {
fn emit_atom(&mut self, span: Span, value: &Atom) -> Result {
self.wr.write_str_lit(span, value)?;

Ok(())
Expand Down
Loading