use std::cell::RefCell;
use crate::eval::compiler::def::FrozenDef;
use crate::values::AllocFrozenValue;
use crate::values::FreezeResult;
use crate::values::FrozenHeap;
use crate::values::FrozenValueTyped;
use crate::values::HeapSendable;
use crate::values::layout::avalue::AValue;
use crate::values::layout::heap::arena::Reservation;
use crate::values::layout::heap::repr::AValueOrForwardUnpack;
use crate::values::layout::heap::send::HeapSyncable;
use crate::values::layout::value::FrozenValue;
use crate::values::layout::value::Value;
pub struct Freezer<'fv> {
pub(crate) heap: &'fv FrozenHeap,
pub(crate) frozen_defs: RefCell<Vec<FrozenValueTyped<'static, FrozenDef>>>,
}
impl<'fv> Freezer<'fv> {
pub(crate) fn new(heap: &'fv FrozenHeap) -> Self {
Freezer {
heap,
frozen_defs: RefCell::new(Vec::new()),
}
}
pub fn alloc<'v, T: AllocFrozenValue>(&'v self, val: T) -> FrozenValue {
val.alloc_frozen_value(self.heap)
}
pub(crate) fn reserve<'v, 'v2, T>(&'v self) -> (FrozenValue, Reservation<'v2, T>)
where
T: AValue<'v2, ExtraElem = ()>,
T::StarlarkValue: HeapSendable<'v2>,
T::StarlarkValue: HeapSyncable<'v2>,
{
let (fv, r, extra) = self.heap.reserve_with_extra::<T>(0);
let extra = unsafe { &mut *extra };
debug_assert!(extra.is_empty());
(fv, r)
}
pub fn freeze(&self, value: Value) -> FreezeResult<FrozenValue> {
if let Some(x) = value.unpack_frozen() {
return Ok(x);
}
let value = value.0.unpack_ptr().unwrap();
match value.unpack() {
AValueOrForwardUnpack::Forward(x) => {
Ok(unsafe { x.forward_ptr().unpack_frozen_value() })
}
AValueOrForwardUnpack::Header(v) => unsafe { v.unpack().heap_freeze(self) },
}
}
pub fn frozen_heap(&self) -> &'fv FrozenHeap {
self.heap
}
}