@@ -158,12 +158,12 @@ impl GC {
158158 total_bytes : 0 ,
159159 state : GcState :: Pause ,
160160 current_white : 0 ,
161- gc_kind : GcKind :: Generational , // Default to generational mode like Lua 5.4
161+ gc_kind : GcKind :: Generational , // Use generational mode like Lua 5.4
162162 sweep_index : 0 ,
163163 propagate_work : 0 ,
164- gc_pause : 200 , // Like Lua: 200 = wait until memory doubles
165- gen_minor_mul : 25 , // Minor GC when memory grows 25 %
166- gen_major_mul : 100 , // Major GC when memory grows 100% since last major
164+ gc_pause : 200 ,
165+ gen_minor_mul : 20 , // Minor GC when memory grows 20 %
166+ gen_major_mul : 50 , // Major GC when memory grows 50% (降低以更频繁触发major GC清除weak tables)
167167 last_atomic : 0 ,
168168 gc_estimate : 0 ,
169169 young_list : Vec :: with_capacity ( 1024 ) ,
@@ -299,63 +299,36 @@ impl GC {
299299 }
300300 }
301301
302- /// Incremental GC step - original incremental mode
302+ /// Incremental GC step - complete one full cycle
303303 fn inc_step ( & mut self , roots : & [ LuaValue ] , pool : & mut ObjectPool ) {
304- const WORK_PER_STEP : usize = 4096 ;
305- let mut work = 0 ;
306-
307- // State machine for incremental GC
308- loop {
309- match self . state {
310- GcState :: Pause => {
311- // Start new cycle: mark roots and transition to propagate
312- self . start_cycle ( roots, pool) ;
313- self . state = GcState :: Propagate ;
314- work += 100 ; // Small fixed cost
315- }
316-
317- GcState :: Propagate => {
318- // Incremental marking: process some gray objects
319- let marked = self . propagate_step ( pool, WORK_PER_STEP - work) ;
320- work += marked;
321-
322- if self . gray . is_empty ( ) && self . grayagain . is_empty ( ) {
323- // All marking done, go to atomic phase
324- self . state = GcState :: Atomic ;
325- }
326- }
327-
328- GcState :: Atomic => {
329- // Atomic phase - must finish marking (like Lua's atomic)
330- // Process any grayagain objects
331- while let Some ( gc_id) = self . grayagain . pop ( ) {
332- self . mark_one ( gc_id, pool) ;
333- }
334- // Clear weak table entries before sweep
335- self . clear_weak_tables ( pool) ;
336- // Start sweep
337- self . sweep_index = 0 ;
338- self . state = GcState :: Sweep ;
339- work += 50 ;
340- }
341-
342- GcState :: Sweep => {
343- // Complete sweep in one step (pools are iterated directly)
344- let swept = self . sweep_step ( pool, WORK_PER_STEP - work) ;
345- work += swept;
346- // sweep_step handles state transition and finish_cycle
347- break ;
348- }
349- }
350-
351- // Check if we've done enough work for this step
352- if work >= WORK_PER_STEP {
353- break ;
354- }
304+ // Pause -> Start cycle and mark roots
305+ if self . state == GcState :: Pause {
306+ self . start_cycle ( roots, pool) ;
307+ self . state = GcState :: Propagate ;
308+ }
309+
310+ // Propagate -> Mark all gray objects
311+ if self . state == GcState :: Propagate {
312+ while let Some ( gc_id) = self . gray . pop ( ) {
313+ self . mark_one ( gc_id, pool) ;
314+ }
315+ self . state = GcState :: Atomic ;
316+ }
317+
318+ // Atomic -> Process grayagain and clear weak tables
319+ if self . state == GcState :: Atomic {
320+ while let Some ( gc_id) = self . grayagain . pop ( ) {
321+ self . mark_one ( gc_id, pool) ;
322+ }
323+ self . clear_weak_tables ( pool) ;
324+ self . sweep_index = 0 ;
325+ self . state = GcState :: Sweep ;
326+ }
327+
328+ // Sweep -> Clean up dead objects
329+ if self . state == GcState :: Sweep {
330+ self . sweep_step ( pool, usize:: MAX ) ;
355331 }
356-
357- // Reduce debt by work done (convert work to "bytes paid off")
358- self . gc_debt -= ( work as isize ) * 2 ;
359332 }
360333
361334 /// Start a new GC cycle - mark roots and build gray list
@@ -664,6 +637,7 @@ impl GC {
664637 }
665638 for id in dead_tables {
666639 pool. tables . free ( id) ;
640+ self . total_bytes = self . total_bytes . saturating_sub ( 256 ) ;
667641 self . record_deallocation ( 256 ) ;
668642 collected += 1 ;
669643 }
@@ -677,6 +651,7 @@ impl GC {
677651 }
678652 for id in dead_funcs {
679653 pool. functions . free ( id) ;
654+ self . total_bytes = self . total_bytes . saturating_sub ( 128 ) ;
680655 self . record_deallocation ( 128 ) ;
681656 collected += 1 ;
682657 }
@@ -703,6 +678,7 @@ impl GC {
703678 }
704679 for id in dead_strings {
705680 pool. strings . free ( id) ;
681+ self . total_bytes = self . total_bytes . saturating_sub ( 64 ) ;
706682 self . record_deallocation ( 64 ) ;
707683 collected += 1 ;
708684 }
@@ -1372,14 +1348,14 @@ impl GC {
13721348 if let Some ( mt_id) = table. data . get_metatable ( ) . and_then ( |v| v. as_table_id ( ) ) {
13731349 if let Some ( mt) = pool. tables . get ( mt_id. 0 ) {
13741350 // Look for __mode key in metatable
1375- // We need to find the string "__mode" in the metatable
13761351 let mode = self . get_weak_mode ( mt, pool) ;
13771352 if let Some ( ( weak_keys, weak_values) ) = mode {
13781353 // Collect keys to remove
13791354 let mut keys_to_remove = Vec :: new ( ) ;
13801355 for ( key, value) in table. data . iter_all ( ) {
13811356 let key_dead = weak_keys && self . is_value_dead ( & key, pool) ;
13821357 let value_dead = weak_values && self . is_value_dead ( & value, pool) ;
1358+
13831359 if key_dead || value_dead {
13841360 keys_to_remove. push ( key) ;
13851361 }
0 commit comments