///|
#cfg(target="native")
fn gc_storage_code(storage : @types.StorageType) -> Int32 {
match storage {
Packed(I8) => 1
Packed(I16) => 2
Val(I32 | F32) => 4
Val(I64 | F64) => 8
Val(V128) => 16
Val(
ContRef
| RefCont
| RefContTyped(_)
| RefNullContTyped(_)
| NullContRef
| RefNoCont
) => -9
Val(_) => -8
}
}
///|
#cfg(target="native")
fn Store::prepare_native_gc_layouts(self : Store) -> Bool {
guard self.references.native.c_heap is Some(heap) else { return true }
let registry = self.native_types
while registry.native_layout_count < registry.representatives.length() {
let identity = registry.native_layout_count
let (graph, index) = registry.representatives[identity]
let (fields, array) = match graph.types[index].composite {
Struct(definition) =>
(
definition.fields.map(field => gc_storage_code(field.storage_type)),
false,
)
Array(definition) =>
([gc_storage_code(definition.element.storage_type)], true)
_ => {
registry.native_layout_count += 1
continue
}
}
if !heap
.get_ptr()
.define_layout(
identity,
FixedArray::makei(fields.length(), i => fields[i]),
array,
) {
return false
}
registry.native_layout_count += 1
}
true
}
///|
#cfg(target="native")
fn Store::allocation_type(
self : Store,
instance : ModuleInstance?,
type_index : Int32,
) -> Int32 raise RuntimeError {
let indices = match instance {
Some(instance) => self.native_types.register(instance)
None => self.module_type_indices()
}
// Publishing a new graph may close the Store or roll back its instance.
self.ensure_open()
if instance is Some(instance) {
self.check_instance(instance)
}
guard type_index >= 0 && type_index < indices.length() else { return -1 }
// Keep this identity even if publication replaced the initialization graph.
indices[type_index]
}
///|
#cfg(target="native")
fn Store::allocation_layout(
self : Store,
identity : Int32,
array~ : Bool = false,
) -> Int32 {
guard identity >= 0 else { return -1 }
let (graph, index) = self.native_types.representatives[identity]
match (array, graph.types[index].composite) {
(false, Struct(_)) | (true, Array(_)) => ()
_ => return -1
}
if !self.prepare_native_gc_layouts() {
return -1
}
identity
}