Refactor memory access interface to fix that writer does not update memory after allocation (#17)

This commit is contained in:
Valery Antopol 2022-04-06 22:25:01 +03:00 committed by GitHub
parent cbdea8e362
commit b233bfcadd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 372 additions and 350 deletions

6
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
pub fn array_lift_memory<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
value_type: &IType,
offset: u32,
@ -61,7 +61,7 @@ pub fn array_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'
Ok(IValue::Array(ivalues))
}
fn read_string_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
fn read_string_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
offset: u32,
elements_count: u32,
@ -83,7 +83,7 @@ fn read_string_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
Ok(result)
}
fn read_array_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
fn read_array_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
ty: &IType,
offset: u32,
@ -105,7 +105,7 @@ fn read_array_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
Ok(result)
}
fn read_record_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
fn read_record_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
record_type_id: u64,
offset: u32,

View File

@ -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<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
pub fn record_lift_memory<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
record_type: &IRecordType,
offset: u32,
@ -68,9 +69,9 @@ pub fn record_lift_memory<R: RecordResolvable, MV: for<'a> SequentialMemoryView<
Ok(IValue::Record(record))
}
fn read_string<MV: for<'a> SequentialMemoryView<'a>>(
fn read_string<MV: MemoryView>(
reader: &MemoryReader<MV>,
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
seq_reader: &SequentialReader<'_, MV>,
) -> LiResult<String> {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
@ -81,9 +82,9 @@ fn read_string<MV: for<'a> SequentialMemoryView<'a>>(
Ok(string)
}
fn read_byte_array<MV: for<'a> SequentialMemoryView<'a>>(
fn read_byte_array<MV: MemoryView>(
reader: &MemoryReader<MV>,
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
seq_reader: &SequentialReader<'_, MV>,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
@ -93,9 +94,9 @@ fn read_byte_array<MV: for<'a> SequentialMemoryView<'a>>(
Ok(IValue::ByteArray(array))
}
fn read_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
fn read_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
seq_reader: &SequentialReader<'_, MV>,
value_type: &IType,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();
@ -104,9 +105,9 @@ fn read_array<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
super::array_lift_memory(lifter, value_type, offset, size)
}
fn read_record<R: RecordResolvable, MV: for<'a> SequentialMemoryView<'a>>(
fn read_record<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
seq_reader: &<MV as SequentialMemoryView<'_>>::SR,
seq_reader: &SequentialReader<'_, MV>,
record_type_id: u64,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();

View File

@ -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));

View File

@ -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<MV> {
pub(self) view: MV,
}
impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
impl<MV: MemoryView> MemoryReader<MV> {
pub fn new(view: MV) -> Self {
Self { view }
}
@ -32,12 +35,9 @@ impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
/// 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<<MV as SequentialMemoryView<'_>>::SR> {
let seq_reader = self.view.sequential_reader(offset, size)?;
pub fn sequential_reader(&self, offset: u32, size: u32) -> LiResult<SequentialReader<'_, MV>> {
self.view.check_bounds(offset, size)?;
let seq_reader = SequentialReader::new(&self, offset);
Ok(seq_reader)
}
@ -78,3 +78,32 @@ impl<MV: for<'a> SequentialMemoryView<'a>> MemoryReader<MV> {
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<MV>,
offset: Cell<u32>,
}
impl<'r, MV: MemoryView> SequentialReader<'r, MV> {
fn new(reader: &'r MemoryReader<MV>, 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);
}

View File

@ -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<T> = std::result::Result<T, error::LiError>;
@ -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 }

View File

@ -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<A: Allocatable, MV: for<'a> SequentialMemoryView<'a>>(
pub fn array_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
lowerer: &ILowerer<'_, A, MV>,
array_values: Vec<IValue>,
) -> LoResult<LoweredArray> {
@ -54,40 +54,40 @@ pub fn array_lower_memory<A: Allocatable, MV: for<'a> 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());
}
}
}

View File

