Skip to content

Commit

Permalink
feat(allocator): introduce Vec::from_array_in
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Nov 17, 2024
1 parent 44fd962 commit b34cf4a
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 4 deletions.
7 changes: 7 additions & 0 deletions crates/oxc_allocator/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ impl<'alloc, T: ?Sized> Box<'alloc, T> {
pub(crate) const unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
Self(ptr, PhantomData)
}

/// Consume a [`Box`] and return a [`NonNull`] pointer to its contents.
#[inline]
#[expect(clippy::needless_pass_by_value)]
pub fn into_non_null(boxed: Self) -> NonNull<T> {
boxed.0
}
}

impl<'alloc, T: ?Sized> ops::Deref for Box<'alloc, T> {
Expand Down
17 changes: 17 additions & 0 deletions crates/oxc_allocator/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,23 @@ impl<'alloc, T> Vec<'alloc, T> {
Self(vec)
}

/// Create a new [`Vec`] from a fixed-size array, allocated in the given `allocator`.
///
/// This is preferable to `from_iter_in` where source is an array, as size is statically known,
/// and compiler is more likely to construct the values directly in arena, rather than constructing
/// on stack and then copying to arena.
#[inline]
pub fn from_array_in<const N: usize>(array: [T; N], allocator: &'alloc Allocator) -> Self {
let boxed = Box::new_in(array, allocator);
let ptr = Box::into_non_null(boxed).as_ptr().cast::<T>();
// SAFETY: `ptr` has correct alignment - it was just allocated as `[T; N]`.
// `ptr` was allocated with correct size for `[T; N]`.
// `len` and `capacity` are both `N`.
// Allocated size cannot be larger than `isize::MAX`, or `Box::new_in` would have failed.
let vec = unsafe { vec::Vec::from_raw_parts_in(ptr, N, N, &**allocator) };
Self(ManuallyDrop::new(vec))
}

/// Converts the vector into [`Box<[T]>`][owned slice].
///
/// Any excess capacity the vector has will not be included in the slice.
Expand Down
10 changes: 10 additions & 0 deletions crates/oxc_ast/src/ast_builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ impl<'a> AstBuilder<'a> {
Vec::from_iter_in(iter, self.allocator)
}

/// Create [`Vec`] from a fixed-size array.
///
/// This is preferable to `vec_from_iter` where source is an array, as size is statically known,
/// and compiler is more likely to construct the values directly in arena, rather than constructing
/// on stack and then copying to arena.
#[inline]
pub fn vec_from_array<T, const N: usize>(self, array: [T; N]) -> Vec<'a, T> {
Vec::from_array_in(array, self.allocator)
}

/// Move a string slice into the memory arena, returning a reference to the slice
/// in the heap.
#[inline]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_isolated_declarations/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<'a> IsolatedDeclarations<'a> {
SPAN,
self.ast.ts_type_union_type(
SPAN,
self.ast.vec_from_iter([
self.ast.vec_from_array([
ts_type,
self.ast.ts_type_undefined_keyword(SPAN),
]),
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_isolated_declarations/src/return_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl<'a> FunctionReturnType<'a> {

let types = transformer
.ast
.vec_from_iter([expr_type, transformer.ast.ts_type_undefined_keyword(SPAN)]);
.vec_from_array([expr_type, transformer.ast.ts_type_undefined_keyword(SPAN)]);
expr_type = transformer.ast.ts_type_union_type(SPAN, types);
}
Some(expr_type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl<'a, 'b> PeepholeFoldConstants {
ValueType::Null | ValueType::Undefined => {
Some(if left.may_have_side_effects() {
// e.g. `(a(), null) ?? 1` => `(a(), null, 1)`
let expressions = ctx.ast.vec_from_iter([
let expressions = ctx.ast.vec_from_array([
ctx.ast.move_expression(&mut logical_expr.left),
ctx.ast.move_expression(&mut logical_expr.right),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> {
let property = ctx.ast.identifier_name(SPAN, "pow");
let callee =
Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false));
let arguments = ctx.ast.vec_from_iter([Argument::from(left), Argument::from(right)]);
let arguments = ctx.ast.vec_from_array([Argument::from(left), Argument::from(right)]);
ctx.ast.expression_call(SPAN, callee, NONE, arguments, false)
}

Expand Down

0 comments on commit b34cf4a

Please sign in to comment.