@@ -4439,79 +4439,84 @@ gc_free_garbage(rb_objspace_t *objspace, VALUE garbage)
4439
4439
return length ;
4440
4440
}
4441
4441
4442
+ static int is_garbage_slot (VALUE obj );
4443
+
4442
4444
static inline int
4443
4445
gc_page_sweep (rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * sweep_page )
4444
4446
{
4445
- int offset , i ;
4446
- int empty_slots = 0 , freed_slots = 0 , freed_objects = 0 , final_objects = 0 ;
4447
- RVALUE * pstart ;
4447
+ int i ;
4448
+ int empty_slots = 0 , freed_slots = 0 , final_objects = 0 ;
4449
+ RVALUE * p , * offset ;
4448
4450
bits_t * bits , bitset ;
4449
4451
4450
4452
gc_report (2 , objspace , "page_sweep: start.\n" );
4451
4453
4452
4454
sweep_page -> flags .before_sweep = FALSE;
4453
4455
4454
- pstart = sweep_page -> start ;
4455
- offset = NUM_IN_PAGE (pstart );
4456
+ p = sweep_page -> start ;
4457
+ offset = p - NUM_IN_PAGE (p );
4456
4458
bits = sweep_page -> mark_bits ;
4457
4459
4458
- for (i = 0 ; i < sweep_page -> total_slots ;) {
4459
- RVALUE * p = pstart + i ;
4460
- VALUE vp = (VALUE )p ;
4460
+ /* create guard : fill 1 out-of-range */
4461
+ bits [BITMAP_INDEX (p )] |= BITMAP_BIT (p )- 1 ;
4461
4462
4462
- GC_ASSERT (!RVALUE_PAGE_MARKING (sweep_page , p ) || sweep_page -> flags .has_remembered_objects );
4463
-
4464
- bitset = (~bits [BITMAP_INDEX (p )] >> BITMAP_OFFSET (p )) & 1 ;
4463
+ int out_of_range_bits = (NUM_IN_PAGE (p ) + sweep_page -> total_slots ) % BITS_BITLENGTH ;
4464
+ if (out_of_range_bits != 0 ) { // sizeof(RVALUE) == 64
4465
+ bits [BITMAP_INDEX (p ) + sweep_page -> total_slots / BITS_BITLENGTH ] |= ~(((bits_t )1 << out_of_range_bits ) - 1 );
4466
+ }
4465
4467
4466
- asan_unpoison_object (vp , false);
4467
- if (bitset ) {
4468
- switch (BUILTIN_TYPE (vp )) {
4469
- default : /* majority case */
4470
- gc_report (2 , objspace , "page_sweep: free %p\n" , (void * )p );
4468
+ for (i = 0 ; i < HEAP_PAGE_BITMAP_LIMIT ; i ++ ) {
4469
+ bitset = ~bits [i ];
4470
+ if (bitset ) {
4471
+ p = offset + i * BITS_BITLENGTH ;
4472
+ do {
4473
+ VALUE vp = (VALUE )p ;
4474
+ asan_unpoison_object (vp , false);
4475
+ if (bitset & 1 ) {
4476
+ switch (BUILTIN_TYPE (vp )) {
4477
+ default : /* majority case */
4478
+ gc_report (2 , objspace , "page_sweep: free %p\n" , (void * )p );
4471
4479
#if RGENGC_CHECK_MODE
4472
- if (!is_full_marking (objspace )) {
4473
- if (RVALUE_OLD_P (vp )) rb_bug ("page_sweep: old while minor GC: %s." , obj_info (p ));
4474
- if (rgengc_remembered_sweep (objspace , vp )) rb_bug ("page_sweep: %p - remembered." , (void * )p );
4475
- }
4476
- #endif
4477
- if (obj_free (objspace , vp )) {
4478
- final_objects ++ ;
4479
- }
4480
- else {
4481
- (void )VALGRIND_MAKE_MEM_UNDEFINED ((void * )p , sizeof (RVALUE ));
4482
- heap_page_add_freeobj (objspace , sweep_page , vp );
4483
- gc_report (3 , objspace , "page_sweep: %s is added to freelist\n" , obj_info (vp ));
4484
-
4485
- freed_objects ++ ;
4486
- freed_slots ++ ;
4487
- asan_poison_object (vp );
4488
- }
4489
- break ;
4490
-
4491
- /* minor cases */
4492
- case T_GARBAGE :
4493
- case T_ZOMBIE :
4494
- /* already counted */
4495
- break ;
4496
- case T_NONE :
4497
- empty_slots ++ ; /* already freed */
4498
- break ;
4499
- }
4500
- }
4501
-
4502
- if (BUILTIN_TYPE ((VALUE )p ) == T_GARBAGE ) {
4503
- i += p -> as .garbage .length ;
4504
- } else {
4505
- i ++ ;
4506
- }
4480
+ if (!is_full_marking (objspace )) {
4481
+ if (RVALUE_OLD_P (vp )) rb_bug ("page_sweep: %p - old while minor GC." , (void * )p );
4482
+ if (rgengc_remembered_sweep (objspace , vp )) rb_bug ("page_sweep: %p - remembered." , (void * )p );
4483
+ }
4484
+ #endif
4485
+ if (!is_garbage_slot (vp )) {
4486
+ if (obj_free (objspace , vp )) {
4487
+ final_objects ++ ;
4488
+ }
4489
+ else {
4490
+ (void )VALGRIND_MAKE_MEM_UNDEFINED ((void * )p , sizeof (RVALUE ));
4491
+ heap_page_add_freeobj (objspace , sweep_page , vp );
4492
+ gc_report (3 , objspace , "page_sweep: %s is added to freelist\n" , obj_info (vp ));
4493
+ freed_slots ++ ;
4494
+ asan_poison_object (vp );
4495
+ }
4496
+ }
4497
+ break ;
4498
+
4499
+ /* minor cases */
4500
+ case T_ZOMBIE :
4501
+ /* already counted */
4502
+ break ;
4503
+ case T_NONE :
4504
+ empty_slots ++ ; /* already freed */
4505
+ break ;
4506
+ }
4507
+ }
4508
+ p ++ ;
4509
+ bitset >>= 1 ;
4510
+ } while (bitset );
4511
+ }
4507
4512
}
4508
4513
4509
4514
gc_setup_mark_bits (sweep_page );
4510
4515
4511
4516
#if GC_PROFILE_MORE_DETAIL
4512
4517
if (gc_prof_enabled (objspace )) {
4513
4518
gc_profile_record * record = gc_prof_record (objspace );
4514
- record -> removing_objects += final_objects + freed_slots ;
4519
+ record -> removing_objects += final_objects + freed_slots ;
4515
4520
record -> empty_objects += empty_slots ;
4516
4521
}
4517
4522
#endif
@@ -4521,7 +4526,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
4521
4526
freed_slots , empty_slots , final_objects );
4522
4527
4523
4528
sweep_page -> free_slots = freed_slots + empty_slots ;
4524
- objspace -> profile .total_freed_objects += freed_objects ;
4529
+ objspace -> profile .total_freed_objects += freed_slots ;
4525
4530
heap_pages_final_objects += final_objects ;
4526
4531
sweep_page -> final_objects += final_objects ;
4527
4532
0 commit comments