Skip to content

Commit bb03baa

Browse files
committed
update gc
1 parent 1aecf9f commit bb03baa

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

crates/luars/src/lua_vm/execute/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,9 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
493493
}
494494
UpvalueState::Closed(val) => *val = value,
495495
};
496+
497+
// GC write barrier for upvalue
498+
vm.gc_barrier_upvalue(upvalue_id, &value);
496499
}
497500
continue 'mainloop;
498501
}

crates/luars/src/lua_vm/execute/table_instructions.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ pub fn exec_settable(
180180
lua_table.raw_set(key_value, set_value);
181181
}
182182

183-
// Note: GC barrier is handled lazily during collection
183+
// GC write barrier: if table is old and value is young, mark table as touched
184+
vm.gc_barrier_back_table(table_id, &set_value);
184185
return Ok(());
185186
}
186187
}
@@ -271,8 +272,8 @@ pub fn exec_seti(
271272
let lua_table = unsafe { vm.object_pool.get_table_mut_unchecked(table_id) };
272273
lua_table.set_int(b, set_value);
273274

274-
// Note: GC barrier is handled lazily during collection
275-
// This significantly improves write performance
275+
// GC write barrier
276+
vm.gc_barrier_back_table(table_id, &set_value);
276277
return Ok(());
277278
}
278279
}
@@ -371,6 +372,8 @@ pub fn exec_setfield(
371372
let table_ref = unsafe { vm.object_pool.get_table_mut_unchecked(table_id) };
372373
// Ultra-fast path: direct set without any metamethod checks
373374
table_ref.raw_set(key_value, set_value);
375+
// GC write barrier
376+
vm.gc_barrier_back_table(table_id, &set_value);
374377
return Ok(());
375378
}
376379
}
@@ -487,7 +490,8 @@ pub fn exec_settabup(
487490
// Ultra-fast path: direct set without any metamethod checks
488491
table_ref.raw_set(key_value.clone(), set_value.clone());
489492

490-
// Note: GC barrier is handled lazily during collection
493+
// GC write barrier
494+
vm.gc_barrier_back_table(table_id, &set_value);
491495
return Ok(());
492496
}
493497
}

crates/luars/src/lua_vm/mod.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod lua_call_frame;
55
mod lua_error;
66
mod opcode;
77

8-
use crate::gc::{GC, GcFunction, ThreadId, UpvalueId};
8+
use crate::gc::{GC, GcFunction, TableId, ThreadId, UpvalueId};
99
#[cfg(feature = "async")]
1010
use crate::lua_async::AsyncExecutor;
1111
use 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

Comments
 (0)