Skip to content

Commit b7aa663

Browse files
committed
refactor(allocator): store allocation pointer in metadata
1 parent 0da255f commit b7aa663

File tree

9 files changed

+106
-74
lines changed

9 files changed

+106
-74
lines changed

crates/oxc_allocator/src/generated/assert_layouts.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,28 @@ use crate::*;
99

1010
#[cfg(target_pointer_width = "64")]
1111
const _: () = {
12-
// Padding: 2 bytes
13-
assert!(size_of::<RawTransferMetadata2>() == 16);
14-
assert!(align_of::<RawTransferMetadata2>() == 4);
15-
assert!(offset_of!(RawTransferMetadata2, data_offset) == 0);
16-
assert!(offset_of!(RawTransferMetadata2, is_ts) == 12);
17-
assert!(offset_of!(RawTransferMetadata2, id) == 4);
18-
assert!(offset_of!(RawTransferMetadata2, can_be_freed) == 13);
19-
assert!(offset_of!(RawTransferMetadata2, _padding) == 8);
12+
// Padding: 6 bytes
13+
assert!(size_of::<RawTransferMetadata2>() == 32);
14+
assert!(align_of::<RawTransferMetadata2>() == 8);
15+
assert!(offset_of!(RawTransferMetadata2, data_offset) == 16);
16+
assert!(offset_of!(RawTransferMetadata2, is_ts) == 24);
17+
assert!(offset_of!(RawTransferMetadata2, id) == 20);
18+
assert!(offset_of!(RawTransferMetadata2, can_be_freed) == 25);
19+
assert!(offset_of!(RawTransferMetadata2, alloc_ptr) == 8);
20+
assert!(offset_of!(RawTransferMetadata2, _padding) == 0);
2021
};
2122

2223
#[cfg(target_pointer_width = "32")]
2324
const _: () = {
2425
// Padding: 2 bytes
25-
assert!(size_of::<RawTransferMetadata2>() == 16);
26-
assert!(align_of::<RawTransferMetadata2>() == 4);
27-
assert!(offset_of!(RawTransferMetadata2, data_offset) == 0);
28-
assert!(offset_of!(RawTransferMetadata2, is_ts) == 12);
29-
assert!(offset_of!(RawTransferMetadata2, id) == 4);
30-
assert!(offset_of!(RawTransferMetadata2, can_be_freed) == 13);
31-
assert!(offset_of!(RawTransferMetadata2, _padding) == 8);
26+
assert!(size_of::<RawTransferMetadata2>() == 24);
27+
assert!(align_of::<RawTransferMetadata2>() == 8);
28+
assert!(offset_of!(RawTransferMetadata2, data_offset) == 12);
29+
assert!(offset_of!(RawTransferMetadata2, is_ts) == 20);
30+
assert!(offset_of!(RawTransferMetadata2, id) == 16);
31+
assert!(offset_of!(RawTransferMetadata2, can_be_freed) == 21);
32+
assert!(offset_of!(RawTransferMetadata2, alloc_ptr) == 8);
33+
assert!(offset_of!(RawTransferMetadata2, _padding) == 0);
3234
};
3335

3436
#[cfg(not(any(target_pointer_width = "64", target_pointer_width = "32")))]

crates/oxc_allocator/src/pool_fixed_size.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,25 @@ pub struct RawTransferMetadata2 {
125125
/// * Also be set to `true` if `FixedSizeAllocator` is dropped on Rust side.
126126
/// Memory will be freed in finalizer when JS garbage collector collects the buffer.
127127
pub(crate) can_be_freed: AtomicBool,
128-
/// Padding to pad struct to size 16.
129-
pub(crate) _padding: u32,
128+
/// Pointer to start of original allocation backing the `Allocator`.
129+
pub(crate) alloc_ptr: NonNull<u8>,
130+
/// Padding to pad struct to size 32.
131+
pub(crate) _padding: u64,
130132
}
131133
use RawTransferMetadata2 as RawTransferMetadata;
132134

133135
const METADATA_SIZE: usize = size_of::<RawTransferMetadata>();
134136

