Skip to content

Commit d8e8b04

Browse files
authoredJul 15, 2024··
fix(allocator): Remove wrong assertions and add tests (#9252)
1 parent 123a9f9 commit d8e8b04

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed
 

‎crates/swc_allocator/src/alloc.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ pub struct Allocator {
2323

2424
impl Allocator {
2525
/// Invokes `f` in a scope where the allocations are done in this allocator.
26+
///
27+
/// # Safety
28+
///
29+
/// [Allocator] must be dropped after dropping all [crate::boxed::Box] and
30+
/// [crate::vec::Vec] created in the scope.
2631
#[inline(always)]
2732
pub fn scope<'a, F, R>(&'a self, f: F) -> R
2833
where
@@ -116,11 +121,6 @@ unsafe impl allocator_api2::alloc::Allocator for FastAlloc {
116121
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
117122
#[cfg(feature = "scoped")]
118123
if self.alloc.is_some() {
119-
debug_assert!(
120-
ALLOC.get().is_some(),
121-
"Deallocating a pointer allocated with arena mode with a non-arena mode allocator"
122-
);
123-
124124
self.with_allocator(|alloc, _| alloc.deallocate(ptr, layout));
125125
return;
126126
}

‎crates/swc_allocator/src/lib.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
//! [crate::vec::Vec] very fast.
2020
//!
2121
//! In this mode, you need to be careful while using [crate::boxed::Box] and
22-
//! [crate::vec::Vec]. Be sure to use same [Allocator] for allocation and
23-
//! deallocation.
22+
//! [crate::vec::Vec]. You should ensure that [Allocator] outlives all
23+
//! [crate::boxed::Box] and [crate::vec::Vec] created in the scope.
2424
//!
2525
//! Recommened way to use this mode is to wrap the whole operations in
2626
//! a call to [Allocator::scope].
@@ -61,3 +61,15 @@ pub struct FastAlloc {
6161
#[cfg(feature = "scoped")]
6262
alloc: Option<&'static Allocator>,
6363
}
64+
65+
impl FastAlloc {
66+
/// [crate::boxed::Box] or [crate::vec::Vec] created with this instance is
67+
/// managed by the global allocator and it can outlive the
68+
/// [crate::Allocator] instance used for [Allocator::scope].
69+
pub const fn global() -> Self {
70+
Self {
71+
#[cfg(feature = "scoped")]
72+
alloc: None,
73+
}
74+
}
75+
}

‎crates/swc_allocator/tests/escape.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use swc_allocator::{boxed::Box, Allocator, FastAlloc};
2+
3+
#[test]
4+
fn escape() {
5+
let allocator = Allocator::default();
6+
7+
let obj = allocator.scope(|| Box::new(1234));
8+
9+
assert_eq!(*obj, 1234);
10+
// It should not segfault, because the allocator is still alive.
11+
drop(obj);
12+
}
13+
14+
#[test]
15+
fn global_allocator() {
16+
let allocator = Allocator::default();
17+
18+
let obj = allocator.scope(|| Box::new_in(1234, FastAlloc::global()));
19+
20+
assert_eq!(*obj, 1234);
21+
drop(allocator);
22+
// Object created with global allocator should outlive the allocator.
23+
drop(obj);
24+
}

0 commit comments

Comments
 (0)
Please sign in to comment.