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

refactor(allocator): Use RAII guard instead of scope #9254

Merged
merged 1 commit into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 15 additions & 15 deletions crates/swc_allocator/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,30 @@ fn bench_alloc(c: &mut Criterion) {
fn direct_alloc_scoped(b: &mut Bencher, times: usize) {
b.iter(|| {
let allocator = Allocator::default();
let _guard = unsafe { allocator.guard() };

allocator.scope(|| {
let mut vec = SwcVec::new();
let mut vec = SwcVec::new();

for i in 0..times {
let item: SwcBox<usize> = black_box(SwcBox::new(black_box(i)));
vec.push(item);
}
});
for i in 0..times {
let item: SwcBox<usize> = black_box(SwcBox::new(black_box(i)));
vec.push(item);
}
})
}

fn fast_alloc_scoped(b: &mut Bencher, times: usize) {
b.iter(|| {
Allocator::default().scope(|| {
let alloc = FastAlloc::default();
let alloc = Allocator::default();
let _guard = unsafe { alloc.guard() };

let alloc = FastAlloc::default();

let mut vec = SwcVec::new_in(alloc);
let mut vec = SwcVec::new_in(alloc);

for i in 0..times {
let item: SwcBox<usize> = black_box(SwcBox::new_in(black_box(i), alloc));
vec.push(item);
}
});
for i in 0..times {
let item: SwcBox<usize> = black_box(SwcBox::new_in(black_box(i), alloc));
vec.push(item);
}
})
}

Expand Down
30 changes: 18 additions & 12 deletions crates/swc_allocator/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,33 @@ pub struct Allocator {
alloc: Bump,
}

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

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

impl Allocator {
/// Invokes `f` in a scope where the allocations are done in this allocator.
/// Creates a RAII guard that enables optimized allocation.
///
/// # Safety
///
/// [Allocator] must be dropped after dropping all [crate::boxed::Box] and
/// [crate::vec::Vec] created in the scope.
#[inline(always)]
pub fn scope<'a, F, R>(&'a self, f: F) -> R
where
F: FnOnce() -> R,
{
/// [Allocator] must outlive [crate::boxed::Box] and [crate::vec::Vec]
/// created while the guard is active.
pub unsafe fn guard(&self) -> AllocGuard {
let orig = ALLOC.get();

let s = unsafe {
// Safery: We are using a scoped API
transmute::<&'a Allocator, &'static Allocator>(self)
transmute::<&Allocator, &'static Allocator>(self)
};

ALLOC.set(Some(s));
let ret = f();
ALLOC.set(None);
ret
AllocGuard { orig }
}
}

Expand Down
34 changes: 33 additions & 1 deletion crates/swc_allocator/src/vec/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Faster vec type.

use std::ops::{Deref, DerefMut};
use std::{
fmt, io,
ops::{Deref, DerefMut},
};

#[cfg(feature = "rkyv")]
mod rkyv;
Expand Down Expand Up @@ -349,3 +352,32 @@ impl<T> Extend<T> for Vec<T> {
self.0.extend(iter)
}
}

impl io::Write for Vec<u8> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
io::Write::write(&mut self.0, buf)
}

fn flush(&mut self) -> io::Result<()> {
io::Write::flush(&mut self.0)
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
io::Write::write_all(&mut self.0, buf)
}

fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
io::Write::write_vectored(&mut self.0, bufs)
}

fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
io::Write::write_fmt(&mut self.0, fmt)
}

fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
{
self
}
}
15 changes: 7 additions & 8 deletions crates/swc_allocator/tests/apis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ fn direct_alloc_no_scope() {
#[test]
fn direct_alloc_in_scope() {
let allocator = Allocator::default();
let _guard = unsafe { allocator.guard() };

allocator.scope(|| {
let mut vec = swc_allocator::vec::Vec::new();
let mut vec = swc_allocator::vec::Vec::new();

for i in 0..1000 {
let item: swc_allocator::boxed::Box<usize> =
black_box(swc_allocator::boxed::Box::new(black_box(i)));
vec.push(item);
}
});
for i in 0..1000 {
let item: swc_allocator::boxed::Box<usize> =
black_box(swc_allocator::boxed::Box::new(black_box(i)));
vec.push(item);
}
}
11 changes: 8 additions & 3 deletions crates/swc_allocator/tests/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use swc_allocator::{boxed::Box, Allocator, FastAlloc};
fn escape() {
let allocator = Allocator::default();

let obj = allocator.scope(|| Box::new(1234));
let obj = {
let _guard = unsafe { allocator.guard() };
Box::new(1234)
};

assert_eq!(*obj, 1234);
// It should not segfault, because the allocator is still alive.
Expand All @@ -14,8 +17,10 @@ fn escape() {
#[test]
fn global_allocator() {
let allocator = Allocator::default();

let obj = allocator.scope(|| Box::new_in(1234, FastAlloc::global()));
let obj = {
let _guard = unsafe { allocator.guard() };
Box::new_in(1234, FastAlloc::global())
};

assert_eq!(*obj, 1234);
drop(allocator);
Expand Down
Loading