135137
impl RawTransferMetadata {
136-
fn new(id: u32) -> Self {
137-
Self { data_offset: 0, is_ts: false, id, can_be_freed: AtomicBool::new(true), _padding: 0 }
138+
fn new(id: u32, alloc_ptr: NonNull<u8>) -> Self {
139+
Self {
140+
data_offset: 0,
141+
is_ts: false,
142+
id,
143+
can_be_freed: AtomicBool::new(true),
144+
alloc_ptr,
145+
_padding: 0,
146+
}
138147
}
139148
}
140149

@@ -175,8 +184,6 @@ const ALLOC_LAYOUT: Layout = match Layout::from_size_align(ALLOC_SIZE, ALLOC_ALI
175184
pub struct FixedSizeAllocator {
176185
/// `Allocator` which utilizes part of the original allocation
177186
allocator: ManuallyDrop<Allocator>,
178-
/// Pointer to start of original allocation
179-
alloc_ptr: NonNull<u8>,
180187
}
181188

182189
impl FixedSizeAllocator {
@@ -215,14 +222,14 @@ impl FixedSizeAllocator {
215222
let allocator = unsafe { Allocator::from_raw_parts(chunk_ptr, CHUNK_SIZE) };
216223

217224
// Store metadata after allocator chunk
218-
let metadata = RawTransferMetadata::new(id);
225+
let metadata = RawTransferMetadata::new(id, alloc_ptr);
219226
// SAFETY: `chunk_ptr` is at least `BUFFER_SIZE` bytes from the end of the allocation.
220227
// `CHUNK_SIZE` had the size of `RawTransferMetadata` subtracted from it.
221228
// So there is space within the allocation for `RawTransferMetadata` after the `Allocator`'s chunk.
222229
unsafe { chunk_ptr.add(CHUNK_SIZE).cast::<RawTransferMetadata>().write(metadata) };
223230

224231
// Store pointer to original allocation, so it can be used to deallocate in `drop`
225-
Self { allocator: ManuallyDrop::new(allocator), alloc_ptr }
232+
Self { allocator: ManuallyDrop::new(allocator) }
226233
}
227234

228235
/// Reset this [`FixedSizeAllocator`].
@@ -245,8 +252,17 @@ impl FixedSizeAllocator {
245252

246253
impl Drop for FixedSizeAllocator {
247254
fn drop(&mut self) {
255+
// Get pointer to start of allocation backing this `FixedSizeAllocator`
256+
let alloc_ptr = {
257+
let metadata_ptr = self.allocator.end_ptr().cast::<RawTransferMetadata>();
258+
// SAFETY: `FixedSizeAllocator` is being dropped, so no other references to data in it may exist.
259+
// `FixedSizeAllocator::new` wrote `RawTransferMetadata` to the location pointed to by `end_ptr`.
260+
let metadata = unsafe { metadata_ptr.as_ref() };
261+
metadata.alloc_ptr
262+
};
263+
248264
// SAFETY: Originally allocated from `System` allocator at `alloc_ptr`, with layout `ALLOC_LAYOUT`
249-
unsafe { System.dealloc(self.alloc_ptr.as_ptr(), ALLOC_LAYOUT) }
265+
unsafe { System.dealloc(alloc_ptr.as_ptr(), ALLOC_LAYOUT) }
250266
}
251267
}
252268

crates/oxc_ast_macros/src/generated/structs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub static STRUCTS: phf::Map<&'static str, StructDetails> = ::phf::Map {
135135
("Decorator", StructDetails { field_order: None }),
136136
("CharacterClass", StructDetails { field_order: Some(&[0, 2, 3, 4, 1]) }),
137137
("TemplateElementValue", StructDetails { field_order: None }),
138-
("RawTransferMetadata", StructDetails { field_order: Some(&[0, 3, 1, 4, 2]) }),
138+
("RawTransferMetadata", StructDetails { field_order: Some(&[2, 4, 3, 5, 1, 0]) }),
139139
("TSTypeParameter", StructDetails { field_order: None }),
140140
("SourceType", StructDetails { field_order: None }),
141141
("ErrorLabel", StructDetails { field_order: Some(&[1, 0]) }),
@@ -266,7 +266,7 @@ pub static STRUCTS: phf::Map<&'static str, StructDetails> = ::phf::Map {
266266
("ImportAttribute", StructDetails { field_order: None }),
267267
("TSConditionalType", StructDetails { field_order: None }),
268268
("TSNamespaceExportDeclaration", StructDetails { field_order: None }),
269-
("RawTransferMetadata2", StructDetails { field_order: Some(&[0, 3, 1, 4, 2]) }),
269+
("RawTransferMetadata2", StructDetails { field_order: Some(&[2, 4, 3, 5, 1, 0]) }),
270270
("AssignmentTargetWithDefault", StructDetails { field_order: None }),
271271
("RegExpLiteral", StructDetails { field_order: None }),
272272
("CapturingGroup", StructDetails { field_order: None }),

napi/parser/generated/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
const BUFFER_SIZE = 2147483632,
55
BUFFER_ALIGN = 4294967296,
66
DATA_POINTER_POS_32 = 536870904,
7-
IS_TS_FLAG_POS = 2147483628,
7+
IS_TS_FLAG_POS = 2147483624,
88
PROGRAM_OFFSET = 0;
99

1010
module.exports = {

napi/parser/generated/deserialize/js.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4028,6 +4028,15 @@ function deserializeBool(pos) {
40284028
return uint8[pos] === 1;
40294029
}
40304030

4031+
function deserializeU8(pos) {
4032+
return uint8[pos];
4033+
}
4034+
4035+
function deserializeU64(pos) {
4036+
const pos32 = pos >> 2;
4037+
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
4038+
}
4039+
40314040
function deserializeStr(pos) {
40324041
const pos32 = pos >> 2,
40334042
len = uint32[pos32 + 2];
@@ -4859,10 +4868,6 @@ function deserializeF64(pos) {
48594868
return float64[pos >> 3];
48604869
}
48614870

4862-
function deserializeU8(pos) {
4863-
return uint8[pos];
4864-
}
4865-
48664871
function deserializeBoxJSXOpeningElement(pos) {
48674872
return deserializeJSXOpeningElement(uint32[pos >> 2]);
48684873
}
@@ -5243,11 +5248,6 @@ function deserializeOptionNameSpan(pos) {
52435248
return deserializeNameSpan(pos);
52445249
}
52455250

5246-
function deserializeU64(pos) {
5247-
const pos32 = pos >> 2;
5248-
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
5249-
}
5250-
52515251
function deserializeOptionU64(pos) {
52525252
if (uint8[pos] === 0) return null;
52535253
return deserializeU64(pos + 8);

napi/parser/generated/deserialize/ts.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4159,6 +4159,15 @@ function deserializeBool(pos) {
41594159
return uint8[pos] === 1;
41604160
}
41614161

4162+
function deserializeU8(pos) {
4163+
return uint8[pos];
4164+
}
4165+
4166+
function deserializeU64(pos) {
4167+
const pos32 = pos >> 2;
4168+
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
4169+
}
4170+
41624171
function deserializeStr(pos) {
41634172
const pos32 = pos >> 2,
41644173
len = uint32[pos32 + 2];
@@ -4990,10 +4999,6 @@ function deserializeF64(pos) {
49904999
return float64[pos >> 3];
49915000
}
49925001

4993-
function deserializeU8(pos) {
4994-
return uint8[pos];
4995-
}
4996-
49975002
function deserializeBoxJSXOpeningElement(pos) {
49985003
return deserializeJSXOpeningElement(uint32[pos >> 2]);
49995004
}
@@ -5374,11 +5379,6 @@ function deserializeOptionNameSpan(pos) {
53745379
return deserializeNameSpan(pos);
53755380
}
53765381

5377-
function deserializeU64(pos) {
5378-
const pos32 = pos >> 2;
5379-
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
5380-
}
5381-
53825382
function deserializeOptionU64(pos) {
53835383
if (uint8[pos] === 0) return null;
53845384
return deserializeU64(pos + 8);

napi/parser/generated/lazy/constructors.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12480,6 +12480,16 @@ function constructBool(pos, ast) {
1248012480
return ast.buffer[pos] === 1;
1248112481
}
1248212482

12483+
function constructU8(pos, ast) {
12484+
return ast.buffer[pos];
12485+
}
12486+
12487+
function constructU64(pos, ast) {
12488+
const { uint32 } = ast.buffer,
12489+
pos32 = pos >> 2;
12490+
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
12491+
}
12492+
1248312493
function constructStr(pos, ast) {
1248412494
const pos32 = pos >> 2,
1248512495
{ buffer } = ast,
@@ -13357,10 +13367,6 @@ function constructF64(pos, ast) {
1335713367
return ast.buffer.float64[pos >> 3];
1335813368
}
1335913369

13360-
function constructU8(pos, ast) {
13361-
return ast.buffer[pos];
13362-
}
13363-
1336413370
function constructBoxJSXOpeningElement(pos, ast) {
1336513371
return new JSXOpeningElement(ast.buffer.uint32[pos >> 2], ast);
1336613372
}
@@ -13757,12 +13763,6 @@ function constructOptionNameSpan(pos, ast) {
1375713763
return new NameSpan(pos, ast);
1375813764
}
1375913765

13760-
function constructU64(pos, ast) {
13761-
const { uint32 } = ast.buffer,
13762-
pos32 = pos >> 2;
13763-
return uint32[pos32] + uint32[pos32 + 1] * 4294967296;
13764-
}
13765-
1376613766
function constructOptionU64(pos, ast) {
1376713767
if (ast.buffer[pos] === 0) return null;
1376813768
return constructU64(pos + 8, ast);

napi/parser/src/generated/assert_layouts.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ const _: () = {
1717
assert!(offset_of!(RawTransferData, module) == 152);
1818
assert!(offset_of!(RawTransferData, errors) == 256);
1919

20-
// Padding: 2 bytes
21-
assert!(size_of::<RawTransferMetadata>() == 16);
22-
assert!(align_of::<RawTransferMetadata>() == 4);
23-
assert!(offset_of!(RawTransferMetadata, data_offset) == 0);
24-
assert!(offset_of!(RawTransferMetadata, is_ts) == 12);
25-
assert!(offset_of!(RawTransferMetadata, id) == 4);
26-
assert!(offset_of!(RawTransferMetadata, can_be_freed) == 13);
27-
assert!(offset_of!(RawTransferMetadata, _padding) == 8);
20+
// Padding: 6 bytes
21+
assert!(size_of::<RawTransferMetadata>() == 32);
22+
assert!(align_of::<RawTransferMetadata>() == 8);
23+
assert!(offset_of!(RawTransferMetadata, data_offset) == 16);
24+
assert!(offset_of!(RawTransferMetadata, is_ts) == 24);
25+
assert!(offset_of!(RawTransferMetadata, id) == 20);
26+
assert!(offset_of!(RawTransferMetadata, can_be_freed) == 25);
27+
assert!(offset_of!(RawTransferMetadata, alloc_ptr) == 8);
28+
assert!(offset_of!(RawTransferMetadata, _padding) == 0);
2829

2930
// Padding: 7 bytes
3031
assert!(size_of::<Error>() == 80);
@@ -78,13 +79,14 @@ const _: () = {
7879
assert!(offset_of!(RawTransferData, errors) == 172);
7980

8081
// Padding: 2 bytes
81-
assert!(size_of::<RawTransferMetadata>() == 16);
82-
assert!(align_of::<RawTransferMetadata>() == 4);
83-
assert!(offset_of!(RawTransferMetadata, data_offset) == 0);
84-
assert!(offset_of!(RawTransferMetadata, is_ts) == 12);
85-
assert!(offset_of!(RawTransferMetadata, id) == 4);
86-
assert!(offset_of!(RawTransferMetadata, can_be_freed) == 13);
87-
assert!(offset_of!(RawTransferMetadata, _padding) == 8);
82+
assert!(size_of::<RawTransferMetadata>() == 24);
83+
assert!(align_of::<RawTransferMetadata>() == 8);
84+
assert!(offset_of!(RawTransferMetadata, data_offset) == 12);
85+
assert!(offset_of!(RawTransferMetadata, is_ts) == 20);
86+
assert!(offset_of!(RawTransferMetadata, id) == 16);
87+
assert!(offset_of!(RawTransferMetadata, can_be_freed) == 21);
88+
assert!(offset_of!(RawTransferMetadata, alloc_ptr) == 8);
89+
assert!(offset_of!(RawTransferMetadata, _padding) == 0);
8890

8991
// Padding: 3 bytes
9092
assert!(size_of::<Error>() == 44);

napi/parser/src/raw_transfer_types.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#![cfg_attr(not(all(target_pointer_width = "64", target_endian = "little")), expect(dead_code))]
22

3-
use std::sync::{Arc, atomic::AtomicBool};
3+
use std::{
4+
ptr::NonNull,
5+
sync::{Arc, atomic::AtomicBool},
6+
};
47

58
use rustc_hash::FxHashMap;
69

@@ -40,13 +43,22 @@ pub struct RawTransferMetadata {
4043
pub(crate) id: u32,
4144
/// Not used in this implementation. Only used by `oxc_allocator`.
4245
pub(crate) can_be_freed: AtomicBool,
43-
/// Padding to pad struct to size 16.
44-
pub(crate) _padding: u32,
46+
/// Not used in this implementation. Only used by `oxc_allocator`.
47+
pub(crate) alloc_ptr: NonNull<u8>,
48+
/// Padding to pad struct to size 32.
49+
pub(crate) _padding: u64,
4550
}
4651

4752
impl RawTransferMetadata {
4853
pub fn new(data_offset: u32, is_ts: bool) -> Self {
49-
Self { data_offset, is_ts, id: 0, can_be_freed: AtomicBool::new(false), _padding: 0 }
54+
Self {
55+
data_offset,
56+
is_ts,
57+
id: 0,
58+
can_be_freed: AtomicBool::new(false),
59+
alloc_ptr: NonNull::dangling(),
60+
_padding: 0,
61+
}
5062
}
5163
}
5264

0 commit comments

Comments
 (0)