@@ -477,29 +477,20 @@ static void gc_deal_with_stack_overflow(void) {
477
477
}
478
478
}
479
479
480
- static void gc_sweep (void ) {
481
- #if MICROPY_PY_GC_COLLECT_RETVAL
482
- MP_STATE_MEM (gc_collected ) = 0 ;
483
- #endif
484
- // free unmarked heads and their tails
485
- int free_tail = 0 ;
486
- #if MICROPY_GC_SPLIT_HEAP_AUTO
487
- mp_state_mem_area_t * prev_area = NULL ;
488
- #endif
489
- for (mp_state_mem_area_t * area = & MP_STATE_MEM (area ); area != NULL ; area = NEXT_AREA (area )) {
490
- size_t end_block = area -> gc_alloc_table_byte_len * BLOCKS_PER_ATB ;
491
- if (area -> gc_last_used_block < end_block ) {
492
- end_block = area -> gc_last_used_block + 1 ;
493
- }
494
-
495
- size_t last_used_block = 0 ;
496
-
497
- for (size_t block = 0 ; block < end_block ; block ++ ) {
498
- MICROPY_GC_HOOK_LOOP (block );
499
- switch (ATB_GET_KIND (area , block )) {
500
- case AT_HEAD :
501
- #if MICROPY_ENABLE_FINALISER
502
- if (FTB_GET (area , block )) {
480
+ // Run finalisers for all to-be-freed blocks
481
+ static void gc_sweep_run_finalisers (void ) {
482
+ #if MICROPY_ENABLE_FINALISER
483
+ for (const mp_state_mem_area_t * area = & MP_STATE_MEM (area ); area != NULL ; area = NEXT_AREA (area )) {
484
+ assert (area -> gc_last_used_block <= area -> gc_alloc_table_byte_len * BLOCKS_PER_ATB );
485
+ // Small speed optimisation: skip over empty FTB blocks
486
+ size_t ftb_end = area -> gc_last_used_block / BLOCKS_PER_FTB ; // index is inclusive
487
+ for (size_t ftb_idx = 0 ; ftb_idx <= ftb_end ; ftb_idx ++ ) {
488
+ byte ftb = area -> gc_finaliser_table_start [ftb_idx ];
489
+ size_t block = ftb_idx * BLOCKS_PER_FTB ;
490
+ while (ftb ) {
491
+ MICROPY_GC_HOOK_LOOP (block );
492
+ if (ftb & 1 ) { // FTB_GET(area, block) shortcut
493
+ if (ATB_GET_KIND (area , block ) == AT_HEAD ) {
503
494
mp_obj_base_t * obj = (mp_obj_base_t * )PTR_FROM_BLOCK (area , block );
504
495
if (obj -> type != NULL ) {
505
496
// if the object has a type then see if it has a __del__ method
@@ -519,7 +510,35 @@ static void gc_sweep(void) {
519
510
// clear finaliser flag
520
511
FTB_CLEAR (area , block );
521
512
}
522
- #endif
513
+ }
514
+ ftb >>= 1 ;
515
+ block ++ ;
516
+ }
517
+ }
518
+ }
519
+ #endif // MICROPY_ENABLE_FINALISER
520
+ }
521
+
522
+ static void gc_sweep (void ) {
523
+ #if MICROPY_PY_GC_COLLECT_RETVAL
524
+ MP_STATE_MEM (gc_collected ) = 0 ;
525
+ #endif
526
+ // free unmarked heads and their tails
527
+ int free_tail = 0 ;
528
+ #if MICROPY_GC_SPLIT_HEAP_AUTO
529
+ mp_state_mem_area_t * prev_area = NULL ;
530
+ #endif
531
+
532
+ gc_sweep_run_finalisers ();
533
+
534
+ for (mp_state_mem_area_t * area = & MP_STATE_MEM (area ); area != NULL ; area = NEXT_AREA (area )) {
535
+ size_t last_used_block = 0 ;
536
+ assert (area -> gc_last_used_block <= area -> gc_alloc_table_byte_len * BLOCKS_PER_ATB );
537
+
538
+ for (size_t block = 0 ; block <= area -> gc_last_used_block ; block ++ ) {
539
+ MICROPY_GC_HOOK_LOOP (block );
540
+ switch (ATB_GET_KIND (area , block )) {
541
+ case AT_HEAD :
523
542
free_tail = 1 ;
524
543
DEBUG_printf ("gc_sweep(%p)\n" , (void * )PTR_FROM_BLOCK (area , block ));
525
544
#if MICROPY_PY_GC_COLLECT_RETVAL
0 commit comments