///|
pub struct Regular {
ptr_field_offset : UInt
n_ptr_fields : UInt
tag : UInt
} derive(Show, ToJson)
///|
pub struct RefArray {
object_size_shift : UInt
len : UInt
} derive(Show, ToJson)
///|
pub struct ValArray {
len : UInt
} derive(Show, ToJson)
///|
pub struct External {
size : UInt
} derive(Show, ToJson)
///|
#external
type Finalizer
///|
pub fn Finalizer::to_funcref(
self : Finalizer,
) -> FuncRef[(@c.Pointer[Unit]) -> Unit] = "%identity"
///|
pub(all) enum Meta {
Regular(Regular)
RefArray(RefArray)
ValArray(ValArray)
External(External)
} derive(Show, ToJson)
///|
pub fn External::finalizer(
self : External,
object : @c.Pointer[Unit],
) -> Finalizer {
let byte_ptr : @c.Pointer[Byte] = object.cast()
let drop_ptr : @c.Pointer[@c.Pointer[Unit]] = byte_ptr
.add(self.size.to_uint64())
.cast()
@c.unsafe_return(drop_ptr.load())
}
///|
pub fn External::set_finalizer(
self : External,
object : @c.Pointer[Unit],
finalizer : FuncRef[(@c.Pointer[Unit]) -> Unit],
) -> Unit {
let byte_ptr : @c.Pointer[Byte] = object.cast()
let drop_ptr : @c.Pointer[@c.Pointer[Unit]] = byte_ptr
.add(self.size.to_uint64())
.cast()
drop_ptr.store(@c.unsafe_borrow(finalizer))
}
///|
pub fn Meta::of_uint(meta : UInt) -> Meta {
let kind = meta >> 30
match kind {
0 => {
// Regular
// 11 bits
let ptr_field_offset = (meta >> 19) & 0x7FF
// 11 bits
let n_ptr_fields = (meta >> 8) & 0x7FF
// 8 bits
let tag = meta & 0xFF
Regular({ ptr_field_offset, n_ptr_fields, tag })
}
1 => {
// RefArray
// 2 bits
let object_size_shift = (meta >> 28) & 0x3
// 28 bits
let len = meta & 0x0FFFFFFF
RefArray({ object_size_shift, len })
}
2 => {
// ValArray
// 2 bits unused
// 28 bits
let len = meta & 0x0FFFFFFF
ValArray({ len, })
}
3 => {
// External
// 30 bits
let size = meta & 0x3FFFFFFF
External({ size, })
}
_ => abort("invalid kind: \{kind}")
}
}
///|
pub fn Meta::to_uint(self : Meta) -> UInt {
match self {
Regular(r) =>
(0 << 30) |
((r.ptr_field_offset & 0x7FF) << 19) |
((r.n_ptr_fields & 0x7FF) << 8) |
(r.tag & 0xFF)
RefArray(ra) =>
(1 << 30) | ((ra.object_size_shift & 0x3) << 28) | (ra.len & 0x0FFFFFFF)
ValArray(va) => (2 << 30) | (va.len & 0x0FFFFFFF)
External(e) => (3 << 30) | (e.size & 0x3FFFFFFF)
}
}
///|
struct Object(@c.Pointer[Int])
///|
pub fn Object::to_pointer(self : Object) -> @c.Pointer[Unit] {
self.0.cast()
}
///|
pub fn Object::rc(self : Object) -> Int {
self.0[0]
}
///|
pub fn Object::set_rc(self : Object, rc : Int) -> Unit {
self.0[0] = rc
}
///|
pub fn Object::meta(self : Object) -> Meta {
Meta::of_uint(self.0[1].reinterpret_as_uint())
}
///|
pub fn Object::set_meta(self : Object, meta : Meta) -> Unit {
self.0[1] = meta.to_uint().reinterpret_as_int()
}
///|
pub fn object_header(object : @c.Pointer[Unit]) -> Object {
Object(object.cast().sub(2))
}
///|
pub extern "c" fn make_external_object(
drop : FuncRef[(@c.Pointer[Unit]) -> Unit],
size : UInt64,
) -> @c.Pointer[Unit] = "tonyfettes_moonbit_make_external_object"
///|
pub extern "c" fn incref(object : @c.Pointer[Unit]) -> Unit = "tonyfettes_moonbit_incref"
///|
pub extern "c" fn decref(object : @c.Pointer[Unit]) -> Unit = "tonyfettes_moonbit_decref"