@@ -177,8 +177,8 @@ bigval_t *big_objects_marked = NULL;
177
177
// See https://algorithmica.org/en/eytzinger
178
178
static arraylist_t eytzinger_image_tree ;
179
179
static arraylist_t eytzinger_idxs ;
180
- static uintptr_t gc_img_min = ( uintptr_t ) 0ull ;
181
- static uintptr_t gc_img_max = ( uintptr_t ) ~ 0ull ;
180
+ static uintptr_t gc_img_min ;
181
+ static uintptr_t gc_img_max ;
182
182
183
183
// -- Finalization --
184
184
// `ptls->finalizers` and `finalizer_list_marked` might have tagged pointers.
@@ -190,15 +190,17 @@ arraylist_t finalizer_list_marked;
190
190
arraylist_t to_finalize ;
191
191
JL_DLLEXPORT _Atomic(int ) jl_gc_have_pending_finalizers = 0 ;
192
192
193
- static int ptr_cmp (const void * l , const void * r ) {
193
+ static int ptr_cmp (const void * l , const void * r )
194
+ {
194
195
uintptr_t left = * (const uintptr_t * )l ;
195
196
uintptr_t right = * (const uintptr_t * )r ;
196
197
// jl_safe_printf("cmp %p %p\n", (void*)left, (void*)right);
197
198
return (left > right ) - (left < right );
198
199
}
199
200
200
201
// Build an eytzinger tree from a sorted array
201
- static int eytzinger (uintptr_t * src , uintptr_t * dest , size_t i , size_t k , size_t n ) {
202
+ static int eytzinger (uintptr_t * src , uintptr_t * dest , size_t i , size_t k , size_t n )
203
+ {
202
204
if (k <= n ) {
203
205
i = eytzinger (src , dest , i , 2 * k , n );
204
206
dest [k - 1 ] = src [i ];
@@ -208,16 +210,15 @@ static int eytzinger(uintptr_t *src, uintptr_t *dest, size_t i, size_t k, size_t
208
210
return i ;
209
211
}
210
212
211
- static size_t eyt_obj_idx (jl_value_t * obj ) JL_NOTSAFEPOINT {
212
- size_t n = eytzinger_image_tree . len ;
213
- if ( n == 0 ) {
214
- return eytzinger_image_tree . len ;
215
- }
216
- assert (eytzinger_image_tree . len % 2 == 0 && "Eytzinger tree not even length!" );
213
+ static size_t eyt_obj_idx (jl_value_t * obj ) JL_NOTSAFEPOINT
214
+ {
215
+ size_t n = eytzinger_image_tree . len - 1 ;
216
+ if ( n == 0 )
217
+ return n ;
218
+ assert (n % 2 == 0 && "Eytzinger tree not even length!" );
217
219
uintptr_t cmp = (uintptr_t ) obj ;
218
- if (cmp < gc_img_min || cmp > gc_img_max ) {
219
- return eytzinger_image_tree .len ;
220
- }
220
+ if (cmp <= gc_img_min || cmp > gc_img_max )
221
+ return n ;
221
222
uintptr_t * tree = (uintptr_t * )eytzinger_image_tree .items ;
222
223
size_t k = 1 ;
223
224
// note that k preserves the history of how we got to the current node
@@ -227,6 +228,7 @@ static size_t eyt_obj_idx(jl_value_t *obj) JL_NOTSAFEPOINT {
227
228
k |= greater ;
228
229
}
229
230
// Free to assume k is nonzero, since we start with k = 1
231
+ // and cmp > gc_img_min
230
232
// This shift does a fast revert of the path until we get
231
233
// to a node that evaluated less than cmp.
232
234
k >>= (__builtin_ctzll (k ) + 1 );
@@ -237,13 +239,16 @@ static size_t eyt_obj_idx(jl_value_t *obj) JL_NOTSAFEPOINT {
237
239
}
238
240
239
241
//used in staticdata.c after we add an image
240
- void rebuild_image_blob_tree (void ) {
242
+ void rebuild_image_blob_tree (void )
243
+ {
241
244
size_t orig = eytzinger_image_tree .len ;
242
- size_t inc = jl_linkage_blobs .len - orig ;
245
+ size_t inc = jl_linkage_blobs .len - orig + 1 ;
243
246
assert (eytzinger_idxs .len == eytzinger_image_tree .len );
244
247
assert (eytzinger_idxs .max == eytzinger_image_tree .max );
245
248
arraylist_grow (& eytzinger_idxs , inc );
246
249
arraylist_grow (& eytzinger_image_tree , inc );
250
+ eytzinger_idxs .items [eytzinger_idxs .len - 1 ] = (void * )jl_linkage_blobs .len ;
251
+ eytzinger_image_tree .items [eytzinger_image_tree .len - 1 ] = (void * )1 ; // outside image
247
252
for (size_t i = 0 ; i < jl_linkage_blobs .len ; i ++ ) {
248
253
assert ((uintptr_t ) jl_linkage_blobs .items [i ] % 4 == 0 && "Linkage blob not 4-byte aligned!" );
249
254
// We abuse the pointer here a little so that a couple of properties are true:
@@ -252,61 +257,49 @@ void rebuild_image_blob_tree(void) {
252
257
// We assume that there exist no 0-size blobs, but that's a safe assumption
253
258
// since it means nothing could be there anyways
254
259
uintptr_t val = (uintptr_t ) jl_linkage_blobs .items [i ];
255
- eytzinger_idxs .items [i ] = (void * )(val + 3 - (i & 1 ));
260
+ eytzinger_idxs .items [i ] = (void * )(val + (i & 1 ));
256
261
}
257
- qsort (eytzinger_idxs .items , eytzinger_idxs .len , sizeof (void * ), ptr_cmp );
258
- // for (size_t i = orig; i < eytzinger_idxs.len; i++) {
259
- // jl_safe_printf("idxs[%lu] = %p\n", i, eytzinger_idxs.items[i]);
260
- // }
262
+ qsort (eytzinger_idxs .items , eytzinger_idxs .len - 1 , sizeof (void * ), ptr_cmp );
261
263
gc_img_min = (uintptr_t ) eytzinger_idxs .items [0 ];
262
- gc_img_max = (uintptr_t ) eytzinger_idxs .items [eytzinger_idxs .len - 1 ] ;
263
- eytzinger ((uintptr_t * )eytzinger_idxs .items , (uintptr_t * )eytzinger_image_tree .items , 0 , 1 , eytzinger_idxs .len );
264
+ gc_img_max = (uintptr_t ) eytzinger_idxs .items [eytzinger_idxs .len - 2 ] + 1 ;
265
+ eytzinger ((uintptr_t * )eytzinger_idxs .items , (uintptr_t * )eytzinger_image_tree .items , 0 , 1 , eytzinger_idxs .len - 1 );
264
266
// Reuse the scratch memory to store the indices
265
267
// Still O(nlogn) because binary search
266
268
for (size_t i = 0 ; i < jl_linkage_blobs .len ; i ++ ) {
267
269
uintptr_t val = (uintptr_t ) jl_linkage_blobs .items [i ];
268
- // This is exactly equal to start + 4/end + 3
269
- uintptr_t cmp = val + 4 - (i & 1 );
270
270
// This is the same computation as in the prior for loop
271
- uintptr_t eyt_val = val + 3 - (i & 1 );
272
- size_t eyt_idx = eyt_obj_idx ((jl_value_t * )cmp );
273
- // jl_safe_printf("eyt_idx: %lu, eytzinger_image_tree.len: %lu\n", eyt_idx, eytzinger_image_tree.len);
274
- // jl_safe_printf("val: %p, cmp: %p, eytzinger_image_tree.items[eyt_idx]: %p\n", (void*)val, (void*)cmp, eyt_idx == eytzinger_image_tree.len ? NULL : eytzinger_image_tree.items[eyt_idx]);
275
- assert (((i % 2 == 1 ) || eytzinger_image_tree .items [eyt_idx ] == (void * )eyt_val ) && "Eytzinger tree failed to find object!" );
276
- assert (((i % 2 == 0 ) || eytzinger_image_tree .items [eyt_idx ] == (void * )eyt_val || cmp == gc_img_max + 1 ) && "Eytzinger tree failed to find object!" );
277
- (void ) eyt_val ;
278
- if (i & 1 ) {
271
+ uintptr_t eyt_val = val + (i & 1 );
272
+ size_t eyt_idx = eyt_obj_idx ((jl_value_t * )(eyt_val + 1 )); assert (eyt_idx < eytzinger_idxs .len - 1 );
273
+ assert (eytzinger_image_tree .items [eyt_idx ] == (void * )eyt_val && "Eytzinger tree failed to find object!" );
274
+ if (i & 1 )
279
275
eytzinger_idxs .items [eyt_idx ] = (void * )n_linkage_blobs ();
280
- } else {
276
+ else
281
277
eytzinger_idxs .items [eyt_idx ] = (void * )(i / 2 );
282
- }
283
278
}
284
279
}
285
280
286
- static int eyt_obj_in_img (jl_value_t * obj ) JL_NOTSAFEPOINT {
281
+ static int eyt_obj_in_img (jl_value_t * obj ) JL_NOTSAFEPOINT
282
+ {
287
283
assert ((uintptr_t ) obj % 4 == 0 && "Object not 4-byte aligned!" );
288
284
int idx = eyt_obj_idx (obj );
289
- if (idx == eytzinger_image_tree .len ) {
290
- return 0 ;
291
- }
292
- // Now we use a tiny trick: tree[idx] & 1 is whether or not tree[idx] is a start or an end
293
- // of a blob. If it's a start, then the object is in the image, otherwise it's not.
294
- int in_image = (uintptr_t ) eytzinger_image_tree .items [idx ] & 1 ;
285
+ // Now we use a tiny trick: tree[idx] & 1 is whether or not tree[idx] is a
286
+ // start (0) or an end (1) of a blob. If it's a start, then the object is
287
+ // in the image, otherwise it is not.
288
+ int in_image = ((uintptr_t )eytzinger_image_tree .items [idx ] & 1 ) == 0 ;
295
289
return in_image ;
296
290
}
297
291
298
- size_t external_blob_index (jl_value_t * v ) JL_NOTSAFEPOINT {
292
+ size_t external_blob_index (jl_value_t * v ) JL_NOTSAFEPOINT
293
+ {
299
294
assert ((uintptr_t ) v % 4 == 0 && "Object not 4-byte aligned!" );
300
295
int eyt_idx = eyt_obj_idx (v );
301
- if (eyt_idx == eytzinger_image_tree .len ) {
302
- return n_linkage_blobs ();
303
- }
304
296
// We fill the invalid slots with the length, so we can just return that
305
297
size_t idx = (size_t ) eytzinger_idxs .items [eyt_idx ];
306
298
return idx ;
307
299
}
308
300
309
- uint8_t jl_object_in_image (jl_value_t * obj ) JL_NOTSAFEPOINT {
301
+ uint8_t jl_object_in_image (jl_value_t * obj ) JL_NOTSAFEPOINT
302
+ {
310
303
return eyt_obj_in_img (obj );
311
304
}
312
305
@@ -3373,8 +3366,10 @@ void jl_gc_init(void)
3373
3366
3374
3367
arraylist_new (& finalizer_list_marked , 0 );
3375
3368
arraylist_new (& to_finalize , 0 );
3376
- arraylist_new (& eytzinger_image_tree , 0 );
3377
- arraylist_new (& eytzinger_idxs , 0 );
3369
+ arraylist_new (& eytzinger_image_tree , 1 );
3370
+ arraylist_new (& eytzinger_idxs , 1 );
3371
+ eytzinger_idxs .items [0 ] = (void * )0 ;
3372
+ eytzinger_image_tree .items [0 ] = (void * )1 ; // outside image
3378
3373
3379
3374
gc_num .interval = default_collect_interval ;
3380
3375
last_long_collect_interval = default_collect_interval ;
0 commit comments