@@ -5,7 +5,7 @@ mod lua_call_frame;
55mod lua_error;
66mod opcode;
77
8- use crate :: gc:: { GC , GcFunction , ThreadId , UpvalueId } ;
8+ use crate :: gc:: { GC , GcFunction , TableId , ThreadId , UpvalueId } ;
99#[ cfg( feature = "async" ) ]
1010use crate :: lua_async:: AsyncExecutor ;
1111use crate :: lua_value:: {
@@ -1532,6 +1532,68 @@ impl LuaVM {
15321532 }
15331533 }
15341534
1535+ // ============ GC Write Barriers ============
1536+ // These are called when modifying old objects to point to young objects
1537+ // Critical for correct generational GC behavior
1538+
1539+ /// Write barrier for table modification
1540+ /// Called when: table[key] = value (fast path)
1541+ /// If table is old and value is young/collectable, mark table as touched
1542+ #[ inline( always) ]
1543+ pub fn gc_barrier_back_table ( & mut self , table_id : TableId , value : & LuaValue ) {
1544+ // Only process in generational mode and if value is collectable
1545+ if self . gc . gc_kind ( ) != crate :: gc:: GcKind :: Generational {
1546+ return ;
1547+ }
1548+
1549+ // Check if value is a collectable GC object
1550+ let value_gc_id = match value. kind ( ) {
1551+ LuaValueKind :: Table => value. as_table_id ( ) . map ( crate :: gc:: GcId :: TableId ) ,
1552+ LuaValueKind :: Function => value. as_function_id ( ) . map ( crate :: gc:: GcId :: FunctionId ) ,
1553+ LuaValueKind :: Thread => value. as_thread_id ( ) . map ( crate :: gc:: GcId :: ThreadId ) ,
1554+ _ => None ,
1555+ } ;
1556+
1557+ if value_gc_id. is_some ( ) {
1558+ // Call back barrier on the table
1559+ let table_gc_id = crate :: gc:: GcId :: TableId ( table_id) ;
1560+ self . gc . barrier_back_gen ( table_gc_id, & mut self . object_pool ) ;
1561+ }
1562+ }
1563+
1564+ /// Write barrier for upvalue modification
1565+ /// Called when: upvalue = value (SETUPVAL)
1566+ /// If upvalue is old/closed and value is young, mark upvalue as touched
1567+ #[ inline( always) ]
1568+ pub fn gc_barrier_upvalue ( & mut self , upvalue_id : UpvalueId , value : & LuaValue ) {
1569+ // Only process in generational mode
1570+ if self . gc . gc_kind ( ) != crate :: gc:: GcKind :: Generational {
1571+ return ;
1572+ }
1573+
1574+ // Check if value is a collectable GC object
1575+ let is_collectable = matches ! (
1576+ value. kind( ) ,
1577+ LuaValueKind :: Table | LuaValueKind :: Function | LuaValueKind :: Thread | LuaValueKind :: String
1578+ ) ;
1579+
1580+ if is_collectable {
1581+ // Forward barrier: mark the value if upvalue is old
1582+ let uv_gc_id = crate :: gc:: GcId :: UpvalueId ( upvalue_id) ;
1583+
1584+ // Get value's GcId for forward barrier
1585+ if let Some ( value_gc_id) = match value. kind ( ) {
1586+ LuaValueKind :: Table => value. as_table_id ( ) . map ( crate :: gc:: GcId :: TableId ) ,
1587+ LuaValueKind :: Function => value. as_function_id ( ) . map ( crate :: gc:: GcId :: FunctionId ) ,
1588+ LuaValueKind :: Thread => value. as_thread_id ( ) . map ( crate :: gc:: GcId :: ThreadId ) ,
1589+ LuaValueKind :: String => value. as_string_id ( ) . map ( crate :: gc:: GcId :: StringId ) ,
1590+ _ => None ,
1591+ } {
1592+ self . gc . barrier_forward_gen ( uv_gc_id, value_gc_id, & mut self . object_pool ) ;
1593+ }
1594+ }
1595+ }
1596+
15351597 /// Create a new table in object pool
15361598 /// GC tracks objects via ObjectPool iteration, no allgc list needed
15371599 #[ inline( always) ]
0 commit comments