@@ -13,8 +13,8 @@ use parking_lot::Mutex;
13
13
#[ cfg( not( feature = "sync" ) ) ]
14
14
use std:: cell:: RefCell ;
15
15
16
- use crate :: layout:: { GcHeader } ;
17
16
use zerogc_context:: utils:: AtomicCell ;
17
+ use zerogc:: format:: { ObjectFormat , OpenAllocObjectFormat } ;
18
18
19
19
/// The minimum size of supported memory (in words)
20
20
///
@@ -26,11 +26,18 @@ pub const MINIMUM_WORDS: usize = 2;
26
26
/// Past this we have to fallback to the global allocator
27
27
pub const MAXIMUM_SMALL_WORDS : usize = 32 ;
28
28
/// The alignment of elements in the arena
29
- pub const ARENA_ELEMENT_ALIGN : usize = mem:: align_of :: < GcHeader > ( ) ;
29
+ pub const ARENA_ELEMENT_ALIGN : usize = ARENA_HEADER_LAYOUT . align ( ) ;
30
+ /// The size of headers in the arena
31
+ ///
32
+ /// This is the same regardless of the underlying object format
33
+ const ARENA_HEADER_LAYOUT : Layout = Layout :: new :: < DummyGcHeader > ( ) ;
34
+
35
+ use super :: DummyGcHeader ;
36
+ use crate :: { RawSimpleCollector , RawObjectFormat } ;
30
37
31
38
#[ inline]
32
39
pub const fn small_object_size < T > ( ) -> usize {
33
- let header_layout = Layout :: new :: < GcHeader > ( ) ;
40
+ let header_layout = ARENA_HEADER_LAYOUT ;
34
41
header_layout. size ( ) + header_layout
35
42
. padding_needed_for ( std:: mem:: align_of :: < T > ( ) )
36
43
+ mem:: size_of :: < T > ( )
@@ -114,7 +121,7 @@ pub struct FreeSlot {
114
121
#[ repr( C ) ]
115
122
pub ( crate ) union MaybeFreeSlot {
116
123
pub free : FreeSlot ,
117
- pub header : GcHeader ,
124
+ pub header : DummyGcHeader ,
118
125
}
119
126
120
127
impl MaybeFreeSlot {
@@ -192,7 +199,7 @@ impl ArenaState {
192
199
self . current_chunk . store ( ptr) ;
193
200
}
194
201
#[ inline]
195
- fn alloc ( & self , element_size : usize ) -> NonNull < GcHeader > {
202
+ fn alloc ( & self , element_size : usize ) -> NonNull < DummyGcHeader > {
196
203
unsafe {
197
204
let chunk = & * self . current_chunk ( ) . as_ptr ( ) ;
198
205
match chunk. try_alloc ( element_size) {
@@ -204,7 +211,7 @@ impl ArenaState {
204
211
205
212
#[ cold]
206
213
#[ inline( never) ]
207
- fn alloc_fallback ( & self , element_size : usize ) -> NonNull < GcHeader > {
214
+ fn alloc_fallback ( & self , element_size : usize ) -> NonNull < DummyGcHeader > {
208
215
let mut chunks = self . lock_chunks ( ) ;
209
216
// Now that we hold the lock, check the current chunk again
210
217
unsafe {
@@ -220,7 +227,7 @@ impl ArenaState {
220
227
self . force_current_chunk ( NonNull :: from ( & * * chunks. last ( ) . unwrap ( ) ) ) ;
221
228
self . current_chunk ( ) . as_ref ( )
222
229
. try_alloc ( element_size) . unwrap ( )
223
- . cast :: < GcHeader > ( )
230
+ . cast :: < DummyGcHeader > ( )
224
231
}
225
232
}
226
233
}
@@ -242,7 +249,7 @@ impl FreeList {
242
249
self . next . store ( next)
243
250
}
244
251
#[ inline]
245
- fn take_free ( & self ) -> Option < NonNull < GcHeader > > {
252
+ fn take_free ( & self ) -> Option < NonNull < DummyGcHeader > > {
246
253
loop {
247
254
let next_free = match self . next . load ( ) {
248
255
Some ( free) => free,
@@ -264,25 +271,27 @@ impl FreeList {
264
271
}
265
272
}
266
273
267
- pub struct SmallArena {
274
+ pub struct SmallArena < Fmt : RawObjectFormat > {
268
275
pub ( crate ) element_size : usize ,
269
276
state : ArenaState ,
270
- pub ( crate ) free : FreeList
277
+ pub ( crate ) free : FreeList ,
278
+ format : & ' static Fmt
271
279
}
272
- impl SmallArena {
280
+ impl < Fmt : RawObjectFormat > SmallArena < Fmt > {
273
281
#[ cold] // Initialization is the slow path
274
- fn with_words ( num_words : usize ) -> SmallArena {
282
+ fn with_words ( format : & ' static Fmt , num_words : usize ) -> SmallArena < Fmt > {
275
283
assert ! ( num_words >= MINIMUM_WORDS ) ;
276
284
let element_size = num_words * mem:: size_of :: < usize > ( ) ;
277
285
assert ! ( INITIAL_SIZE >= element_size * 2 ) ;
278
286
let chunks = vec ! [ Chunk :: alloc( INITIAL_SIZE ) ] ;
279
287
SmallArena {
280
288
state : ArenaState :: new ( chunks) ,
281
289
element_size, free : Default :: default ( ) ,
290
+ format
282
291
}
283
292
}
284
293
#[ inline]
285
- pub ( crate ) fn alloc ( & self ) -> NonNull < GcHeader > {
294
+ pub ( crate ) fn alloc ( & self ) -> NonNull < DummyGcHeader > {
286
295
// Check the free list
287
296
if let Some ( free) = self . free . take_free ( ) {
288
297
free
@@ -303,11 +312,11 @@ impl SmallArena {
303
312
}
304
313
}
305
314
macro_rules! arena_match {
306
- ( $arenas: expr, $target: ident, max = $max: expr; $( $size: pat => $num_words: literal @ $idx: expr) ,* ) => {
315
+ ( $format : expr , $ arenas: expr, $target: ident, max = $max: expr; $( $size: pat => $num_words: literal @ $idx: expr) ,* ) => {
307
316
Some ( match $target {
308
317
$( $size => $arenas[ $idx] . get_or_init( || {
309
318
assert_eq!( SMALL_ARENA_SIZES [ $idx] , $num_words) ;
310
- SmallArena :: with_words( $num_words)
319
+ SmallArena :: with_words( $format , $ num_words)
311
320
} ) , ) *
312
321
_ => {
313
322
assert!( $target > $max) ;
@@ -321,35 +330,35 @@ const SMALL_ARENA_SIZES: [usize; NUM_SMALL_ARENAS] = [
321
330
10 , 12 , 14 , 16 ,
322
331
20 , 24 , 28 , 32
323
332
] ;
324
- pub struct SmallArenaList {
333
+ pub struct SmallArenaList < Fmt : RawObjectFormat > {
325
334
// NOTE: Internally boxed to avoid bloating main struct
326
- arenas : Box < [ OnceCell < SmallArena > ; NUM_SMALL_ARENAS ] >
335
+ arenas : Box < [ OnceCell < SmallArena < Fmt > > ; NUM_SMALL_ARENAS ] >
327
336
}
328
- impl SmallArenaList {
337
+ impl < Fmt : RawObjectFormat > SmallArenaList < Fmt > {
329
338
pub fn new ( ) -> Self {
330
339
// NOTE: Why does writing arrays have to be so difficult:?
331
340
unsafe {
332
341
let mut arenas: Box < [
333
- MaybeUninit < OnceCell < SmallArena > > ;
342
+ MaybeUninit < OnceCell < SmallArena < Fmt > > > ;
334
343
NUM_SMALL_ARENAS
335
344
] > = Box :: new_uninit ( ) . assume_init ( ) ;
336
345
for i in 0 ..NUM_SMALL_ARENAS {
337
346
arenas[ i] . as_mut_ptr ( ) . write ( OnceCell :: new ( ) ) ;
338
347
}
339
348
SmallArenaList {
340
- // NOTE: This is done becuase I want to explicitly specifiy types
349
+ // NOTE: This is done because I want to explicitly specify types
341
350
arenas : mem:: transmute :: <
342
- Box < [ MaybeUninit < OnceCell < SmallArena > > ; NUM_SMALL_ARENAS ] > ,
343
- Box < [ OnceCell < SmallArena > ; NUM_SMALL_ARENAS ] >
351
+ Box < [ MaybeUninit < OnceCell < SmallArena < Fmt > > > ; NUM_SMALL_ARENAS ] > ,
352
+ Box < [ OnceCell < SmallArena < Fmt > > ; NUM_SMALL_ARENAS ] >
344
353
> ( arenas)
345
354
}
346
355
}
347
356
}
348
- pub fn iter ( & self ) -> impl Iterator < Item =& SmallArena > + ' _ {
357
+ pub fn iter ( & self ) -> impl Iterator < Item =& SmallArena < Fmt > > + ' _ {
349
358
self . arenas . iter ( ) . filter_map ( OnceCell :: get)
350
359
}
351
360
#[ inline] // This should be constant folded away (size/align is const)
352
- pub fn find < T > ( & self ) -> Option < & SmallArena > {
361
+ pub fn find < T > ( & self ) -> Option < & SmallArena < Fmt > > {
353
362
if std:: mem:: align_of :: < T > ( ) > ARENA_ELEMENT_ALIGN {
354
363
return None
355
364
}
@@ -359,9 +368,9 @@ impl SmallArenaList {
359
368
/ word_size;
360
369
self . find_raw ( num_words)
361
370
}
362
- #[ inline( always ) ] // We want this constant-folded away......
363
- fn find_raw ( & self , num_words : usize ) -> Option < & SmallArena > {
364
- arena_match ! (
371
+ #[ inline] // We want this constant-folded away......
372
+ fn find_raw ( & self , num_words : usize ) -> Option < & SmallArena < Fmt > > {
373
+ arena_match ! ( self . format ,
365
374
self . arenas, num_words, max = 32 ;
366
375
0 ..=2 => 2 @ 0 ,
367
376
3 => 3 @ 1 ,
0 commit comments