From b233bfcadd8606d0f8fa55ec2f66288fdadb042c Mon Sep 17 00:00:00 2001 From: Valery Antopol Date: Wed, 6 Apr 2022 22:25:01 +0300 Subject: [PATCH] Refactor memory access interface to fix that writer does not update memory after allocation (#17) --- Cargo.lock | 6 +- crates/it-lilo/Cargo.toml | 4 +- crates/it-lilo/src/lifter/lift_array.rs | 10 +- crates/it-lilo/src/lifter/lift_record.rs | 21 ++-- crates/it-lilo/src/lifter/macros.rs | 22 ++--- crates/it-lilo/src/lifter/memory_reader.rs | 45 +++++++-- crates/it-lilo/src/lifter/mod.rs | 4 +- crates/it-lilo/src/lowerer/lower_array.rs | 44 ++++----- crates/it-lilo/src/lowerer/lower_record.rs | 4 +- crates/it-lilo/src/lowerer/memory_writer.rs | 95 ++++++++++++++++--- crates/it-lilo/src/lowerer/mod.rs | 6 +- crates/it-lilo/src/traits/allocatable.rs | 5 +- crates/it-memory-traits/Cargo.toml | 2 +- crates/it-memory-traits/src/lib.rs | 75 ++++++--------- wasmer-it/Cargo.toml | 6 +- .../src/interpreter/instructions/arrays.rs | 44 +++------ .../interpreter/instructions/byte_arrays.rs | 13 ++- .../instructions/lilo/li_helper.rs | 30 +++--- .../instructions/lilo/lo_helper.rs | 44 +++++---- wasmer-it/src/interpreter/instructions/mod.rs | 40 ++++---- .../src/interpreter/instructions/records.rs | 44 +++------ .../src/interpreter/instructions/strings.rs | 18 ++-- wasmer-it/src/interpreter/mod.rs | 67 ++++++------- wasmer-it/src/interpreter/wasm/structures.rs | 55 ++++------- wasmer-it/src/macros.rs | 18 ++-- 25 files changed, 372 insertions(+), 350 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbce22b..e389b55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,7 +39,7 @@ dependencies = [ [[package]] name = "it-lilo" -version = "0.3.0" +version = "0.4.0" dependencies = [ "fluence-it-types", "it-memory-traits", @@ -50,7 +50,7 @@ dependencies = [ [[package]] name = "it-memory-traits" -version = "0.2.0" +version = "0.3.0" dependencies = [ "thiserror", ] @@ -280,7 +280,7 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "wasmer-interface-types-fl" -version = "0.22.0" +version = "0.23.0" dependencies = [ "fluence-it-types", "it-lilo", diff --git a/crates/it-lilo/Cargo.toml b/crates/it-lilo/Cargo.toml index 3300c16..047a5b0 100644 --- a/crates/it-lilo/Cargo.toml +++ b/crates/it-lilo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "it-lilo" -version = "0.3.0" +version = "0.4.0" authors = ["Fluence Labs"] description = "Defines some helper utils for lifting/lowering IT" edition = "2018" @@ -12,7 +12,7 @@ path = "src/lib.rs" [dependencies] fluence-it-types = { path = "../it-types/", version = "0.3.0" } -it-memory-traits = { path = "../it-memory-traits", version = "0.2.0" } +it-memory-traits = { path = "../it-memory-traits", version = "0.3.0" } paste = "1.0.5" thiserror = "1.0.24" diff --git a/crates/it-lilo/src/lifter/lift_array.rs b/crates/it-lilo/src/lifter/lift_array.rs index 665bab5..ae8d381 100644 --- a/crates/it-lilo/src/lifter/lift_array.rs +++ b/crates/it-lilo/src/lifter/lift_array.rs @@ -22,9 +22,9 @@ use crate::utils::ser_type_size; use crate::IType; use crate::IValue; -use it_memory_traits::{SequentialMemoryView, SequentialReader}; +use it_memory_traits::MemoryView; -pub fn array_lift_memory SequentialMemoryView<'a>>( +pub fn array_lift_memory( lifter: &ILifter<'_, R, MV>, value_type: &IType, offset: u32, @@ -61,7 +61,7 @@ pub fn array_lift_memory SequentialMemoryView<' Ok(IValue::Array(ivalues)) } -fn read_string_array SequentialMemoryView<'a>>( +fn read_string_array( lifter: &ILifter<'_, R, MV>, offset: u32, elements_count: u32, @@ -83,7 +83,7 @@ fn read_string_array SequentialMemoryView<'a>>( Ok(result) } -fn read_array_array SequentialMemoryView<'a>>( +fn read_array_array( lifter: &ILifter<'_, R, MV>, ty: &IType, offset: u32, @@ -105,7 +105,7 @@ fn read_array_array SequentialMemoryView<'a>>( Ok(result) } -fn read_record_array SequentialMemoryView<'a>>( +fn read_record_array( lifter: &ILifter<'_, R, MV>, record_type_id: u64, offset: u32, diff --git a/crates/it-lilo/src/lifter/lift_record.rs b/crates/it-lilo/src/lifter/lift_record.rs index 944c16e..396077a 100644 --- a/crates/it-lilo/src/lifter/lift_record.rs +++ b/crates/it-lilo/src/lifter/lift_record.rs @@ -18,6 +18,7 @@ use super::ILifter; use super::LiError; use super::LiResult; use super::MemoryReader; +use crate::lifter::memory_reader::SequentialReader; use crate::traits::RecordResolvable; use crate::utils::record_size; use crate::IRecordType; @@ -25,9 +26,9 @@ use crate::IType; use crate::IValue; use crate::NEVec; -use it_memory_traits::{SequentialMemoryView, SequentialReader}; +use it_memory_traits::MemoryView; -pub fn record_lift_memory SequentialMemoryView<'a>>( +pub fn record_lift_memory( lifter: &ILifter<'_, R, MV>, record_type: &IRecordType, offset: u32, @@ -68,9 +69,9 @@ pub fn record_lift_memory SequentialMemoryView< Ok(IValue::Record(record)) } -fn read_string SequentialMemoryView<'a>>( +fn read_string( reader: &MemoryReader, - seq_reader: &>::SR, + seq_reader: &SequentialReader<'_, MV>, ) -> LiResult { let offset = seq_reader.read_u32(); let size = seq_reader.read_u32(); @@ -81,9 +82,9 @@ fn read_string SequentialMemoryView<'a>>( Ok(string) } -fn read_byte_array SequentialMemoryView<'a>>( +fn read_byte_array( reader: &MemoryReader, - seq_reader: &>::SR, + seq_reader: &SequentialReader<'_, MV>, ) -> LiResult { let offset = seq_reader.read_u32(); let size = seq_reader.read_u32(); @@ -93,9 +94,9 @@ fn read_byte_array SequentialMemoryView<'a>>( Ok(IValue::ByteArray(array)) } -fn read_array SequentialMemoryView<'a>>( +fn read_array( lifter: &ILifter<'_, R, MV>, - seq_reader: &>::SR, + seq_reader: &SequentialReader<'_, MV>, value_type: &IType, ) -> LiResult { let offset = seq_reader.read_u32(); @@ -104,9 +105,9 @@ fn read_array SequentialMemoryView<'a>>( super::array_lift_memory(lifter, value_type, offset, size) } -fn read_record SequentialMemoryView<'a>>( +fn read_record( lifter: &ILifter<'_, R, MV>, - seq_reader: &>::SR, + seq_reader: &SequentialReader<'_, MV>, record_type_id: u64, ) -> LiResult { let offset = seq_reader.read_u32(); diff --git a/crates/it-lilo/src/lifter/macros.rs b/crates/it-lilo/src/lifter/macros.rs index a57175a..d78a293 100644 --- a/crates/it-lilo/src/lifter/macros.rs +++ b/crates/it-lilo/src/lifter/macros.rs @@ -17,34 +17,34 @@ #[macro_export] macro_rules! value_der { ($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => { - [$($self.memory.get($offset + $ids)),+] + [$($self.reader.view.read_byte($offset + $ids)),+] }; ($self:expr, $offset:expr, 1) => { - crate::value_der!($self, $offset, @seq_start 0 @seq_end); + crate::value_der!($self, $offset, @seq_start 0 @seq_end) }; ($self:expr, $offset:expr, 2) => { - crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end); + crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end) }; ($self:expr, $offset:expr, 4) => { - crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end); + crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end) }; ($self:expr, $offset:expr, 8) => { - crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end); + crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end) }; ($self:expr, $offset:expr, 16) => { - crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @seq_end); + crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @seq_end) }; } #[macro_export] macro_rules! read_ty { ($func_name:ident, $ty:ty, 1) => { - fn $func_name(&self) -> $ty { + pub fn $func_name(&self) -> $ty { let offset = self.offset.get(); let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 1)); @@ -54,7 +54,7 @@ macro_rules! read_ty { }; ($func_name:ident, $ty:ty, 2) => { - fn $func_name(&self) -> $ty { + pub fn $func_name(&self) -> $ty { let offset = self.offset.get(); let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 2)); @@ -64,7 +64,7 @@ macro_rules! read_ty { }; ($func_name:ident, $ty:ty, 4) => { - fn $func_name(&self) -> $ty { + pub fn $func_name(&self) -> $ty { let offset = self.offset.get(); let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 4)); @@ -74,7 +74,7 @@ macro_rules! read_ty { }; ($func_name:ident, $ty:ty, 8) => { - fn $func_name(&self) -> $ty { + pub fn $func_name(&self) -> $ty { let offset = self.offset.get(); let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 8)); @@ -84,7 +84,7 @@ macro_rules! read_ty { }; ($func_name:ident, $ty:ty, 16) => { - fn $func_name(&self) -> $ty { + pub fn $func_name(&self) -> $ty { let offset = self.offset.get(); let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 16)); diff --git a/crates/it-lilo/src/lifter/memory_reader.rs b/crates/it-lilo/src/lifter/memory_reader.rs index 3d2e179..a616adf 100644 --- a/crates/it-lilo/src/lifter/memory_reader.rs +++ b/crates/it-lilo/src/lifter/memory_reader.rs @@ -16,15 +16,18 @@ use super::LiResult; use crate::read_array_ty; +use crate::read_ty; use crate::IValue; -use it_memory_traits::{SequentialMemoryView, SequentialReader}; +use it_memory_traits::MemoryView; + +use std::cell::Cell; pub struct MemoryReader { pub(self) view: MV, } -impl SequentialMemoryView<'a>> MemoryReader { +impl MemoryReader { pub fn new(view: MV) -> Self { Self { view } } @@ -32,12 +35,9 @@ impl SequentialMemoryView<'a>> MemoryReader { /// Returns reader that allows read sequentially. It's important that memory limit is checked /// only inside this function. All others functions of the returned reader don't have any /// checks assuming that reader is well-formed. - pub fn sequential_reader( - &self, - offset: u32, - size: u32, - ) -> LiResult<>::SR> { - let seq_reader = self.view.sequential_reader(offset, size)?; + pub fn sequential_reader(&self, offset: u32, size: u32) -> LiResult> { + self.view.check_bounds(offset, size)?; + let seq_reader = SequentialReader::new(&self, offset); Ok(seq_reader) } @@ -78,3 +78,32 @@ impl SequentialMemoryView<'a>> MemoryReader { read_array_ty!(read_i64_array, i64, I64); read_array_ty!(read_f64_array, f64, F64); } + +pub struct SequentialReader<'r, MV: MemoryView> { + reader: &'r MemoryReader, + offset: Cell, +} + +impl<'r, MV: MemoryView> SequentialReader<'r, MV> { + fn new(reader: &'r MemoryReader, offset: u32) -> Self { + Self { + reader, + offset: Cell::new(offset), + } + } + + pub fn read_bool(&self) -> bool { + self.read_u8() != 0 + } + + read_ty!(read_u8, u8, 1); + read_ty!(read_i8, i8, 1); + read_ty!(read_u16, u16, 2); + read_ty!(read_i16, i16, 2); + read_ty!(read_u32, u32, 4); + read_ty!(read_i32, i32, 4); + read_ty!(read_f32, f32, 4); + read_ty!(read_u64, u64, 8); + read_ty!(read_i64, i64, 8); + read_ty!(read_f64, f64, 8); +} diff --git a/crates/it-lilo/src/lifter/mod.rs b/crates/it-lilo/src/lifter/mod.rs index 11093b2..83c822e 100644 --- a/crates/it-lilo/src/lifter/mod.rs +++ b/crates/it-lilo/src/lifter/mod.rs @@ -27,7 +27,7 @@ pub use memory_reader::MemoryReader; use super::traits::RecordResolvable; -pub use it_memory_traits::SequentialMemoryView; +pub use it_memory_traits::MemoryView; pub type LiResult = std::result::Result; @@ -36,7 +36,7 @@ pub struct ILifter<'r, R: RecordResolvable, MV> { pub resolver: &'r R, } -impl<'r, R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>> ILifter<'r, R, MV> { +impl<'r, R: RecordResolvable, MV: MemoryView> ILifter<'r, R, MV> { pub fn new(view: MV, resolver: &'r R) -> Self { let reader = MemoryReader::new(view); Self { reader, resolver } diff --git a/crates/it-lilo/src/lowerer/lower_array.rs b/crates/it-lilo/src/lowerer/lower_array.rs index 0e7c060..3563e82 100644 --- a/crates/it-lilo/src/lowerer/lower_array.rs +++ b/crates/it-lilo/src/lowerer/lower_array.rs @@ -21,7 +21,7 @@ use crate::utils::ser_value_size; use crate::utils::type_tag_form_ivalue; use crate::IValue; -use it_memory_traits::{SequentialMemoryView, SequentialWriter}; +use it_memory_traits::MemoryView; pub struct LoweredArray { pub offset: u32, @@ -38,7 +38,7 @@ impl LoweredArray { } } -pub fn array_lower_memory SequentialMemoryView<'a>>( +pub fn array_lower_memory, MV: MemoryView>( lowerer: &ILowerer<'_, A, MV>, array_values: Vec, ) -> LoResult { @@ -54,40 +54,40 @@ pub fn array_lower_memory SequentialMemoryView<'a>>( // here it's known that all interface values have the same type for value in array_values { match value { - IValue::Boolean(value) => seq_writer.write_u8(value as _), - IValue::S8(value) => seq_writer.write_u8(value as _), - IValue::S16(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::S32(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::S64(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::U8(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::U16(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::U32(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::U64(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::I32(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::I64(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::F32(value) => seq_writer.write_bytes(&value.to_le_bytes()), - IValue::F64(value) => seq_writer.write_bytes(&value.to_le_bytes()), + IValue::Boolean(value) => seq_writer.write_u8(&lowerer.writer, value as _), + IValue::S8(value) => seq_writer.write_u8(&lowerer.writer, value as _), + IValue::S16(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::S32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::S64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::U8(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::U16(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::U32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::U64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::I32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::I64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::F32(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), + IValue::F64(value) => seq_writer.write_bytes(&lowerer.writer, &value.to_le_bytes()), IValue::String(value) => { let offset = lowerer.writer.write_bytes(&value.as_bytes())? as u32; - seq_writer.write_bytes(&offset.to_le_bytes()); - seq_writer.write_bytes(&(value.len() as u32).to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &(value.len() as u32).to_le_bytes()); } IValue::ByteArray(values) => { let offset = lowerer.writer.write_bytes(&values)? as u32; - seq_writer.write_bytes(&offset.to_le_bytes()); - seq_writer.write_bytes(&(values.len() as u32).to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &(values.len() as u32).to_le_bytes()); } IValue::Array(values) => { let LoweredArray { offset, size } = array_lower_memory(lowerer, values)?; - seq_writer.write_bytes(&(offset as u32).to_le_bytes()); - seq_writer.write_bytes(&(size as u32).to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &(offset as u32).to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &(size as u32).to_le_bytes()); } IValue::Record(values) => { let offset = super::record_lower_memory(lowerer, values)? as u32; - seq_writer.write_bytes(&offset.to_le_bytes()); + seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes()); } } } diff --git a/crates/it-lilo/src/lowerer/lower_record.rs b/crates/it-lilo/src/lowerer/lower_record.rs index c9a73d2..b52534e 100644 --- a/crates/it-lilo/src/lowerer/lower_record.rs +++ b/crates/it-lilo/src/lowerer/lower_record.rs @@ -21,9 +21,9 @@ use crate::traits::Allocatable; use crate::IValue; use crate::NEVec; -use it_memory_traits::SequentialMemoryView; +use it_memory_traits::MemoryView; -pub fn record_lower_memory SequentialMemoryView<'a>>( +pub fn record_lower_memory, MV: MemoryView>( lowerer: &ILowerer<'_, A, MV>, values: NEVec, ) -> LoResult { diff --git a/crates/it-lilo/src/lowerer/memory_writer.rs b/crates/it-lilo/src/lowerer/memory_writer.rs index 3dcbb63..c186be6 100644 --- a/crates/it-lilo/src/lowerer/memory_writer.rs +++ b/crates/it-lilo/src/lowerer/memory_writer.rs @@ -18,34 +18,103 @@ use super::LoResult; use crate::traits::Allocatable; use crate::utils::type_tag_form_itype; -use it_memory_traits::{SequentialMemoryView, SequentialWriter}; +use it_memory_traits::MemoryView; -pub struct MemoryWriter<'i, R: Allocatable, MV> { +use std::cell::{Cell, RefCell}; + +pub struct MemoryWriter<'i, R: Allocatable, MV: MemoryView> { heap_manager: &'i R, - view: MV, + view: RefCell, } -impl<'i, A: Allocatable, MV: for<'a> SequentialMemoryView<'a>> MemoryWriter<'i, A, MV> { +impl<'i, A: Allocatable, MV: MemoryView> MemoryWriter<'i, A, MV> { pub fn new(view: MV, heap_manager: &'i A) -> LoResult { - let writer = Self { heap_manager, view }; + let writer = Self { + heap_manager, + view: RefCell::new(view), + }; Ok(writer) } pub fn write_bytes(&self, bytes: &[u8]) -> LoResult { let byte_type_tag = type_tag_form_itype(&crate::IType::U8); let seq_writer = self.sequential_writer(bytes.len() as u32, byte_type_tag)?; - seq_writer.write_bytes(bytes); + seq_writer.write_bytes(&self, bytes); Ok(seq_writer.start_offset()) } - pub fn sequential_writer( - &self, - size: u32, - type_tag: u32, - ) -> LoResult<>::SW> { - let offset = self.heap_manager.allocate(size, type_tag)?; - let seq_writer = self.view.sequential_writer(offset, size)?; + pub fn sequential_writer(&self, size: u32, type_tag: u32) -> LoResult { + let (offset, view) = self.heap_manager.allocate(size, type_tag)?; + self.view.replace(view); + let seq_writer = SequentialWriter::new(offset); Ok(seq_writer) } } + +pub struct SequentialWriter { + start_offset: u32, + offset: Cell, +} + +impl SequentialWriter { + pub(self) fn new(offset: u32) -> Self { + Self { + offset: Cell::new(offset), + start_offset: offset, + } + } + + pub fn start_offset(&self) -> u32 { + self.start_offset + } + + pub fn write_array, const N: usize>( + &self, + writer: &MemoryWriter<'_, A, MV>, + values: [u8; N], + ) { + let offset = self.offset.get(); + + writer.view.borrow().write_bytes(offset, &values); + + self.offset.set(offset + N as u32); + } + + pub fn write_u8>( + &self, + writer: &MemoryWriter<'_, A, MV>, + value: u8, + ) { + let offset = self.offset.get(); + + writer.view.borrow().write_byte(offset, value); + + self.offset.set(offset + 1); + } + + pub fn write_u32>( + &self, + writer: &MemoryWriter<'_, A, MV>, + value: u32, + ) { + let offset = self.offset.get(); + + let value = value.to_le_bytes(); + writer.view.borrow().write_bytes(offset, &value); + + self.offset.set(offset + 4); + } + + pub fn write_bytes>( + &self, + writer: &MemoryWriter<'_, A, MV>, + bytes: &[u8], + ) { + let offset = self.offset.get(); + + writer.view.borrow().write_bytes(offset, bytes); + + self.offset.set(offset + bytes.len() as u32); + } +} diff --git a/crates/it-lilo/src/lowerer/mod.rs b/crates/it-lilo/src/lowerer/mod.rs index 68c2974..575d321 100644 --- a/crates/it-lilo/src/lowerer/mod.rs +++ b/crates/it-lilo/src/lowerer/mod.rs @@ -27,15 +27,15 @@ pub use lower_array::array_lower_memory; pub use lower_array::LoweredArray; pub use lower_record::record_lower_memory; -pub use it_memory_traits::SequentialMemoryView; +pub use it_memory_traits::MemoryView; pub type LoResult = std::result::Result; -pub struct ILowerer<'m, A: Allocatable, MV> { +pub struct ILowerer<'m, A: Allocatable, MV: MemoryView> { pub writer: MemoryWriter<'m, A, MV>, } -impl<'m, A: Allocatable, MV: for<'a> SequentialMemoryView<'a>> ILowerer<'m, A, MV> { +impl<'m, A: Allocatable, MV: MemoryView> ILowerer<'m, A, MV> { pub fn new(view: MV, allocatable: &'m A) -> LoResult { let writer = MemoryWriter::new(view, allocatable)?; let lowerer = Self { writer }; diff --git a/crates/it-lilo/src/traits/allocatable.rs b/crates/it-lilo/src/traits/allocatable.rs index 634e6f5..986d64d 100644 --- a/crates/it-lilo/src/traits/allocatable.rs +++ b/crates/it-lilo/src/traits/allocatable.rs @@ -14,12 +14,13 @@ * limitations under the License. */ +use it_memory_traits::MemoryView; use thiserror::Error as ThisError; pub const DEFAULT_MEMORY_INDEX: usize = 0; -pub trait Allocatable { - fn allocate(&self, size: u32, type_tag: u32) -> Result; +pub trait Allocatable { + fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MV), AllocatableError>; } #[derive(Debug, ThisError)] diff --git a/crates/it-memory-traits/Cargo.toml b/crates/it-memory-traits/Cargo.toml index 062e550..ac334cb 100644 --- a/crates/it-memory-traits/Cargo.toml +++ b/crates/it-memory-traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "it-memory-traits" -version = "0.2.0" +version = "0.3.0" authors = ["Fluence Labs"] description = "Defines traits that IT uses for accessing memory" edition = "2018" diff --git a/crates/it-memory-traits/src/lib.rs b/crates/it-memory-traits/src/lib.rs index f5d66ef..b38e03a 100644 --- a/crates/it-memory-traits/src/lib.rs +++ b/crates/it-memory-traits/src/lib.rs @@ -18,61 +18,44 @@ mod errors; pub use errors::MemoryAccessError; -macro_rules! read_ty { - ($func_name:ident, $ty:ty, $size:literal) => { - fn $func_name(&self) -> $ty { - <$ty>::from_le_bytes(self.read_bytes::<$size>()) - } - }; +pub trait MemoryReadable { + /// This function will panic if the `offset` is out of bounds. + /// It is caller's responsibility to check if the offset is in bounds + /// using `MemoryView::check_bounds` function + fn read_byte(&self, offset: u32) -> u8; + + /// This function will panic if `[offset..offset + COUNT]` is out of bounds. + /// It is caller's responsibility to check if the offset is in bounds + /// using `MemoryView::check_bounds` function. + fn read_array(&self, offset: u32) -> [u8; COUNT]; + + /// This function will panic if `[offset..offset + size]` is out of bounds. + /// It is caller's responsibility to check if the offset is in bounds + /// using `MemoryView::check_bounds` function. + fn read_vec(&self, offset: u32, size: u32) -> Vec; } -pub trait SequentialReader { - fn read_byte(&self) -> u8; +pub trait MemoryWritable { + /// This function will panic if `offset` is out of bounds. + /// It is caller's responsibility to check if the offset is in bounds + /// using `MemoryView::check_bounds` function. + fn write_byte(&self, offset: u32, value: u8); - fn read_bytes(&self) -> [u8; COUNT]; - - fn read_bool(&self) -> bool { - self.read_byte() != 0 - } - - read_ty!(read_u8, u8, 1); - read_ty!(read_i8, i8, 1); - read_ty!(read_u16, u16, 2); - read_ty!(read_i16, i16, 2); - read_ty!(read_u32, u32, 4); - read_ty!(read_i32, i32, 4); - read_ty!(read_f32, f32, 4); - read_ty!(read_u64, u64, 8); - read_ty!(read_i64, i64, 8); - read_ty!(read_f64, f64, 8); + /// This function will panic if `[offset..offset + bytes.len()]`.is out of bounds. + /// It is caller's responsibility to check if the offset is in bounds + /// using `MemoryView::check_bounds` function. + fn write_bytes(&self, offset: u32, bytes: &[u8]); } -pub trait SequentialWriter { - fn start_offset(&self) -> u32; - - // specialization of write_array for u8 - fn write_u8(&self, value: u8); - - // specialization of write_array for u32 - fn write_u32(&self, value: u32); - - fn write_bytes(&self, bytes: &[u8]); -} - -// the lifetime is needed because some implementations -// need to bind SR and SW lifetimes to lifetime of &self in methods -pub trait SequentialMemoryView<'s> { - type SR: SequentialReader + 's; - type SW: SequentialWriter + 's; - - fn sequential_writer(&'s self, offset: u32, size: u32) -> Result; - - fn sequential_reader(&'s self, offset: u32, size: u32) -> Result; +pub trait MemoryView: MemoryWritable + MemoryReadable { + /// For optimization purposes, user must check bounds first, then try read-write to memory + /// `MemoryWritable` and `MemoryReadable` functions will panic in case of out of bounds access` + fn check_bounds(&self, offset: u32, size: u32) -> Result<(), MemoryAccessError>; } pub trait Memory where - View: for<'a> SequentialMemoryView<'a>, + View: MemoryView, { fn view(&self) -> View; } diff --git a/wasmer-it/Cargo.toml b/wasmer-it/Cargo.toml index 7f9e6fe..e8f25f8 100644 --- a/wasmer-it/Cargo.toml +++ b/wasmer-it/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-interface-types-fl" -version = "0.22.0" +version = "0.23.0" description = "WebAssembly Interface Types library for Wasmer" license = "MIT" authors = ["The Wasmer Engineering Team "] @@ -10,8 +10,8 @@ edition = "2018" [dependencies] fluence-it-types = { path = "../crates/it-types", version = "0.3.1", features = ["impls"] } it-to-bytes = { path = "../crates/to-bytes", version = "0.1.0" } -it-lilo = { path = "../crates/it-lilo", version = "0.3.0" } -it-memory-traits = { path = "../crates/it-memory-traits", version = "0.2.0" } +it-lilo = { path = "../crates/it-lilo", version = "0.4.0" } +it-memory-traits = { path = "../crates/it-memory-traits", version = "0.3.0" } nom = "5.1" wast = "8.0" diff --git a/wasmer-it/src/interpreter/instructions/arrays.rs b/wasmer-it/src/interpreter/instructions/arrays.rs index 3f88366..edf8795 100644 --- a/wasmer-it/src/interpreter/instructions/arrays.rs +++ b/wasmer-it/src/interpreter/instructions/arrays.rs @@ -14,27 +14,17 @@ use it_lilo::traits::DEFAULT_MEMORY_INDEX; use std::convert::TryInto; -pub(crate) fn array_lift_memory( +pub(crate) fn array_lift_memory( instruction: Instruction, value_type: IType, -) -> crate::interpreter::ExecutableInstruction< - Instance, - Export, - LocalImport, - Memory, - SequentialMemoryView, -> +) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - SequentialMemoryView: for<'a> crate::interpreter::wasm::structures::SequentialMemoryView<'a>, - Instance: crate::interpreter::wasm::structures::Instance< - Export, - LocalImport, - Memory, - SequentialMemoryView, - >, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: + crate::interpreter::wasm::structures::Instance, { #[allow(unused_imports)] use crate::interpreter::stack::Stackable; @@ -90,27 +80,17 @@ where }) } -pub(crate) fn array_lower_memory( +pub(crate) fn array_lower_memory( instruction: Instruction, value_type: IType, -) -> crate::interpreter::ExecutableInstruction< - Instance, - Export, - LocalImport, - Memory, - SequentialMemoryView, -> +) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - SequentialMemoryView: for<'a> crate::interpreter::wasm::structures::SequentialMemoryView<'a>, - Instance: crate::interpreter::wasm::structures::Instance< - Export, - LocalImport, - Memory, - SequentialMemoryView, - >, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: + crate::interpreter::wasm::structures::Instance, { #[allow(unused_imports)] use crate::interpreter::stack::Stackable; diff --git a/wasmer-it/src/interpreter/instructions/byte_arrays.rs b/wasmer-it/src/interpreter/instructions/byte_arrays.rs index e0b76b1..5fcb575 100644 --- a/wasmer-it/src/interpreter/instructions/byte_arrays.rs +++ b/wasmer-it/src/interpreter/instructions/byte_arrays.rs @@ -8,7 +8,6 @@ use crate::{ }; use it_lilo::traits::DEFAULT_MEMORY_INDEX; -use it_memory_traits::{SequentialReader, SequentialWriter}; use std::convert::TryInto; @@ -50,11 +49,11 @@ executable_instruction!( return Ok(()) } - let reader = memory_view - .sequential_reader(pointer, length) + memory_view + .check_bounds(pointer, length) .map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?; - let data = (0..length).map(|_| reader.read_u8()).collect::>(); + let data = memory_view.read_vec(pointer, length); log::debug!("byte_array.lift_memory: pushing {:?} on the stack", data); runtime.stack.push(IValue::ByteArray(data)); @@ -98,11 +97,11 @@ executable_instruction!( })? .view(); - let writer = memory_view - .sequential_writer(array_pointer, array.len() as u32) + memory_view + .check_bounds(array_pointer, array.len() as u32) .map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?; - writer.write_bytes(&array); + memory_view.write_bytes(array_pointer, &array); log::debug!("string.lower_memory: pushing {}, {} on the stack", array_pointer, length); runtime.stack.push(IValue::I32(array_pointer as i32)); diff --git a/wasmer-it/src/interpreter/instructions/lilo/li_helper.rs b/wasmer-it/src/interpreter/instructions/lilo/li_helper.rs index 8a8c311..2a605ca 100644 --- a/wasmer-it/src/interpreter/instructions/lilo/li_helper.rs +++ b/wasmer-it/src/interpreter/instructions/lilo/li_helper.rs @@ -6,29 +6,29 @@ use it_lilo::traits::RecordResolvableError; use std::marker::PhantomData; -pub struct LiHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +pub struct LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>) + 'i, - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView + 'i, + Instance: wasm::structures::Instance, { pub(crate) instance: &'i Instance, _export: PhantomData, _local_import: PhantomData, _memory: PhantomData, - _memory_view: PhantomData, + _memory_view: PhantomData, } -impl<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> - LiHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +impl<'i, Instance, Export, LocalImport, Memory, MemoryView> + LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { pub(crate) fn new(instance: &'i Instance) -> Self { Self { @@ -41,14 +41,14 @@ where } } -impl<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> RecordResolvable - for LiHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +impl<'i, Instance, Export, LocalImport, Memory, MemoryView> RecordResolvable + for LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { fn resolve_record(&self, record_type_id: u64) -> Result<&IRecordType, RecordResolvableError> { let record = self diff --git a/wasmer-it/src/interpreter/instructions/lilo/lo_helper.rs b/wasmer-it/src/interpreter/instructions/lilo/lo_helper.rs index d79ae4c..c7b45cf 100644 --- a/wasmer-it/src/interpreter/instructions/lilo/lo_helper.rs +++ b/wasmer-it/src/interpreter/instructions/lilo/lo_helper.rs @@ -4,32 +4,33 @@ use crate::IValue; use it_lilo::traits::Allocatable; use it_lilo::traits::AllocatableError; +use it_lilo::traits::DEFAULT_MEMORY_INDEX; use std::marker::PhantomData; -pub struct LoHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +pub struct LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { pub(crate) instance: &'i Instance, _export: PhantomData, _local_import: PhantomData, _memory: PhantomData, - _memory_view: PhantomData, + _memory_view: PhantomData, } -impl<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> - LoHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +impl<'i, Instance, Export, LocalImport, Memory, MemoryView> + LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { pub(crate) fn new(instance: &'i Instance) -> Self { Self { @@ -42,16 +43,16 @@ where } } -impl<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> Allocatable - for LoHelper<'i, Instance, Export, LocalImport, Memory, SequentialMemoryView> +impl<'i, Instance, Export, LocalImport, Memory, MemoryView> Allocatable + for LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView> where Export: wasm::structures::Export + 'i, LocalImport: wasm::structures::LocalImport + 'i, - Memory: wasm::structures::Memory + 'i, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'i, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { - fn allocate(&self, size: u32, type_tag: u32) -> Result { + fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MemoryView), AllocatableError> { use AllocatableError::*; use crate::interpreter::instructions::ALLOCATE_FUNC_INDEX; @@ -83,7 +84,16 @@ where } match outcome[0] { - IValue::I32(offset) => Ok(offset as _), + IValue::I32(offset) => { + let view = + self.instance + .memory_view(DEFAULT_MEMORY_INDEX) + .ok_or(MemoryIsMissing { + memory_index: DEFAULT_MEMORY_INDEX, + })?; + + Ok((offset as _, view)) + } _ => Err(AllocateFuncIncompatibleOutput), } } diff --git a/wasmer-it/src/interpreter/instructions/mod.rs b/wasmer-it/src/interpreter/instructions/mod.rs index 7f55ee5..b396f7f 100644 --- a/wasmer-it/src/interpreter/instructions/mod.rs +++ b/wasmer-it/src/interpreter/instructions/mod.rs @@ -232,7 +232,7 @@ pub(crate) fn check_function_signature< Export, LocalImport, Memory, - SequentialMemoryView, + MemoryView, >( instance: &'instance Instance, local_import: &LocalImport, @@ -241,9 +241,9 @@ pub(crate) fn check_function_signature< where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, - Memory: wasm::structures::Memory + 'instance, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'instance, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { let func_inputs = local_import.arguments(); @@ -261,7 +261,7 @@ pub(crate) fn is_value_compatible_to_type< Export, LocalImport, Memory, - SequentialMemoryView, + MemoryView, >( instance: &'instance Instance, interface_type: &IType, @@ -270,9 +270,9 @@ pub(crate) fn is_value_compatible_to_type< where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, - Memory: wasm::structures::Memory + 'instance, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'instance, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { match (&interface_type, interface_value) { (IType::Boolean, IValue::Boolean(_)) => Ok(()), @@ -332,7 +332,7 @@ pub(crate) fn is_record_fields_compatible_to_type< Export, LocalImport, Memory, - SequentialMemoryView, + MemoryView, >( instance: &'instance Instance, record_type_id: u64, @@ -341,9 +341,9 @@ pub(crate) fn is_record_fields_compatible_to_type< where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, - Memory: wasm::structures::Memory + 'instance, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory + 'instance, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { let record_type = instance .wit_record_by_id(record_type_id) @@ -428,11 +428,11 @@ pub(crate) mod tests { } #[derive(Default, Clone)] - pub(crate) struct SequentialMemoryView(Rc>>); + pub(crate) struct MemoryView(Rc>>); - impl wasm::structures::SequentialMemoryView for SequentialMemoryView {} + impl wasm::structures::MemoryView for MemoryView {} - impl Deref for SequentialMemoryView { + impl Deref for MemoryView { type Target = [Cell]; fn deref(&self) -> &Self::Target { @@ -442,19 +442,19 @@ pub(crate) mod tests { #[derive(Default)] pub(crate) struct Memory { - pub(crate) view: SequentialMemoryView, + pub(crate) view: MemoryView, } impl Memory { pub(crate) fn new(data: Vec>) -> Self { Self { - view: SequentialMemoryView(Rc::new(data)), + view: MemoryView(Rc::new(data)), } } } - impl wasm::structures::Memory for Memory { - fn view(&self) -> SequentialMemoryView { + impl wasm::structures::Memory for Memory { + fn view(&self) -> MemoryView { self.view.clone() } } @@ -554,7 +554,7 @@ pub(crate) mod tests { } } - impl wasm::structures::Instance for Instance { + impl wasm::structures::Instance for Instance { fn export(&self, export_name: &str) -> Option<&Export> { self.exports.get(export_name) } diff --git a/wasmer-it/src/interpreter/instructions/records.rs b/wasmer-it/src/interpreter/instructions/records.rs index 9b9074a..a4fc9f9 100644 --- a/wasmer-it/src/interpreter/instructions/records.rs +++ b/wasmer-it/src/interpreter/instructions/records.rs @@ -11,27 +11,17 @@ use it_lilo::traits::DEFAULT_MEMORY_INDEX; use std::convert::TryInto; -pub(crate) fn record_lift_memory( +pub(crate) fn record_lift_memory( record_type_id: u64, instruction: Instruction, -) -> crate::interpreter::ExecutableInstruction< - Instance, - Export, - LocalImport, - Memory, - SequentialMemoryView, -> +) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - SequentialMemoryView: for<'a> crate::interpreter::wasm::structures::SequentialMemoryView<'a>, - Instance: crate::interpreter::wasm::structures::Instance< - Export, - LocalImport, - Memory, - SequentialMemoryView, - >, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: + crate::interpreter::wasm::structures::Instance, { #[allow(unused_imports)] use crate::interpreter::stack::Stackable; @@ -88,27 +78,17 @@ where }) } -pub(crate) fn record_lower_memory( +pub(crate) fn record_lower_memory( record_type_id: u64, instruction: Instruction, -) -> crate::interpreter::ExecutableInstruction< - Instance, - Export, - LocalImport, - Memory, - SequentialMemoryView, -> +) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - SequentialMemoryView: for<'a> crate::interpreter::wasm::structures::SequentialMemoryView<'a>, - Instance: crate::interpreter::wasm::structures::Instance< - Export, - LocalImport, - Memory, - SequentialMemoryView, - >, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: + crate::interpreter::wasm::structures::Instance, { #[allow(unused_imports)] use crate::interpreter::stack::Stackable; diff --git a/wasmer-it/src/interpreter/instructions/strings.rs b/wasmer-it/src/interpreter/instructions/strings.rs index d16e92f..97e9029 100644 --- a/wasmer-it/src/interpreter/instructions/strings.rs +++ b/wasmer-it/src/interpreter/instructions/strings.rs @@ -8,7 +8,6 @@ use crate::{ }; use it_lilo::traits::DEFAULT_MEMORY_INDEX; -use it_memory_traits::{SequentialReader, SequentialWriter}; use std::convert::TryInto; @@ -49,11 +48,11 @@ executable_instruction!( return Ok(()) } - let reader = memory_view - .sequential_reader(pointer, length) + memory_view + .check_bounds(pointer, length) .map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?; - let data = (0..length).map(|_| reader.read_u8()).collect::>(); + let data = memory_view.read_vec(pointer, length); let string = String::from_utf8(data) .map_err(|error| InstructionError::from_error_kind(instruction.clone(), InstructionErrorKind::String(error)))?; @@ -91,20 +90,19 @@ executable_instruction!( let instance = &mut runtime.wasm_instance; let memory_index = DEFAULT_MEMORY_INDEX; let memory_view = instance - .memory(memory_index) + .memory_view(memory_index) .ok_or_else(|| { InstructionError::from_error_kind( instruction.clone(), InstructionErrorKind::MemoryIsMissing { memory_index }, ) - })? - .view(); + })?; - let seq_writer = memory_view - .sequential_writer(string_pointer, string_length) + memory_view + .check_bounds(string_pointer, string_length) .map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?; - seq_writer.write_bytes(&string_bytes); + memory_view.write_bytes(string_pointer, string_bytes); log::debug!("string.lower_memory: pushing {}, {} on the stack", string_pointer, string_length); runtime.stack.push(IValue::I32(string_pointer as i32)); diff --git a/wasmer-it/src/interpreter/mod.rs b/wasmer-it/src/interpreter/mod.rs index 7a307c9..4fbcbdb 100644 --- a/wasmer-it/src/interpreter/mod.rs +++ b/wasmer-it/src/interpreter/mod.rs @@ -13,21 +13,13 @@ use std::{convert::TryFrom, marker::PhantomData}; /// Represents the `Runtime`, which is used by an adapter to execute /// its instructions. -pub(crate) struct Runtime< - 'invocation, - 'instance, - Instance, - Export, - LocalImport, - Memory, - SequentialMemoryView, -> where +pub(crate) struct Runtime<'invocation, 'instance, Instance, Export, LocalImport, Memory, MemoryView> +where Export: wasm::structures::Export + 'instance, LocalImport: wasm::structures::LocalImport + 'instance, - Memory: wasm::structures::Memory + 'instance, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: - wasm::structures::Instance + 'instance, + Memory: wasm::structures::Memory + 'instance, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance + 'instance, { /// The invocation inputs are all the arguments received by an /// adapter. @@ -41,18 +33,15 @@ pub(crate) struct Runtime< wasm_instance: &'instance mut Instance, /// Phantom data. - _phantom: PhantomData<(Export, LocalImport, Memory, SequentialMemoryView)>, + _phantom: PhantomData<(Export, LocalImport, Memory, MemoryView)>, } /// Type alias for an executable instruction. It's an implementation /// details, but an instruction is a boxed closure instance. -pub(crate) type ExecutableInstruction = - Box< - dyn Fn( - &mut Runtime, - ) -> InstructionResult<()> - + Send, - >; +pub(crate) type ExecutableInstruction = Box< + dyn Fn(&mut Runtime) -> InstructionResult<()> + + Send, +>; /// An interpreter is the central piece of this crate. It is a set of /// executable instructions. Each instruction takes the runtime as @@ -72,7 +61,7 @@ pub(crate) type ExecutableInstruction = (&vec![ +/// let interpreter: Interpreter = (&vec![ /// Instruction::ArgumentGet { index: 1 }, /// Instruction::ArgumentGet { index: 0 }, /// Instruction::CallCore { function_index: 42 }, @@ -132,31 +121,31 @@ pub(crate) type ExecutableInstruction +pub struct Interpreter where Export: wasm::structures::Export, LocalImport: wasm::structures::LocalImport, - Memory: wasm::structures::Memory, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { executable_instructions: - Vec>, + Vec>, } -impl - Interpreter +impl + Interpreter where Export: wasm::structures::Export, LocalImport: wasm::structures::LocalImport, - Memory: wasm::structures::Memory, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { fn iter( &self, ) -> impl Iterator< - Item = &ExecutableInstruction, + Item = &ExecutableInstruction, > + '_ { self.executable_instructions.iter() } @@ -187,14 +176,14 @@ where } /// Transforms a `Vec` into an `Interpreter`. -impl TryFrom> - for Interpreter +impl TryFrom> + for Interpreter where Export: wasm::structures::Export, LocalImport: wasm::structures::LocalImport, - Memory: wasm::structures::Memory, - SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>), - Instance: wasm::structures::Instance, + Memory: wasm::structures::Memory, + MemoryView: wasm::structures::MemoryView, + Instance: wasm::structures::Instance, { type Error = (); diff --git a/wasmer-it/src/interpreter/wasm/structures.rs b/wasmer-it/src/interpreter/wasm/structures.rs index 07fb263..be50a4e 100644 --- a/wasmer-it/src/interpreter/wasm/structures.rs +++ b/wasmer-it/src/interpreter/wasm/structures.rs @@ -6,9 +6,8 @@ use crate::IType; use crate::IValue; use std::rc::Rc; -pub use it_memory_traits::{ - Memory, MemoryAccessError, SequentialMemoryView, SequentialReader, SequentialWriter, -}; +pub use it_memory_traits::{Memory, MemoryAccessError, MemoryView}; +use it_memory_traits::{MemoryReadable, MemoryWritable}; pub trait TypedIndex: Copy + Clone { fn new(index: usize) -> Self; @@ -69,7 +68,7 @@ where E: Export, LI: LocalImport, M: Memory, - MV: for<'a> SequentialMemoryView<'a>, + MV: MemoryView, { fn export(&self, export_name: &str) -> Option<&E>; fn local_or_import(&self, index: I) -> Option<&LI>; @@ -132,47 +131,31 @@ impl LocalImport for () { pub(crate) struct EmptyMemoryView; -pub(crate) struct EmptySequentialReader; -pub(crate) struct EmptySequentialWriter; +impl MemoryWritable for EmptyMemoryView { + fn write_byte(&self, _offset: u32, _value: u8) {} -impl SequentialReader for EmptySequentialReader { - fn read_byte(&self) -> u8 { - 0u8 - } - - fn read_bytes(&self) -> [u8; COUNT] { - [0u8; COUNT] - } + fn write_bytes(&self, _offset: u32, _bytes: &[u8]) {} } -impl SequentialWriter for EmptySequentialWriter { - fn start_offset(&self) -> u32 { +impl MemoryReadable for EmptyMemoryView { + fn read_byte(&self, _offset: u32) -> u8 { 0 } - fn write_u8(&self, _value: u8) {} - - fn write_u32(&self, _value: u32) {} - - fn write_bytes(&self, _bytes: &[u8]) {} -} - -impl<'a> SequentialMemoryView<'a> for EmptyMemoryView { - type SR = EmptySequentialReader; - type SW = EmptySequentialWriter; - - fn sequential_writer(&self, offset: u32, size: u32) -> Result { - Err(MemoryAccessError::OutOfBounds { - offset, - size, - memory_size: 0, - }) + fn read_array(&self, _offset: u32) -> [u8; COUNT] { + [0; COUNT] } - fn sequential_reader(&self, offset: u32, size: u32) -> Result { + fn read_vec(&self, _offset: u32, _size: u32) -> Vec { + Vec::default() + } +} + +impl MemoryView for EmptyMemoryView { + fn check_bounds(&self, offset: u32, size: u32) -> Result<(), MemoryAccessError> { Err(MemoryAccessError::OutOfBounds { - offset, size, + offset, memory_size: 0, }) } @@ -189,7 +172,7 @@ where E: Export, LI: LocalImport, M: Memory, - MV: for<'a> SequentialMemoryView<'a>, + MV: MemoryView, { fn export(&self, _export_name: &str) -> Option<&E> { None diff --git a/wasmer-it/src/macros.rs b/wasmer-it/src/macros.rs index 4dd7e9a..897fad7 100644 --- a/wasmer-it/src/macros.rs +++ b/wasmer-it/src/macros.rs @@ -67,15 +67,15 @@ macro_rules! consume { /// Check the existing executable instruction to get more examples. macro_rules! executable_instruction { ($name:ident ( $($argument_name:ident: $argument_type:ty),* ) -> _ $implementation:block ) => { - pub(crate) fn $name( + pub(crate) fn $name( $($argument_name: $argument_type),* - ) -> crate::interpreter::ExecutableInstruction + ) -> crate::interpreter::ExecutableInstruction where Export: crate::interpreter::wasm::structures::Export, LocalImport: crate::interpreter::wasm::structures::LocalImport, - Memory: crate::interpreter::wasm::structures::Memory, - SequentialMemoryView: for<'a> crate::interpreter::wasm::structures::SequentialMemoryView<'a>, - Instance: crate::interpreter::wasm::structures::Instance, + Memory: crate::interpreter::wasm::structures::Memory, + MemoryView: crate::interpreter::wasm::structures::MemoryView, + Instance: crate::interpreter::wasm::structures::Instance, { #[allow(unused_imports)] use crate::interpreter::{stack::Stackable}; @@ -100,7 +100,7 @@ macro_rules! test_executable_instruction { fn $test_name() { use crate::{ interpreter::{ - instructions::tests::{Export, Instance, LocalImport, Memory, SequentialMemoryView}, + instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView}, stack::Stackable, Instruction, Interpreter, }, @@ -109,7 +109,7 @@ macro_rules! test_executable_instruction { }; use std::{cell::Cell, collections::HashMap, convert::TryInto}; - let interpreter: Interpreter = + let interpreter: Interpreter = (&vec![$($instructions),*]).try_into().unwrap(); let invocation_inputs = vec![$($invocation_inputs),*]; @@ -142,7 +142,7 @@ macro_rules! test_executable_instruction { fn $test_name() { use crate::{ interpreter::{ - instructions::tests::{Export, Instance, LocalImport, Memory, SequentialMemoryView}, + instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView}, stack::Stackable, Instruction, Interpreter, }, @@ -151,7 +151,7 @@ macro_rules! test_executable_instruction { }; use std::{cell::Cell, collections::HashMap, convert::TryInto}; - let interpreter: Interpreter = + let interpreter: Interpreter = (&vec![$($instructions),*]).try_into().unwrap(); let invocation_inputs = vec![$($invocation_inputs),*];