@@ -4439,79 +4439,84 @@ gc_free_garbage(rb_objspace_t *objspace, VALUE garbage)
44394439 return length ;
44404440}
44414441
4442+ static int is_garbage_slot (VALUE obj );
4443+
44424444static inline int
44434445gc_page_sweep (rb_objspace_t * objspace , rb_heap_t * heap , struct heap_page * sweep_page )
44444446{
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 ;
44484450 bits_t * bits , bitset ;
44494451
44504452 gc_report (2 , objspace , "page_sweep: start.\n" );
44514453
44524454 sweep_page -> flags .before_sweep = FALSE;
44534455
4454- pstart = sweep_page -> start ;
4455- offset = NUM_IN_PAGE (pstart );
4456+ p = sweep_page -> start ;
4457+ offset = p - NUM_IN_PAGE (p );
44564458 bits = sweep_page -> mark_bits ;
44574459
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 ;
44614462
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+ }
44654467
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 );
44714479#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+ }
45074512 }
45084513
45094514 gc_setup_mark_bits (sweep_page );
45104515
45114516#if GC_PROFILE_MORE_DETAIL
45124517 if (gc_prof_enabled (objspace )) {
45134518 gc_profile_record * record = gc_prof_record (objspace );
4514- record -> removing_objects += final_objects + freed_slots ;
4519+ record -> removing_objects += final_objects + freed_slots ;
45154520 record -> empty_objects += empty_slots ;
45164521 }
45174522#endif
@@ -4521,7 +4526,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
45214526 freed_slots , empty_slots , final_objects );
45224527
45234528 sweep_page -> free_slots = freed_slots + empty_slots ;
4524- objspace -> profile .total_freed_objects += freed_objects ;
4529+ objspace -> profile .total_freed_objects += freed_slots ;
45254530 heap_pages_final_objects += final_objects ;
45264531 sweep_page -> final_objects += final_objects ;
45274532
0 commit comments