diff --git a/crates/oxc_allocator/src/generated/fixed_size_constants.rs b/crates/oxc_allocator/src/generated/fixed_size_constants.rs index 8b54171c9f176..9d14020a19b1c 100644 --- a/crates/oxc_allocator/src/generated/fixed_size_constants.rs +++ b/crates/oxc_allocator/src/generated/fixed_size_constants.rs @@ -4,6 +4,6 @@ #![expect(clippy::unreadable_literal)] #![allow(dead_code)] -pub const BUFFER_SIZE: usize = 2147483632; -pub const BUFFER_ALIGN: usize = 4294967296; -pub const METADATA_SIZE: usize = 16; +pub const BLOCK_SIZE: usize = 2147483632; +pub const BLOCK_ALIGN: usize = 4294967296; +pub const RAW_METADATA_SIZE: usize = 16; diff --git a/crates/oxc_allocator/src/pool_fixed_size.rs b/crates/oxc_allocator/src/pool_fixed_size.rs index bbbc9ec707755..3bd81a65632ae 100644 --- a/crates/oxc_allocator/src/pool_fixed_size.rs +++ b/crates/oxc_allocator/src/pool_fixed_size.rs @@ -8,7 +8,7 @@ use std::{ use crate::{ Allocator, - fixed_size_constants::{BUFFER_ALIGN, BUFFER_SIZE, METADATA_SIZE}, + fixed_size_constants::{BLOCK_ALIGN, BLOCK_SIZE, RAW_METADATA_SIZE}, }; const TWO_GIB: usize = 1 << 31; @@ -101,7 +101,7 @@ impl Drop for AllocatorGuard<'_> { // Could just use that built-in workaround, rather than implementing our own, or allocate a 6 GiB chunk // with alignment 16, to skip Rust's built-in workaround. // Note: Rust's workaround will likely commit a whole page of memory, just to store the real pointer. -const ALLOC_SIZE: usize = BUFFER_SIZE + TWO_GIB; +const ALLOC_SIZE: usize = BLOCK_SIZE + TWO_GIB; const ALLOC_ALIGN: usize = TWO_GIB; const ALLOC_LAYOUT: Layout = match Layout::from_size_align(ALLOC_SIZE, ALLOC_ALIGN) { @@ -152,9 +152,9 @@ impl FixedSizeAllocator { // SAFETY: We allocated 4 GiB of memory, so adding `offset` to `alloc_ptr` is in bounds let chunk_ptr = unsafe { alloc_ptr.add(offset) }; - debug_assert!(chunk_ptr.as_ptr() as usize % BUFFER_ALIGN == 0); + debug_assert!(chunk_ptr.as_ptr() as usize % BLOCK_ALIGN == 0); - const CHUNK_SIZE: usize = BUFFER_SIZE - METADATA_SIZE; + const CHUNK_SIZE: usize = BLOCK_SIZE - RAW_METADATA_SIZE; const _: () = assert!(CHUNK_SIZE % Allocator::RAW_MIN_ALIGN == 0); // SAFETY: Memory region starting at `chunk_ptr` with `CHUNK_SIZE` bytes is within @@ -172,12 +172,12 @@ impl FixedSizeAllocator { self.allocator.reset(); // Set data pointer back to start. - // SAFETY: Fixed-size allocators have data pointer originally aligned on `BUFFER_ALIGN`, - // and size less than `BUFFER_ALIGN`. So we can restore original data pointer by rounding down - // to next multiple of `BUFFER_ALIGN`. + // SAFETY: Fixed-size allocators have data pointer originally aligned on `BLOCK_ALIGN`, + // and size less than `BLOCK_ALIGN`. So we can restore original data pointer by rounding down + // to next multiple of `BLOCK_ALIGN`. unsafe { let data_ptr = self.allocator.data_ptr(); - let offset = data_ptr.as_ptr() as usize % BUFFER_ALIGN; + let offset = data_ptr.as_ptr() as usize % BLOCK_ALIGN; let data_ptr = data_ptr.sub(offset); self.allocator.set_data_ptr(data_ptr); } diff --git a/napi/parser/src/generated/raw_transfer_constants.rs b/napi/parser/src/generated/raw_transfer_constants.rs index 8b54171c9f176..9d14020a19b1c 100644 --- a/napi/parser/src/generated/raw_transfer_constants.rs +++ b/napi/parser/src/generated/raw_transfer_constants.rs @@ -4,6 +4,6 @@ #![expect(clippy::unreadable_literal)] #![allow(dead_code)] -pub const BUFFER_SIZE: usize = 2147483632; -pub const BUFFER_ALIGN: usize = 4294967296; -pub const METADATA_SIZE: usize = 16; +pub const BLOCK_SIZE: usize = 2147483632; +pub const BLOCK_ALIGN: usize = 4294967296; +pub const RAW_METADATA_SIZE: usize = 16; diff --git a/napi/parser/src/raw_transfer.rs b/napi/parser/src/raw_transfer.rs index ee9b166292d15..8ffb483b531aa 100644 --- a/napi/parser/src/raw_transfer.rs +++ b/napi/parser/src/raw_transfer.rs @@ -19,7 +19,7 @@ use oxc_napi::get_source_type; use crate::{ AstType, ParserOptions, get_ast_type, parse, - raw_transfer_constants::{BUFFER_ALIGN, BUFFER_SIZE}, + raw_transfer_constants::{BLOCK_ALIGN as BUFFER_ALIGN, BLOCK_SIZE as BUFFER_SIZE}, raw_transfer_types::{EcmaScriptModule, Error, RawTransferData, RawTransferMetadata}, }; @@ -182,14 +182,14 @@ unsafe fn parse_raw_impl( // Leave space for source before it, and space for metadata after it. // Metadata actually only takes 5 bytes, but round everything up to multiple of 16, // as `bumpalo` requires that alignment. - const METADATA_SIZE: usize = size_of::(); + const RAW_METADATA_SIZE: usize = size_of::(); const { - assert!(METADATA_SIZE >= BUMP_ALIGN); - assert!(is_multiple_of(METADATA_SIZE, BUMP_ALIGN)); + assert!(RAW_METADATA_SIZE >= BUMP_ALIGN); + assert!(is_multiple_of(RAW_METADATA_SIZE, BUMP_ALIGN)); }; let source_len = source_len as usize; let data_offset = source_len.next_multiple_of(BUMP_ALIGN); - let data_size = BUFFER_SIZE.saturating_sub(data_offset + METADATA_SIZE); + let data_size = BUFFER_SIZE.saturating_sub(data_offset + RAW_METADATA_SIZE); assert!(data_size >= Allocator::RAW_MIN_SIZE, "Source text is too long"); // Create `Allocator`. @@ -274,13 +274,13 @@ unsafe fn parse_raw_impl( // Write metadata into end of buffer #[allow(clippy::cast_possible_truncation)] let metadata = RawTransferMetadata::new(data_ptr as u32, ast_type == AstType::TypeScript); - const METADATA_OFFSET: usize = BUFFER_SIZE - METADATA_SIZE; - const _: () = assert!(is_multiple_of(METADATA_OFFSET, BUMP_ALIGN)); - // SAFETY: `METADATA_OFFSET` is less than length of `buffer`. - // `METADATA_OFFSET` is aligned on 16. + const RAW_METADATA_OFFSET: usize = BUFFER_SIZE - RAW_METADATA_SIZE; + const _: () = assert!(is_multiple_of(RAW_METADATA_OFFSET, BUMP_ALIGN)); + // SAFETY: `RAW_METADATA_OFFSET` is less than length of `buffer`. + // `RAW_METADATA_OFFSET` is aligned on 16. #[expect(clippy::cast_ptr_alignment)] unsafe { - buffer_ptr.add(METADATA_OFFSET).cast::().write(metadata); + buffer_ptr.add(RAW_METADATA_OFFSET).cast::().write(metadata); } } diff --git a/tasks/ast_tools/src/generators/raw_transfer.rs b/tasks/ast_tools/src/generators/raw_transfer.rs index bdb7d96de9740..faee8e9d6c007 100644 --- a/tasks/ast_tools/src/generators/raw_transfer.rs +++ b/tasks/ast_tools/src/generators/raw_transfer.rs @@ -26,13 +26,23 @@ use crate::{ use super::define_generator; -/// Size of raw transfer buffer. -/// Must be a multiple of 16. +/// Bytes reserved for `malloc`'s metadata +const MALLOC_RESERVED_SIZE: u32 = 16; + +/// Minimum alignment requirement for end of `Allocator`'s chunk +#[expect(dead_code)] +const ALLOCATOR_CHUNK_END_ALIGN: u32 = 16; + +/// Size of block of memory used for raw transfer. +/// This size includes metadata stored after the `Allocator` chunk which contains AST data. +/// +/// Must be a multiple of [`ALLOCATOR_CHUNK_END_ALIGN`]. /// 16 bytes less than 2 GiB, to allow 16 bytes for `malloc` metadata (like Bumpalo does). -const BUFFER_SIZE: u32 = (1 << 31) - 16; // 2 GiB - 16 bytes -const _: () = assert!(BUFFER_SIZE % 16 == 0); -/// Alignment of raw transfer buffer. -const BUFFER_ALIGN: u64 = 1 << 32; // 4 GiB +const BLOCK_SIZE: u32 = (1 << 31) - MALLOC_RESERVED_SIZE; // 2 GiB - 16 bytes +const _: () = assert!(BLOCK_SIZE % ALLOCATOR_CHUNK_END_ALIGN == 0); + +/// Alignment of block of memory used for raw transfer. +const BLOCK_ALIGN: u64 = 1 << 32; // 4 GiB // Offsets of `Vec`'s fields. // `Vec` is `#[repr(transparent)]` and `RawVec` is `#[repr(C)]`, so these offsets are fixed. @@ -92,7 +102,7 @@ fn generate_deserializers(consts: Constants, schema: &Schema, codegen: &Codegen) // Prelude to generated deserializer. // Defines the main `deserialize` function. - let Constants { data_pointer_pos_32, .. } = consts; + let data_pointer_pos_32 = consts.data_pointer_pos / 4; #[rustfmt::skip] let prelude = format!(" @@ -992,20 +1002,26 @@ impl DeserializeFunctionName for PointerDef { /// Constants for position of fields in buffer which deserialization starts from. #[derive(Clone, Copy)] struct Constants { - data_pointer_pos_32: u32, + /// Offset within buffer of `u32` containing position of `RawTransferData` + data_pointer_pos: u32, + /// Offset within buffer of `bool` indicating if AST is TS or JS is_ts_pos: u32, + /// Offset of `Program` in buffer, relative to position of `RawTransferData` program_offset: u32, - metadata_size: u32, + /// Size of `RawTransferData` in bytes + raw_metadata_size: u32, } /// Generate constants file. fn generate_constants(consts: Constants) -> (String, TokenStream) { - let Constants { data_pointer_pos_32, is_ts_pos, program_offset, metadata_size } = consts; + let Constants { data_pointer_pos, is_ts_pos, program_offset, raw_metadata_size } = consts; + + let data_pointer_pos_32 = data_pointer_pos / 4; #[rustfmt::skip] let js_output = format!(" - const BUFFER_SIZE = {BUFFER_SIZE}, - BUFFER_ALIGN = {BUFFER_ALIGN}, + const BUFFER_SIZE = {BLOCK_SIZE}, + BUFFER_ALIGN = {BLOCK_ALIGN}, DATA_POINTER_POS_32 = {data_pointer_pos_32}, IS_TS_FLAG_POS = {is_ts_pos}, PROGRAM_OFFSET = {program_offset}; @@ -1019,17 +1035,17 @@ fn generate_constants(consts: Constants) -> (String, TokenStream) { }}; "); - let buffer_size = number_lit(BUFFER_SIZE); - let buffer_align = number_lit(BUFFER_ALIGN); - let metadata_size = number_lit(metadata_size); + let block_size = number_lit(BLOCK_SIZE); + let block_align = number_lit(BLOCK_ALIGN); + let raw_metadata_size = number_lit(raw_metadata_size); let rust_output = quote! { #![expect(clippy::unreadable_literal)] #![allow(dead_code)] ///@@line_break - pub const BUFFER_SIZE: usize = #buffer_size; - pub const BUFFER_ALIGN: usize = #buffer_align; - pub const METADATA_SIZE: usize = #metadata_size; + pub const BLOCK_SIZE: usize = #block_size; + pub const BLOCK_ALIGN: usize = #block_align; + pub const RAW_METADATA_SIZE: usize = #raw_metadata_size; }; (js_output, rust_output) @@ -1037,12 +1053,12 @@ fn generate_constants(consts: Constants) -> (String, TokenStream) { /// Calculate constants. fn get_constants(schema: &Schema) -> Constants { - let metadata_struct = schema.type_by_name("RawTransferMetadata").as_struct().unwrap(); - let metadata_size = metadata_struct.layout_64().size; - let metadata_pos = BUFFER_SIZE - metadata_size; - let data_pointer_pos = metadata_pos + metadata_struct.field_by_name("data_offset").offset_64(); - let data_pointer_pos_32 = data_pointer_pos / 4; - let is_ts_pos = metadata_pos + metadata_struct.field_by_name("is_ts").offset_64(); + let raw_metadata_struct = schema.type_by_name("RawTransferMetadata").as_struct().unwrap(); + let raw_metadata_size = raw_metadata_struct.layout_64().size; + let raw_metadata_pos = BLOCK_SIZE - raw_metadata_size; + let data_pointer_pos = + raw_metadata_pos + raw_metadata_struct.field_by_name("data_offset").offset_64(); + let is_ts_pos = raw_metadata_pos + raw_metadata_struct.field_by_name("is_ts").offset_64(); let program_offset = schema .type_by_name("RawTransferData") @@ -1051,5 +1067,5 @@ fn get_constants(schema: &Schema) -> Constants { .field_by_name("program") .offset_64(); - Constants { data_pointer_pos_32, is_ts_pos, program_offset, metadata_size } + Constants { data_pointer_pos, is_ts_pos, program_offset, raw_metadata_size } }