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): Use swc_allocator #9245

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
515b0f1
Dep on allocator
kdy1 Jul 15, 2024
28eb1e6
cargo lockfile
kdy1 Jul 15, 2024
a3c78d0
Use box & vec
kdy1 Jul 15, 2024
1f22ed4
fix
kdy1 Jul 15, 2024
bc1acf2
fix more
kdy1 Jul 15, 2024
c773b67
lint
kdy1 Jul 15, 2024
a3351e2
More box
kdy1 Jul 15, 2024
c672cc4
`#[fundamental]`
kdy1 Jul 15, 2024
f756595
fix
kdy1 Jul 15, 2024
37c165a
Fix AST
kdy1 Jul 15, 2024
4589e5e
Dep
kdy1 Jul 15, 2024
8f4e381
cargo lockfile
kdy1 Jul 15, 2024
c2ff010
Dep
kdy1 Jul 15, 2024
e7f92b6
cargo lockfile
kdy1 Jul 15, 2024
d282b2e
Import for vistor
kdy1 Jul 15, 2024
755db34
Fix parser
kdy1 Jul 15, 2024
05f9996
Fix more
kdy1 Jul 15, 2024
b74d02c
Fix more
kdy1 Jul 15, 2024
6d08d0e
vec![]
kdy1 Jul 15, 2024
f499a1a
More work
kdy1 Jul 15, 2024
212a87d
More work
kdy1 Jul 15, 2024
a0449c3
More work
kdy1 Jul 15, 2024
3b3041e
More work
kdy1 Jul 15, 2024
fdf2f1e
More work
kdy1 Jul 15, 2024
6ee8b26
More work
kdy1 Jul 15, 2024
ad831af
More work
kdy1 Jul 15, 2024
ca89380
More work
kdy1 Jul 15, 2024
43c7e0f
fix `vec!`
kdy1 Jul 15, 2024
9331e1b
fix `vec!`
kdy1 Jul 15, 2024
01046c4
Fix macro
kdy1 Jul 15, 2024
555ddce
Fix allocator
kdy1 Jul 15, 2024
fc63819
Fix allocator
kdy1 Jul 15, 2024
4651c43
fixup
kdy1 Jul 15, 2024
4b6cc0d
Fix parser
kdy1 Jul 15, 2024
2bc6ace
Fix for rebase
kdy1 Jul 15, 2024
f9361fc
allocator
kdy1 Jul 15, 2024
f113358
Use scoped
kdy1 Jul 15, 2024
ed943de
dep
kdy1 Jul 15, 2024
c10b4c2
cargo lockifle
kdy1 Jul 15, 2024
3a64b91
Lifetime to guard
kdy1 Jul 15, 2024
4ac82d6
cleanup
kdy1 Jul 16, 2024
0454242
comment
kdy1 Jul 16, 2024
18cd361
fix drop impl
kdy1 Jul 16, 2024
c850fd2
Try pin
kdy1 Jul 16, 2024
ff91e26
Add segfault test
kdy1 Jul 16, 2024
f18b948
fix unbox()
kdy1 Jul 16, 2024
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
4 changes: 3 additions & 1 deletion Cargo.lock

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

28 changes: 15 additions & 13 deletions crates/swc_allocator/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
cell::Cell,
mem::transmute,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};

Expand All @@ -11,8 +12,10 @@ use bumpalo::Bump;

use crate::FastAlloc;

pub(crate) type Alloc = Pin<&'static Allocator>;

thread_local! {
static ALLOC: Cell<Option<&'static Allocator>> = const { Cell::new(None) };
static ALLOC: Cell<Option<Alloc>> = const { Cell::new(None) };
}

/// The actual storage for [FastAlloc].
Expand All @@ -21,13 +24,15 @@ pub struct Allocator {
alloc: Bump,
}

pub struct AllocGuard {
orig: Option<&'static Allocator>,
pub struct AllocGuard<'a> {
orig: Option<Alloc>,

_ref: &'a Allocator,
}

impl Drop for AllocGuard {
impl Drop for AllocGuard<'_> {
fn drop(&mut self) {
ALLOC.set(self.orig.take());
ALLOC.set(self.orig);
}
}

Expand All @@ -41,25 +46,22 @@ impl Allocator {
pub unsafe fn guard(&self) -> AllocGuard {
let orig = ALLOC.get();

let pin: Pin<&Allocator> = Pin::new(self);
let s = unsafe {
// Safery: We are using a scoped API
transmute::<&Allocator, &'static Allocator>(self)
// Safery: Guard holds &self, so it cannot be moved nor dropped.
transmute::<Pin<&Allocator>, Pin<&'static Allocator>>(pin)
};

ALLOC.set(Some(s));
AllocGuard { orig }
AllocGuard { orig, _ref: self }
}
}