@ -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<A: Allocatable, MV: for<'a> SequentialMemoryView<'a>>(
pub fn record_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
lowerer: &ILowerer<'_, A, MV>,
values: NEVec<IValue>,
) -> LoResult<u32> {

View File

@ -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>, MV: MemoryView> {
heap_manager: &'i R,
view: MV,
view: RefCell<MV>,
}
impl<'i, A: Allocatable, MV: for<'a> SequentialMemoryView<'a>> MemoryWriter<'i, A, MV> {
impl<'i, A: Allocatable<MV>, MV: MemoryView> MemoryWriter<'i, A, MV> {
pub fn new(view: MV, heap_manager: &'i A) -> LoResult<Self> {
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<u32> {
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<<MV as SequentialMemoryView<'_>>::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<SequentialWriter> {
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<u32>,
}
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<MV: MemoryView, A: Allocatable<MV>, 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<MV: MemoryView, A: Allocatable<MV>>(
&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<MV: MemoryView, A: Allocatable<MV>>(
&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<MV: MemoryView, A: Allocatable<MV>>(
&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);
}
}

View File

@ -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<T> = std::result::Result<T, error::LoError>;
pub struct ILowerer<'m, A: Allocatable, MV> {
pub struct ILowerer<'m, A: Allocatable<MV>, 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>, MV: MemoryView> ILowerer<'m, A, MV> {
pub fn new(view: MV, allocatable: &'m A) -> LoResult<Self> {
let writer = MemoryWriter::new(view, allocatable)?;
let lowerer = Self { writer };

View File

@ -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<u32, AllocatableError>;
pub trait Allocatable<MV: MemoryView> {
fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MV), AllocatableError>;
}
#[derive(Debug, ThisError)]

View File

@ -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"

View File

@ -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<const COUNT: usize>(&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<u8>;
}
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<const COUNT: usize>(&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<Self::SW, MemoryAccessError>;
fn sequential_reader(&'s self, offset: u32, size: u32) -> Result<Self::SR, MemoryAccessError>;
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<View>
where
View: for<'a> SequentialMemoryView<'a>,
View: MemoryView,
{
fn view(&self) -> View;
}

View File

@ -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 <engineering@wasmer.io>"]
@ -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"

View File

@ -14,27 +14,17 @@ use it_lilo::traits::DEFAULT_MEMORY_INDEX;
use std::convert::TryInto;
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, SequentialMemoryView>(
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
instruction: Instruction,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
SequentialMemoryView,
>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<SequentialMemoryView>,
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>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -90,27 +80,17 @@ where
})
}
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, SequentialMemoryView>(
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
instruction: Instruction,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
SequentialMemoryView,
>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<SequentialMemoryView>,
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>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;

View File

@ -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::<Vec<_>>();
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));

View File

@ -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<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>) + 'i,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView + 'i,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
pub(crate) instance: &'i Instance,
_export: PhantomData<Export>,
_local_import: PhantomData<LocalImport>,
_memory: PhantomData<Memory>,
_memory_view: PhantomData<SequentialMemoryView>,
_memory_view: PhantomData<MemoryView>,
}
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<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
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<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
fn resolve_record(&self, record_type_id: u64) -> Result<&IRecordType, RecordResolvableError> {
let record = self

View File

@ -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<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
pub(crate) instance: &'i Instance,
_export: PhantomData<Export>,
_local_import: PhantomData<LocalImport>,
_memory: PhantomData<Memory>,
_memory_view: PhantomData<SequentialMemoryView>,
_memory_view: PhantomData<MemoryView>,
}
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<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
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<MemoryView>
for LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<SequentialMemoryView> + 'i,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
fn allocate(&self, size: u32, type_tag: u32) -> Result<u32, AllocatableError> {
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),
}
}

View File

@ -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<SequentialMemoryView> + 'instance,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
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<SequentialMemoryView> + 'instance,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
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<SequentialMemoryView> + 'instance,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
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<Vec<Cell<u8>>>);
pub(crate) struct MemoryView(Rc<Vec<Cell<u8>>>);
impl wasm::structures::SequentialMemoryView for SequentialMemoryView {}
impl wasm::structures::MemoryView for MemoryView {}
impl Deref for SequentialMemoryView {
impl Deref for MemoryView {
type Target = [Cell<u8>];
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<Cell<u8>>) -> Self {
Self {
view: SequentialMemoryView(Rc::new(data)),
view: MemoryView(Rc::new(data)),
}
}
}
impl wasm::structures::Memory<SequentialMemoryView> for Memory {
fn view(&self) -> SequentialMemoryView {
impl wasm::structures::Memory<MemoryView> for Memory {
fn view(&self) -> MemoryView {
self.view.clone()
}
}
@ -554,7 +554,7 @@ pub(crate) mod tests {
}
}
impl wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView> for Instance {
impl wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> for Instance {
fn export(&self, export_name: &str) -> Option<&Export> {
self.exports.get(export_name)
}

View File

@ -11,27 +11,17 @@ use it_lilo::traits::DEFAULT_MEMORY_INDEX;
use std::convert::TryInto;
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, SequentialMemoryView>(
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
SequentialMemoryView,
>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<SequentialMemoryView>,
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>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -88,27 +78,17 @@ where
})
}
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, SequentialMemoryView>(
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
SequentialMemoryView,
>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<SequentialMemoryView>,
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>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;

View File

@ -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::<Vec<_>>();
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));

