somewhat working

This commit is contained in:
NikVolf
2017-05-15 19:15:09 +03:00
parent 1083eaa65d
commit 20496ae9b2
6 changed files with 139 additions and 22 deletions

View File

@ -1,4 +1,4 @@
use parity_wasm::interpreter; use parity_wasm::interpreter::{self, ModuleInstance};
use runtime::Runtime; use runtime::Runtime;
pub struct Arena { pub struct Arena {
@ -18,7 +18,7 @@ impl Arena {
} }
impl interpreter::UserFunctionInterface for Arena { impl interpreter::UserFunctionInterface for Arena {
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> { fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
let amount = context.value_stack.pop_as::<i32>()?; let amount = context.value_stack.pop_as::<i32>()?;
self.alloc(amount as u32) self.alloc(amount as u32)
.map(|val| Some((val as i32).into())) .map(|val| Some((val as i32).into()))

View File

@ -60,6 +60,7 @@ pub fn init(
write_u32(&mut input_length, input.len() as u32); write_u32(&mut input_length, input.len() as u32);
memory.set(input_ptr, input)?; memory.set(input_ptr, input)?;
println!("input_ptr: {}", input_ptr); println!("input_ptr: {}", input_ptr);
println!("input: {:?}", memory.get(input_ptr, input.len()));
} }
memory.set(descriptor_ptr, &context_ptr_slc)?; memory.set(descriptor_ptr, &context_ptr_slc)?;

View File

@ -1,4 +1,4 @@
use parity_wasm::interpreter; use parity_wasm::interpreter::{self, ModuleInstance};
use runtime::Runtime; use runtime::Runtime;
pub struct GasCounter { pub struct GasCounter {
@ -6,7 +6,7 @@ pub struct GasCounter {
} }
impl interpreter::UserFunctionInterface for GasCounter { impl interpreter::UserFunctionInterface for GasCounter {
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> { fn call(&mut self, _module: &ModuleInstance, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
let prev = self.runtime.env().gas_counter.get(); let prev = self.runtime.env().gas_counter.get();
let update = context.value_stack.pop_as::<i32>()? as u64; let update = context.value_stack.pop_as::<i32>()? as u64;
if prev + update > self.runtime.env().gas_limit { if prev + update > self.runtime.env().gas_limit {

View File

@ -53,7 +53,29 @@ fn main() {
closure: Box::new(runtime.allocator()), closure: Box::new(runtime.allocator()),
} }
); );
user_functions.insert("_storage_size".to_owned(),
interpreter::UserFunction {
params: vec![elements::ValueType::I32],
result: Some(elements::ValueType::I32),
closure: Box::new(runtime.storage().sizer()),
}
);
user_functions.insert("_storage_read".to_owned(),
interpreter::UserFunction {
params: vec![elements::ValueType::I32],
result: Some(elements::ValueType::I32),
closure: Box::new(runtime.storage().reader()),
}
);
user_functions.insert("_storage_write".to_owned(),
interpreter::UserFunction {
params: vec![elements::ValueType::I32],
result: Some(elements::ValueType::I32),
closure: Box::new(runtime.storage().writer()),
}
);
runtime::user_trap(&mut user_functions, "_emscripten_memcpy_big"); runtime::user_trap(&mut user_functions, "_emscripten_memcpy_big");
runtime::user_noop(&mut user_functions, "_free");
let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions) let program = parity_wasm::interpreter::ProgramInstance::with_functions(user_functions)
.expect("Program instance to be created"); .expect("Program instance to be created");

View File

@ -1,14 +1,15 @@
use std::sync::Arc; use std::sync::Arc;
use std::cell::Cell; use std::cell::{Cell, RefCell};
use parity_wasm::{interpreter, elements}; use parity_wasm::{interpreter, elements};
use {alloc, gas_counter}; use {alloc, gas_counter, storage};
#[derive(Default)] #[derive(Default)]
pub struct RuntimeEnv { pub struct RuntimeEnv {
pub gas_counter: Cell<u64>, pub gas_counter: Cell<u64>,
pub gas_limit: u64, pub gas_limit: u64,
pub dynamic_top: Cell<u32>, pub dynamic_top: Cell<u32>,
pub storage: RefCell<Vec<u8>>,
} }
#[derive(Default, Clone)] #[derive(Default, Clone)]
@ -20,6 +21,7 @@ impl Runtime {
gas_counter: Cell::new(0), gas_counter: Cell::new(0),
gas_limit: gas_limit, gas_limit: gas_limit,
dynamic_top: Cell::new(stack_space), dynamic_top: Cell::new(stack_space),
storage: Default::default(),
})) }))
} }
@ -35,6 +37,10 @@ impl Runtime {
} }
} }
pub fn storage(&self) -> storage::Storage {
storage::Storage::new(self.clone())
}
pub fn env(&self) -> &RuntimeEnv { pub fn env(&self) -> &RuntimeEnv {
&*self.0 &*self.0
} }
@ -44,7 +50,7 @@ pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) {
let func_str = func_name.to_owned(); let func_str = func_name.to_owned();
funcs.insert(func_str.clone(), funcs.insert(func_str.clone(),
interpreter::UserFunction { interpreter::UserFunction {
params: vec![elements::ValueType::I32], params: vec![],
result: Some(elements::ValueType::I32), result: Some(elements::ValueType::I32),
closure: Box::new(UserTrap(func_str)), closure: Box::new(UserTrap(func_str)),
} }
@ -54,7 +60,32 @@ pub fn user_trap(funcs: &mut interpreter::UserFunctions, func_name: &str) {
struct UserTrap(String); struct UserTrap(String);
impl interpreter::UserFunctionInterface for UserTrap { impl interpreter::UserFunctionInterface for UserTrap {
fn call(&mut self, context: interpreter::CallerContext) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> { fn call(&mut self,
_module: &interpreter::ModuleInstance,
_context: interpreter::CallerContext
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
Err(interpreter::Error::Trap(self.0.clone())) Err(interpreter::Error::Trap(self.0.clone()))
} }
}
struct UserNoop;
pub fn user_noop(funcs: &mut interpreter::UserFunctions, func_name: &str) {
let func_str = func_name.to_owned();
funcs.insert(func_str.clone(),
interpreter::UserFunction {
params: vec![],
result: None,
closure: Box::new(UserNoop),
}
);
}
impl interpreter::UserFunctionInterface for UserNoop {
fn call(&mut self,
_module: &interpreter::ModuleInstance,
_context: interpreter::CallerContext
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
Ok(None)
}
} }

View File

@ -1,32 +1,41 @@
use parity_wasm::interpreter::ModuleInstanceInterface; use parity_wasm::interpreter::{self, ItemIndex, ModuleInstanceInterface};
use parity_wasm::interpreter::ItemIndex;
use std::sync::Arc; use std::sync::Arc;
use DEFAULT_MEMORY_INDEX; use DEFAULT_MEMORY_INDEX;
use runtime::Runtime;
pub struct Storage { pub struct Storage {
data: Vec<u8>, runtime: Runtime,
module: Arc<ModuleInstanceInterface>,
} }
pub struct Error; pub struct Error;
impl Storage { impl Storage {
pub fn read(&self, offset: u32, len: u32, dst: u32) -> i32 { pub fn new(runtime: Runtime) -> Self {
let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) { Storage {
runtime: runtime,
}
}
pub fn read(&self, module: &interpreter::ModuleInstance, offset: u32, len: u32, dst: u32) -> i32 {
let data = self.runtime.env().storage.borrow();
let memory = match module.memory(DEFAULT_MEMORY_INDEX) {
Err(_) => { return -1; }, Err(_) => { return -1; },
Ok(memory) => memory, Ok(memory) => memory,
}; };
match memory.set(dst, &self.data[offset as usize..offset as usize + len as usize]) { match memory.set(dst, &data[offset as usize..offset as usize + len as usize]) {
Err(_) => { return -1; } Err(_) => { return -1; }
Ok(_) => { return len as i32; } Ok(_) => { return len as i32; }
} }
} }
pub fn write(&mut self, offset: u32, len: u32, src: u32) -> i32 { pub fn write(&mut self, module: &interpreter::ModuleInstance, offset: u32, len: u32, src: u32) -> i32 {
let memory = match self.module.memory(DEFAULT_MEMORY_INDEX) { let mut data = self.runtime.env().storage.borrow_mut();
let memory = match module.memory(DEFAULT_MEMORY_INDEX) {
Err(_) => { return -1; }, Err(_) => { return -1; },
Ok(memory) => memory, Ok(memory) => memory,
}; };
@ -36,16 +45,70 @@ impl Storage {
Ok(slice) => slice, Ok(slice) => slice,
}; };
if self.data.len() < offset as usize + slice.len() { if data.len() < offset as usize + slice.len() {
self.data.reserve(offset as usize + slice.len()); data.reserve(offset as usize + slice.len());
unsafe { unsafe {
self.data.set_len(offset as usize + slice.len()); data.set_len(offset as usize + slice.len());
} }
} }
self.data[offset as usize..offset as usize + slice.len()].copy_from_slice(&slice[..]); data[offset as usize..offset as usize + slice.len()].copy_from_slice(&slice[..]);
slice.len() as i32 slice.len() as i32
} }
pub fn size(&self) -> u32 { self.data.len() as u32 } pub fn size(&self, _module: &interpreter::ModuleInstance) -> u32 { self.runtime.env().storage.borrow().len() as u32 }
pub fn writer(self) -> StorageWrite {
StorageWrite(self)
}
pub fn reader(self) -> StorageRead {
StorageRead(self)
}
pub fn sizer(self) -> StorageSize {
StorageSize(self)
}
}
pub struct StorageWrite(Storage);
impl interpreter::UserFunctionInterface for StorageWrite {
fn call(&mut self,
module: &interpreter::ModuleInstance,
context: interpreter::CallerContext,
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
let offset = context.value_stack.pop_as::<i32>()?;
let len = context.value_stack.pop_as::<i32>()?;
let ptr = context.value_stack.pop_as::<i32>()?;
Ok(Some(self.0.write(module, offset as u32, len as u32, ptr as u32).into()))
}
}
pub struct StorageRead(Storage);
impl interpreter::UserFunctionInterface for StorageRead {
fn call(&mut self,
module: &interpreter::ModuleInstance,
context: interpreter::CallerContext,
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
let offset = context.value_stack.pop_as::<i32>()?;
let len = context.value_stack.pop_as::<i32>()?;
let ptr = context.value_stack.pop_as::<i32>()?;
Ok(Some(self.0.read(module, offset as u32, len as u32, ptr as u32).into()))
}
}
pub struct StorageSize(Storage);
impl interpreter::UserFunctionInterface for StorageSize {
fn call(&mut self,
module: &interpreter::ModuleInstance,
context: interpreter::CallerContext,
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{
Ok(Some((self.0.size(module) as i32).into()))
}
} }