impl Default for FastAlloc {
fn default() -> Self {
Self {
#[cfg(feature = "scoped")]
alloc: if let Some(v) = ALLOC.get() {
Some(v)
} else {
None
},
alloc: ALLOC.get(),
}
}
}
Expand Down
78 changes: 76 additions & 2 deletions crates/swc_allocator/src/boxed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ use std::{
iter::FusedIterator,
ops::{Deref, DerefMut},
pin::Pin,
ptr,
};

use crate::FastAlloc;
use crate::{vec::Vec, FastAlloc};

#[cfg(feature = "rkyv")]
mod rkyv;
Expand All @@ -19,6 +20,7 @@ mod serde;
/// Faster alterantive for [`std::boxed::Box`].
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[fundamental]
pub struct Box<T: ?Sized>(pub(crate) allocator_api2::boxed::Box<T, FastAlloc>);

impl<T> From<T> for Box<T> {
Expand Down Expand Up @@ -81,7 +83,9 @@ impl<T> Box<T> {

/// Moves the value out of the box.
pub fn unbox(self) -> T {
allocator_api2::boxed::Box::into_inner(self.0)
let raw = allocator_api2::boxed::Box::into_raw(self.0);

unsafe { ptr::read(raw) }
}
}

Expand Down Expand Up @@ -134,6 +138,56 @@ impl<T: ?Sized> Box<T> {
))
}

/// Constructs a box from a raw pointer in the given allocator.
///
/// After calling this function, the raw pointer is owned by the
/// resulting `Box`. Specifically, the `Box` destructor will call
/// the destructor of `T` and free the allocated memory. For this
/// to be safe, the memory must have been allocated in accordance
/// with the [memory layout] used by `Box` .
///
/// # Safety
///
/// This function is unsafe because improper use may lead to
/// memory problems. For example, a double-free may occur if the
/// function is called twice on the same raw pointer.
///
///
/// # Examples
///
/// Recreate a `Box` which was previously converted to a raw pointer
/// using [`Box::into_raw_with_allocator`]:
/// ```
/// use std::alloc::System;
/// # use allocator_api2::boxed::Box;
///
/// let x = Box::new_in(5, System);
/// let (ptr, alloc) = Box::into_raw_with_allocator(x);
/// let x = unsafe { Box::from_raw_in(ptr, alloc) };
/// ```
/// Manually create a `Box` from scratch by using the system allocator:
/// ```
/// use allocator_api2::alloc::{Allocator, Layout, System};
/// # use allocator_api2::boxed::Box;
///
/// unsafe {
/// let ptr = System.allocate(Layout::new::<i32>())?.as_ptr().cast::<i32>();
/// // In general .write is required to avoid attempting to destruct
/// // the (uninitialized) previous contents of `ptr`, though for this
/// // simple example `*ptr = 5` would have worked as well.
/// ptr.write(5);
/// let x = Box::from_raw_in(ptr, System);
/// }
/// # Ok::<(), allocator_api2::alloc::AllocError>(())
/// ```
///
/// [memory layout]: self#memory-layout
/// [`Layout`]: crate::Layout
#[inline(always)]
pub const unsafe fn from_raw_in(raw: *mut T, alloc: FastAlloc) -> Self {
Box(allocator_api2::boxed::Box::from_raw_in(raw, alloc))
}

/// Consumes the `Box`, returning a wrapped raw pointer.
///
/// The pointer will be properly aligned and non-null.
Expand Down Expand Up @@ -648,3 +702,23 @@ where
self.0.len()
}
}

impl<T> Box<[T]> {
/// Converts a boxed slice into a `Vec`.
pub fn into_vec(self) -> Vec<T> {
allocator_api2::boxed::Box::<[T], FastAlloc>::into_vec(self.0).into()
}
}

impl<T, const N: usize> Box<[T; N]> {
/// Converts a boxed slice into a `Vec`.
#[inline(always)]
pub fn slice(b: Self) -> Box<[T]> {
Box(allocator_api2::boxed::Box::slice(b.0))
}

/// Converts a boxed slice into a `Vec`.
pub fn into_vec(self) -> Vec<T> {
allocator_api2::boxed::Box::<[T; N], FastAlloc>::into_vec(self.0).into()
}
}
26 changes: 25 additions & 1 deletion crates/swc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(missing_docs)]
#![allow(clippy::derivable_impls)]
#![feature(fundamental, fn_ptr_trait, with_negative_coherence)]