View File

@ -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<SequentialMemoryView> + 'instance,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance:
wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView> + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> + '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<Instance, Export, LocalImport, Memory, SequentialMemoryView> =
Box<
dyn Fn(
&mut Runtime<Instance, Export, LocalImport, Memory, SequentialMemoryView>,
) -> InstructionResult<()>
+ Send,
>;
pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView> = Box<
dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory, MemoryView>) -> 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<Instance, Export, LocalImport, Memory, Seq
/// use std::{cell::Cell, collections::HashMap, convert::TryInto};
/// use wasmer_interface_types::{
/// interpreter::{
/// instructions::tests::{Export, Instance, LocalImport, Memory, SequentialMemoryView},
/// instructions::tests::{Export, Instance, LocalImport, Memory, MemoryView},
/// // ^^^^^^^^^^^^ This is private and for testing purposes only.
/// // It is basically a fake WebAssembly runtime.
/// stack::Stackable,
@ -84,7 +73,7 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Seq
///
/// // 1. Creates an interpreter from a set of instructions. They will
/// // be transformed into executable instructions.
/// let interpreter: Interpreter<Instance, Export, LocalImport, Memory, SequentialMemoryView> = (&vec![
/// let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> = (&vec![
/// Instruction::ArgumentGet { index: 1 },
/// Instruction::ArgumentGet { index: 0 },
/// Instruction::CallCore { function_index: 42 },
@ -132,31 +121,31 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Seq
/// // 5. Read the stack to get the result.
/// assert_eq!(stack.as_slice(), &[IValue::I32(7)]);
/// ```
pub struct Interpreter<Instance, Export, LocalImport, Memory, SequentialMemoryView>
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<SequentialMemoryView>,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
executable_instructions:
Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory, SequentialMemoryView>>,
Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>>,
}
impl<Instance, Export, LocalImport, Memory, SequentialMemoryView>
Interpreter<Instance, Export, LocalImport, Memory, SequentialMemoryView>
impl<Instance, Export, LocalImport, Memory, MemoryView>
Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<SequentialMemoryView>,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
fn iter(
&self,
) -> impl Iterator<
Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory, SequentialMemoryView>,
Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>,
> + '_ {
self.executable_instructions.iter()
}
@ -187,14 +176,14 @@ where
}
/// Transforms a `Vec<Instruction>` into an `Interpreter`.
impl<Instance, Export, LocalImport, Memory, SequentialMemoryView> TryFrom<Vec<Instruction>>
for Interpreter<Instance, Export, LocalImport, Memory, SequentialMemoryView>
impl<Instance, Export, LocalImport, Memory, MemoryView> TryFrom<Vec<Instruction>>
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<SequentialMemoryView>,
SequentialMemoryView: (for<'a> wasm::structures::SequentialMemoryView<'a>),
Instance: wasm::structures::Instance<Export, LocalImport, Memory, SequentialMemoryView>,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
type Error = ();

View File

@ -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>,
MV: for<'a> SequentialMemoryView<'a>,
MV: MemoryView,
{
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&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<const COUNT: usize>(&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<Self::SW, MemoryAccessError> {
Err(MemoryAccessError::OutOfBounds {
offset,
size,
memory_size: 0,
})
fn read_array<const COUNT: usize>(&self, _offset: u32) -> [u8; COUNT] {
[0; COUNT]
}
fn sequential_reader(&self, offset: u32, size: u32) -> Result<Self::SR, MemoryAccessError> {
fn read_vec(&self, _offset: u32, _size: u32) -> Vec<u8> {
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>,
MV: for<'a> SequentialMemoryView<'a>,
MV: MemoryView,
{
fn export(&self, _export_name: &str) -> Option<&E> {
None

View File

@ -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<Instance, Export, LocalImport, Memory, SequentialMemoryView>(
pub(crate) fn $name<Instance, Export, LocalImport, Memory, MemoryView>(
$($argument_name: $argument_type),*
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, SequentialMemoryView>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<SequentialMemoryView>,
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>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
#[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<Instance, Export, LocalImport, Memory, SequentialMemoryView> =
let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
(&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<Instance, Export, LocalImport, Memory, SequentialMemoryView> =
let interpreter: Interpreter<Instance, Export, LocalImport, Memory, MemoryView> =
(&vec![$($instructions),*]).try_into().unwrap();
let invocation_inputs = vec![$($invocation_inputs),*];