feat(gc): WIP

This commit is contained in:
2025-06-02 12:00:38 +08:00
parent 20b2b6f1ef
commit d3442e87e7
7 changed files with 72 additions and 77 deletions

View File

@@ -1,5 +1,6 @@
use std::cell::RefCell;
use gc_arena::arena::CollectionPhase;
use gc_arena::{Arena, Collect, Gc, Mutation, Rootable};
use hashbrown::{HashMap, HashSet};
use inkwell::context::Context;
@@ -21,6 +22,7 @@ use ecow::EcoString;
mod test;
const STACK_SIZE: usize = 8 * 1024 / size_of::<Value>();
const COLLECTOR_GRANULARITY: f64 = 1024.0;
#[derive(Collect)]
#[collect(require_static)]
@@ -59,6 +61,7 @@ pub fn run(mut prog: Program) -> Result<p::Value> {
Ok(val.to_public(&root.vm, &mut HashSet::new()))
})
}
pub fn eval<T, F: for<'gc> FnOnce(Value<'gc>, &mut GcRoot<'gc>, &Mutation<'gc>) -> Result<T>>(
opcodes: Box<[OpCode]>,
arena: &mut Arena<impl for<'gc> Rootable<'gc, Root = GcRoot<'gc>>>,
@@ -85,21 +88,23 @@ pub fn eval<T, F: for<'gc> FnOnce(Value<'gc>, &mut GcRoot<'gc>, &Mutation<'gc>)
opcodes.extend(code);
root.envs.push(env);
}
Consq::PopEnv => _ = root.envs.pop().unwrap(),
Consq::PopEnv => {
let _ = root.envs.pop().unwrap();
}
Consq::Call => {
let arg = root.stack.pop();
let func = root.stack.pop().unwrap_func();
let env = func.env.enter_arg(arg, mc);
let count = func.count.get();
func.count.set(count + 1);
if count >= 1 {
if count > 1 {
let compiled = func
.compiled
.borrow_mut(mc)
.get_or_insert_with(|| root.vm.compile_func(func.func))
.clone();
let ret =
unsafe { compiled.call(env.as_ref() as *const VmEnv, mc as *const _) };
unsafe { compiled(env.as_ref() as *const VmEnv, mc as *const _) };
root.stack.push(ret.into())?;
} else {
root.envs.push(env);
@@ -110,7 +115,13 @@ pub fn eval<T, F: for<'gc> FnOnce(Value<'gc>, &mut GcRoot<'gc>, &Mutation<'gc>)
}
Result::Ok(())
})?;
arena.finish_cycle();
if arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY {
if arena.collection_phase() == CollectionPhase::Sweeping {
arena.collect_debt();
} else if let Some(marked) = arena.mark_debt() {
marked.start_sweeping();
}
}
}
arena.collect_debt();
arena.mutate_root(|mc, root| {
@@ -128,6 +139,11 @@ enum Consq {
NoOp,
}
enum CycleAction {
Collect,
NoOp
}
#[inline(always)]
fn single_op<'gc, const CAP: usize>(
vm: &'gc VM<'gc>,
@@ -159,7 +175,7 @@ fn single_op<'gc, const CAP: usize>(
let Some(val) = stack.tos().as_ref().unwrap_thunk().get_value() else {
return Ok(Consq::Force);
};
*stack.tos_mut() = val;
*stack.tos_mut() = val.clone();
}
OpCode::InsertValue => {
let val = stack.pop();
@@ -186,7 +202,7 @@ fn single_op<'gc, const CAP: usize>(
stack.push(Value::Func(Gc::new(mc, Func::new(func, *env, mc))))?;
}
OpCode::Arg { level } => {
stack.push(env.lookup_arg(level))?;
stack.push(env.lookup_arg(level).clone())?;
}
OpCode::UnOp { op } => {
use UnOp::*;
@@ -289,7 +305,7 @@ fn single_op<'gc, const CAP: usize>(
)?;
}
OpCode::LookUpLet { level, idx } => {
stack.push(env.lookup_let(level, idx))?;
stack.push(env.lookup_let(level, idx).clone())?;
}
OpCode::LeaveEnv => *env = env.leave(),
OpCode::EnterWithEnv => {