Skip to content

Commit 3943563

Browse files
committed
feat(allocator): connect Vec2 module and make it compile (oxc-project#9647)
This PR aims to connect the Vec2 with the whole program and make it compile and pass the CI. Since the diff is hard to understand, we may need to read the commit one by one to understand the changes.
1 parent 5c5e010 commit 3943563

File tree

3 files changed

+104
-17
lines changed

3 files changed

+104
-17
lines changed

crates/oxc_allocator/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ mod from_raw_parts;
2525
pub mod hash_map;
2626
pub mod string;
2727
mod vec;
28+
mod vec2;
2829

2930
pub use address::{Address, GetAddress};
3031
pub use allocator::Allocator;

crates/oxc_allocator/src/vec2/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@
108108
clippy::undocumented_unsafe_blocks
109109
)]
110110

111-
use super::raw_vec::RawVec;
112-
use crate::Bump;
113-
use crate::collections::CollectionAllocErr;
111+
use bumpalo::{Bump, collections::CollectionAllocErr};
114112
use core::borrow::{Borrow, BorrowMut};
115113
use core::cmp::Ordering;
116114
use core::fmt;
@@ -128,6 +126,9 @@ use core::slice;
128126
// #[cfg(feature = "std")]
129127
// use std::io;
130128

129+
mod raw_vec;
130+
use raw_vec::RawVec;
131+
131132
unsafe fn arith_offset<T>(p: *const T, offset: isize) -> *const T {
132133
p.offset(offset)
133134
}

crates/oxc_allocator/src/vec2/raw_vec.rs

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@
2323
#![allow(unstable_name_collisions)]
2424
#![allow(dead_code)]
2525

26-
use crate::Bump;
26+
use allocator_api2::alloc::{AllocError, Allocator};
27+
use bumpalo::Bump;
2728

29+
pub use core::alloc::Layout;
2830
use core::cmp;
2931
use core::mem;
3032
use core::ptr::{self, NonNull};
3133

32-
use crate::alloc::{Alloc, Layout, UnstableLayoutMethods, handle_alloc_error};
33-
use crate::collections::CollectionAllocErr;
34-
use crate::collections::CollectionAllocErr::*;
34+
use bumpalo::collections::CollectionAllocErr::{self, AllocErr, CapacityOverflow};
35+
3536
// use boxed::Box;
3637

