Skip to content

Commit

Permalink
Fix local memory ownership issue -- WIP
Browse files Browse the repository at this point in the history
This commit contains a ton of debug code that we'll need to remove
  • Loading branch information
Mark McCaskey committed Oct 14, 2020
1 parent dd62823 commit 4fc8ace
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 53 deletions.
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,9 @@ required-features = ["cranelift", "wasi"]
[[example]]
name = "table"
path = "examples/table.rs"
required-features = ["cranelift"]
required-features = ["cranelift"]

[[example]]
name = "memory"
path = "examples/memory.rs"
required-features = ["cranelift"]
100 changes: 100 additions & 0 deletions examples/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use wasmer::{
imports, wat2wasm, Extern, Function, Instance, Memory, MemoryType, Module, NativeFunc, Pages,
Store, Table, TableType, Type, Value,
};
//use wasmer_compiler_cranelift::Cranelift;
use wasmer_compiler_singlepass::Singlepass;
use wasmer_engine_jit::JIT;

/// A function we'll call through a table.
fn host_callback(arg1: i32, arg2: i32) -> i32 {
arg1 + arg2
}

fn main() -> anyhow::Result<()> {
let wasm_bytes = wat2wasm(
r#"
(module
(type $mem_size_t (func (result i32)))
(type $get_at_t (func (param i32) (result i32)))
(type $set_at_t (func (param i32) (param i32)))
(memory $mem 1)
;;(import "env" "memory" (memory $mem 1))
(func $get_at (type $get_at_t) (param $idx i32) (result i32)
(i32.load (local.get $idx)))
(func $set_at (type $set_at_t) (param $idx i32) (param $val i32)
(i32.store (local.get $idx) (local.get $val)))
(func $mem_size (type $mem_size_t) (result i32)
(memory.size))
(export "get_at" (func $get_at))
(export "set_at" (func $set_at))
(export "mem_size" (func $mem_size))
(export "memory" (memory $mem)))
"#
.as_bytes(),
)?;

// We set up our store with an engine and a compiler.
//let store = Store::new(&JIT::new(&Cranelift::default()).engine());
let store = Store::new(&JIT::new(&Singlepass::default()).engine());
// Then compile our Wasm.
let module = Module::new(&store, wasm_bytes)?;
//let memory = Memory::new(&store, MemoryType::new(1, None, false))?;
let import_object = imports! {
/*"env" => {
"memory" => memory,
}*/
};
// And instantiate it with no imports.
let instance = Instance::new(&module, &import_object)?;

let mem_size: NativeFunc<(), i32> = instance.exports.get_native_function("mem_size")?;
let get_at: NativeFunc<i32, i32> = instance.exports.get_native_function("get_at")?;
let set_at: NativeFunc<(i32, i32), ()> = instance.exports.get_native_function("set_at")?;
let memory = instance.exports.get_memory("memory")?;

let mem_addr = 0x2220;
let val = 0xFEFEFFE;

dbg!("before grow");

assert_eq!(memory.size(), Pages::from(1));
memory.grow(2)?;
dbg!("after first grow");
assert_eq!(memory.size(), Pages::from(3));
let result = mem_size.call()?;
assert_eq!(result, 3);

dbg!("Setting value to read later");
// -------------
set_at.call(mem_addr, val)?;
// -------------
dbg!("Value set correctly");

let page_size = 0x1_0000;
let result = get_at.call(page_size * 3 - 4)?;
dbg!("Before second grow");
memory.grow(1025)?;
dbg!("After second grow");
assert_eq!(memory.size(), Pages::from(1028));
set_at.call(page_size * 1027 - 4, 123456)?;
let result = get_at.call(page_size * 1027 - 4)?;
assert_eq!(result, 123456);
set_at.call(1024, 123456)?;
let result = get_at.call(1024)?;
assert_eq!(result, 123456);

// -------------
let result = get_at.call(mem_addr)?;
assert_eq!(result, val);
// -------------

//let result = get_at.call(page_size * 1028 - 4)?;

Ok(())
}
25 changes: 22 additions & 3 deletions examples/table.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use wasmer::{imports, wat2wasm, Function, Instance, Module, NativeFunc, Store, TableType, Type};
use wasmer::{
imports, wat2wasm, Function, Instance, Module, NativeFunc, Store, TableType, Type, Value,
};
use wasmer_compiler_cranelift::Cranelift;
//use wasmer_compiler_llvm::LLVM;
use wasmer_engine_jit::JIT;

