@@ -184,6 +184,7 @@ typedef struct _gcval_t {
184
184
185
185
#define GC_PAGE_LG2 14 // log2(size of a page)
186
186
#define GC_PAGE_SZ (1 << GC_PAGE_LG2) // 16k
187
+ #define GC_PAGE_OFFSET (16 - (sizeof(jl_taggedvalue_t) % 16))
187
188
188
189
// pool page metadata
189
190
typedef struct _gcpage_t {
@@ -219,7 +220,7 @@ typedef struct {
219
220
char pages [REGION_PG_COUNT ][GC_PAGE_SZ ]; // must be first, to preserve page alignment
220
221
uint32_t freemap [REGION_PG_COUNT /32 ];
221
222
gcpage_t meta [REGION_PG_COUNT ];
222
- } region_t ;
223
+ } region_t __attribute__(( aligned ( GC_PAGE_SZ ))) ;
223
224
static region_t * regions [REGION_COUNT ] = {NULL };
224
225
// store a lower bound of the first free page in each region
225
226
static int regions_lb [REGION_COUNT ] = {0 };
@@ -234,12 +235,12 @@ typedef struct _pool_t {
234
235
uint16_t nfree ; // number of free objects in page pointed into by free_list
235
236
} pool_t ;
236
237
237
- #define PAGE_INDEX (region , data ) ((GC_PAGE_DATA(data) - &(region)->pages[0][0])/GC_PAGE_SZ)
238
+ #define PAGE_INDEX (region , data ) ((GC_PAGE_DATA(( data) - GC_PAGE_OFFSET ) - &(region)->pages[0][0])/GC_PAGE_SZ)
238
239
static region_t * find_region (void * ptr )
239
240
{
240
241
// on 64bit systems we could probably use a single region and remove this loop
241
242
for (int i = 0 ; i < REGION_COUNT && regions [i ]; i ++ ) {
242
- if (regions [ i ] && (char * )ptr >= (char * )regions [i ] && (char * )ptr <= (char * )regions [i ] + sizeof (region_t ))
243
+ if ((char * )ptr >= (char * )regions [i ] && (char * )ptr <= (char * )regions [i ] + sizeof (region_t ))
243
244
return regions [i ];
244
245
}
245
246
assert (0 && "find_region failed" );
@@ -257,7 +258,7 @@ static uint8_t *page_age(gcpage_t *pg)
257
258
return pg -> ages ;
258
259
}
259
260
260
- #define GC_POOL_END_OFS (osize ) (((GC_PAGE_SZ/ osize) - 1)*osize)
261
+ #define GC_POOL_END_OFS (osize ) (((( GC_PAGE_SZ - GC_PAGE_OFFSET)/( osize)) - 1)*( osize) + GC_PAGE_OFFSET )
261
262
262
263
263
264
// layout for big (>2k) objects
@@ -701,7 +702,7 @@ static void free_page(void *p)
701
702
int pg_idx = -1 ;
702
703
int i ;
703
704
for (i = 0 ; i < REGION_COUNT && regions [i ] != NULL ; i ++ ) {
704
- pg_idx = PAGE_INDEX (regions [i ], p );
705
+ pg_idx = PAGE_INDEX (regions [i ], ( char * ) p + GC_PAGE_OFFSET );
705
706
if (pg_idx >= 0 && pg_idx < REGION_PG_COUNT ) break ;
706
707
}
707
708
assert (i < REGION_COUNT && regions [i ] != NULL );
@@ -717,7 +718,7 @@ static void free_page(void *p)
717
718
size_t n_pages = (GC_PAGE_SZ + system_page_size - 1 ) / GC_PAGE_SZ ;
718
719
decommit_size = system_page_size ;
719
720
p = (void * )((uintptr_t )& region -> pages [pg_idx ][0 ] & ~(system_page_size - 1 )); // round down to the nearest page
720
- pg_idx = PAGE_INDEX (region , p );
721
+ pg_idx = PAGE_INDEX (region , ( char * ) p + GC_PAGE_OFFSET );
721
722
if (pg_idx + n_pages > REGION_PG_COUNT ) goto no_decommit ;
722
723
for (; n_pages -- ; pg_idx ++ ) {
723
724
msk = (uint32_t )(1 << ((pg_idx % 32 )));
@@ -985,15 +986,15 @@ static void sweep_malloced_arrays(void)
985
986
static inline gcval_t * reset_page (pool_t * p , gcpage_t * pg , gcval_t * fl )
986
987
{
987
988
pg -> gc_bits = 0 ;
988
- pg -> nfree = GC_PAGE_SZ / p -> osize ;
989
+ pg -> nfree = ( GC_PAGE_SZ - GC_PAGE_OFFSET ) / p -> osize ;
989
990
pg -> pool_n = p - norm_pools ;
990
- memset (page_age (pg ), 0 , (GC_PAGE_SZ / p -> osize + 7 )/ 8 );
991
- gcval_t * beg = (gcval_t * )pg -> data ;
991
+ memset (page_age (pg ), 0 , LLT_ALIGN (GC_PAGE_SZ / p -> osize , 8 ) );
992
+ gcval_t * beg = (gcval_t * )( pg -> data + GC_PAGE_OFFSET ) ;
992
993
gcval_t * end = (gcval_t * )((char * )beg + (pg -> nfree - 1 )* p -> osize );
993
994
end -> next = fl ;
994
995
pg -> allocd = 0 ;
995
- pg -> fl_begin_offset = 0 ;
996
- pg -> fl_end_offset = (char * )end - (char * )beg ;
996
+ pg -> fl_begin_offset = GC_PAGE_OFFSET ;
997
+ pg -> fl_end_offset = (char * )end - (char * )beg + GC_PAGE_OFFSET ;
997
998
return beg ;
998
999
}
999
1000
@@ -1002,10 +1003,10 @@ static NOINLINE void add_page(pool_t *p)
1002
1003
char * data = (char * )malloc_page ();
1003
1004
if (data == NULL )
1004
1005
jl_throw (jl_memory_exception );
1005
- gcpage_t * pg = page_metadata (data );
1006
+ gcpage_t * pg = page_metadata (data + GC_PAGE_OFFSET );
1006
1007
pg -> data = data ;
1007
1008
pg -> osize = p -> osize ;
1008
- pg -> ages = (uint8_t * )malloc ((GC_PAGE_SZ / p -> osize + 7 )/ 8 );
1009
+ pg -> ages = (uint8_t * )malloc (LLT_ALIGN (GC_PAGE_SZ / p -> osize , 8 ) );
1009
1010
gcval_t * fl = reset_page (p , pg , p -> newpages );
1010
1011
p -> newpages = fl ;
1011
1012
}
@@ -1132,7 +1133,7 @@ static void sweep_pool_region(int region_i, int sweep_mask)
1132
1133
last = p -> newpages ;
1133
1134
if (last ) {
1134
1135
gcpage_t * pg = page_metadata (last );
1135
- pg -> nfree = (GC_PAGE_SZ - ((char * )last - GC_PAGE_DATA (last )))/ p -> osize ;
1136
+ pg -> nfree = (GC_PAGE_SZ - ((char * )last - GC_PAGE_DATA (last ))) / p -> osize ;
1136
1137
pg -> allocd = 1 ;
1137
1138
}
1138
1139
p -> newpages = NULL ;
@@ -1187,11 +1188,11 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma
1187
1188
gcval_t * v ;
1188
1189
size_t old_nfree = 0 , nfree = 0 ;
1189
1190
int pg_freedall = 0 , pg_total = 0 , pg_skpd = 0 ;
1190
- int obj_per_page = GC_PAGE_SZ /osize ;
1191
+ int obj_per_page = ( GC_PAGE_SZ - GC_PAGE_OFFSET ) /osize ;
1191
1192
char * data = pg -> data ;
1192
1193
uint8_t * ages = page_age (pg );
1193
- v = (gcval_t * )data ;
1194
- char * lim = (char * )v + GC_PAGE_SZ - osize ;
1194
+ v = (gcval_t * )( data + GC_PAGE_OFFSET ) ;
1195
+ char * lim = (char * )v + GC_PAGE_SZ - GC_PAGE_OFFSET - osize ;
1195
1196
freedall = 1 ;
1196
1197
old_nfree += pg -> nfree ;
1197
1198
@@ -1909,10 +1910,10 @@ static void clear_mark(int bits)
1909
1910
if (!!~line ) {
1910
1911
for (int j = 0 ; j < 32 ; j ++ ) {
1911
1912
if (!((line >> j ) & 1 )) {
1912
- gcpage_t * pg = page_metadata (region -> pages [pg_i * 32 + j ]);
1913
+ gcpage_t * pg = page_metadata (& region -> pages [pg_i * 32 + j ][ 0 ] + GC_PAGE_OFFSET );
1913
1914
pool_t * pool = & norm_pools [pg -> pool_n ];
1914
- pv = (gcval_t * )pg -> data ;
1915
- char * lim = (char * )pv + GC_PAGE_SZ - pool -> osize ;
1915
+ pv = (gcval_t * )( pg -> data + GC_PAGE_OFFSET ) ;
1916
+ char * lim = (char * )pv + GC_PAGE_SZ - GC_PAGE_OFFSET - pool -> osize ;
1916
1917
while ((char * )pv <= lim ) {
1917
1918
if (!verifying ) arraylist_push (& bits_save [gc_bits (pv )], pv );
1918
1919
gc_bits (pv ) = bits ;
@@ -2439,7 +2440,7 @@ static void jl_mk_thread_heap(void) {
2439
2440
p [i ].osize = szc [i ];
2440
2441
p [i ].freelist = NULL ;
2441
2442
p [i ].newpages = NULL ;
2442
- p [i ].end_offset = (( GC_PAGE_SZ / szc [i ]) - 1 ) * szc [ i ] ;
2443
+ p [i ].end_offset = GC_POOL_END_OFS ( szc [i ]);
2443
2444
}
2444
2445
arraylist_new (& preserved_values , 0 );
2445
2446
arraylist_new (& weak_refs , 0 );
@@ -2504,8 +2505,8 @@ static size_t pool_stats(pool_t *p, size_t *pwaste, size_t *np, size_t *pnold)
2504
2505
2505
2506
while (pg != NULL ) {
2506
2507
npgs ++ ;
2507
- v = (gcval_t * )pg -> data ;
2508
- char * lim = (char * )v + GC_PAGE_SZ - osize ;
2508
+ v = (gcval_t * )( pg -> data + GC_PAGE_OFFSET ) ;
2509
+ char * lim = (char * )v + GC_PAGE_SZ - GC_PAGE_OFFSET - osize ;
2509
2510
int i = 0 ;
2510
2511
while ((char * )v <= lim ) {
2511
2512
if (!gc_marked (v )) {
@@ -2523,7 +2524,7 @@ static size_t pool_stats(pool_t *p, size_t *pwaste, size_t *np, size_t *pnold)
2523
2524
gcpage_t * nextpg = NULL ;
2524
2525
pg = nextpg ;
2525
2526
}
2526
- * pwaste = npgs * GC_PAGE_SZ - (nused * p -> osize );
2527
+ * pwaste = npgs * GC_PAGE_SZ - (nused * p -> osize );
2527
2528
* np = npgs ;
2528
2529
* pnold = nold ;
2529
2530
if (npgs != 0 ) {
0 commit comments