3738
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
@@ -103,8 +104,7 @@ impl<'a, T> RawVec<'a, T> {
103104
} else {
104105
let align = mem::align_of::<T>();
105106
let layout = Layout::from_size_align(alloc_size, align).unwrap();
106-
let result =
107-
if zeroed { a.alloc_zeroed(layout) } else { Alloc::alloc(&mut a, layout) };
107+
let result = if zeroed { a.allocate_zeroed(layout) } else { a.allocate(layout) };
108108
match result {
109109
Ok(ptr) => ptr.cast(),
110110
Err(_) => handle_alloc_error(layout),
@@ -533,7 +533,7 @@ impl<'a, T> RawVec<'a, T> {
533533
let new_size = elem_size * amount;
534534
let align = mem::align_of::<T>();
535535
let old_layout = Layout::from_size_align_unchecked(old_size, align);
536-
match self.a.realloc(self.ptr.cast(), old_layout, new_size) {
536+
match realloc(self.a, self.ptr.cast(), old_layout, new_size) {
537537
Ok(p) => self.ptr = p.cast(),
538538
Err(_) => {
539539
handle_alloc_error(Layout::from_size_align_unchecked(new_size, align))
@@ -656,8 +656,6 @@ impl<'a, T> RawVec<'a, T> {
656656
strategy: ReserveStrategy,
657657
) -> Result<(), CollectionAllocErr> {
658658
unsafe {
659-
use crate::AllocErr;
660-
661659
// NOTE: we don't early branch on ZSTs here because we want this
662660
// to actually catch "asking for more than usize::MAX" in that case.
663661
// If we make it past the first branch then we are guaranteed to
@@ -675,16 +673,16 @@ impl<'a, T> RawVec<'a, T> {
675673
let res = match self.current_layout() {
676674
Some(layout) => {
677675
debug_assert!(new_layout.align() == layout.align());
678-
self.a.realloc(self.ptr.cast(), layout, new_layout.size())
676+
realloc(self.a, self.ptr.cast(), layout, new_layout.size())
679677
}
680-
None => Alloc::alloc(&mut self.a, new_layout),
678+
None => self.a.allocate(new_layout),
681679
};
682680

683-
if let (Err(AllocErr), Infallible) = (&res, fallibility) {
681+
if let (Err(AllocError), Infallible) = (&res, fallibility) {
684682
handle_alloc_error(new_layout);
685683
}
686684

687-
self.ptr = res?.cast();
685+
self.ptr = res.map_err(|_| AllocErr)?.cast();
688686
self.cap = new_cap;
689687

690688
Ok(())
@@ -698,7 +696,7 @@ impl<'a, T> RawVec<'a, T> {
698696
let elem_size = mem::size_of::<T>();
699697
if elem_size != 0 {
700698
if let Some(layout) = self.current_layout() {
701-
self.a.dealloc(self.ptr.cast(), layout);
699+
self.a.deallocate(self.ptr.cast(), layout);
702700
}
703701
}
704702
}
@@ -738,6 +736,93 @@ fn capacity_overflow() -> ! {
738736
panic!("capacity overflow")
739737
}
740738

739+
// Copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/alloc.rs#L29-L31
740+
fn handle_alloc_error(layout: Layout) -> ! {
741+
panic!("encountered allocation error: {:?}", layout)
742+
}
743+
744+
// Copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/lib.rs#L482-L486
745+
/// Wrapper around `Layout::from_size_align` that adds debug assertions.
746+
#[inline]
747+
fn layout_from_size_align(size: usize, align: usize) -> Result<Layout, AllocError> {
748+
Layout::from_size_align(size, align).map_err(|_| AllocError)
749+
}
750+
751+
// Code copied from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/lib.rs#L1917-L1936
752+
// Doc comment from https://github.com/fitzgen/bumpalo/blob/1d2fbea9e3d0c2be56367b9ad5382ff33852a188/src/alloc.rs#L322-L402
753+
//
754+
/// Returns a pointer suitable for holding data described by
755+
/// a new layout with `layout`’s alignment and a size given
756+
/// by `new_size`. To
757+
/// accomplish this, this may extend or shrink the allocation
758+
/// referenced by `ptr` to fit the new layout.
759+
///
760+
/// If this returns `Ok`, then ownership of the memory block
761+
/// referenced by `ptr` has been transferred to this
762+
/// allocator. The memory may or may not have been freed, and
763+
/// should be considered unusable (unless of course it was
764+
/// transferred back to the caller again via the return value of
765+
/// this method).
766+
///
767+
/// If this method returns `Err`, then ownership of the memory
768+
/// block has not been transferred to this allocator, and the
769+
/// contents of the memory block are unaltered.
770+
///
771+
/// # Safety
772+
///
773+
/// This function is unsafe because undefined behavior can result
774+
/// if the caller does not ensure all of the following:
775+
///
776+
/// * `ptr` must be currently allocated via this allocator,
777+
///
778+
/// * `layout` must *fit* the `ptr` (see above). (The `new_size`
779+
/// argument need not fit it.)
780+
///
781+
/// * `new_size` must be greater than zero.
782+
///
783+
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
784+
/// must not overflow (i.e. the rounded value must be less than `usize::MAX`).
785+
///
786+
/// (Extension subtraits might provide more specific bounds on
787+
/// behavior, e.g. guarantee a sentinel address or a null pointer
788+
/// in response to a zero-size allocation request.)
789+
///
790+
/// # Errors
791+
///
792+
/// Returns `Err` only if the new layout
793+
/// does not meet the allocator's size
794+
/// and alignment constraints of the allocator, or if reallocation
795+
/// otherwise fails.
796+
///
797+
/// Implementations are encouraged to return `Err` on memory
798+
/// exhaustion rather than panicking or aborting, but this is not
799+
/// a strict requirement. (Specifically: it is *legal* to
800+
/// implement this trait atop an underlying native allocation
801+
/// library that aborts on memory exhaustion.)
802+
///
803+
/// Clients wishing to abort computation in response to a
804+
/// reallocation error are encouraged to call the [`handle_alloc_error`] function,
805+
/// rather than directly invoking `panic!` or similar.
806+
unsafe fn realloc(
807+
bump: &Bump,
808+
ptr: NonNull<u8>,
809+
layout: Layout,
810+
new_size: usize,
811+
) -> Result<NonNull<[u8]>, AllocError> {
812+
let old_size = layout.size();
813+
814+
if old_size == 0 {
815+
return bump.allocate(layout);
816+
}
817+
818+
let new_layout = layout_from_size_align(new_size, layout.align())?;
819+
if new_size <= old_size {
820+
bump.shrink(ptr, layout, new_layout)
821+
} else {
822+
bump.grow(ptr, layout, new_layout)
823+
}
824+
}
825+
741826
#[cfg(test)]
742827
mod tests {
743828
use super::*;

0 commit comments

Comments
 (0)