feat(gc): WIP
This commit is contained in:
@@ -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 => {
|
||||
|
||||
Reference in New Issue
Block a user