runtime: refactor Memory to always use Box<dyn RuntimeLinearMemory> (#4086)

While working with the runtime `Memory` object, it became clear that
some refactoring was needed. In order to implement shared memory from
the threads proposal, we must be able to atomically change the memory
size. Previously, the split into variants, `Memory::Static` and
`Memory::Dynamic`, made any attempt to lock forced us to duplicate logic
in various places.

This change moves `enum Memory { Static..., Dynamic... }` to simply
`struct Memory(Box<dyn RuntimeLinearMemory>)`. A new type,
`ExternalMemory`, takes the place of `Memory::Static` and also
implements the `RuntimeLinearMemory` trait, allowing `Memory` to contain
the same two options as before: `MmapMemory` for `Memory::Dynamic` and
`ExternalMemory` for `Memory::Static`. To interface with the
`PoolingAllocator`, this change also required the ability to downcast to
the internal representation.
This commit is contained in:
Andrew Brown
2022-04-29 08:12:38 -07:00
committed by GitHub
parent 5b7d56f6f7
commit 3dbdcfa220
3 changed files with 181 additions and 173 deletions

View File

@@ -445,34 +445,25 @@ impl InstancePool {
instance_index: usize,
memories: &mut PrimaryMap<DefinedMemoryIndex, Memory>,
) {
// Decommit any linear memories that were used
for ((def_mem_idx, memory), base) in
memories.iter_mut().zip(self.memories.get(instance_index))
// Decommit any linear memories that were used.
let memories = mem::take(memories);
for ((def_mem_idx, mut memory), base) in
memories.into_iter().zip(self.memories.get(instance_index))
{
let memory = mem::take(memory);
assert!(memory.is_static());
match memory {
Memory::Static {
memory_image: Some(mut image),
..
} => {
// If there was any error clearing the image, just
// drop it here, and let the drop handler for the
// slot unmap in a way that retains the
// address space reservation.
if image.clear_and_remain_ready().is_ok() {
self.memories
.return_memory_image_slot(instance_index, def_mem_idx, image);
}
}
_ => {
let size = memory.byte_size();
drop(memory);
decommit_memory_pages(base, size)
.expect("failed to decommit linear memory pages");
let size = memory.byte_size();
if let Some(mut image) = memory.unwrap_static_image() {
// Reset the image slot. If there is any error clearing the
// image, just drop it here, and let the drop handler for the
// slot unmap in a way that retains the address space
// reservation.
if image.clear_and_remain_ready().is_ok() {
self.memories
.return_memory_image_slot(instance_index, def_mem_idx, image);
}
} else {
// Otherwise, decommit the memory pages.
decommit_memory_pages(base, size).expect("failed to decommit linear memory pages");
}
}
}