#[cfg(not(target_family = "wasm"))]
use std::collections::HashMap;
use crate::runtime_core::{HeapObject, Value, HEAP_TAG, PTR_TAG_MASK};
pub type CodeHandle = u64;
pub trait ValueStore {
fn alloc(&mut self, object: HeapObject) -> Value;
fn try_get(&self, value: Value) -> Option<&HeapObject>;
fn try_get_mut(&mut self, value: Value) -> Option<&mut HeapObject>;
}
#[derive(Default)]
pub struct HandleStore {
arena: Vec<HeapObject>,
}
impl HandleStore {
pub fn new() -> HandleStore {
HandleStore::default()
}
fn index_of(value: Value) -> Option<usize> {
if value & PTR_TAG_MASK != HEAP_TAG {
return None;
}
Some((value >> 3) as usize)
}
}
impl ValueStore for HandleStore {
fn alloc(&mut self, object: HeapObject) -> Value {
self.arena.push(object);
(((self.arena.len() - 1) as u64) << 3) | HEAP_TAG
}
fn try_get(&self, value: Value) -> Option<&HeapObject> {
self.arena.get(Self::index_of(value)?)
}
fn try_get_mut(&mut self, value: Value) -> Option<&mut HeapObject> {
let index = Self::index_of(value)?;
self.arena.get_mut(index)
}
}
#[cfg(not(target_family = "wasm"))]
#[repr(align(8))]
struct HeapCell(HeapObject);
#[cfg(not(target_family = "wasm"))]
#[derive(Default)]
pub struct PointerStore {
cells: HashMap<Value, Box<HeapCell>>,
}
#[cfg(not(target_family = "wasm"))]
impl PointerStore {
pub fn new() -> PointerStore {
PointerStore::default()
}
}
#[cfg(not(target_family = "wasm"))]
impl ValueStore for PointerStore {
fn alloc(&mut self, object: HeapObject) -> Value {
let cell = Box::new(HeapCell(object));
let address = cell.as_ref() as *const HeapCell as u64;
debug_assert_eq!(address & PTR_TAG_MASK, 0, "heap cells must be 8-byte aligned");
let value = address | HEAP_TAG;
let replaced = self.cells.insert(value, cell);
debug_assert!(replaced.is_none(), "live heap addresses must be unique");
value
}
fn try_get(&self, value: Value) -> Option<&HeapObject> {
if value & PTR_TAG_MASK != HEAP_TAG {
return None;
}
self.cells.get(&value).map(|cell| &cell.0)
}
fn try_get_mut(&mut self, value: Value) -> Option<&mut HeapObject> {
if value & PTR_TAG_MASK != HEAP_TAG {
return None;
}
self.cells.get_mut(&value).map(|cell| &mut cell.0)
}
}