Skip to content

Commit

Permalink
fix(allocator): Remove wrong assertions and add tests (#9252)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 authored Jul 15, 2024
1 parent 123a9f9 commit d8e8b04
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 7 deletions.
10 changes: 5 additions & 5 deletions crates/swc_allocator/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ pub struct Allocator {

impl Allocator {
/// Invokes `f` in a scope where the allocations are done in this allocator.
///
/// # 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
Expand Down Expand Up @@ -116,11 +121,6 @@ unsafe impl allocator_api2::alloc::Allocator for FastAlloc {
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
#[cfg(feature = "scoped")]
if self.alloc.is_some() {
debug_assert!(
ALLOC.get().is_some(),
"Deallocating a pointer allocated with arena mode with a non-arena mode allocator"
);

self.with_allocator(|alloc, _| alloc.deallocate(ptr, layout));
return;
}
Expand Down
16 changes: 14 additions & 2 deletions crates/swc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
//! [crate::vec::Vec] very fast.
//!
//! In this mode, you need to be careful while using [crate::boxed::Box] and
//! [crate::vec::Vec]. Be sure to use same [Allocator] for allocation and
//! deallocation.
//! [crate::vec::Vec]. You should ensure that [Allocator] outlives all
//! [crate::boxed::Box] and [crate::vec::Vec] created in the scope.
//!
//! Recommened way to use this mode is to wrap the whole operations in
//! a call to [Allocator::scope].
Expand Down Expand Up @@ -61,3 +61,15 @@ pub struct FastAlloc {
#[cfg(feature = "scoped")]
alloc: Option<&'static Allocator>,
}

impl FastAlloc {
/// [crate::boxed::Box] or [crate::vec::Vec] created with this instance is
/// managed by the global allocator and it can outlive the
/// [crate::Allocator] instance used for [Allocator::scope].
pub const fn global() -> Self {
Self {
#[cfg(feature = "scoped")]
alloc: None,
}
}
}
24 changes: 24 additions & 0 deletions crates/swc_allocator/tests/escape.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use swc_allocator::{boxed::Box, Allocator, FastAlloc};

#[test]
fn escape() {
let allocator = Allocator::default();

let obj = allocator.scope(|| Box::new(1234));

assert_eq!(*obj, 1234);
// It should not segfault, because the allocator is still alive.
drop(obj);
}

#[test]
fn global_allocator() {
let allocator = Allocator::default();

let obj = allocator.scope(|| Box::new_in(1234, FastAlloc::global()));

assert_eq!(*obj, 1234);
drop(allocator);
// Object created with global allocator should outlive the allocator.
drop(obj);
}

0 comments on commit d8e8b04

Please sign in to comment.