feat: gc-arena (WIP, does not compile)

This commit is contained in:
2025-05-25 17:18:54 +08:00
parent b41fd38bcc
commit cc06369c5e
17 changed files with 882 additions and 585 deletions

View File

@@ -1,5 +1,6 @@
use std::rc::Rc;
use std::ops::Deref;
use gc_arena::{Collect, Gc};
use inkwell::OptimizationLevel;
use inkwell::builder::Builder;
use inkwell::context::Context;
@@ -55,42 +56,36 @@ pub union JITValueData {
ptr: *const (),
}
impl<'jit: 'vm, 'vm> From<JITValue> for Value<'jit, 'vm> {
impl<'gc> From<JITValue> for Value<'gc> {
fn from(value: JITValue) -> Self {
use ValueTag::*;
match value.tag {
List | AttrSet | String | Function | Thunk | Path => unsafe {
Rc::increment_strong_count(value.data.ptr);
},
_ => (),
}
match value.tag {
Int => Value::Const(Const::Int(unsafe { value.data.int })),
Null => Value::Const(Const::Null),
Function => Value::Func(unsafe { Rc::from_raw(value.data.ptr as *const _) }),
Thunk => Value::Thunk(unsafe { Rc::from_raw(value.data.ptr as *const _) }),
Function => Value::Func(unsafe { Gc::from_ptr(value.data.ptr as *const _) }),
Thunk => Value::Thunk(self::Thunk { thunk: unsafe { Gc::from_ptr(value.data.ptr as *const _) } }),
_ => todo!("not implemented for {:?}", value.tag),
}
}
}
impl From<&Value<'_, '_>> for JITValue {
fn from(value: &Value<'_, '_>) -> Self {
match value {
impl From<&Value<'_>> for JITValue {
fn from(value: &Value<'_>) -> Self {
match *value {
Value::Const(Const::Int(int)) => JITValue {
tag: ValueTag::Int,
data: JITValueData { int: *int },
data: JITValueData { int },
},
Value::Func(func) => JITValue {
tag: ValueTag::Function,
data: JITValueData {
ptr: Rc::as_ptr(func) as *const _,
ptr: Gc::as_ptr(func) as *const _,
},
},
Value::Thunk(thunk) => JITValue {
Value::Thunk(ref thunk) => JITValue {
tag: ValueTag::Thunk,
data: JITValueData {
ptr: Rc::as_ptr(thunk) as *const _,
ptr: Gc::as_ptr(thunk.thunk) as *const _,
},
},
_ => todo!(),
@@ -98,8 +93,8 @@ impl From<&Value<'_, '_>> for JITValue {
}
}
impl From<Value<'_, '_>> for JITValue {
fn from(value: Value<'_, '_>) -> Self {
impl From<Value<'_>> for JITValue {
fn from(value: Value) -> Self {
match value {
Value::Const(Const::Int(int)) => JITValue {
tag: ValueTag::Int,
@@ -108,13 +103,13 @@ impl From<Value<'_, '_>> for JITValue {
Value::Func(func) => JITValue {
tag: ValueTag::Function,
data: JITValueData {
ptr: Rc::into_raw(func) as *const _,
ptr: Gc::as_ptr(func) as *const _,
},
},
Value::Thunk(thunk) => JITValue {
tag: ValueTag::Thunk,
data: JITValueData {
ptr: Rc::into_raw(thunk) as *const _,
ptr: Gc::as_ptr(thunk.thunk) as *const _,
},
},
_ => todo!(),
@@ -122,20 +117,43 @@ impl From<Value<'_, '_>> for JITValue {
}
}
pub type JITFunc<'jit, 'vm> =
unsafe extern "C" fn(*const VM<'jit>, *const VmEnv<'jit, 'vm>) -> JITValue;
#[derive(Collect)]
#[collect(require_static)]
pub struct JITFunc<'gc>(JitFunction<'gc, unsafe extern "C" fn(*const VM<'gc>, *const VmEnv<'gc>) -> JITValue>);
pub struct JITContext<'ctx> {
context: &'ctx Context,
module: Module<'ctx>,
builder: Builder<'ctx>,
execution_engine: ExecutionEngine<'ctx>,
helpers: Helpers<'ctx>,
impl<'gc> From<JitFunction<'gc, unsafe extern "C" fn(*const VM<'gc>, *const VmEnv<'gc>) -> JITValue>> for JITFunc<'gc> {
fn from(value: JitFunction<'gc, unsafe extern "C" fn(*const VM<'gc>, *const VmEnv<'gc>) -> JITValue>) -> Self {
Self(value)
}
}
impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
pub fn new(context: &'ctx Context) -> Self {
impl<'gc> Deref for JITFunc<'gc> {
type Target = JitFunction<'gc, unsafe extern "C" fn(*const VM<'gc>, *const VmEnv<'gc>) -> JITValue>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct JITContext<'gc> {
context: &'gc Context,
module: Module<'gc>,
builder: Builder<'gc>,
execution_engine: ExecutionEngine<'gc>,
helpers: Helpers<'gc>,
}
unsafe impl<'gc> Collect for JITContext<'gc> {
fn trace(&self, _cc: &gc_arena::Collection) {}
fn needs_trace() -> bool
where
Self: Sized, {
false
}
}
impl<'gc> JITContext<'gc> {
pub fn new(context: &'gc Context) -> Self {
// force linker to link JIT engine
unsafe {
inkwell::llvm_sys::execution_engine::LLVMLinkInMCJIT();
@@ -156,7 +174,7 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
}
}
pub fn new_ptr<T>(&self, ptr: *const T) -> PointerValue<'ctx> {
pub fn new_ptr<T>(&self, ptr: *const T) -> PointerValue<'gc> {
self.builder
.build_int_to_ptr(
self.helpers.int_type.const_int(ptr as _, false),
@@ -166,11 +184,11 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
.unwrap()
}
pub fn compile_function<'bump>(
pub fn compile_function(
&self,
func: &Func,
vm: &'vm VM<'ctx>,
) -> Result<JitFunction<'ctx, JITFunc<'ctx, 'vm>>> {
func: &'gc Func,
vm: &'gc VM<'gc>,
) -> Result<JITFunc<'gc>> {
let mut stack = Stack::<_, STACK_SIZE>::new();
let mut iter = func.opcodes.iter().copied();
let func_ = self
@@ -190,8 +208,8 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
if func_.verify(true) {
unsafe {
let name = func_.get_name().to_str().unwrap();
let addr = self.execution_engine.get_function(name).unwrap();
Ok(addr)
let func = self.execution_engine.get_function(name).unwrap();
Ok(func.into())
}
} else {
todo!()
@@ -201,10 +219,10 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
fn build_expr<const CAP: usize>(
&self,
iter: &mut impl Iterator<Item = OpCode>,
vm: &'vm VM<'_>,
env: PointerValue<'ctx>,
stack: &mut Stack<BasicValueEnum<'ctx>, CAP>,
func: FunctionValue<'ctx>,
vm: &'gc VM<'gc>,
env: PointerValue<'gc>,
stack: &mut Stack<BasicValueEnum<'gc>, CAP>,
func: FunctionValue<'gc>,
mut length: usize,
) -> Result<usize> {
while length > 1 {
@@ -270,9 +288,9 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
fn single_op<const CAP: usize>(
&self,
opcode: OpCode,
vm: &'vm VM<'_>,
env: PointerValue<'ctx>,
stack: &mut Stack<BasicValueEnum<'ctx>, CAP>,
vm: &'gc VM<'_>,
env: PointerValue<'gc>,
stack: &mut Stack<BasicValueEnum<'gc>, CAP>,
) -> Result<usize> {
match opcode {
OpCode::Const { idx } => {
@@ -287,7 +305,7 @@ impl<'vm, 'ctx: 'vm> JITContext<'ctx> {
}
OpCode::LoadThunk { idx } => stack.push(
self.helpers
.new_thunk(Rc::into_raw(Rc::new(Thunk::new(vm.get_thunk(idx))))),
.new_thunk(Thunk::new(vm.get_thunk(idx))),
)?,
OpCode::CaptureEnv => {
let thunk = *stack.tos();