mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 05:31:32 +00:00
Local/Import index differentiation
This commit is contained in:
@ -25,9 +25,9 @@ use wasmer_runtime::{
|
|||||||
types::{
|
types::{
|
||||||
ElementType as WasmerElementType, FuncIndex as WasmerFuncIndex, FuncSig as WasmerSignature,
|
ElementType as WasmerElementType, FuncIndex as WasmerFuncIndex, FuncSig as WasmerSignature,
|
||||||
Global as WasmerGlobal, GlobalDesc as WasmerGlobalDesc, GlobalIndex as WasmerGlobalIndex,
|
Global as WasmerGlobal, GlobalDesc as WasmerGlobalDesc, GlobalIndex as WasmerGlobalIndex,
|
||||||
Initializer as WasmerInitializer, Map, MapIndex, Memory as WasmerMemory,
|
GlobalInit as WasmerGlobalInit, Initializer as WasmerInitializer, Map,
|
||||||
MemoryIndex as WasmerMemoryIndex, SigIndex as WasmerSignatureIndex, Table as WasmerTable,
|
Memory as WasmerMemory, MemoryIndex as WasmerMemoryIndex, SigIndex as WasmerSignatureIndex,
|
||||||
TableIndex as WasmerTableIndex, Type as WasmerType,
|
Table as WasmerTable, TableIndex as WasmerTableIndex, Type as WasmerType, TypedIndex,
|
||||||
},
|
},
|
||||||
vm::{self, Ctx as WasmerVMContext},
|
vm::{self, Ctx as WasmerVMContext},
|
||||||
};
|
};
|
||||||
@ -142,14 +142,14 @@ pub mod converter {
|
|||||||
|
|
||||||
// TODO: WasmerGlobal does not support `Import` as Global values.
|
// TODO: WasmerGlobal does not support `Import` as Global values.
|
||||||
let init = match global.initializer {
|
let init = match global.initializer {
|
||||||
I32Const(val) => Const(val.into()),
|
I32Const(val) => WasmerGlobalInit::Init(Const(val.into())),
|
||||||
I64Const(val) => Const(val.into()),
|
I64Const(val) => WasmerGlobalInit::Init(Const(val.into())),
|
||||||
F32Const(val) => Const(f32::from_bits(val).into()),
|
F32Const(val) => WasmerGlobalInit::Init(Const(f32::from_bits(val).into())),
|
||||||
F64Const(val) => Const(f64::from_bits(val).into()),
|
F64Const(val) => WasmerGlobalInit::Init(Const(f64::from_bits(val).into())),
|
||||||
GlobalInit::GetGlobal(index) => {
|
GlobalInit::GetGlobal(index) => WasmerGlobalInit::Init(WasmerInitializer::GetGlobal(
|
||||||
WasmerInitializer::GetGlobal(WasmerGlobalIndex::new(index.index()))
|
WasmerGlobalIndex::new(index.index()),
|
||||||
},
|
)),
|
||||||
GlobalInit::Import => WasmerInitializer::Import
|
GlobalInit::Import => WasmerGlobalInit::Import,
|
||||||
};
|
};
|
||||||
|
|
||||||
WasmerGlobal { desc, init }
|
WasmerGlobal { desc, init }
|
||||||
@ -173,6 +173,7 @@ pub mod converter {
|
|||||||
|
|
||||||
/// Converts a Cranelift table to a Wasmer table.
|
/// Converts a Cranelift table to a Wasmer table.
|
||||||
pub fn convert_memory(memory: Memory) -> WasmerMemory {
|
pub fn convert_memory(memory: Memory) -> WasmerMemory {
|
||||||
|
println!("codegen memory: {:?}", memory);
|
||||||
WasmerMemory {
|
WasmerMemory {
|
||||||
shared: memory.shared,
|
shared: memory.shared,
|
||||||
min: memory.minimum,
|
min: memory.minimum,
|
||||||
@ -350,29 +351,71 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
/// by `index`.
|
/// by `index`.
|
||||||
///
|
///
|
||||||
/// The index space covers both imported and locally declared globals.
|
/// The index space covers both imported and locally declared globals.
|
||||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
fn make_global(
|
||||||
|
&mut self,
|
||||||
|
func: &mut ir::Function,
|
||||||
|
global_index: GlobalIndex,
|
||||||
|
) -> GlobalVariable {
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
let ptr_size = self.pointer_bytes();
|
|
||||||
let globals_offset = WasmerVMContext::offset_globals();
|
|
||||||
|
|
||||||
// Load value at (vmctx + globals_offset), i.e. the address at Ctx.globals.
|
if global_index.index() < self.module.imported_globals.len() {
|
||||||
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
// imported global
|
||||||
base: vmctx,
|
|
||||||
offset: Offset32::new(globals_offset as i32),
|
|
||||||
global_type: self.pointer_type(),
|
|
||||||
readonly: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// *Ctx.globals -> [ u8, u8, .. ]
|
let imported_globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
// Based on the index provided, we need to know the offset into globals array
|
base: vmctx,
|
||||||
let offset = index.index() * ptr_size as usize;
|
offset: (vm::Ctx::offset_imported_globals() as i32).into(),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Create global variable based on the data above.
|
let offset = global_index.index() * vm::ImportedGlobal::size() as usize;
|
||||||
GlobalVariable::Memory {
|
|
||||||
gv: globals_base_addr,
|
let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
offset: (offset as i32).into(),
|
base: imported_globals_base_addr,
|
||||||
ty: self.module.get_global(index).ty,
|
offset: (offset as i64).into(),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let local_global_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: imported_global_addr,
|
||||||
|
offset: (vm::ImportedGlobal::offset_global() as i32).into(),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
GlobalVariable::Memory {
|
||||||
|
gv: local_global_addr,
|
||||||
|
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
||||||
|
ty: self.module.get_global(global_index).ty,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// locally defined global
|
||||||
|
|
||||||
|
let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load {
|
||||||
|
base: vmctx,
|
||||||
|
offset: (vm::Ctx::offset_globals() as i32).into(),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// *Ctx.globals -> [ u8, u8, .. ]
|
||||||
|
// Based on the index provided, we need to know the offset into globals array
|
||||||
|
let offset = (global_index.index() - self.module.imported_globals.len())
|
||||||
|
* vm::LocalGlobal::size() as usize;
|
||||||
|
|
||||||
|
let local_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
|
base: globals_base_addr,
|
||||||
|
offset: (offset as i64).into(),
|
||||||
|
global_type: self.pointer_type(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create global variable based on the data above.
|
||||||
|
GlobalVariable::Memory {
|
||||||
|
gv: local_global_addr,
|
||||||
|
offset: (vm::LocalGlobal::offset_data() as i32).into(),
|
||||||
|
ty: self.module.get_global(global_index).ty,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,13 +913,18 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
elements: Vec<FuncIndex>,
|
elements: Vec<FuncIndex>,
|
||||||
) {
|
) {
|
||||||
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
// Convert Cranelift GlobalIndex to wamser GlobalIndex
|
||||||
let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
|
// let base = base.map(|index| WasmerGlobalIndex::new(index.index()));
|
||||||
|
let base = match base {
|
||||||
|
Some(global_index) => {
|
||||||
|
WasmerInitializer::GetGlobal(WasmerGlobalIndex::new(global_index.index()))
|
||||||
|
}
|
||||||
|
None => WasmerInitializer::Const((offset as i32).into()),
|
||||||
|
};
|
||||||
|
|
||||||
// Add table initializer to list of table initializers
|
// Add table initializer to list of table initializers
|
||||||
self.table_initializers.push(TableInitializer {
|
self.table_initializers.push(TableInitializer {
|
||||||
table_index: WasmerTableIndex::new(table_index.index()),
|
table_index: WasmerTableIndex::new(table_index.index()),
|
||||||
base,
|
base,
|
||||||
offset,
|
|
||||||
elements: elements
|
elements: elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|index| WasmerFuncIndex::new(index.index()))
|
.map(|index| WasmerFuncIndex::new(index.index()))
|
||||||
|
@ -2,6 +2,7 @@ pub mod codegen;
|
|||||||
mod libcalls;
|
mod libcalls;
|
||||||
mod relocation;
|
mod relocation;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
// mod module;
|
||||||
|
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
isa,
|
isa,
|
||||||
|
20
lib/clif-backend/src/module.rs
Normal file
20
lib/clif-backend/src/module.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use wasmer_runtime::{
|
||||||
|
backend::SigRegistry,
|
||||||
|
memory::LinearMemory,
|
||||||
|
module::{
|
||||||
|
DataInitializer, ExportIndex, ImportName, ModuleInner, TableInitializer,
|
||||||
|
},
|
||||||
|
types::{
|
||||||
|
ElementType, FuncIndex, FuncSig,
|
||||||
|
Global, GlobalDesc, GlobalIndex,
|
||||||
|
Initializer, Map, TypedIndex, Memory,
|
||||||
|
MemoryIndex as WasmerMemoryIndex, SigIndex as WasmerSignatureIndex, Table as WasmerTable,
|
||||||
|
TableIndex as WasmerTableIndex, Type as WasmerType, GlobalInit as WasmerGlobalInit,
|
||||||
|
},
|
||||||
|
vm::{self, Ctx as WasmerVMContext},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is a wasmer module.
|
||||||
|
pub struct Module {
|
||||||
|
|
||||||
|
}
|
@ -7,15 +7,15 @@ use std::ptr::{write_unaligned, NonNull};
|
|||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
self,
|
self,
|
||||||
backend::{self, Mmap, Protect},
|
backend::{self, Mmap, Protect},
|
||||||
types::{FuncIndex, Map, MapIndex},
|
types::{LocalFuncIndex, Map, TypedIndex},
|
||||||
vm, vmcalls,
|
vm, vmcalls,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct FuncResolverBuilder {
|
pub struct FuncResolverBuilder {
|
||||||
resolver: FuncResolver,
|
resolver: FuncResolver,
|
||||||
relocations: Map<FuncIndex, Vec<Relocation>>,
|
relocations: Map<LocalFuncIndex, Vec<Relocation>>,
|
||||||
trap_sinks: Map<FuncIndex, TrapSink>,
|
trap_sinks: Map<LocalFuncIndex, TrapSink>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncResolverBuilder {
|
impl FuncResolverBuilder {
|
||||||
@ -158,15 +158,13 @@ impl FuncResolverBuilder {
|
|||||||
/// Resolves a function index to a function address.
|
/// Resolves a function index to a function address.
|
||||||
pub struct FuncResolver {
|
pub struct FuncResolver {
|
||||||
num_imported_funcs: usize,
|
num_imported_funcs: usize,
|
||||||
map: Map<FuncIndex, usize>,
|
map: Map<LocalFuncIndex, usize>,
|
||||||
memory: Mmap,
|
memory: Mmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncResolver {
|
impl FuncResolver {
|
||||||
fn lookup(&self, index: FuncIndex) -> Option<NonNull<vm::Func>> {
|
fn lookup(&self, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||||
let offset = *self
|
let offset = *self.map.get(local_func_index)?;
|
||||||
.map
|
|
||||||
.get(FuncIndex::new(index.index() - self.num_imported_funcs))?;
|
|
||||||
let ptr = unsafe { self.memory.as_ptr().add(offset) };
|
let ptr = unsafe { self.memory.as_ptr().add(offset) };
|
||||||
|
|
||||||
NonNull::new(ptr).map(|nonnull| nonnull.cast())
|
NonNull::new(ptr).map(|nonnull| nonnull.cast())
|
||||||
|
@ -88,8 +88,8 @@ static IMPORT_MODULE: &str = r#"
|
|||||||
(type $t1 (func))
|
(type $t1 (func))
|
||||||
(func $print_i32 (export "print_i32") (type $t0) (param $lhs i32))
|
(func $print_i32 (export "print_i32") (type $t0) (param $lhs i32))
|
||||||
(func $print (export "print") (type $t1))
|
(func $print (export "print") (type $t1))
|
||||||
(table $table (export "table") 10 anyfunc)
|
(table $table (export "table") 10 20 anyfunc)
|
||||||
(memory $memory (export "memory") 1)
|
(memory $memory (export "memory") 1 2)
|
||||||
(global $global_i32 (export "global_i32") i32 (i32.const 666)))
|
(global $global_i32 (export "global_i32") i32 (i32.const 666)))
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
@ -350,6 +350,7 @@ fn test_module_{}() {{
|
|||||||
format!(
|
format!(
|
||||||
"fn create_module_{}() -> Instance {{
|
"fn create_module_{}() -> Instance {{
|
||||||
let module_str = \"{}\";
|
let module_str = \"{}\";
|
||||||
|
println!(\"{{}}\", module_str);
|
||||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\");
|
let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\");
|
||||||
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect(\"WASM can't be compiled\");
|
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect(\"WASM can't be compiled\");
|
||||||
module.instantiate(&mut generate_imports()).expect(\"WASM can't be instantiated\")
|
module.instantiate(&mut generate_imports()).expect(\"WASM can't be instantiated\")
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{module::ModuleInner, types::FuncIndex, vm};
|
use crate::{module::ModuleInner, types::LocalFuncIndex, vm};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
pub use crate::mmap::{Mmap, Protect};
|
pub use crate::mmap::{Mmap, Protect};
|
||||||
@ -10,5 +10,9 @@ pub trait Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait FuncResolver {
|
pub trait FuncResolver {
|
||||||
fn get(&self, module: &ModuleInner, index: FuncIndex) -> Option<NonNull<vm::Func>>;
|
fn get(
|
||||||
|
&self,
|
||||||
|
module: &ModuleInner,
|
||||||
|
local_func_index: LocalFuncIndex,
|
||||||
|
) -> Option<NonNull<vm::Func>>;
|
||||||
}
|
}
|
||||||
|
@ -3,28 +3,34 @@ use crate::{
|
|||||||
import::Imports,
|
import::Imports,
|
||||||
memory::LinearMemory,
|
memory::LinearMemory,
|
||||||
module::{ImportName, ModuleInner},
|
module::{ImportName, ModuleInner},
|
||||||
|
structures::{BoxedMap, Map, SliceMap, TypedIndex},
|
||||||
table::{TableBacking, TableElements},
|
table::{TableBacking, TableElements},
|
||||||
types::{Initializer, MapIndex, Value},
|
types::{
|
||||||
|
ElementType, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex,
|
||||||
|
ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport,
|
||||||
|
LocalTableIndex, Type, Value,
|
||||||
|
},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LocalBacking {
|
pub struct LocalBacking {
|
||||||
pub(crate) memories: Box<[LinearMemory]>,
|
pub(crate) memories: BoxedMap<LocalMemoryIndex, LinearMemory>,
|
||||||
pub(crate) tables: Box<[TableBacking]>,
|
pub(crate) tables: BoxedMap<LocalTableIndex, TableBacking>,
|
||||||
|
|
||||||
pub(crate) vm_memories: Box<[vm::LocalMemory]>,
|
pub(crate) vm_memories: BoxedMap<LocalMemoryIndex, vm::LocalMemory>,
|
||||||
pub(crate) vm_tables: Box<[vm::LocalTable]>,
|
pub(crate) vm_tables: BoxedMap<LocalTableIndex, vm::LocalTable>,
|
||||||
pub(crate) vm_globals: Box<[vm::LocalGlobal]>,
|
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalBacking {
|
impl LocalBacking {
|
||||||
pub fn memory(&mut self, index: u32) -> &mut LinearMemory {
|
pub fn memory(&mut self, local_memory_index: LocalMemoryIndex) -> &mut LinearMemory {
|
||||||
&mut self.memories[index as usize]
|
&mut self.memories[local_memory_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table(&mut self, index: u32) -> &mut TableBacking {
|
pub fn table(&mut self, local_table_index: LocalTableIndex) -> &mut TableBacking {
|
||||||
&mut self.tables[index as usize]
|
&mut self.tables[local_table_index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,9 +40,9 @@ impl LocalBacking {
|
|||||||
let mut tables = Self::generate_tables(module);
|
let mut tables = Self::generate_tables(module);
|
||||||
let globals = Self::generate_globals(module);
|
let globals = Self::generate_globals(module);
|
||||||
|
|
||||||
let vm_memories = Self::finalize_memories(module, &mut memories[..]);
|
let vm_memories = Self::finalize_memories(module, imports, &mut memories);
|
||||||
let vm_tables = Self::finalize_tables(module, imports, &mut tables[..], vmctx);
|
let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx);
|
||||||
let vm_globals = Self::finalize_globals(module, imports, globals);
|
let vm_globals = Self::finalize_globals(module, globals);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
memories,
|
memories,
|
||||||
@ -48,8 +54,8 @@ impl LocalBacking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_memories(module: &ModuleInner) -> Box<[LinearMemory]> {
|
fn generate_memories(module: &ModuleInner) -> BoxedMap<LocalMemoryIndex, LinearMemory> {
|
||||||
let mut memories = Vec::with_capacity(module.memories.len());
|
let mut memories = Map::with_capacity(module.memories.len());
|
||||||
|
|
||||||
for (_, mem) in &module.memories {
|
for (_, mem) in &module.memories {
|
||||||
// If we use emscripten, we set a fixed initial and maximum
|
// If we use emscripten, we set a fixed initial and maximum
|
||||||
@ -66,75 +72,155 @@ impl LocalBacking {
|
|||||||
memories.push(memory);
|
memories.push(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
memories.into_boxed_slice()
|
memories.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_memories(
|
fn finalize_memories(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
memories: &mut [LinearMemory],
|
imports: &ImportBacking,
|
||||||
) -> Box<[vm::LocalMemory]> {
|
memories: &mut SliceMap<LocalMemoryIndex, LinearMemory>,
|
||||||
for init in &module.data_initializers {
|
) -> BoxedMap<LocalMemoryIndex, vm::LocalMemory> {
|
||||||
|
// For each init that has some data...
|
||||||
|
for init in module
|
||||||
|
.data_initializers
|
||||||
|
.iter()
|
||||||
|
.filter(|init| init.data.len() > 0)
|
||||||
|
{
|
||||||
assert!(init.base.is_none(), "global base not supported yet");
|
assert!(init.base.is_none(), "global base not supported yet");
|
||||||
assert!(init.offset + init.data.len() <= memories[init.memory_index.index()].size());
|
|
||||||
let offset = init.offset;
|
match init.memory_index.local_or_import(module) {
|
||||||
let mem: &mut LinearMemory = &mut memories[init.memory_index.index()];
|
LocalOrImport::Local(local_memory_index) => {
|
||||||
// let end_of_init = offset + init.data.len();
|
let memory_desc = &module.memories[local_memory_index];
|
||||||
// if end_of_init > mem.current_size() {
|
let data_top = init.offset + init.data.len();
|
||||||
// let grow_pages = (end_of_init / LinearMemory::PAGE_SIZE as usize) + 1;
|
assert!(memory_desc.min as usize >= data_top);
|
||||||
// mem.grow(grow_pages as u32)
|
let mem: &mut LinearMemory = &mut memories[local_memory_index];
|
||||||
// .expect("failed to grow memory for data initializers");
|
|
||||||
// }
|
let to_init = &mut mem[init.offset..init.offset + init.data.len()];
|
||||||
let to_init = &mut mem[offset..offset + init.data.len()];
|
to_init.copy_from_slice(&init.data);
|
||||||
to_init.copy_from_slice(&init.data);
|
}
|
||||||
|
LocalOrImport::Import(imported_memory_index) => {
|
||||||
|
let _ = imported_memory_index;
|
||||||
|
let _ = imports;
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memories
|
memories
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|mem| mem.into_vm_memory())
|
.map(|(_, mem)| mem.into_vm_memory())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Map<_, _>>()
|
||||||
.into_boxed_slice()
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_tables(module: &ModuleInner) -> Box<[TableBacking]> {
|
fn generate_tables(module: &ModuleInner) -> BoxedMap<LocalTableIndex, TableBacking> {
|
||||||
let mut tables = Vec::with_capacity(module.tables.len());
|
let mut tables = Map::with_capacity(module.tables.len());
|
||||||
|
|
||||||
for (_, table) in &module.tables {
|
for (_, table) in &module.tables {
|
||||||
let table_backing = TableBacking::new(table);
|
let table_backing = TableBacking::new(table);
|
||||||
tables.push(table_backing);
|
tables.push(table_backing);
|
||||||
}
|
}
|
||||||
|
|
||||||
tables.into_boxed_slice()
|
tables.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_tables(
|
fn finalize_tables(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &ImportBacking,
|
imports: &ImportBacking,
|
||||||
tables: &mut [TableBacking],
|
tables: &mut SliceMap<LocalTableIndex, TableBacking>,
|
||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
) -> Box<[vm::LocalTable]> {
|
) -> BoxedMap<LocalTableIndex, vm::LocalTable> {
|
||||||
for init in &module.table_initializers {
|
for init in &module.table_initializers {
|
||||||
assert!(init.base.is_none(), "global base not supported yet");
|
let init_base = match init.base {
|
||||||
let table = &mut tables[init.table_index.index()];
|
Initializer::Const(Value::I32(offset)) => offset as u32,
|
||||||
match table.elements {
|
Initializer::Const(_) => panic!("a const initializer must be the i32 type"),
|
||||||
TableElements::Anyfunc(ref mut elements) => {
|
Initializer::GetGlobal(imported_global_index) => {
|
||||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
if module.imported_globals[imported_global_index].1.desc.ty == Type::I32 {
|
||||||
let sig_index = module.func_assoc[func_index];
|
unsafe { (*imports.globals[imported_global_index].global).data as u32 }
|
||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
} else {
|
||||||
|
panic!("unsupported global type for initialzer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as usize;
|
||||||
|
|
||||||
let func_data = if module.is_imported_function(func_index) {
|
assert!(
|
||||||
imports.functions[func_index.index()].clone()
|
init_base + init.elements.len()
|
||||||
} else {
|
<= match init.table_index.local_or_import(module) {
|
||||||
vm::ImportedFunc {
|
LocalOrImport::Local(local_table_index) => {
|
||||||
func: module
|
module.tables[local_table_index].min
|
||||||
.func_resolver
|
}
|
||||||
.get(module, func_index)
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
.unwrap()
|
let (_, table_desc) = module.imported_tables[imported_table_index];
|
||||||
.as_ptr(),
|
table_desc.min
|
||||||
vmctx,
|
}
|
||||||
|
} as usize
|
||||||
|
);
|
||||||
|
|
||||||
|
match init.table_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_table_index) => {
|
||||||
|
let table = &mut tables[local_table_index];
|
||||||
|
match table.elements {
|
||||||
|
TableElements::Anyfunc(ref mut elements) => {
|
||||||
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
|
let sig_index = module.func_assoc[func_index];
|
||||||
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
|
let func_data = match func_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
||||||
|
func: module
|
||||||
|
.func_resolver
|
||||||
|
.get(module, local_func_index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr(),
|
||||||
|
vmctx,
|
||||||
|
},
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
imports.functions[imported_func_index].clone()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
elements[init_base + i] = vm::Anyfunc { func_data, sig_id };
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
|
let imported_table = &imports.tables[imported_table_index];
|
||||||
|
|
||||||
elements[init.offset + i] = vm::Anyfunc { func_data, sig_id };
|
let imported_local_table_slice = unsafe {
|
||||||
|
let imported_local_table = (*imported_table).table;
|
||||||
|
|
||||||
|
slice::from_raw_parts_mut(
|
||||||
|
(*imported_local_table).base as *mut vm::Anyfunc,
|
||||||
|
(*imported_local_table).current_elements,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (_, table_description) = module.imported_tables[imported_table_index];
|
||||||
|
match table_description.ty {
|
||||||
|
ElementType::Anyfunc => {
|
||||||
|
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||||
|
let sig_index = module.func_assoc[func_index];
|
||||||
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
|
let func_data = match func_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
||||||
|
func: module
|
||||||
|
.func_resolver
|
||||||
|
.get(module, local_func_index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ptr(),
|
||||||
|
vmctx,
|
||||||
|
},
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
imports.functions[imported_func_index].clone()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
imported_local_table_slice[init_base + i] =
|
||||||
|
vm::Anyfunc { func_data, sig_id };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,34 +228,29 @@ impl LocalBacking {
|
|||||||
|
|
||||||
tables
|
tables
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|table| table.into_vm_table())
|
.map(|(_, table)| table.into_vm_table())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Map<_, _>>()
|
||||||
.into_boxed_slice()
|
.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_globals(module: &ModuleInner) -> Box<[vm::LocalGlobal]> {
|
fn generate_globals(module: &ModuleInner) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
|
||||||
let globals = vec![vm::LocalGlobal::null(); module.globals.len()];
|
let mut globals = Map::with_capacity(module.globals.len());
|
||||||
|
|
||||||
globals.into_boxed_slice()
|
globals.resize(module.globals.len(), vm::LocalGlobal::null());
|
||||||
|
|
||||||
|
globals.into_boxed_map()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_globals(
|
fn finalize_globals(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &ImportBacking,
|
mut globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
|
||||||
mut globals: Box<[vm::LocalGlobal]>,
|
) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
|
||||||
) -> Box<[vm::LocalGlobal]> {
|
for ((_, to), (_, from)) in globals.iter_mut().zip(module.globals.into_iter()) {
|
||||||
for (to, (global_index, from)) in globals.iter_mut().zip(module.globals.into_iter()) {
|
|
||||||
to.data = match from.init {
|
to.data = match from.init {
|
||||||
Initializer::Const(Value::I32(x)) => x as u64,
|
Value::I32(x) => x as u64,
|
||||||
Initializer::Const(Value::I64(x)) => x as u64,
|
Value::I64(x) => x as u64,
|
||||||
Initializer::Const(Value::F32(x)) => x.to_bits() as u64,
|
Value::F32(x) => x.to_bits() as u64,
|
||||||
Initializer::Const(Value::F64(x)) => x.to_bits(),
|
Value::F64(x) => x.to_bits(),
|
||||||
Initializer::GetGlobal(index) => unsafe {
|
|
||||||
(*imports.globals[index.index()].global).data
|
|
||||||
},
|
|
||||||
Initializer::Import => unsafe {
|
|
||||||
(*imports.globals[global_index.index()].global).data
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,10 +260,10 @@ impl LocalBacking {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportBacking {
|
pub struct ImportBacking {
|
||||||
pub functions: Box<[vm::ImportedFunc]>,
|
pub functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||||
pub memories: Box<[vm::ImportedMemory]>,
|
pub memories: BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>,
|
||||||
pub tables: Box<[vm::ImportedTable]>,
|
pub tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
||||||
pub globals: Box<[vm::ImportedGlobal]>,
|
pub globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportBacking {
|
impl ImportBacking {
|
||||||
@ -200,12 +281,56 @@ impl ImportBacking {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn import_functions(
|
||||||
|
module: &ModuleInner,
|
||||||
|
imports: &mut Imports,
|
||||||
|
vmctx: *mut vm::Ctx,
|
||||||
|
) -> Result<BoxedMap<ImportedFuncIndex, vm::ImportedFunc>, String> {
|
||||||
|
let mut functions = Map::with_capacity(module.imported_functions.len());
|
||||||
|
for (index, ImportName { namespace, name }) in &module.imported_functions {
|
||||||
|
let sig_index = module.func_assoc[index.convert_up(module)];
|
||||||
|
let expected_sig = module.sig_registry.lookup_func_sig(sig_index);
|
||||||
|
let import = imports
|
||||||
|
.get_namespace(namespace)
|
||||||
|
.and_then(|namespace| namespace.get_export(name));
|
||||||
|
match import {
|
||||||
|
Some(Export::Function {
|
||||||
|
func,
|
||||||
|
ctx,
|
||||||
|
signature,
|
||||||
|
}) => {
|
||||||
|
if expected_sig == &signature {
|
||||||
|
functions.push(vm::ImportedFunc {
|
||||||
|
func: func.inner(),
|
||||||
|
vmctx: match ctx {
|
||||||
|
Context::External(ctx) => ctx,
|
||||||
|
Context::Internal => vmctx,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"unexpected signature for {:?}:{:?}",
|
||||||
|
namespace, name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
return Err(format!("incorrect import type for {}:{}", namespace, name));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(format!("import not found: {}:{}", namespace, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(functions.into_boxed_map())
|
||||||
|
}
|
||||||
|
|
||||||
fn import_memories(
|
fn import_memories(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
) -> Result<Box<[vm::ImportedMemory]>, String> {
|
) -> Result<BoxedMap<ImportedMemoryIndex, vm::ImportedMemory>, String> {
|
||||||
let mut memories = Vec::with_capacity(module.imported_memories.len());
|
let mut memories = Map::with_capacity(module.imported_memories.len());
|
||||||
for (_index, (ImportName { namespace, name }, expected_memory_desc)) in
|
for (_index, (ImportName { namespace, name }, expected_memory_desc)) in
|
||||||
&module.imported_memories
|
&module.imported_memories
|
||||||
{
|
{
|
||||||
@ -241,15 +366,15 @@ fn import_memories(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(memories.into_boxed_slice())
|
Ok(memories.into_boxed_map())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_tables(
|
fn import_tables(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
) -> Result<Box<[vm::ImportedTable]>, String> {
|
) -> Result<BoxedMap<ImportedTableIndex, vm::ImportedTable>, String> {
|
||||||
let mut tables = Vec::with_capacity(module.imported_tables.len());
|
let mut tables = Map::with_capacity(module.imported_tables.len());
|
||||||
for (_index, (ImportName { namespace, name }, expected_table_desc)) in &module.imported_tables {
|
for (_index, (ImportName { namespace, name }, expected_table_desc)) in &module.imported_tables {
|
||||||
let table_import = imports
|
let table_import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(namespace)
|
||||||
@ -283,65 +408,21 @@ fn import_tables(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(tables.into_boxed_slice())
|
Ok(tables.into_boxed_map())
|
||||||
}
|
|
||||||
|
|
||||||
fn import_functions(
|
|
||||||
module: &ModuleInner,
|
|
||||||
imports: &mut Imports,
|
|
||||||
vmctx: *mut vm::Ctx,
|
|
||||||
) -> Result<Box<[vm::ImportedFunc]>, String> {
|
|
||||||
let mut functions = Vec::with_capacity(module.imported_functions.len());
|
|
||||||
for (index, ImportName { namespace, name }) in &module.imported_functions {
|
|
||||||
let sig_index = module.func_assoc[index];
|
|
||||||
let expected_sig = module.sig_registry.lookup_func_sig(sig_index);
|
|
||||||
let import = imports
|
|
||||||
.get_namespace(namespace)
|
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
|
||||||
match import {
|
|
||||||
Some(Export::Function {
|
|
||||||
func,
|
|
||||||
ctx,
|
|
||||||
signature,
|
|
||||||
}) => {
|
|
||||||
if expected_sig == &signature {
|
|
||||||
functions.push(vm::ImportedFunc {
|
|
||||||
func: func.inner(),
|
|
||||||
vmctx: match ctx {
|
|
||||||
Context::External(ctx) => ctx,
|
|
||||||
Context::Internal => vmctx,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(format!(
|
|
||||||
"unexpected signature for {:?}:{:?}",
|
|
||||||
namespace, name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(_) => {
|
|
||||||
return Err(format!("incorrect import type for {}:{}", namespace, name));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(format!("import not found: {}:{}", namespace, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(functions.into_boxed_slice())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_globals(
|
fn import_globals(
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
) -> Result<Box<[vm::ImportedGlobal]>, String> {
|
) -> Result<BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>, String> {
|
||||||
let mut globals = Vec::with_capacity(module.imported_globals.len());
|
let mut globals = Map::with_capacity(module.imported_globals.len());
|
||||||
for (_, (ImportName { namespace, name }, global_desc)) in &module.imported_globals {
|
for (_, (ImportName { namespace, name }, imported_global)) in &module.imported_globals {
|
||||||
let import = imports
|
let import = imports
|
||||||
.get_namespace(namespace)
|
.get_namespace(namespace)
|
||||||
.and_then(|namespace| namespace.get_export(name));
|
.and_then(|namespace| namespace.get_export(name));
|
||||||
match import {
|
match import {
|
||||||
Some(Export::Global { local, global }) => {
|
Some(Export::Global { local, global }) => {
|
||||||
if &global == global_desc {
|
if global == imported_global.desc {
|
||||||
globals.push(vm::ImportedGlobal {
|
globals.push(vm::ImportedGlobal {
|
||||||
global: local.inner(),
|
global: local.inner(),
|
||||||
});
|
});
|
||||||
@ -360,5 +441,5 @@ fn import_globals(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(globals.into_boxed_slice())
|
Ok(globals.into_boxed_map())
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
import::{Imports, Namespace},
|
import::{Imports, Namespace},
|
||||||
module::{ExportIndex, Module, ModuleInner},
|
module::{ExportIndex, Module, ModuleInner},
|
||||||
types::{
|
types::{
|
||||||
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, MapIndex, Memory, MemoryIndex, Table,
|
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, Memory, MemoryIndex, Table,
|
||||||
TableIndex, Type, Value,
|
TableIndex, Type, Value,
|
||||||
},
|
},
|
||||||
vm,
|
vm,
|
||||||
@ -202,22 +202,23 @@ impl InstanceInner {
|
|||||||
.get(func_index)
|
.get(func_index)
|
||||||
.expect("broken invariant, incorrect func index");
|
.expect("broken invariant, incorrect func index");
|
||||||
|
|
||||||
let (func_ptr, ctx) = if module.is_imported_function(func_index) {
|
let (func_ptr, ctx) = match func_index.local_or_import(module) {
|
||||||
let imported_func = &self.import_backing.functions[func_index.index()];
|
LocalOrImport::Local(local_func_index) => (
|
||||||
(
|
|
||||||
imported_func.func as *const _,
|
|
||||||
Context::External(imported_func.vmctx),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
module
|
module
|
||||||
.func_resolver
|
.func_resolver
|
||||||
.get(&module, func_index)
|
.get(&module, local_func_index)
|
||||||
.expect("broken invariant, func resolver not synced with module.exports")
|
.expect("broken invariant, func resolver not synced with module.exports")
|
||||||
.cast()
|
.cast()
|
||||||
.as_ptr() as *const _,
|
.as_ptr() as *const _,
|
||||||
Context::Internal,
|
Context::Internal,
|
||||||
)
|
),
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
let imported_func = &self.import_backing.functions[imported_func_index];
|
||||||
|
(
|
||||||
|
imported_func.func as *const _,
|
||||||
|
Context::External(imported_func.vmctx),
|
||||||
|
)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let signature = module.sig_registry.lookup_func_sig(sig_index).clone();
|
let signature = module.sig_registry.lookup_func_sig(sig_index).clone();
|
||||||
@ -230,28 +231,31 @@ impl InstanceInner {
|
|||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
mem_index: MemoryIndex,
|
mem_index: MemoryIndex,
|
||||||
) -> (MemoryPointer, Context, Memory) {
|
) -> (MemoryPointer, Context, Memory) {
|
||||||
if module.is_imported_memory(mem_index) {
|
match mem_index.local_or_import(module) {
|
||||||
let &(_, mem) = &module
|
LocalOrImport::Local(local_mem_index) => {
|
||||||
.imported_memories
|
let vm_mem = &mut self.backing.memories[local_mem_index];
|
||||||
.get(mem_index)
|
(
|
||||||
.expect("missing imported memory index");
|
unsafe { MemoryPointer::new(&mut vm_mem.into_vm_memory()) },
|
||||||
let vm::ImportedMemory { memory, vmctx } =
|
Context::Internal,
|
||||||
&self.import_backing.memories[mem_index.index()];
|
*module
|
||||||
(
|
.memories
|
||||||
unsafe { MemoryPointer::new(*memory) },
|
.get(local_mem_index)
|
||||||
Context::External(*vmctx),
|
.expect("broken invariant, memories"),
|
||||||
*mem,
|
)
|
||||||
)
|
}
|
||||||
} else {
|
LocalOrImport::Import(imported_mem_index) => {
|
||||||
let vm_mem = &mut self.backing.memories[mem_index.index() as usize];
|
let &(_, mem) = &module
|
||||||
(
|
.imported_memories
|
||||||
unsafe { MemoryPointer::new(&mut vm_mem.into_vm_memory()) },
|
.get(imported_mem_index)
|
||||||
Context::Internal,
|
.expect("missing imported memory index");
|
||||||
*module
|
let vm::ImportedMemory { memory, vmctx } =
|
||||||
.memories
|
&self.import_backing.memories[imported_mem_index];
|
||||||
.get(mem_index)
|
(
|
||||||
.expect("broken invariant, memories"),
|
unsafe { MemoryPointer::new(*memory) },
|
||||||
)
|
Context::External(*vmctx),
|
||||||
|
*mem,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,23 +264,27 @@ impl InstanceInner {
|
|||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
global_index: GlobalIndex,
|
global_index: GlobalIndex,
|
||||||
) -> (GlobalPointer, GlobalDesc) {
|
) -> (GlobalPointer, GlobalDesc) {
|
||||||
if module.is_imported_global(global_index) {
|
match global_index.local_or_import(module) {
|
||||||
let &(_, desc) = &module
|
LocalOrImport::Local(local_global_index) => {
|
||||||
.imported_globals
|
let vm_global = &mut self.backing.vm_globals[local_global_index];
|
||||||
.get(global_index)
|
(
|
||||||
.expect("missing imported global index");
|
unsafe { GlobalPointer::new(vm_global) },
|
||||||
let vm::ImportedGlobal { global } = &self.import_backing.globals[global_index.index()];
|
module
|
||||||
(unsafe { GlobalPointer::new(*global) }, *desc)
|
.globals
|
||||||
} else {
|
.get(local_global_index)
|
||||||
let vm_global = &mut self.backing.vm_globals[global_index.index() as usize];
|
.expect("broken invariant, globals")
|
||||||
(
|
.desc,
|
||||||
unsafe { GlobalPointer::new(vm_global) },
|
)
|
||||||
module
|
}
|
||||||
.globals
|
LocalOrImport::Import(imported_global_index) => {
|
||||||
.get(global_index)
|
let &(_, imported_global) = &module
|
||||||
.expect("broken invariant, globals")
|
.imported_globals
|
||||||
.desc,
|
.get(imported_global_index)
|
||||||
)
|
.expect("missing imported global index");
|
||||||
|
let vm::ImportedGlobal { global } =
|
||||||
|
&self.import_backing.globals[imported_global_index];
|
||||||
|
(unsafe { GlobalPointer::new(*global) }, imported_global.desc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,28 +293,31 @@ impl InstanceInner {
|
|||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
table_index: TableIndex,
|
table_index: TableIndex,
|
||||||
) -> (TablePointer, Context, Table) {
|
) -> (TablePointer, Context, Table) {
|
||||||
if module.is_imported_table(table_index) {
|
match table_index.local_or_import(module) {
|
||||||
let &(_, tab) = &module
|
LocalOrImport::Local(local_table_index) => {
|
||||||
.imported_tables
|
let vm_table = &mut self.backing.tables[local_table_index];
|
||||||
.get(table_index)
|
(
|
||||||
.expect("missing imported table index");
|
unsafe { TablePointer::new(&mut vm_table.into_vm_table()) },
|
||||||
let vm::ImportedTable { table, vmctx } =
|
Context::Internal,
|
||||||
&self.import_backing.tables[table_index.index()];
|
*module
|
||||||
(
|
.tables
|
||||||
unsafe { TablePointer::new(*table) },
|
.get(local_table_index)
|
||||||
Context::External(*vmctx),
|
.expect("broken invariant, tables"),
|
||||||
*tab,
|
)
|
||||||
)
|
}
|
||||||
} else {
|
LocalOrImport::Import(imported_table_index) => {
|
||||||
let vm_table = &mut self.backing.tables[table_index.index() as usize];
|
let &(_, tab) = &module
|
||||||
(
|
.imported_tables
|
||||||
unsafe { TablePointer::new(&mut vm_table.into_vm_table()) },
|
.get(imported_table_index)
|
||||||
Context::Internal,
|
.expect("missing imported table index");
|
||||||
*module
|
let vm::ImportedTable { table, vmctx } =
|
||||||
.tables
|
&self.import_backing.tables[imported_table_index];
|
||||||
.get(table_index)
|
(
|
||||||
.expect("broken invariant, tables"),
|
unsafe { TablePointer::new(*table) },
|
||||||
)
|
Context::External(*vmctx),
|
||||||
|
*tab,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ pub mod module;
|
|||||||
mod recovery;
|
mod recovery;
|
||||||
mod sig_registry;
|
mod sig_registry;
|
||||||
mod sighandler;
|
mod sighandler;
|
||||||
|
pub mod structures;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
@ -93,7 +93,7 @@ impl LinearMemory {
|
|||||||
self.mmap.as_ptr()
|
self.mmap.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a number of allocated wasm pages.
|
/// Returns the size in bytes
|
||||||
pub(crate) fn size(&self) -> usize {
|
pub(crate) fn size(&self) -> usize {
|
||||||
self.current as usize * Self::PAGE_SIZE as usize
|
self.current as usize * Self::PAGE_SIZE as usize
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ use crate::{
|
|||||||
backend::FuncResolver,
|
backend::FuncResolver,
|
||||||
import::Imports,
|
import::Imports,
|
||||||
sig_registry::SigRegistry,
|
sig_registry::SigRegistry,
|
||||||
|
structures::Map,
|
||||||
types::{
|
types::{
|
||||||
FuncIndex, Global, GlobalDesc, GlobalIndex, Map, MapIndex, Memory, MemoryIndex, SigIndex,
|
FuncIndex, Global, GlobalIndex, ImportedFuncIndex, ImportedGlobal, ImportedGlobalIndex,
|
||||||
Table, TableIndex,
|
ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex,
|
||||||
|
LocalTableIndex, Memory, MemoryIndex, SigIndex, Table, TableIndex,
|
||||||
},
|
},
|
||||||
Instance,
|
Instance,
|
||||||
};
|
};
|
||||||
@ -15,14 +17,16 @@ use std::rc::Rc;
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct ModuleInner {
|
pub struct ModuleInner {
|
||||||
pub func_resolver: Box<dyn FuncResolver>,
|
pub func_resolver: Box<dyn FuncResolver>,
|
||||||
pub memories: Map<MemoryIndex, Memory>,
|
// This are strictly local and the typsystem ensures that.
|
||||||
pub globals: Map<GlobalIndex, Global>,
|
pub memories: Map<LocalMemoryIndex, Memory>,
|
||||||
pub tables: Map<TableIndex, Table>,
|
pub globals: Map<LocalGlobalIndex, Global>,
|
||||||
|
pub tables: Map<LocalTableIndex, Table>,
|
||||||
|
|
||||||
pub imported_functions: Map<FuncIndex, ImportName>,
|
// These are strictly imported and the typesystem ensures that.
|
||||||
pub imported_memories: Map<MemoryIndex, (ImportName, Memory)>,
|
pub imported_functions: Map<ImportedFuncIndex, ImportName>,
|
||||||
pub imported_tables: Map<TableIndex, (ImportName, Table)>,
|
pub imported_memories: Map<ImportedMemoryIndex, (ImportName, Memory)>,
|
||||||
pub imported_globals: Map<GlobalIndex, (ImportName, GlobalDesc)>,
|
pub imported_tables: Map<ImportedTableIndex, (ImportName, Table)>,
|
||||||
|
pub imported_globals: Map<ImportedGlobalIndex, (ImportName, ImportedGlobal)>,
|
||||||
|
|
||||||
pub exports: HashMap<String, ExportIndex>,
|
pub exports: HashMap<String, ExportIndex>,
|
||||||
|
|
||||||
@ -47,23 +51,7 @@ impl Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleInner {
|
impl ModuleInner {}
|
||||||
pub(crate) fn is_imported_function(&self, func_index: FuncIndex) -> bool {
|
|
||||||
func_index.index() < self.imported_functions.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_imported_memory(&self, memory_index: MemoryIndex) -> bool {
|
|
||||||
memory_index.index() < self.imported_memories.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_imported_table(&self, table_index: TableIndex) -> bool {
|
|
||||||
table_index.index() < self.imported_tables.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_imported_global(&self, global_index: GlobalIndex) -> bool {
|
|
||||||
global_index.index() < self.imported_globals.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -90,7 +78,7 @@ pub enum ExportIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A data initializer for linear memory.
|
/// A data initializer for linear memory.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DataInitializer {
|
pub struct DataInitializer {
|
||||||
/// The index of the memory to initialize.
|
/// The index of the memory to initialize.
|
||||||
pub memory_index: MemoryIndex,
|
pub memory_index: MemoryIndex,
|
||||||
@ -103,14 +91,12 @@ pub struct DataInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A WebAssembly table initializer.
|
/// A WebAssembly table initializer.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableInitializer {
|
pub struct TableInitializer {
|
||||||
/// The index of a table to initialize.
|
/// The index of a table to initialize.
|
||||||
pub table_index: TableIndex,
|
pub table_index: TableIndex,
|
||||||
/// Optionally, a global variable giving a base index.
|
/// Either a constant offset or a `get_global`
|
||||||
pub base: Option<GlobalIndex>,
|
pub base: Initializer,
|
||||||
/// The offset to add to the base.
|
|
||||||
pub offset: usize,
|
|
||||||
/// The values to write into the table elements.
|
/// The values to write into the table elements.
|
||||||
pub elements: Vec<FuncIndex>,
|
pub elements: Vec<FuncIndex>,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::types::{FuncSig, Map, SigIndex};
|
use crate::{
|
||||||
|
structures::Map,
|
||||||
|
types::{FuncSig, SigIndex},
|
||||||
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
46
lib/runtime/src/structures/boxed.rs
Normal file
46
lib/runtime/src/structures/boxed.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use super::{SliceMap, TypedIndex};
|
||||||
|
use std::{
|
||||||
|
marker::PhantomData,
|
||||||
|
mem,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BoxedMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
elems: Box<[V]>,
|
||||||
|
_marker: PhantomData<K>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> BoxedMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
pub(in crate::structures) fn new(elems: Box<[V]>) -> Self {
|
||||||
|
Self {
|
||||||
|
elems,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Deref for BoxedMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
type Target = SliceMap<K, V>;
|
||||||
|
fn deref(&self) -> &SliceMap<K, V> {
|
||||||
|
unsafe { mem::transmute::<&[V], _>(&*self.elems) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> DerefMut for BoxedMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut SliceMap<K, V> {
|
||||||
|
unsafe { mem::transmute::<&mut [V], _>(&mut *self.elems) }
|
||||||
|
}
|
||||||
|
}
|
174
lib/runtime/src/structures/map.rs
Normal file
174
lib/runtime/src/structures/map.rs
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
use super::{BoxedMap, SliceMap, TypedIndex};
|
||||||
|
use std::{
|
||||||
|
iter::{self, Extend, FromIterator},
|
||||||
|
marker::PhantomData,
|
||||||
|
mem,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
slice,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Dense item map
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
elems: Vec<V>,
|
||||||
|
_marker: PhantomData<K>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
elems: Vec::new(),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
elems: Vec::with_capacity(capacity),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.elems.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, value: V) -> K {
|
||||||
|
let len = self.len();
|
||||||
|
self.elems.push(value);
|
||||||
|
K::new(len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reserve_exact(&mut self, size: usize) {
|
||||||
|
self.elems.reserve_exact(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_boxed_map(self) -> BoxedMap<K, V> {
|
||||||
|
BoxedMap::new(self.elems.into_boxed_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
V: Clone,
|
||||||
|
{
|
||||||
|
pub fn resize(&mut self, new_len: usize, value: V) {
|
||||||
|
self.elems.resize(new_len, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Extend<V> for Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
fn extend<I: IntoIterator<Item = V>>(&mut self, iter: I) {
|
||||||
|
self.elems.extend(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> FromIterator<V> for Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
fn from_iter<I: IntoIterator<Item = V>>(iter: I) -> Self {
|
||||||
|
let elems: Vec<V> = iter.into_iter().collect();
|
||||||
|
Self {
|
||||||
|
elems,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Deref for Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
type Target = SliceMap<K, V>;
|
||||||
|
fn deref(&self) -> &SliceMap<K, V> {
|
||||||
|
unsafe { mem::transmute::<&[V], _>(self.elems.as_slice()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> DerefMut for Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut SliceMap<K, V> {
|
||||||
|
unsafe { mem::transmute::<&mut [V], _>(self.elems.as_mut_slice()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> IntoIterator for &'a Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
type Item = (K, &'a V);
|
||||||
|
type IntoIter = Iter<'a, K, V>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
Iter::new(self.elems.iter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K, V> IntoIterator for &'a mut Map<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
type Item = (K, &'a mut V);
|
||||||
|
type IntoIter = IterMut<'a, K, V>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
IterMut::new(self.elems.iter_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Iter<'a, K: TypedIndex, V: 'a> {
|
||||||
|
enumerated: iter::Enumerate<slice::Iter<'a, V>>,
|
||||||
|
_marker: PhantomData<K>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: TypedIndex, V: 'a> Iter<'a, K, V> {
|
||||||
|
pub(in crate::structures) fn new(iter: slice::Iter<'a, V>) -> Self {
|
||||||
|
Self {
|
||||||
|
enumerated: iter.enumerate(),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: TypedIndex, V: 'a> Iterator for Iter<'a, K, V> {
|
||||||
|
type Item = (K, &'a V);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.enumerated.next().map(|(i, v)| (K::new(i), v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IterMut<'a, K: TypedIndex, V: 'a> {
|
||||||
|
enumerated: iter::Enumerate<slice::IterMut<'a, V>>,
|
||||||
|
_marker: PhantomData<K>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: TypedIndex, V: 'a> IterMut<'a, K, V> {
|
||||||
|
pub(in crate::structures) fn new(iter: slice::IterMut<'a, V>) -> Self {
|
||||||
|
Self {
|
||||||
|
enumerated: iter.enumerate(),
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: TypedIndex, V: 'a> Iterator for IterMut<'a, K, V> {
|
||||||
|
type Item = (K, &'a mut V);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.enumerated.next().map(|(i, v)| (K::new(i), v))
|
||||||
|
}
|
||||||
|
}
|
12
lib/runtime/src/structures/mod.rs
Normal file
12
lib/runtime/src/structures/mod.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
mod boxed;
|
||||||
|
mod map;
|
||||||
|
mod slice;
|
||||||
|
|
||||||
|
pub use self::boxed::BoxedMap;
|
||||||
|
pub use self::map::{Iter, IterMut, Map};
|
||||||
|
pub use self::slice::SliceMap;
|
||||||
|
|
||||||
|
pub trait TypedIndex {
|
||||||
|
fn new(index: usize) -> Self;
|
||||||
|
fn index(&self) -> usize;
|
||||||
|
}
|
86
lib/runtime/src/structures/mono_vec.rs
Normal file
86
lib/runtime/src/structures/mono_vec.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum MonoVecInner<T> {
|
||||||
|
None,
|
||||||
|
Inline(T),
|
||||||
|
Heap(Vec<T>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type that can hold zero items,
|
||||||
|
/// one item, or many items.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MonoVec<T> {
|
||||||
|
inner: MonoVecInner<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MonoVec<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: MonoVecInner::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_inline(item: T) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: MonoVecInner::Inline(item),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
match capacity {
|
||||||
|
0 | 1 => Self::new(),
|
||||||
|
_ => Self {
|
||||||
|
inner: MonoVecInner::Heap(Vec::with_capacity(capacity)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, item: T) {
|
||||||
|
let uninit = unsafe { mem::uninitialized() };
|
||||||
|
let prev = mem::replace(&mut self.inner, uninit);
|
||||||
|
let next = match prev {
|
||||||
|
MonoVecInner::None => MonoVecInner::Inline(item),
|
||||||
|
MonoVecInner::Inline(previous_item) => MonoVecInner::Heap(vec![previous_item, item]),
|
||||||
|
MonoVecInner::Heap(mut v) => {
|
||||||
|
v.push(item);
|
||||||
|
MonoVecInner::Heap(v)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let uninit = mem::replace(&mut self.inner, next);
|
||||||
|
mem::forget(uninit);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
|
match self.inner {
|
||||||
|
MonoVecInner::None => None,
|
||||||
|
MonoVecInner::Inline(ref mut item) => {
|
||||||
|
let uninit = unsafe { mem::uninitialized() };
|
||||||
|
let item = mem::replace(item, uninit);
|
||||||
|
let uninit = mem::replace(&mut self.inner, MonoVecInner::None);
|
||||||
|
mem::forget(uninit);
|
||||||
|
Some(item)
|
||||||
|
}
|
||||||
|
MonoVecInner::Heap(ref mut v) => v.pop(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice(&self) -> &[T] {
|
||||||
|
match self.inner {
|
||||||
|
MonoVecInner::None => unsafe {
|
||||||
|
slice::from_raw_parts(mem::align_of::<T>() as *const T, 0)
|
||||||
|
},
|
||||||
|
MonoVecInner::Inline(ref item) => slice::from_ref(item),
|
||||||
|
MonoVecInner::Heap(ref v) => &v[..],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_slice_mut(&mut self) -> &mut [T] {
|
||||||
|
match self.inner {
|
||||||
|
MonoVecInner::None => unsafe {
|
||||||
|
slice::from_raw_parts_mut(mem::align_of::<T>() as *mut T, 0)
|
||||||
|
},
|
||||||
|
MonoVecInner::Inline(ref mut item) => slice::from_mut(item),
|
||||||
|
MonoVecInner::Heap(ref mut v) => &mut v[..],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
lib/runtime/src/structures/slice.rs
Normal file
68
lib/runtime/src/structures/slice.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use super::{Iter, IterMut, TypedIndex};
|
||||||
|
use std::{
|
||||||
|
marker::PhantomData,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This is a dynamically-sized slice
|
||||||
|
/// that can only be indexed by the
|
||||||
|
/// correct index type.
|
||||||
|
pub struct SliceMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
_marker: PhantomData<K>,
|
||||||
|
slice: [V],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> SliceMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
pub fn get(&self, index: K) -> Option<&V> {
|
||||||
|
self.slice.get(index.index())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut(&mut self, index: K) -> Option<&mut V> {
|
||||||
|
self.slice.get_mut(index.index())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.slice.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> Iter<K, V> {
|
||||||
|
Iter::new(self.slice.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_mut(&mut self) -> IterMut<K, V> {
|
||||||
|
IterMut::new(self.slice.iter_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ptr(&self) -> *const V {
|
||||||
|
self as *const SliceMap<K, V> as *const V
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_mut_ptr(&mut self) -> *mut V {
|
||||||
|
self as *mut SliceMap<K, V> as *mut V
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> Index<K> for SliceMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
type Output = V;
|
||||||
|
fn index(&self, index: K) -> &V {
|
||||||
|
&self.slice[index.index()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> IndexMut<K> for SliceMap<K, V>
|
||||||
|
where
|
||||||
|
K: TypedIndex,
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: K) -> &mut V {
|
||||||
|
&mut self.slice[index.index()]
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
use std::marker::PhantomData;
|
use crate::{module::ModuleInner, structures::TypedIndex};
|
||||||
use std::{
|
|
||||||
iter, mem,
|
|
||||||
ops::{Index, IndexMut},
|
|
||||||
slice,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
@ -82,21 +77,22 @@ pub struct Table {
|
|||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub(crate) fn fits_in_imported(&self, imported: &Table) -> bool {
|
pub(crate) fn fits_in_imported(&self, imported: &Table) -> bool {
|
||||||
self.max == imported.max && self.min <= imported.min
|
// TODO: We should define implementation limits.
|
||||||
|
let imported_max = imported.max.unwrap_or(u32::max_value());
|
||||||
|
let self_max = self.max.unwrap_or(u32::max_value());
|
||||||
|
self.ty == imported.ty && imported_max <= self_max && self.min <= imported.min
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A global value initializer.
|
/// A const value initializer.
|
||||||
/// Overtime, this will be able to represent more and more
|
/// Over time, this will be able to represent more and more
|
||||||
/// complex expressions.
|
/// complex expressions.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Initializer {
|
pub enum Initializer {
|
||||||
/// Corresponds to a `const.*` instruction.
|
/// Corresponds to a `const.*` instruction.
|
||||||
Const(Value),
|
Const(Value),
|
||||||
/// Corresponds to a `get_global` instruction.
|
/// Corresponds to a `get_global` instruction.
|
||||||
GetGlobal(GlobalIndex),
|
GetGlobal(ImportedGlobalIndex),
|
||||||
/// Initialized externally
|
|
||||||
Import,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -105,11 +101,23 @@ pub struct GlobalDesc {
|
|||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum ImportedGlobalInit {
|
||||||
|
GetGlobal(ImportedGlobalIndex),
|
||||||
|
Import,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct ImportedGlobal {
|
||||||
|
pub desc: GlobalDesc,
|
||||||
|
pub init: ImportedGlobalInit,
|
||||||
|
}
|
||||||
|
|
||||||
/// A wasm global.
|
/// A wasm global.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
pub desc: GlobalDesc,
|
pub desc: GlobalDesc,
|
||||||
pub init: Initializer,
|
pub init: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wasm memory.
|
/// A wasm memory.
|
||||||
@ -129,11 +137,15 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn fits_in_imported(&self, imported: &Memory) -> bool {
|
pub(crate) fn fits_in_imported(&self, imported: &Memory) -> bool {
|
||||||
self.shared == imported.shared && self.max == imported.max && self.min <= imported.min
|
let imported_max = imported.max.unwrap_or(65_536);
|
||||||
|
let self_max = self.max.unwrap_or(65_536);
|
||||||
|
|
||||||
|
self.shared == imported.shared && imported_max <= self_max && self.min <= imported.min
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wasm func.
|
/// The signature of a function that is either implemented
|
||||||
|
/// in a wasm module or exposed to wasm by the host.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct FuncSig {
|
pub struct FuncSig {
|
||||||
pub params: Vec<Type>,
|
pub params: Vec<Type>,
|
||||||
@ -151,158 +163,17 @@ impl FuncSig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MapIndex {
|
pub trait LocalImport {
|
||||||
fn new(index: usize) -> Self;
|
type Local: TypedIndex;
|
||||||
fn index(&self) -> usize;
|
type Import: TypedIndex;
|
||||||
}
|
|
||||||
|
|
||||||
/// Dense item map
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
elems: Vec<T>,
|
|
||||||
_marker: PhantomData<I>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, T> Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
elems: Vec::new(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
elems: Vec::with_capacity(capacity),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, index: I) -> Option<&T> {
|
|
||||||
self.elems.get(index.index())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.elems.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, value: T) -> I {
|
|
||||||
let len = self.len();
|
|
||||||
self.elems.push(value);
|
|
||||||
I::new(len)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_ptr(&self) -> *const T {
|
|
||||||
self.elems.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reserve_exact(&mut self, size: usize) {
|
|
||||||
self.elems.reserve_exact(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> Iter<T, I> {
|
|
||||||
Iter::new(self.elems.iter())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, T> Index<I> for Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
type Output = T;
|
|
||||||
fn index(&self, index: I) -> &T {
|
|
||||||
&self.elems[index.index()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, T> IndexMut<I> for Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
fn index_mut(&mut self, index: I) -> &mut T {
|
|
||||||
&mut self.elems[index.index()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, I, T> IntoIterator for &'a Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
type Item = (I, &'a T);
|
|
||||||
type IntoIter = Iter<'a, T, I>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
Iter::new(self.elems.iter())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, I, T> IntoIterator for &'a mut Map<I, T>
|
|
||||||
where
|
|
||||||
I: MapIndex,
|
|
||||||
{
|
|
||||||
type Item = (I, &'a mut T);
|
|
||||||
type IntoIter = IterMut<'a, T, I>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
IterMut::new(self.elems.iter_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Iter<'a, T: 'a, I: MapIndex> {
|
|
||||||
enumerated: iter::Enumerate<slice::Iter<'a, T>>,
|
|
||||||
_marker: PhantomData<I>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: 'a, I: MapIndex> Iter<'a, T, I> {
|
|
||||||
fn new(iter: slice::Iter<'a, T>) -> Self {
|
|
||||||
Self {
|
|
||||||
enumerated: iter.enumerate(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: 'a, I: MapIndex> Iterator for Iter<'a, T, I> {
|
|
||||||
type Item = (I, &'a T);
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.enumerated.next().map(|(i, v)| (I::new(i), v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IterMut<'a, T: 'a, I: MapIndex> {
|
|
||||||
enumerated: iter::Enumerate<slice::IterMut<'a, T>>,
|
|
||||||
_marker: PhantomData<I>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: 'a, I: MapIndex> IterMut<'a, T, I> {
|
|
||||||
fn new(iter: slice::IterMut<'a, T>) -> Self {
|
|
||||||
Self {
|
|
||||||
enumerated: iter.enumerate(),
|
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: 'a, I: MapIndex> Iterator for IterMut<'a, T, I> {
|
|
||||||
type Item = (I, &'a mut T);
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.enumerated.next().map(|(i, v)| (I::new(i), v))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
macro_rules! define_map_index {
|
macro_rules! define_map_index {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct $ty (u32);
|
pub struct $ty (u32);
|
||||||
impl MapIndex for $ty {
|
impl TypedIndex for $ty {
|
||||||
fn new(index: usize) -> Self {
|
fn new(index: usize) -> Self {
|
||||||
$ty (index as _)
|
$ty (index as _)
|
||||||
}
|
}
|
||||||
@ -312,20 +183,72 @@ macro_rules! define_map_index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($($ty:ident,)*) => {
|
($($normal_ty:ident,)* | local: $($local_ty:ident,)* | imported: $($imported_ty:ident,)*) => {
|
||||||
$(
|
$(
|
||||||
define_map_index!($ty);
|
define_map_index!($normal_ty);
|
||||||
|
define_map_index!($local_ty);
|
||||||
|
define_map_index!($imported_ty);
|
||||||
|
|
||||||
|
impl LocalImport for $normal_ty {
|
||||||
|
type Local = $local_ty;
|
||||||
|
type Import = $imported_ty;
|
||||||
|
}
|
||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
define_map_index![FuncIndex, MemoryIndex, TableIndex, SigIndex,];
|
#[rustfmt::skip]
|
||||||
|
define_map_index![
|
||||||
|
FuncIndex, MemoryIndex, TableIndex, GlobalIndex,
|
||||||
|
| local: LocalFuncIndex, LocalMemoryIndex, LocalTableIndex, LocalGlobalIndex,
|
||||||
|
| imported: ImportedFuncIndex, ImportedMemoryIndex, ImportedTableIndex, ImportedGlobalIndex,
|
||||||
|
];
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
macro_rules! define_local_or_import {
|
||||||
|
($ty:ident, $local_ty:ident, $imported_ty:ident, $imports:ident) => {
|
||||||
|
impl $ty {
|
||||||
|
pub fn local_or_import(self, module: &ModuleInner) -> LocalOrImport<$ty> {
|
||||||
|
if self.index() < module.$imports.len() {
|
||||||
|
LocalOrImport::Import(<Self as LocalImport>::Import::new(self.index()))
|
||||||
|
} else {
|
||||||
|
LocalOrImport::Local(<Self as LocalImport>::Local::new(self.index() - module.$imports.len()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $local_ty {
|
||||||
|
pub fn convert_up(self, module: &ModuleInner) -> $ty {
|
||||||
|
$ty ((self.index() + module.$imports.len()) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $imported_ty {
|
||||||
|
pub fn convert_up(self, _module: &ModuleInner) -> $ty {
|
||||||
|
$ty (self.index() as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($(($ty:ident | ($local_ty:ident, $imported_ty:ident): $imports:ident),)*) => {
|
||||||
|
$(
|
||||||
|
define_local_or_import!($ty, $local_ty, $imported_ty, $imports);
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
define_local_or_import![
|
||||||
|
(FuncIndex | (LocalFuncIndex, ImportedFuncIndex): imported_functions),
|
||||||
|
(MemoryIndex | (LocalMemoryIndex, ImportedMemoryIndex): imported_memories),
|
||||||
|
(TableIndex | (LocalTableIndex, ImportedTableIndex): imported_tables),
|
||||||
|
(GlobalIndex | (LocalGlobalIndex, ImportedGlobalIndex): imported_globals),
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct GlobalIndex(u32);
|
pub struct SigIndex(u32);
|
||||||
impl MapIndex for GlobalIndex {
|
impl TypedIndex for SigIndex {
|
||||||
fn new(index: usize) -> Self {
|
fn new(index: usize) -> Self {
|
||||||
GlobalIndex(index as _)
|
SigIndex(index as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn index(&self) -> usize {
|
fn index(&self) -> usize {
|
||||||
@ -333,88 +256,10 @@ impl MapIndex for GlobalIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
pub enum LocalOrImport<T>
|
||||||
enum MonoVecInner<T> {
|
where
|
||||||
None,
|
T: LocalImport,
|
||||||
Inline(T),
|
{
|
||||||
Heap(Vec<T>),
|
Local(T::Local),
|
||||||
}
|
Import(T::Import),
|
||||||
|
|
||||||
/// A type that can hold zero items,
|
|
||||||
/// one item, or many items.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MonoVec<T> {
|
|
||||||
inner: MonoVecInner<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MonoVec<T> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: MonoVecInner::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_inline(item: T) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: MonoVecInner::Inline(item),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
|
||||||
match capacity {
|
|
||||||
0 | 1 => Self::new(),
|
|
||||||
_ => Self {
|
|
||||||
inner: MonoVecInner::Heap(Vec::with_capacity(capacity)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, item: T) {
|
|
||||||
let uninit = unsafe { mem::uninitialized() };
|
|
||||||
let prev = mem::replace(&mut self.inner, uninit);
|
|
||||||
let next = match prev {
|
|
||||||
MonoVecInner::None => MonoVecInner::Inline(item),
|
|
||||||
MonoVecInner::Inline(previous_item) => MonoVecInner::Heap(vec![previous_item, item]),
|
|
||||||
MonoVecInner::Heap(mut v) => {
|
|
||||||
v.push(item);
|
|
||||||
MonoVecInner::Heap(v)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let uninit = mem::replace(&mut self.inner, next);
|
|
||||||
mem::forget(uninit);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
|
||||||
match self.inner {
|
|
||||||
MonoVecInner::None => None,
|
|
||||||
MonoVecInner::Inline(ref mut item) => {
|
|
||||||
let uninit = unsafe { mem::uninitialized() };
|
|
||||||
let item = mem::replace(item, uninit);
|
|
||||||
let uninit = mem::replace(&mut self.inner, MonoVecInner::None);
|
|
||||||
mem::forget(uninit);
|
|
||||||
Some(item)
|
|
||||||
}
|
|
||||||
MonoVecInner::Heap(ref mut v) => v.pop(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_slice(&self) -> &[T] {
|
|
||||||
match self.inner {
|
|
||||||
MonoVecInner::None => unsafe {
|
|
||||||
slice::from_raw_parts(mem::align_of::<T>() as *const T, 0)
|
|
||||||
},
|
|
||||||
MonoVecInner::Inline(ref item) => slice::from_ref(item),
|
|
||||||
MonoVecInner::Heap(ref v) => &v[..],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_slice_mut(&mut self) -> &mut [T] {
|
|
||||||
match self.inner {
|
|
||||||
MonoVecInner::None => unsafe {
|
|
||||||
slice::from_raw_parts_mut(mem::align_of::<T>() as *mut T, 0)
|
|
||||||
},
|
|
||||||
MonoVecInner::Inline(ref mut item) => slice::from_mut(item),
|
|
||||||
MonoVecInner::Heap(ref mut v) => &mut v[..],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,10 @@ impl LocalGlobal {
|
|||||||
pub fn null() -> Self {
|
pub fn null() -> Self {
|
||||||
Self { data: 0 }
|
Self { data: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size() -> u8 {
|
||||||
|
mem::size_of::<Self>() as u8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -213,6 +217,10 @@ impl ImportedGlobal {
|
|||||||
pub fn offset_global() -> u8 {
|
pub fn offset_global() -> u8 {
|
||||||
0 * (mem::size_of::<usize>() as u8)
|
0 * (mem::size_of::<usize>() as u8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size() -> u8 {
|
||||||
|
mem::size_of::<Self>() as u8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{memory::LinearMemory, vm};
|
use crate::{memory::LinearMemory, structures::TypedIndex, types::LocalMemoryIndex, vm};
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_grow_static(
|
pub unsafe extern "C" fn memory_grow_static(
|
||||||
memory_index: u32,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
by_pages: u32,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: *mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
@ -10,7 +10,7 @@ pub unsafe extern "C" fn memory_grow_static(
|
|||||||
.grow_static(by_pages)
|
.grow_static(by_pages)
|
||||||
{
|
{
|
||||||
// Store the new size back into the vmctx.
|
// Store the new size back into the vmctx.
|
||||||
(*(*ctx).memories.add(memory_index as usize)).size =
|
(*(*ctx).memories.add(memory_index.index())).size =
|
||||||
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
||||||
old
|
old
|
||||||
} else {
|
} else {
|
||||||
@ -18,12 +18,12 @@ pub unsafe extern "C" fn memory_grow_static(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_size(memory_index: u32, ctx: *mut vm::Ctx) -> u32 {
|
pub unsafe extern "C" fn memory_size(memory_index: LocalMemoryIndex, ctx: *mut vm::Ctx) -> u32 {
|
||||||
(*(*ctx).local_backing).memory(memory_index).pages()
|
(*(*ctx).local_backing).memory(memory_index).pages()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn memory_grow_dynamic(
|
pub unsafe extern "C" fn memory_grow_dynamic(
|
||||||
memory_index: u32,
|
memory_index: LocalMemoryIndex,
|
||||||
by_pages: u32,
|
by_pages: u32,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: *mut vm::Ctx,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
@ -32,7 +32,7 @@ pub unsafe extern "C" fn memory_grow_dynamic(
|
|||||||
.grow_dynamic(by_pages)
|
.grow_dynamic(by_pages)
|
||||||
{
|
{
|
||||||
// Store the new size back into the vmctx.
|
// Store the new size back into the vmctx.
|
||||||
(*(*ctx).memories.add(memory_index as usize)).size =
|
(*(*ctx).memories.add(memory_index.index())).size =
|
||||||
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
(old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize;
|
||||||
old
|
old
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user