diff --git a/Cargo.lock b/Cargo.lock index c85cc9408857..3e88c830f125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,6 +62,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +dependencies = [ + "serde", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -406,6 +415,9 @@ name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +dependencies = [ + "allocator-api2", +] [[package]] name = "bytecheck" @@ -3310,9 +3322,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -3340,9 +3352,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -3688,7 +3700,13 @@ dependencies = [ name = "swc_allocator" version = "0.1.1" dependencies = [ + "allocator-api2", "bumpalo", + "ptr_meta", + "rkyv", + "scoped-tls", + "serde", + "serde_derive", ] [[package]] @@ -3810,6 +3828,7 @@ dependencies = [ "serde_json", "siphasher", "sourcemap", + "swc_allocator", "swc_atoms", "swc_eq_ignore_macros", "swc_visit", @@ -4123,6 +4142,7 @@ dependencies = [ "serde", "serde_json", "string_enum", + "swc_allocator", "swc_atoms", "swc_common", "unicode-id-start", diff --git a/Cargo.toml b/Cargo.toml index 66a445736df2..ae8f45d1ca9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ resolver = "2" Inflector = "0.11.4" ahash = "0.8.8" + allocator-api2 = "0.2.18" ansi_term = "0.12.1" anyhow = "1.0.81" arbitrary = "1" @@ -95,6 +96,7 @@ resolver = "2" phf = "0.11.2" pretty_assertions = "1.3" proc-macro2 = "1.0.24" + ptr_meta = "0.1.4" quote = "1.0.7" rayon = "1.7.0" regex = "1.5.4" diff --git a/crates/swc_allocator/Cargo.toml b/crates/swc_allocator/Cargo.toml index ca32f62fd4c1..da8812f0a248 100644 --- a/crates/swc_allocator/Cargo.toml +++ b/crates/swc_allocator/Cargo.toml @@ -9,4 +9,14 @@ repository = { workspace = true } version = "0.1.1" [dependencies] -bumpalo = { workspace = true, features = ["boxed", "collections"] } +allocator-api2 = { workspace = true, features = ["serde"] } +bumpalo = { workspace = true, features = [ + "allocator-api2", + "boxed", + "collections", +] } +ptr_meta = { workspace = true } +rkyv = { workspace = true } +scoped-tls = { workspace = true } +serde = { workspace = true } +serde_derive = { workspace = true } diff --git a/crates/swc_allocator/src/alloc.rs b/crates/swc_allocator/src/alloc.rs new file mode 100644 index 000000000000..f5109002368d --- /dev/null +++ b/crates/swc_allocator/src/alloc.rs @@ -0,0 +1,153 @@ +use std::{alloc::Layout, ptr::NonNull}; + +use allocator_api2::alloc::Global; +use scoped_tls::scoped_thread_local; + +use crate::Allocator; + +scoped_thread_local!(pub(crate) static ALLOC: Allocator); + +#[derive(Debug, Clone, Copy, Default)] +pub struct SwcAlloc; + +impl SwcAlloc { + /// `true` is passed to `f` if the box is allocated with a custom allocator. + fn with_allocator( + &self, + f: impl FnOnce(&dyn allocator_api2::alloc::Allocator, bool) -> T, + ) -> T { + if ALLOC.is_set() { + ALLOC.with(|a| { + // + f(&&**a as &dyn allocator_api2::alloc::Allocator, true) + }) + } else { + f(&allocator_api2::alloc::Global, false) + } + } +} + +/// Set the last bit to 1 +fn mark_ptr_as_arena_mode(ptr: NonNull<[u8]>) -> NonNull<[u8]> { + let ptr = ptr.as_ptr() as *mut () as usize | 1; + unsafe { NonNull::new_unchecked(ptr as *mut [u8]) } +} + +fn is_ptr_in_arena_mode(ptr: NonNull) -> bool { + let ptr = ptr.as_ptr() as usize; + ptr & 1 == 1 +} + +unsafe impl allocator_api2::alloc::Allocator for SwcAlloc { + fn allocate(&self, layout: Layout) -> Result, allocator_api2::alloc::AllocError> { + self.with_allocator(|a, is_arena_mode| { + let ptr = a.allocate(layout)?; + + if is_arena_mode { + Ok(mark_ptr_as_arena_mode(ptr)) + } else { + Ok(ptr) + } + }) + } + + fn allocate_zeroed( + &self, + layout: Layout, + ) -> Result, allocator_api2::alloc::AllocError> { + self.with_allocator(|a, is_arena_mode| { + let ptr = a.allocate_zeroed(layout)?; + + if is_arena_mode { + Ok(mark_ptr_as_arena_mode(ptr)) + } else { + Ok(ptr) + } + }) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + if is_ptr_in_arena_mode(ptr) { + debug_assert!( + ALLOC.is_set(), + "Deallocating a pointer allocated with arena mode with a non-arena mode allocator" + ); + + ALLOC.with(|alloc| { + unsafe { + // Safety: We are in unsafe fn + (&**alloc).deallocate(ptr, layout) + } + }) + } else { + Global.deallocate(ptr, layout) + } + } + + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, allocator_api2::alloc::AllocError> { + if is_ptr_in_arena_mode(ptr) { + debug_assert!( + ALLOC.is_set(), + "Growing a pointer allocated with arena mode with a non-arena mode allocator" + ); + + ALLOC.with(|alloc| { + return (&**alloc).grow(ptr, old_layout, new_layout); + }) + } else { + Global.grow(ptr, old_layout, new_layout) + } + } + + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, allocator_api2::alloc::AllocError> { + if is_ptr_in_arena_mode(ptr) { + debug_assert!( + ALLOC.is_set(), + "Growing a pointer allocated with arena mode with a non-arena mode allocator" + ); + + ALLOC.with(|alloc| { + return (&**alloc).grow_zeroed(ptr, old_layout, new_layout); + }) + } else { + Global.grow_zeroed(ptr, old_layout, new_layout) + } + } + + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, allocator_api2::alloc::AllocError> { + if is_ptr_in_arena_mode(ptr) { + debug_assert!( + ALLOC.is_set(), + "Shrinking a pointer allocated with arena mode with a non-arena mode allocator" + ); + + ALLOC.with(|alloc| { + return (&**alloc).shrink(ptr, old_layout, new_layout); + }) + } else { + Global.shrink(ptr, old_layout, new_layout) + } + } + + fn by_ref(&self) -> &Self + where + Self: Sized, + { + self + } +} diff --git a/crates/swc_allocator/src/boxed/mod.rs b/crates/swc_allocator/src/boxed/mod.rs new file mode 100644 index 000000000000..78c5fc68c045 --- /dev/null +++ b/crates/swc_allocator/src/boxed/mod.rs @@ -0,0 +1,93 @@ +use std::ops::{Deref, DerefMut}; + +use crate::alloc::SwcAlloc; + +mod rkyv; +mod serde; + +/// A special `Box` which has size of [`std::boxed::Box`] but **may** be +/// allocated with a custom allocator. +/// +/// +/// # Representation +/// +/// The last bit is 1 if the box is allocated with a custom allocator. +#[repr(transparent)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Box(pub(crate) allocator_api2::boxed::Box); + +impl From for Box { + #[inline(always)] + fn from(v: T) -> Self { + Box::new(v) + } +} + +pub trait IntoBox: Sized { + fn boxed(self) -> Box; +} + +impl IntoBox for V +where + V: Into, +{ + #[inline(always)] + fn boxed(self) -> Box { + Box::new(self.into()) + } +} + +impl Default for Box +where + T: Default, +{ + fn default() -> Self { + Box::new(Default::default()) + } +} + +impl Box { + #[inline(always)] + pub fn new(value: T) -> Self { + Self(allocator_api2::boxed::Box::new_in(value, SwcAlloc)) + } + + pub fn unbox(self) -> T { + allocator_api2::boxed::Box::into_inner(self.0) + } +} + +impl Box { + pub unsafe fn from_raw(raw: *mut T) -> Self { + Self(allocator_api2::boxed::Box::from_raw_in( + raw, + SwcAlloc::default(), + )) + } +} + +impl AsRef for Box { + fn as_ref(&self) -> &T { + &self.0 + } +} + +impl AsMut for Box { + fn as_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl Deref for Box { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl DerefMut for Box { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} diff --git a/crates/swc_allocator/src/boxed/rkyv.rs b/crates/swc_allocator/src/boxed/rkyv.rs new file mode 100644 index 000000000000..2c55abf28d37 --- /dev/null +++ b/crates/swc_allocator/src/boxed/rkyv.rs @@ -0,0 +1,59 @@ +use std::{alloc, cmp}; + +use rkyv::{ + boxed::{ArchivedBox, BoxResolver}, + Archive, ArchivePointee, ArchiveUnsized, Deserialize, DeserializeUnsized, Fallible, Serialize, + SerializeUnsized, +}; + +use super::Box; + +impl Archive for Box { + type Archived = ArchivedBox; + type Resolver = BoxResolver; + + #[inline] + unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { + ArchivedBox::resolve_from_ref(self.as_ref(), pos, resolver, out); + } +} + +impl + ?Sized, S: Fallible + ?Sized> Serialize for Box { + #[inline] + fn serialize(&self, serializer: &mut S) -> Result { + ArchivedBox::serialize_from_ref(self.as_ref(), serializer) + } +} + +impl Deserialize, D> for ArchivedBox +where + T: ArchiveUnsized + ?Sized, + T::Archived: DeserializeUnsized, + D: Fallible + ?Sized, +{ + #[inline] + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + unsafe { + let data_address = self + .get() + .deserialize_unsized(deserializer, |layout| alloc::alloc(layout))?; + let metadata = self.get().deserialize_metadata(deserializer)?; + let ptr = ptr_meta::from_raw_parts_mut(data_address, metadata); + Ok(Box::from_raw(ptr)) + } + } +} + +impl + ?Sized, U: ?Sized> PartialEq> for ArchivedBox { + #[inline] + fn eq(&self, other: &Box) -> bool { + self.get().eq(other.as_ref()) + } +} + +impl + ?Sized, U: ?Sized> PartialOrd> for ArchivedBox { + #[inline] + fn partial_cmp(&self, other: &Box) -> Option { + self.get().partial_cmp(other.as_ref()) + } +} diff --git a/crates/swc_allocator/src/boxed/serde.rs b/crates/swc_allocator/src/boxed/serde.rs new file mode 100644 index 000000000000..17c76e81d71d --- /dev/null +++ b/crates/swc_allocator/src/boxed/serde.rs @@ -0,0 +1,27 @@ +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use super::Box; + +impl Serialize for Box +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for Box +where + T: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + Ok(Box(allocator_api2::boxed::Box::deserialize(deserializer)?)) + } +} diff --git a/crates/swc_allocator/src/lib.rs b/crates/swc_allocator/src/lib.rs index 5c6a3917885a..5a85d03f448e 100644 --- a/crates/swc_allocator/src/lib.rs +++ b/crates/swc_allocator/src/lib.rs @@ -6,11 +6,28 @@ use std::ops::{Deref, DerefMut}; use bumpalo::Bump; +use crate::alloc::ALLOC; + +mod alloc; +pub mod boxed; +pub mod vec; + #[derive(Default)] pub struct Allocator { alloc: Bump, } +impl Allocator { + /// Invokes `f` in a scope where the allocations are done in this allocator. + #[inline(always)] + pub fn scope(&self, f: F) -> R + where + F: FnOnce() -> R, + { + ALLOC.set(self, f) + } +} + impl From for Allocator { fn from(alloc: Bump) -> Self { Self { alloc } @@ -30,115 +47,3 @@ impl DerefMut for Allocator { &mut self.alloc } } - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct Box<'alloc, T>(bumpalo::boxed::Box<'alloc, T>); - -impl<'alloc, T> Box<'alloc, T> { - #[inline(always)] - pub fn new(alloc: &'alloc Allocator, value: T) -> Self { - Self(bumpalo::boxed::Box::new_in(value, alloc)) - } -} - -impl<'alloc, T> Deref for Box<'alloc, T> { - type Target = T; - - fn deref(&self) -> &T { - &self.0 - } -} - -impl<'alloc, T> DerefMut for Box<'alloc, T> { - fn deref_mut(&mut self) -> &mut T { - &mut self.0 - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct Vec<'alloc, T>(bumpalo::collections::Vec<'alloc, T>); - -impl<'alloc, T> Vec<'alloc, T> { - #[inline(always)] - pub fn new(alloc: &'alloc Allocator) -> Self { - Self(bumpalo::collections::Vec::new_in(alloc)) - } - - #[inline(always)] - pub fn with_capacity(alloc: &'alloc Allocator, capacity: usize) -> Self { - Self(bumpalo::collections::Vec::with_capacity_in(capacity, alloc)) - } -} - -impl<'alloc, T> Deref for Vec<'alloc, T> { - type Target = [T]; - - fn deref(&self) -> &[T] { - &self.0 - } -} - -impl<'alloc, T> DerefMut for Vec<'alloc, T> { - fn deref_mut(&mut self) -> &mut [T] { - &mut self.0 - } -} - -impl<'alloc, T> IntoIterator for Vec<'alloc, T> { - type IntoIter = bumpalo::collections::vec::IntoIter<'alloc, T>; - type Item = T; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct String<'alloc>(bumpalo::collections::String<'alloc>); - -impl<'alloc> String<'alloc> { - #[inline(always)] - pub fn new(alloc: &'alloc Allocator) -> Self { - Self(bumpalo::collections::String::new_in(alloc)) - } - - #[inline(always)] - pub fn with_capacity(alloc: &'alloc Allocator, capacity: usize) -> Self { - Self(bumpalo::collections::String::with_capacity_in( - capacity, alloc, - )) - } -} - -impl Deref for String<'_> { - type Target = str; - - fn deref(&self) -> &str { - &self.0 - } -} - -impl DerefMut for String<'_> { - fn deref_mut(&mut self) -> &mut str { - &mut self.0 - } -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum CowStr<'alloc> { - Borrowed(&'alloc str), - Owned(String<'alloc>), -} - -impl Deref for CowStr<'_> { - type Target = str; - - fn deref(&self) -> &str { - match self { - CowStr::Borrowed(s) => s, - CowStr::Owned(s) => s, - } - } -} diff --git a/crates/swc_allocator/src/vec/mod.rs b/crates/swc_allocator/src/vec/mod.rs new file mode 100644 index 000000000000..f3825c15880c --- /dev/null +++ b/crates/swc_allocator/src/vec/mod.rs @@ -0,0 +1,114 @@ +use std::ops::{Deref, DerefMut}; + +use rkyv::{vec::ArchivedVec, DeserializeUnsized}; +use serde_derive::{Deserialize, Serialize}; + +use crate::{alloc::SwcAlloc, boxed::Box}; + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[repr(transparent)] +pub struct Vec(allocator_api2::vec::Vec); + +impl Vec { + pub fn new() -> Self { + Default::default() + } +} + +impl Deref for Vec { + type Target = allocator_api2::vec::Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Default for Vec { + fn default() -> Self { + Self(allocator_api2::vec::Vec::new_in(SwcAlloc::default())) + } +} + +impl IntoIterator for Vec { + type IntoIter = allocator_api2::vec::IntoIter; + type Item = T; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} +impl<'a, T> IntoIterator for &'a Vec { + type IntoIter = std::slice::Iter<'a, T>; + type Item = &'a T; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T> IntoIterator for &'a mut Vec { + type IntoIter = std::slice::IterMut<'a, T>; + type Item = &'a mut T; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl FromIterator for Vec { + fn from_iter>(iter: I) -> Self { + let mut vec = Vec::default(); + vec.extend(iter); + vec + } +} + +impl From> for Vec { + fn from(v: Box<[T]>) -> Self { + Self(allocator_api2::vec::Vec::from(v.0)) + } +} + +impl rkyv::Archive for Vec +where + T: rkyv::Archive, +{ + type Archived = rkyv::vec::ArchivedVec; + type Resolver = rkyv::vec::VecResolver; + + unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { + rkyv::vec::ArchivedVec::resolve_from_slice(self, pos, resolver, out); + } +} + +impl, S: rkyv::ser::ScratchSpace + rkyv::ser::Serializer + ?Sized> + rkyv::Serialize for Vec +{ + #[inline] + fn serialize(&self, serializer: &mut S) -> Result { + ArchivedVec::::serialize_from_slice(self, serializer) + } +} + +impl rkyv::Deserialize, D> + for ArchivedVec +where + [T::Archived]: rkyv::DeserializeUnsized<[T], D>, +{ + #[inline] + fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { + unsafe { + let data_address = + (**self).deserialize_unsized(deserializer, |layout| std::alloc::alloc(layout))?; + let metadata = self.as_slice().deserialize_metadata(deserializer)?; + let ptr = ptr_meta::from_raw_parts_mut(data_address, metadata); + Ok(Box::<[T]>::from_raw(ptr).into()) + } + } +} diff --git a/crates/swc_common/Cargo.toml b/crates/swc_common/Cargo.toml index 15480f7386de..7e842f79c9c5 100644 --- a/crates/swc_common/Cargo.toml +++ b/crates/swc_common/Cargo.toml @@ -65,6 +65,7 @@ url = { workspace = true } ast_node = { version = "0.9.8", path = "../ast_node" } better_scoped_tls = { version = "0.1.1", path = "../better_scoped_tls" } from_variant = { version = "0.1.8", path = "../from_variant" } +swc_allocator = { version = "0.1.1", path = "../swc_allocator" } swc_atoms = { version = "0.6.5", path = "../swc_atoms" } swc_eq_ignore_macros = { version = "0.1.3", path = "../swc_eq_ignore_macros" } swc_visit = { version = "0.5.14", path = "../swc_visit" } diff --git a/crates/swc_common/src/eq.rs b/crates/swc_common/src/eq.rs index 57d2d8911b49..ffd615011b0b 100644 --- a/crates/swc_common/src/eq.rs +++ b/crates/swc_common/src/eq.rs @@ -63,6 +63,19 @@ where } } +impl EqIgnoreSpan for swc_allocator::vec::Vec +where + T: EqIgnoreSpan, +{ + fn eq_ignore_span(&self, other: &Self) -> bool { + self.len() == other.len() + && self + .iter() + .zip(other.iter()) + .all(|(a, b)| a.eq_ignore_span(b)) + } +} + /// Derive with `#[derive(TypeEq)]`. pub trait TypeEq { /// **Note**: This method should return `true` for non-type values. @@ -172,6 +185,26 @@ macro_rules! deref { deref!(Box, Rc, Arc); +impl EqIgnoreSpan for swc_allocator::boxed::Box +where + N: EqIgnoreSpan, +{ + #[inline] + fn eq_ignore_span(&self, other: &Self) -> bool { + (**self).eq_ignore_span(&**other) + } +} + +impl TypeEq for swc_allocator::boxed::Box +where + N: TypeEq, +{ + #[inline] + fn type_eq(&self, other: &Self) -> bool { + (**self).type_eq(&**other) + } +} + impl<'a, N> EqIgnoreSpan for &'a N where N: EqIgnoreSpan, diff --git a/crates/swc_common/src/pos.rs b/crates/swc_common/src/pos.rs index 9fb8d3ced480..07196bc52e9c 100644 --- a/crates/swc_common/src/pos.rs +++ b/crates/swc_common/src/pos.rs @@ -190,3 +190,12 @@ where } } } + +impl Spanned for swc_allocator::boxed::Box +where + T: Spanned, +{ + fn span(&self) -> Span { + self.as_ref().span() + } +} diff --git a/crates/swc_common/src/util/take.rs b/crates/swc_common/src/util/take.rs index 8dfd21394c27..376a987940f8 100644 --- a/crates/swc_common/src/util/take.rs +++ b/crates/swc_common/src/util/take.rs @@ -54,3 +54,18 @@ impl Take for Span { DUMMY_SP } } + +impl Take for swc_allocator::boxed::Box +where + T: Take, +{ + fn dummy() -> Self { + swc_allocator::boxed::Box::new(T::dummy()) + } +} + +impl Take for swc_allocator::vec::Vec { + fn dummy() -> Self { + Default::default() + } +} diff --git a/crates/swc_ecma_ast/Cargo.toml b/crates/swc_ecma_ast/Cargo.toml index 2a871818c148..31a9f37bad52 100644 --- a/crates/swc_ecma_ast/Cargo.toml +++ b/crates/swc_ecma_ast/Cargo.toml @@ -42,10 +42,12 @@ rkyv = { workspace = true, features = [ ], optional = true } scoped-tls = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } -string_enum = { version = "0.4.4", path = "../string_enum" } -swc_atoms = { version = "0.6.5", path = "../swc_atoms" } -swc_common = { version = "0.35.0", path = "../swc_common" } unicode-id-start = { workspace = true } +string_enum = { version = "0.4.4", path = "../string_enum" } +swc_allocator = { version = "0.1.1", path = "../swc_allocator" } +swc_atoms = { version = "0.6.5", path = "../swc_atoms" } +swc_common = { version = "0.35.0", path = "../swc_common" } + [dev-dependencies] serde_json = { workspace = true } diff --git a/crates/swc_ecma_ast/src/class.rs b/crates/swc_ecma_ast/src/class.rs index 4574c0edb5bb..ab07be5089f8 100644 --- a/crates/swc_ecma_ast/src/class.rs +++ b/crates/swc_ecma_ast/src/class.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, DUMMY_SP}; use crate::{ diff --git a/crates/swc_ecma_ast/src/decl.rs b/crates/swc_ecma_ast/src/decl.rs index af6d89e7ab84..3f5d28984af8 100644 --- a/crates/swc_ecma_ast/src/decl.rs +++ b/crates/swc_ecma_ast/src/decl.rs @@ -1,5 +1,6 @@ use is_macro::Is; use string_enum::StringEnum; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, DUMMY_SP}; use crate::{ @@ -70,8 +71,6 @@ decl_from!( macro_rules! decl_from_boxed { ($($variant_ty:ty),*) => { $( - bridge_from!(Box, Decl, $variant_ty); - bridge_from!(Box, Decl, Box<$variant_ty>); bridge_from!(crate::Stmt, Decl, Box<$variant_ty>); bridge_from!(crate::ModuleItem, crate::Stmt, Box<$variant_ty>); )* diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index 489daa80759a..440e7f2232c8 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -3,6 +3,7 @@ use std::{borrow::Cow, mem::transmute}; use is_macro::Is; use string_enum::StringEnum; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_atoms::Atom; use swc_common::{ ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanned, SyntaxContext, DUMMY_SP, @@ -168,7 +169,7 @@ pub enum Expr { Invalid(Invalid), } -bridge_from!(Box, Box, JSXElement); +bridge_from!(Expr, Box, JSXElement); // Memory layout depends on the version of rustc. // #[cfg(target_pointer_width = "64")] @@ -467,7 +468,6 @@ boxed_expr!(ParenExpr); boxed_expr!(JSXMemberExpr); boxed_expr!(JSXNamespacedName); boxed_expr!(JSXEmptyExpr); -boxed_expr!(Box); boxed_expr!(JSXFragment); boxed_expr!(TsTypeAssertion); boxed_expr!(TsSatisfiesExpr); @@ -528,7 +528,7 @@ impl ObjectLit { /// /// Returns [None] if this is not a valid for `with` of [crate::ImportDecl]. pub fn as_import_with(&self) -> Option { - let mut values = vec![]; + let mut values = Vec::default(); for prop in &self.props { match prop { PropOrSpread::Spread(..) => return None, @@ -1401,7 +1401,7 @@ impl TryFrom> for AssignTarget { type Error = Box; fn try_from(p: Box) -> Result { - (*p).try_into().map_err(Box::new) + p.unbox().try_into().map_err(Box::new) } } @@ -1502,7 +1502,8 @@ impl TryFrom> for SimpleAssignTarget { type Error = Box; fn try_from(e: Box) -> Result { - Ok(match *e { + let e = e.unbox(); + Ok(match e { Expr::Ident(i) => SimpleAssignTarget::Ident(i.into()), Expr::Member(m) => SimpleAssignTarget::Member(m), Expr::SuperProp(s) => SimpleAssignTarget::SuperProp(s), @@ -1513,7 +1514,7 @@ impl TryFrom> for SimpleAssignTarget { Expr::TsNonNull(n) => SimpleAssignTarget::TsNonNull(n), Expr::TsTypeAssertion(a) => SimpleAssignTarget::TsTypeAssertion(a), Expr::TsInstantiation(a) => SimpleAssignTarget::TsInstantiation(a), - _ => return Err(e), + _ => return Err(Box::new(e)), }) } } diff --git a/crates/swc_ecma_ast/src/function.rs b/crates/swc_ecma_ast/src/function.rs index 1d34eeca9772..510b3a8205d8 100644 --- a/crates/swc_ecma_ast/src/function.rs +++ b/crates/swc_ecma_ast/src/function.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, DUMMY_SP}; use crate::{ diff --git a/crates/swc_ecma_ast/src/ident.rs b/crates/swc_ecma_ast/src/ident.rs index fa67207b645a..cc286fb10cfc 100644 --- a/crates/swc_ecma_ast/src/ident.rs +++ b/crates/swc_ecma_ast/src/ident.rs @@ -5,6 +5,7 @@ use std::{ }; use phf::phf_set; +use swc_allocator::boxed::Box; use swc_atoms::{js_word, Atom}; use swc_common::{ ast_node, util::take::Take, BytePos, EqIgnoreSpan, Mark, Span, Spanned, SyntaxContext, DUMMY_SP, diff --git a/crates/swc_ecma_ast/src/jsx.rs b/crates/swc_ecma_ast/src/jsx.rs index 41055f03b864..0bf698918079 100644 --- a/crates/swc_ecma_ast/src/jsx.rs +++ b/crates/swc_ecma_ast/src/jsx.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_atoms::Atom; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; diff --git a/crates/swc_ecma_ast/src/lit.rs b/crates/swc_ecma_ast/src/lit.rs index bb7555c59a4b..95f2d103931a 100644 --- a/crates/swc_ecma_ast/src/lit.rs +++ b/crates/swc_ecma_ast/src/lit.rs @@ -5,6 +5,7 @@ use std::{ }; use num_bigint::BigInt as BigIntValue; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_atoms::{js_word, Atom}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; diff --git a/crates/swc_ecma_ast/src/macros.rs b/crates/swc_ecma_ast/src/macros.rs index 8cea2656f6f8..eafd85239e30 100644 --- a/crates/swc_ecma_ast/src/macros.rs +++ b/crates/swc_ecma_ast/src/macros.rs @@ -217,7 +217,7 @@ macro_rules! bridge_from { macro_rules! bridge_expr_from { ($bridge:ty, $src:ty) => { bridge_from!(crate::Expr, $bridge, $src); - bridge_from!(Box, crate::Expr, $src); + // bridge_into!(Box, crate::Expr, $src); }; } @@ -225,6 +225,6 @@ macro_rules! bridge_pat_from { ($bridge:ty, $src:ty) => { bridge_from!(crate::Pat, $bridge, $src); bridge_from!(crate::Param, crate::Pat, $src); - bridge_from!(Box, crate::Pat, $src); + // bridge_into!(Box, crate::Pat, $src); }; } diff --git a/crates/swc_ecma_ast/src/module.rs b/crates/swc_ecma_ast/src/module.rs index fe9456d323e1..72c2b5b13a3b 100644 --- a/crates/swc_ecma_ast/src/module.rs +++ b/crates/swc_ecma_ast/src/module.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_atoms::Atom; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; diff --git a/crates/swc_ecma_ast/src/module_decl.rs b/crates/swc_ecma_ast/src/module_decl.rs index df23cd837afd..0c872d75f71d 100644 --- a/crates/swc_ecma_ast/src/module_decl.rs +++ b/crates/swc_ecma_ast/src/module_decl.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_atoms::Atom; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; diff --git a/crates/swc_ecma_ast/src/operators.rs b/crates/swc_ecma_ast/src/operators.rs index f64efc54a3af..fd4eff7fdb50 100644 --- a/crates/swc_ecma_ast/src/operators.rs +++ b/crates/swc_ecma_ast/src/operators.rs @@ -1,4 +1,5 @@ use string_enum::StringEnum; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::EqIgnoreSpan; #[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan, Default)] diff --git a/crates/swc_ecma_ast/src/pat.rs b/crates/swc_ecma_ast/src/pat.rs index ab42072eb61a..86c40c45828d 100644 --- a/crates/swc_ecma_ast/src/pat.rs +++ b/crates/swc_ecma_ast/src/pat.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; use crate::{ @@ -71,7 +72,7 @@ bridge_pat_from!(BindingIdent, Id); macro_rules! pat_to_other { ($T:ty) => { bridge_from!(crate::Param, crate::Pat, $T); - bridge_from!(Box, crate::Pat, $T); + // bridge_into!(Box, crate::Pat, $T); }; } diff --git a/crates/swc_ecma_ast/src/prop.rs b/crates/swc_ecma_ast/src/prop.rs index 40318dcffd0a..2bf90e754dfb 100644 --- a/crates/swc_ecma_ast/src/prop.rs +++ b/crates/swc_ecma_ast/src/prop.rs @@ -1,4 +1,8 @@ use is_macro::Is; +use swc_allocator::{ + boxed::{Box, IntoBox}, + vec::Vec, +}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP}; use crate::{ @@ -132,15 +136,15 @@ impl From for MemberProp { PropName::Computed(p) => MemberProp::Computed(p), PropName::Str(p) => MemberProp::Computed(ComputedPropName { span: DUMMY_SP, - expr: p.into(), + expr: p.boxed(), }), PropName::Num(p) => MemberProp::Computed(ComputedPropName { span: DUMMY_SP, - expr: p.into(), + expr: p.boxed(), }), PropName::BigInt(p) => MemberProp::Computed(ComputedPropName { span: DUMMY_SP, - expr: p.into(), + expr: p.boxed(), }), } } diff --git a/crates/swc_ecma_ast/src/source_map.rs b/crates/swc_ecma_ast/src/source_map.rs index 27440fea7491..f50021dd69d4 100644 --- a/crates/swc_ecma_ast/src/source_map.rs +++ b/crates/swc_ecma_ast/src/source_map.rs @@ -1,5 +1,6 @@ use std::{rc::Rc, sync::Arc}; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{BytePos, SourceMap, SourceMapper, SourceMapperDyn, Span, Spanned}; use crate::list::ListFormat; diff --git a/crates/swc_ecma_ast/src/stmt.rs b/crates/swc_ecma_ast/src/stmt.rs index 32665b359a73..22ba3d6f23d4 100644 --- a/crates/swc_ecma_ast/src/stmt.rs +++ b/crates/swc_ecma_ast/src/stmt.rs @@ -1,4 +1,5 @@ use is_macro::Is; +use swc_allocator::{boxed::Box, vec::Vec}; use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, SyntaxContext, DUMMY_SP}; use crate::{ @@ -23,11 +24,7 @@ pub struct BlockStmt { impl Take for BlockStmt { fn dummy() -> Self { - BlockStmt { - span: DUMMY_SP, - stmts: vec![], - ctxt: Default::default(), - } + Default::default() } }