feat: gc-arena (WIP, does not compile)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use gc_arena::{Gc, Mutation};
|
||||
use inkwell::AddressSpace;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::execution_engine::ExecutionEngine;
|
||||
@@ -56,7 +57,7 @@ impl<'ctx> Helpers<'ctx> {
|
||||
"capture_env",
|
||||
context
|
||||
.void_type()
|
||||
.fn_type(&[value_type.into(), ptr_type.into()], false),
|
||||
.fn_type(&[value_type.into(), ptr_type.into(), ptr_type.into()], false),
|
||||
None,
|
||||
);
|
||||
let neg = module.add_function(
|
||||
@@ -202,10 +203,10 @@ extern "C" fn helper_debug(value: JITValue) {
|
||||
dbg!(value.tag);
|
||||
}
|
||||
|
||||
extern "C" fn helper_capture_env(thunk: JITValue, env: *const VmEnv) {
|
||||
extern "C" fn helper_capture_env<'gc>(thunk: JITValue, env: *const VmEnv<'gc>, mc: *const Mutation<'gc>) {
|
||||
let thunk = unsafe { (thunk.data.ptr as *const Thunk).as_ref().unwrap() };
|
||||
let env = unsafe { env.as_ref() }.unwrap();
|
||||
thunk.capture(env);
|
||||
let env = unsafe { Gc::from_ptr(env) };
|
||||
thunk.capture(env, unsafe { mc.as_ref() }.unwrap());
|
||||
}
|
||||
|
||||
extern "C" fn helper_neg(rhs: JITValue, _env: *const VmEnv) -> JITValue {
|
||||
@@ -308,12 +309,12 @@ extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_call<'jit>(func: JITValue, arg: JITValue, vm: *const VM<'jit>) -> JITValue {
|
||||
extern "C" fn helper_call(func: JITValue, arg: JITValue, vm: *const VM, mc: *const Mutation) -> JITValue {
|
||||
use ValueTag::*;
|
||||
match func.tag {
|
||||
Function => {
|
||||
let mut func: Value = func.into();
|
||||
func.call(unsafe { vm.as_ref() }.unwrap(), arg.into())
|
||||
func.call(arg.into(), unsafe { vm.as_ref() }.unwrap(), unsafe { mc.as_ref() }.unwrap())
|
||||
.unwrap();
|
||||
func.into()
|
||||
}
|
||||
@@ -321,14 +322,14 @@ extern "C" fn helper_call<'jit>(func: JITValue, arg: JITValue, vm: *const VM<'ji
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn helper_lookup<'jit, 'vm>(sym: usize, env: *const VmEnv<'jit, 'vm>) -> JITValue {
|
||||
extern "C" fn helper_lookup(sym: usize, env: *const VmEnv) -> JITValue {
|
||||
let env = unsafe { env.as_ref() }.unwrap();
|
||||
let val: JITValue = env.lookup(&sym).unwrap().into();
|
||||
val
|
||||
}
|
||||
|
||||
extern "C" fn helper_force<'jit>(thunk: JITValue, vm: *const VM<'jit>) -> JITValue {
|
||||
extern "C" fn helper_force(thunk: JITValue, vm: *const VM, mc: *const Mutation) -> JITValue {
|
||||
let mut val = Value::from(thunk);
|
||||
val.force(unsafe { vm.as_ref() }.unwrap()).unwrap();
|
||||
val.force(unsafe { vm.as_ref() }.unwrap(), unsafe { mc.as_ref() }.unwrap()).unwrap();
|
||||
val.into()
|
||||
}
|
||||
|
||||
112
src/jit/mod.rs
112
src/jit/mod.rs
@@ -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();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
extern crate test;
|
||||
|
||||
use bumpalo::Bump;
|
||||
use gc_arena::Arena;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
|
||||
use inkwell::context::Context;
|
||||
@@ -31,7 +32,6 @@ fn test_expr(expr: &str, expected: Value) {
|
||||
prog.symbols.into(),
|
||||
prog.symmap.into(),
|
||||
prog.consts,
|
||||
Bump::new(),
|
||||
jit,
|
||||
);
|
||||
let env = env(&vm);
|
||||
|
||||
Reference in New Issue
Block a user