/// NOT A PUBLIC API.
#[doc(hidden)]
pub extern crate allocator_api2;

use crate::alloc::Alloc;
pub use crate::alloc::Allocator;

mod alloc;
Expand Down Expand Up @@ -59,7 +65,7 @@ pub mod vec;
#[derive(Clone, Copy)]
pub struct FastAlloc {
#[cfg(feature = "scoped")]
alloc: Option<&'static Allocator>,
alloc: Option<Alloc>,
}

impl FastAlloc {
Expand All @@ -73,3 +79,21 @@ impl FastAlloc {
}
}
}

/// Creates a `Vec<T>` from a list of elements.
#[macro_export]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
);
($elem:expr; $n:expr) => (
$crate::vec::from_elem_in($elem, $n, $crate::FastAlloc::default())
);
($($x:expr),+ $(,)?) => (
$crate::boxed::Box::<[_]>::into_vec(
$crate::boxed::Box::slice(
$crate::boxed::Box::new([$($x),+])
)
)
);
}
6 changes: 6 additions & 0 deletions crates/swc_allocator/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ use crate::{boxed::Box, FastAlloc};
)]
pub struct Vec<T>(allocator_api2::vec::Vec<T, FastAlloc>);

impl<T> From<allocator_api2::vec::Vec<T, FastAlloc>> for Vec<T> {
fn from(v: allocator_api2::vec::Vec<T, FastAlloc>) -> Self {
Self(v)
}
}

impl<T> Vec<T> {
/// Constructs a new, empty `Vec<T>`.
///
Expand Down
4 changes: 3 additions & 1 deletion crates/swc_ecma_ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ rkyv-impl = [
"__rkyv",
"rkyv",
"bytecheck",
"swc_allocator/rkyv",
"swc_atoms/rkyv-impl",
"swc_common/rkyv-impl",
]
serde-impl = ["serde"]
serde-impl = ["serde", "swc_allocator/serde"]

[dependencies]
arbitrary = { workspace = true, features = ["derive"], optional = true }
Expand All @@ -43,6 +44,7 @@ rkyv = { workspace = true, features = [
scoped-tls = { workspace = true }
serde = { workspace = true, features = ["derive"], optional = true }
string_enum = { version = "0.4.4", path = "../string_enum" }
swc_allocator = { version = "0.1.4", path = "../swc_allocator" }
swc_atoms = { version = "0.6.5", path = "../swc_atoms" }
swc_common = { version = "0.35.0", path = "../swc_common" }
unicode-id-start = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/class.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/decl.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down
9 changes: 5 additions & 4 deletions crates/swc_ecma_ast/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -528,7 +529,7 @@ impl ObjectLit {
///
/// Returns [None] if this is not a valid for `with` of [crate::ImportDecl].
pub fn as_import_with(&self) -> Option<ImportWith> {
let mut values = vec![];
let mut values = Vec::new();
for prop in &self.props {
match prop {
PropOrSpread::Spread(..) => return None,
Expand Down Expand Up @@ -1401,7 +1402,7 @@ impl TryFrom<Box<Pat>> for AssignTarget {
type Error = Box<Pat>;

fn try_from(p: Box<Pat>) -> Result<Self, Self::Error> {
(*p).try_into().map_err(Box::new)
p.unbox().try_into().map_err(Box::new)
}
}

Expand Down Expand Up @@ -1502,7 +1503,7 @@ impl TryFrom<Box<Expr>> for SimpleAssignTarget {
type Error = Box<Expr>;

fn try_from(e: Box<Expr>) -> Result<Self, Self::Error> {
Ok(match *e {
Ok(match e.unbox() {
Expr::Ident(i) => SimpleAssignTarget::Ident(i.into()),
Expr::Member(m) => SimpleAssignTarget::Member(m),
Expr::SuperProp(s) => SimpleAssignTarget::SuperProp(s),
Expand All @@ -1513,7 +1514,7 @@ impl TryFrom<Box<Expr>> for SimpleAssignTarget {
Expr::TsNonNull(n) => SimpleAssignTarget::TsNonNull(n),
Expr::TsTypeAssertion(a) => SimpleAssignTarget::TsTypeAssertion(a),
Expr::TsInstantiation(a) => SimpleAssignTarget::TsInstantiation(a),
_ => return Err(e),
e => return Err(Box::new(e)),
})
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/function.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/jsx.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{
};

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

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/module.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use is_macro::Is;
use swc_allocator::vec::Vec;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/module_decl.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/pat.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_ast/src/prop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use is_macro::Is;
use swc_allocator::boxed::Box;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};

use crate::{
Expand Down
Loading
Loading