Skip to content

Commit 3e8c580

Browse files
autofix-ci[bot]camchenry
authored andcommitted
[autofix.ci] apply automated fixes
1 parent 52bbae3 commit 3e8c580

File tree

8 files changed

+164
-93
lines changed

8 files changed

+164
-93
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,8 @@ jobs:
314314
if: steps.filter.outputs.src == 'true'
315315
run: |
316316
cargo allocs
317-
git diff --exit-code
317+
git diff --exit-code ||
318+
(echo 'Allocations have changed. Run the `cargo allocs` command to update the allocation snapshot, otherwise please fix the regression.' && exit 1)
318319
319320
ast_changes:
320321
name: AST Changes

crates/oxc_allocator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ disable_fixed_size = []
4141
from_raw_parts = []
4242
serialize = ["dep:serde", "oxc_estree/serialize"]
4343
track_allocations = []
44+
disable_track_allocations = []

crates/oxc_allocator/src/alloc.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ impl Alloc for Bump {
9595
/// Panics if reserving space for `layout` fails.
9696
#[inline(always)]
9797
fn alloc(&self, layout: Layout) -> NonNull<u8> {
98+
// SAFETY: We only use `Bump` inside of `Allocator` in oxc, so the `self` reference should
99+
// also be pointing to a valid `Allocator` struct, which we can use for finding the stats fields.
100+
// This will go away when we add a custom allocator to oxc.
101+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
102+
unsafe {
103+
use crate::Allocator;
104+
use std::{
105+
mem::offset_of,
106+
ptr,
107+
sync::atomic::{AtomicUsize, Ordering},
108+
};
109+
#[expect(clippy::cast_possible_wrap)]
110+
const OFFSET: isize = (offset_of!(Allocator, num_alloc) as isize)
111+
- (offset_of!(Allocator, bump) as isize);
112+
let num_alloc_ptr = ptr::from_ref(self).byte_offset(OFFSET).cast::<AtomicUsize>();
113+
let num_alloc = num_alloc_ptr.as_ref().unwrap_unchecked();
114+
num_alloc.fetch_add(1, Ordering::SeqCst);
115+
}
116+
98117
self.alloc_layout(layout)
99118
}
100119

@@ -133,6 +152,25 @@ impl Alloc for Bump {
133152
/// Panics / aborts if reserving space for `new_layout` fails.
134153
#[inline(always)]
135154
unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> NonNull<u8> {
155+
// SAFETY: We only use `Bump` inside of `Allocator` in oxc, so the `self` reference should
156+
// also be pointing to a valid `Allocator` struct, which we can use for finding the stats fields.
157+
// This will go away when we add a custom allocator to oxc.
158+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
159+
unsafe {
160+
use crate::Allocator;
161+
use std::{
162+
mem::offset_of,
163+
ptr,
164+
sync::atomic::{AtomicUsize, Ordering},
165+
};
166+
#[expect(clippy::cast_possible_wrap)]
167+
const OFFSET: isize = (offset_of!(Allocator, num_realloc) as isize)
168+
- (offset_of!(Allocator, bump) as isize);
169+
let num_realloc_ptr = ptr::from_ref(self).byte_offset(OFFSET).cast::<AtomicUsize>();
170+
let num_realloc = num_realloc_ptr.as_ref().unwrap_unchecked();
171+
num_realloc.fetch_add(1, Ordering::SeqCst);
172+
}
173+
136174
// SAFETY: Safety requirements of `Allocator::grow` are the same as for this method
137175
let res = unsafe { Allocator::grow(&self, ptr, old_layout, new_layout) };
138176
match res {

crates/oxc_allocator/src/allocator.rs

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ use bumpalo::Bump;
88

99
use oxc_data_structures::assert_unchecked;
1010

11-
#[cfg(feature = "track_allocations")]
12-
use std::sync::atomic::{
13-
AtomicUsize,
14-
Ordering::{Relaxed, SeqCst},
15-
};
16-
#[cfg(feature = "track_allocations")]
17-
static NUM_ALLOC: AtomicUsize = AtomicUsize::new(0);
18-
1911
/// A bump-allocated memory arena.
2012
///
2113
/// # Anatomy of an Allocator
@@ -222,7 +214,20 @@ static NUM_ALLOC: AtomicUsize = AtomicUsize::new(0);
222214
/// [`HashMap::new_in`]: crate::HashMap::new_in
223215
#[derive(Default)]
224216
pub struct Allocator {
217+
#[cfg(not(all(feature = "track_allocations", not(feature = "disable_track_allocations"))))]
225218
bump: Bump,
219+
// NOTE: We need to expose `bump` publicly here for calculating its field offset in memory.
220+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
221+
#[doc(hidden)]
222+
pub bump: Bump,
223+
/// Used to track the total number of allocations made in this allocator when the `track_allocations` feature is enabled.
224+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
225+
#[doc(hidden)]
226+
pub num_alloc: std::sync::atomic::AtomicUsize,
227+
/// Used to track the total number of re-allocations made in this allocator when the `track_allocations` feature is enabled.
228+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
229+
#[doc(hidden)]
230+
pub num_realloc: std::sync::atomic::AtomicUsize,
226231
}
227232

228233
impl Allocator {
@@ -249,7 +254,13 @@ impl Allocator {
249254
#[expect(clippy::inline_always)]
250255
#[inline(always)]
251256
pub fn new() -> Self {
252-
Self { bump: Bump::new() }
257+
Self {
258+
bump: Bump::new(),
259+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
260+
num_alloc: std::sync::atomic::AtomicUsize::new(0),
261+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
262+
num_realloc: std::sync::atomic::AtomicUsize::new(0),
263+
}
253264
}
254265

255266
/// Create a new [`Allocator`] with specified capacity.
@@ -260,7 +271,13 @@ impl Allocator {
260271
#[expect(clippy::inline_always)]
261272
#[inline(always)]
262273
pub fn with_capacity(capacity: usize) -> Self {
263-
Self { bump: Bump::with_capacity(capacity) }
274+
Self {
275+
bump: Bump::with_capacity(capacity),
276+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
277+
num_alloc: std::sync::atomic::AtomicUsize::new(0),
278+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
279+
num_realloc: std::sync::atomic::AtomicUsize::new(0),
280+
}
264281
}
265282

266283
/// Allocate an object in this [`Allocator`] and return an exclusive reference to it.
@@ -284,10 +301,9 @@ impl Allocator {
284301
pub fn alloc<T>(&self, val: T) -> &mut T {
285302
const { assert!(!std::mem::needs_drop::<T>(), "Cannot allocate Drop type in arena") };
286303

287-
#[cfg(feature = "track_allocations")]
288-
{
289-
NUM_ALLOC.fetch_add(1, Relaxed);
290-
}
304+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
305+
self.num_alloc.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
306+
291307
self.bump.alloc(val)
292308
}
293309

@@ -309,10 +325,9 @@ impl Allocator {
309325
#[expect(clippy::inline_always)]
310326
#[inline(always)]
311327
pub fn alloc_str<'alloc>(&'alloc self, src: &str) -> &'alloc str {
312-
#[cfg(feature = "track_allocations")]
313-
{
314-
NUM_ALLOC.fetch_add(1, Relaxed);
315-
}
328+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
329+
self.num_alloc.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
330+
316331
self.bump.alloc_str(src)
317332
}
318333

@@ -333,10 +348,9 @@ impl Allocator {
333348
#[expect(clippy::inline_always)]
334349
#[inline(always)]
335350
pub fn alloc_slice_copy<T: Copy>(&self, src: &[T]) -> &mut [T] {
336-
#[cfg(feature = "track_allocations")]
337-
{
338-
NUM_ALLOC.fetch_add(1, Relaxed);
339-
}
351+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
352+
self.num_alloc.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
353+
340354
self.bump.alloc_slice_copy(src)
341355
}
342356

@@ -349,10 +363,9 @@ impl Allocator {
349363
///
350364
/// Panics if reserving space matching `layout` fails.
351365
pub fn alloc_layout(&self, layout: Layout) -> NonNull<u8> {
352-
#[cfg(feature = "track_allocations")]
353-
{
354-
NUM_ALLOC.fetch_add(1, Relaxed);
355-
}
366+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
367+
self.num_alloc.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
368+
356369
self.bump.alloc_layout(layout)
357370
}
358371

@@ -403,10 +416,8 @@ impl Allocator {
403416
"attempted to create a string longer than `isize::MAX` bytes"
404417
);
405418

406-
#[cfg(feature = "track_allocations")]
407-
{
408-
NUM_ALLOC.fetch_add(1, Relaxed);
409-
}
419+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
420+
self.num_alloc.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
410421

411422
// Create actual `&str` in a separate function, to ensure that `alloc_concat_strs_array`
412423
// is inlined, so that compiler has knowledge to remove the overflow checks above.
@@ -500,10 +511,12 @@ impl Allocator {
500511
#[expect(clippy::inline_always)]
501512
#[inline(always)]
502513
pub fn reset(&mut self) {
503-
#[cfg(feature = "track_allocations")]
514+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
504515
{
505-
NUM_ALLOC.store(0, SeqCst);
516+
self.num_alloc.store(0, std::sync::atomic::Ordering::SeqCst);
517+
self.num_realloc.store(0, std::sync::atomic::Ordering::SeqCst);
506518
}
519+
507520
self.bump.reset();
508521
}
509522

@@ -604,12 +617,6 @@ impl Allocator {
604617
bytes
605618
}
606619

607-
/// Returns the total number of allocations that have been made in this [`Allocator`] instance.
608-
#[cfg(feature = "track_allocations")]
609-
pub fn num_alloc() -> usize {
610-
NUM_ALLOC.load(SeqCst)
611-
}
612-
613620
/// Get inner [`bumpalo::Bump`].
614621
///
615622
/// This method is not public. We don't want to expose `Bump` to user.
@@ -631,7 +638,13 @@ impl Allocator {
631638
#[expect(clippy::inline_always)]
632639
#[inline(always)]
633640
pub(crate) fn from_bump(bump: Bump) -> Self {
634-
Self { bump }
641+
Self {
642+
bump,
643+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
644+
num_alloc: std::sync::atomic::AtomicUsize::new(0),
645+
#[cfg(all(feature = "track_allocations", not(feature = "disable_track_allocations")))]
646+
num_realloc: std::sync::atomic::AtomicUsize::new(0),
647+
}
635648
}
636649
}
637650

crates/oxc_parser/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,3 @@ default = ["regular_expression"]
4848
regular_expression = ["dep:oxc_regular_expression"]
4949
# Expose Lexer for benchmarks
5050
benchmarking = []
51-
# Enable tracking arena and system allocations
52-
track_allocations = ["oxc_allocator/track_allocations"]

tasks/allocs/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ oxc_tasks_common = { workspace = true }
2525
humansize = { workspace = true }
2626
mimalloc-safe = { workspace = true }
2727

28+
[features]
29+
# Sentinel flag that should only get enabled if we're running under `--all-features`
30+
is_all_features = []

tasks/allocs/allocs_parser.snap

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
File | File size | Sys allocs | Sys bytes | Sys ratio | Arena allocs | Arena bytes | Arena ratio |
2-
-------------------------------------------------------------------------------------------------------------------------------------
3-
checker.ts | 2.92 MB | 10176 | 17.60 MB | 6.02 | 228746 | 12.47 MB | 4.27
4-
cal.com.tsx | 1.06 MB | 2209 | 279.52 kB | 0.26 | 113688 | 7.79 MB | 7.37
5-
RadixUIAdoptionSection.jsx | 2.52 kB | 4 | 724 B | 0.29 | 310 | 19.10 kB | 7.58
6-
pdf.mjs | 567.30 kB | 688 | 55.86 kB | 0.10 | 77969 | 4.31 MB | 7.59
7-
antd.js | 4.12 MB | 6862 | 50.83 MB | 12.34 | 425919 | 25.57 MB | 6.21
8-
binder.ts | 193.08 kB | 540 | 43.75 kB | 0.23 | 14376 | 873.70 kB | 4.53
1+
File | File size || Sys allocs | Sys reallocs || Arena allocs | Arena reallocs | Arena bytes
2+
--------------------------------------------------------------------------------------------------------------------------------------------------
3+
checker.ts | 2.92 MB || 10161 | 21 slow / 21 || 268665 | 23341 | 12.42 MB
4+
5+
cal.com.tsx | 1.06 MB || 2209 | 54 slow / 54 || 138188 | 13712 | 7.79 MB
6+
7+
RadixUIAdoptionSection.jsx | 2.52 kB || 4 | 0 slow / 0 || 365 | 66 | 19.10 kB
8+
9+
pdf.mjs | 567.30 kB || 688 | 71 slow / 71 || 90678 | 8148 | 4.31 MB
10+
11+
antd.js | 4.12 MB || 6860 | 282 slow / 282 || 509752 | 55282 | 25.57 MB
12+
13+
binder.ts | 193.08 kB || 540 | 7 slow / 7 || 16807 | 1475 | 873.70 kB
14+

0 commit comments

Comments
 (0)