/// A function we'll call through a table.
Expand Down Expand Up @@ -50,6 +53,7 @@ fn main() -> anyhow::Result<()> {

// We set up our store with an engine and a compiler.
let store = Store::new(&JIT::new(&Cranelift::default()).engine());
//let store = Store::new(&JIT::new(&LLVM::default()).engine());
// Then compile our Wasm.
let module = Module::new(&store, wasm_bytes)?;
let import_object = imports! {};
Expand Down Expand Up @@ -97,7 +101,6 @@ fn main() -> anyhow::Result<()> {

// == Growing a table ==

/*
// We again construct a `Function` over our host_callback.
let func = Function::new_native(&store, host_callback);

Expand All @@ -115,6 +118,16 @@ fn main() -> anyhow::Result<()> {
maximum: Some(6),
}
);
for table_index in 3..6 {
dbg!("hmm1");
if let Value::FuncRef(f) = guest_table.get(table_index as _).unwrap() {
let result = f.call(&[Value::I32(1), Value::I32(9)])?;
dbg!(&result);
assert_eq!(result[0], Value::I32(10));
} else {
panic!("expected to find funcref in table!");
}
}

if let Some(Value::FuncRef(f)) = guest_table.get(3) {
let result = f.call(&[Value::I32(1), Value::I32(9)]);
Expand All @@ -134,10 +147,16 @@ fn main() -> anyhow::Result<()> {

for table_index in 3..6 {
dbg!("hmm");
if let Value::FuncRef(f) = guest_table.get(table_index as _).unwrap() {
let result = f.call(&[Value::I32(1), Value::I32(9)])?;
dbg!(&result);
assert_eq!(result[0], Value::I32(10));
} else {
panic!("expected to find funcref in table!");
}
let result = call_via_table.call(table_index, 1, 9)?;
assert_eq!(result, 10);
}
*/

Ok(())
}
2 changes: 1 addition & 1 deletion lib/api/src/externals/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Memory {
pub fn new(store: &Store, ty: MemoryType) -> Result<Memory, MemoryError> {
let tunables = store.tunables();
let style = tunables.memory_style(&ty);
let memory = tunables.create_memory(&ty, &style)?;
let memory = tunables.create_memory(&ty, &style, None)?;

Ok(Memory {
store: store.clone(),
Expand Down
2 changes: 2 additions & 0 deletions lib/api/src/externals/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ impl Table {
let item = init.into_checked_anyfunc(&self.store)?;
match self.table.grow(delta) {
Some(len) => {
dbg!("In Some result of table.grow");
for i in 0..delta {
dbg!("setting element", i);
set_table_item(self.table.as_ref(), len + i, item.clone())?;
}
Ok(len)
Expand Down
14 changes: 11 additions & 3 deletions lib/api/src/tunables.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::{MemoryType, Pages, TableType};
use more_asserts::assert_ge;
use std::cmp::min;
use std::ptr::NonNull;
use std::sync::Arc;
use target_lexicon::{OperatingSystem, PointerWidth};
use wasmer_compiler::Target;
use wasmer_engine::Tunables as BaseTunables;
use wasmer_vm::MemoryError;
use wasmer_vm::{LinearMemory, LinearTable, Memory, MemoryStyle, Table, TableStyle};
use wasmer_vm::{
LinearMemory, LinearTable, Memory, MemoryStyle, Table, TableStyle, VMMemoryDefinition,
};

/// Tunable parameters for WebAssembly compilation.
#[derive(Clone)]
Expand Down Expand Up @@ -66,7 +69,7 @@ impl BaseTunables for Tunables {
//
// If the module doesn't declare an explicit maximum treat it as 4GiB.
let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
if maximum <= self.static_memory_bound {
if false && maximum <= self.static_memory_bound {
assert_ge!(self.static_memory_bound, memory.minimum);
MemoryStyle::Static {
bound: self.static_memory_bound,
Expand All @@ -89,8 +92,13 @@ impl BaseTunables for Tunables {
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: Option<NonNull<VMMemoryDefinition>>,
) -> Result<Arc<dyn Memory>, MemoryError> {
Ok(Arc::new(LinearMemory::new(&ty, &style)?))
Ok(Arc::new(LinearMemory::new(
&ty,
&style,
vm_definition_location,
)?))
}

/// Create a table given a [`TableType`] and a [`TableStyle`].
Expand Down
1 change: 1 addition & 0 deletions lib/compiler-singlepass/src/codegen_x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,7 @@ impl<'a> FuncGen<'a> {
MemoryStyle::Static { .. } => false,
MemoryStyle::Dynamic { .. } => true,
};
dbg!(need_check);
let tmp_addr = self.machine.acquire_temp_gpr().unwrap();

// Reusing `tmp_addr` for temporary indirection here, since it's not used before the last reference to `{base,bound}_loc`.
Expand Down
8 changes: 7 additions & 1 deletion lib/engine/src/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub trait Artifact: Send + Sync + Upcastable {
self.preinstantiate()?;

let module = self.module();
let (instance_ptr, offsets) = InstanceHandle::allocate_instance(&module);
let imports = resolve_imports(
&module,
resolver,
Expand All @@ -98,8 +99,11 @@ pub trait Artifact: Send + Sync + Upcastable {
self.table_styles(),
)
.map_err(InstantiationError::Link)?;
let memory_definition_locations =
InstanceHandle::memory_definition_locations(instance_ptr, &offsets);
dbg!(&memory_definition_locations);
let finished_memories = tunables
.create_memories(&module, self.memory_styles())
.create_memories(&module, self.memory_styles(), &memory_definition_locations)
.map_err(InstantiationError::Link)?
.into_boxed_slice();
let finished_tables = tunables
Expand All @@ -114,6 +118,8 @@ pub trait Artifact: Send + Sync + Upcastable {
self.register_frame_info();

InstanceHandle::new(
instance_ptr,
offsets,
module,
self.finished_functions().clone(),
finished_memories,
Expand Down
8 changes: 7 additions & 1 deletion lib/engine/src/tunables.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::error::LinkError;
use std::ptr::NonNull;
use std::sync::Arc;
use wasmer_types::entity::{EntityRef, PrimaryMap};
use wasmer_types::{
GlobalType, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType,
TableIndex, TableType,
};
use wasmer_vm::MemoryError;
use wasmer_vm::VMMemoryDefinition;
use wasmer_vm::{Global, Memory, ModuleInfo, Table};
use wasmer_vm::{MemoryStyle, TableStyle};

Expand All @@ -23,6 +25,7 @@ pub trait Tunables {
&self,
ty: &MemoryType,
style: &MemoryStyle,
vm_definition_location: Option<NonNull<VMMemoryDefinition>>,
) -> Result<Arc<dyn Memory>, MemoryError>;

/// Create a memory given a memory type
Expand All @@ -38,6 +41,7 @@ pub trait Tunables {
&self,
module: &ModuleInfo,
memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
memory_definition_locations: &[NonNull<VMMemoryDefinition>],
) -> Result<PrimaryMap<LocalMemoryIndex, Arc<dyn Memory>>, LinkError> {
let num_imports = module.num_imported_memories;
let mut memories: PrimaryMap<LocalMemoryIndex, _> =
Expand All @@ -46,8 +50,10 @@ pub trait Tunables {
let mi = MemoryIndex::new(index);
let ty = &module.memories[mi];
let style = &memory_styles[mi];
// TODO: error handling
let mdl = memory_definition_locations[index];
memories.push(
self.create_memory(ty, style)
self.create_memory(ty, style, Some(mdl))
.map_err(|e| LinkError::Resource(format!("Failed to create memory: {}", e)))?,
);
}
Expand Down
Loading

0 comments on commit 4fc8ace

Please sign in to comment.