use crate::hash_map::{Entry, HashMap};
use crate::module::RegisteredModuleId;
use crate::vm::{GcStoreTraceState, NopHasher, TraceInfo};
use wasmtime_environ::{ModuleInternedTypeIndex, VMSharedTypeIndex};
#[derive(Clone, Copy)]
enum TraceInfoLoc {
HostType(VMSharedTypeIndex),
Module(RegisteredModuleId, ModuleInternedTypeIndex),
}
#[derive(Default)]
pub(super) struct TraceInfos {
map: HashMap<VMSharedTypeIndex, TraceInfoLoc, NopHasher>,
}
impl TraceInfos {
pub fn new() -> Self {
Self {
map: HashMap::default(),
}
}
pub fn clear(&mut self) {
self.map.clear();
}
pub fn trace_info<'a>(
&mut self,
ty: &VMSharedTypeIndex,
state: &'a GcStoreTraceState<'_>,
) -> &'a TraceInfo {
self.trace_info_(ty, state)
.unwrap_or_else(|| panic!("failed to find trace information for {ty:?}"))
}
fn trace_info_<'a>(
&mut self,
ty: &VMSharedTypeIndex,
state: &'a GcStoreTraceState<'_>,
) -> Option<&'a TraceInfo> {
let loc = match self.map.entry(*ty) {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(find_trace_info(ty, state)?),
};
Some(match loc {
TraceInfoLoc::HostType(ty) => state.gc_host_alloc_types[ty].1.as_ref()?,
TraceInfoLoc::Module(module_id, ty) => state
.modules
.module_by_id(*module_id)?
.signatures()
.trace_info(*ty)?,
})
}
}
fn find_trace_info(ty: &VMSharedTypeIndex, state: &GcStoreTraceState<'_>) -> Option<TraceInfoLoc> {
if state.gc_host_alloc_types.contains_key(ty) {
return Some(TraceInfoLoc::HostType(*ty));
}
for (id, module) in state.modules.all_modules() {
if let Some(module_ty) = module.signatures().shared_type_with_trace_info(*ty) {
return Some(TraceInfoLoc::Module(id, module_ty));
}
}
None
}