feat!: pass a context object through the API to the wasm engine functions (#34)

This commit is contained in:
Valery Antopol 2023-02-14 17:48:09 +03:00 committed by GitHub
parent da020b8c6a
commit 06e0dd40d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 687 additions and 382 deletions

View File

@ -24,8 +24,13 @@ use crate::IValue;
use it_memory_traits::MemoryView;
pub fn array_lift_memory<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
pub fn array_lift_memory<
R: RecordResolvable,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
value_type: &IType,
offset: u32,
elements_count: u32,
@ -37,45 +42,48 @@ pub fn array_lift_memory<R: RecordResolvable, MV: MemoryView>(
let reader = &lifter.reader;
let ivalues = match value_type {
IType::Boolean => reader.read_bool_array(offset, elements_count)?,
IType::S8 => reader.read_s8_array(offset, elements_count)?,
IType::S16 => reader.read_s16_array(offset, elements_count)?,
IType::S32 => reader.read_s32_array(offset, elements_count)?,
IType::S64 => reader.read_s64_array(offset, elements_count)?,
IType::I32 => reader.read_i32_array(offset, elements_count)?,
IType::I64 => reader.read_i64_array(offset, elements_count)?,
IType::U8 => reader.read_u8_array(offset, elements_count)?,
IType::U16 => reader.read_u16_array(offset, elements_count)?,
IType::U32 => reader.read_u32_array(offset, elements_count)?,
IType::U64 => reader.read_u64_array(offset, elements_count)?,
IType::F32 => reader.read_f32_array(offset, elements_count)?,
IType::F64 => reader.read_f64_array(offset, elements_count)?,
IType::String => read_string_array(lifter, offset, elements_count)?,
IType::ByteArray => read_array_array(lifter, &IType::U8, offset, elements_count)?,
IType::Array(ty) => read_array_array(lifter, &ty, offset, elements_count)?,
IType::Boolean => reader.read_bool_array(store, offset, elements_count)?,
IType::S8 => reader.read_s8_array(store, offset, elements_count)?,
IType::S16 => reader.read_s16_array(store, offset, elements_count)?,
IType::S32 => reader.read_s32_array(store, offset, elements_count)?,
IType::S64 => reader.read_s64_array(store, offset, elements_count)?,
IType::I32 => reader.read_i32_array(store, offset, elements_count)?,
IType::I64 => reader.read_i64_array(store, offset, elements_count)?,
IType::U8 => reader.read_u8_array(store, offset, elements_count)?,
IType::U16 => reader.read_u16_array(store, offset, elements_count)?,
IType::U32 => reader.read_u32_array(store, offset, elements_count)?,
IType::U64 => reader.read_u64_array(store, offset, elements_count)?,
IType::F32 => reader.read_f32_array(store, offset, elements_count)?,
IType::F64 => reader.read_f64_array(store, offset, elements_count)?,
IType::String => read_string_array(store, lifter, offset, elements_count)?,
IType::ByteArray => read_array_array(store, lifter, &IType::U8, offset, elements_count)?,
IType::Array(ty) => read_array_array(store, lifter, &ty, offset, elements_count)?,
IType::Record(record_type_id) => {
read_record_array(lifter, *record_type_id, offset, elements_count)?
read_record_array(store, lifter, *record_type_id, offset, elements_count)?
}
};
Ok(IValue::Array(ivalues))
}
fn read_string_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
fn read_string_array<R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
offset: u32,
elements_count: u32,
) -> LiResult<Vec<IValue>> {
let mut result = Vec::with_capacity(elements_count as usize);
let seq_reader = lifter
.reader
.sequential_reader(offset, ser_type_size(&IType::String) * elements_count)?;
let seq_reader = lifter.reader.sequential_reader(
store,
offset,
ser_type_size(&IType::String) * elements_count,
)?;
for _ in 0..elements_count {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let size = seq_reader.read_u32(store);
let raw_str = lifter.reader.read_raw_u8_array(offset, size)?;
let raw_str = lifter.reader.read_raw_u8_array(store, offset, size)?;
let str = String::from_utf8(raw_str)?;
result.push(IValue::String(str));
}
@ -83,44 +91,49 @@ fn read_string_array<R: RecordResolvable, MV: MemoryView>(
Ok(result)
}
fn read_array_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
fn read_array_array<R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
ty: &IType,
offset: u32,
elements_count: u32,
) -> LiResult<Vec<IValue>> {
let mut result = Vec::with_capacity(elements_count as usize);
let seq_reader = lifter
.reader
.sequential_reader(offset, ser_type_size(ty) * elements_count)?;
let seq_reader =
lifter
.reader
.sequential_reader(store, offset, ser_type_size(ty) * elements_count)?;
for _ in 0..elements_count {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let size = seq_reader.read_u32(store);
let array = array_lift_memory(lifter, ty, offset, size)?;
let array = array_lift_memory(store, lifter, ty, offset, size)?;
result.push(array);
}
Ok(result)
}
fn read_record_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
fn read_record_array<R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
record_type_id: u64,
offset: u32,
elements_count: u32,
) -> LiResult<Vec<IValue>> {
let mut result = Vec::with_capacity(elements_count as usize);
let seq_reader = lifter
.reader
.sequential_reader(offset, ser_type_size(&IType::Record(0)) * elements_count)?;
let seq_reader = lifter.reader.sequential_reader(
store,
offset,
ser_type_size(&IType::Record(0)) * elements_count,
)?;
for _ in 0..elements_count {
let offset = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let record_ty = lifter.resolver.resolve_record(record_type_id)?;
let record = record_lift_memory(lifter, &record_ty, offset)?;
let record = record_lift_memory(store, lifter, &record_ty, offset)?;
result.push(record);
}

View File

@ -28,8 +28,13 @@ use crate::NEVec;
use it_memory_traits::MemoryView;
pub fn record_lift_memory<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
pub fn record_lift_memory<
R: RecordResolvable,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
record_type: &IRecordType,
offset: u32,
) -> LiResult<IValue> {
@ -37,28 +42,28 @@ pub fn record_lift_memory<R: RecordResolvable, MV: MemoryView>(
let size = record_size(record_type);
let reader = &lifter.reader;
let seq_reader = reader.sequential_reader(offset, size)?;
let seq_reader = reader.sequential_reader(store, offset, size)?;
for field in (*record_type.fields).iter() {
match &field.ty {
IType::Boolean => values.push(IValue::Boolean(seq_reader.read_u8() != 0)),
IType::S8 => values.push(IValue::S8(seq_reader.read_i8())),
IType::S16 => values.push(IValue::S16(seq_reader.read_i16())),
IType::S32 => values.push(IValue::S32(seq_reader.read_i32())),
IType::S64 => values.push(IValue::S64(seq_reader.read_i64())),
IType::I32 => values.push(IValue::I32(seq_reader.read_i32())),
IType::I64 => values.push(IValue::I64(seq_reader.read_i64())),
IType::U8 => values.push(IValue::U8(seq_reader.read_u8())),
IType::U16 => values.push(IValue::U16(seq_reader.read_u16())),
IType::U32 => values.push(IValue::U32(seq_reader.read_u32())),
IType::U64 => values.push(IValue::U64(seq_reader.read_u64())),
IType::F32 => values.push(IValue::F32(seq_reader.read_f32())),
IType::F64 => values.push(IValue::F64(seq_reader.read_f64())),
IType::String => values.push(IValue::String(read_string(reader, &seq_reader)?)),
IType::ByteArray => values.push(read_byte_array(reader, &seq_reader)?),
IType::Array(ty) => values.push(read_array(&lifter, &seq_reader, &**ty)?),
IType::Boolean => values.push(IValue::Boolean(seq_reader.read_u8(store) != 0)),
IType::S8 => values.push(IValue::S8(seq_reader.read_i8(store))),
IType::S16 => values.push(IValue::S16(seq_reader.read_i16(store))),
IType::S32 => values.push(IValue::S32(seq_reader.read_i32(store))),
IType::S64 => values.push(IValue::S64(seq_reader.read_i64(store))),
IType::I32 => values.push(IValue::I32(seq_reader.read_i32(store))),
IType::I64 => values.push(IValue::I64(seq_reader.read_i64(store))),
IType::U8 => values.push(IValue::U8(seq_reader.read_u8(store))),
IType::U16 => values.push(IValue::U16(seq_reader.read_u16(store))),
IType::U32 => values.push(IValue::U32(seq_reader.read_u32(store))),
IType::U64 => values.push(IValue::U64(seq_reader.read_u64(store))),
IType::F32 => values.push(IValue::F32(seq_reader.read_f32(store))),
IType::F64 => values.push(IValue::F64(seq_reader.read_f64(store))),
IType::String => values.push(IValue::String(read_string(store, reader, &seq_reader)?)),
IType::ByteArray => values.push(read_byte_array(store, reader, &seq_reader)?),
IType::Array(ty) => values.push(read_array(store, &lifter, &seq_reader, &**ty)?),
IType::Record(record_type_id) => {
values.push(read_record(lifter, &seq_reader, *record_type_id)?)
values.push(read_record(store, lifter, &seq_reader, *record_type_id)?)
}
}
}
@ -69,50 +74,54 @@ pub fn record_lift_memory<R: RecordResolvable, MV: MemoryView>(
Ok(IValue::Record(record))
}
fn read_string<MV: MemoryView>(
reader: &MemoryReader<MV>,
seq_reader: &SequentialReader<'_, MV>,
fn read_string<MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
reader: &MemoryReader<MV, Store>,
seq_reader: &SequentialReader<'_, MV, Store>,
) -> LiResult<String> {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let size = seq_reader.read_u32(store);
let string_mem = reader.read_raw_u8_array(offset, size)?;
let string_mem = reader.read_raw_u8_array(store, offset, size)?;
let string = String::from_utf8(string_mem)?;
Ok(string)
}
fn read_byte_array<MV: MemoryView>(
reader: &MemoryReader<MV>,
seq_reader: &SequentialReader<'_, MV>,
fn read_byte_array<MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
reader: &MemoryReader<MV, Store>,
seq_reader: &SequentialReader<'_, MV, Store>,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let size = seq_reader.read_u32(store);
let array = reader.read_raw_u8_array(offset, size)?;
let array = reader.read_raw_u8_array(store, offset, size)?;
Ok(IValue::ByteArray(array))
}
fn read_array<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
seq_reader: &SequentialReader<'_, MV>,
fn read_array<R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
seq_reader: &SequentialReader<'_, MV, Store>,
value_type: &IType,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();
let size = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let size = seq_reader.read_u32(store);
super::array_lift_memory(lifter, value_type, offset, size)
super::array_lift_memory(store, lifter, value_type, offset, size)
}
fn read_record<R: RecordResolvable, MV: MemoryView>(
lifter: &ILifter<'_, R, MV>,
seq_reader: &SequentialReader<'_, MV>,
fn read_record<R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lifter: &ILifter<'_, R, MV, Store>,
seq_reader: &SequentialReader<'_, MV, Store>,
record_type_id: u64,
) -> LiResult<IValue> {
let offset = seq_reader.read_u32();
let offset = seq_reader.read_u32(store);
let record_type = lifter.resolver.resolve_record(record_type_id)?;
record_lift_memory(lifter, &record_type, offset)
record_lift_memory(store, lifter, &record_type, offset)
}

View File

@ -16,37 +16,40 @@
#[macro_export]
macro_rules! value_der {
($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
[$($self.reader.view.read_byte($offset + $ids)),+]
($self:expr, $store:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
[$($self.reader.view.read_byte($store, $offset + $ids)),+]
};
($self:expr, $offset:expr, 1) => {
crate::value_der!($self, $offset, @seq_start 0 @seq_end)
($self:expr, $store:expr, $offset:expr, 1) => {
crate::value_der!($self, $store, $offset, @seq_start 0 @seq_end)
};
($self:expr, $offset:expr, 2) => {
crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end)
($self:expr, $store:expr, $offset:expr, 2) => {
crate::value_der!($self, $store, $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)
($self:expr, $store:expr, $offset:expr, 4) => {
crate::value_der!($self, $store, $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)
($self:expr, $store:expr, $offset:expr, 8) => {
crate::value_der!($self, $store, $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)
($self:expr, $store:expr, $offset:expr, 16) => {
crate::value_der!($self, $store, $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) => {
pub fn $func_name(&self) -> $ty {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 1));
let result = <$ty>::from_le_bytes(crate::value_der!(self, store, offset, 1));
self.offset.set(offset + 1);
result
@ -54,9 +57,12 @@ macro_rules! read_ty {
};
($func_name:ident, $ty:ty, 2) => {
pub fn $func_name(&self) -> $ty {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 2));
let result = <$ty>::from_le_bytes(crate::value_der!(self, store, offset, 2));
self.offset.set(offset + 2);
result
@ -64,9 +70,12 @@ macro_rules! read_ty {
};
($func_name:ident, $ty:ty, 4) => {
pub fn $func_name(&self) -> $ty {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 4));
let result = <$ty>::from_le_bytes(crate::value_der!(self, store, offset, 4));
self.offset.set(offset + 4);
result
@ -74,9 +83,12 @@ macro_rules! read_ty {
};
($func_name:ident, $ty:ty, 8) => {
pub fn $func_name(&self) -> $ty {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 8));
let result = <$ty>::from_le_bytes(crate::value_der!(self, store, offset, 8));
self.offset.set(offset + 8);
result
@ -84,9 +96,12 @@ macro_rules! read_ty {
};
($func_name:ident, $ty:ty, 16) => {
pub fn $func_name(&self) -> $ty {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty {
let offset = self.offset.get();
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 16));
let result = <$ty>::from_le_bytes(crate::value_der!(self, store, offset, 16));
self.offset.set(offset + 16);
result
@ -97,23 +112,38 @@ macro_rules! read_ty {
#[macro_export]
macro_rules! read_ty_decl {
($func_name:ident, $ty:ty, 1) => {
fn $func_name(&self) -> $ty;
fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty;
};
($func_name:ident, $ty:ty, 2) => {
fn $func_name(&self) -> $ty;
fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty;
};
($func_name:ident, $ty:ty, 4) => {
fn $func_name(&self) -> $ty;
fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty;
};
($func_name:ident, $ty:ty, 8) => {
fn $func_name(&self) -> $ty;
fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty;
};
($func_name:ident, $ty:ty, 16) => {
fn $func_name(&self) -> $ty;
fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> $ty;
};
}
@ -122,15 +152,19 @@ macro_rules! read_array_ty {
($func_name:ident, $ty:ident, $ity:ident) => {
pub fn $func_name(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
offset: u32,
elements_count: u32,
) -> super::LiResult<Vec<crate::IValue>> {
let reader = self
.sequential_reader(offset, (std::mem::size_of::<$ty>() as u32) * elements_count)?;
let reader = self.sequential_reader(
store,
offset,
(std::mem::size_of::<$ty>() as u32) * elements_count,
)?;
let mut result = Vec::with_capacity(elements_count as usize);
for _ in 0..elements_count {
let value = paste::paste! { reader.[<read_ $ty>]()};
let value = paste::paste! { reader.[<read_ $ty>](store)};
result.push(IValue::$ity(value));
}

View File

@ -22,43 +22,63 @@ use crate::IValue;
use it_memory_traits::MemoryView;
use std::cell::Cell;
use std::marker::PhantomData;
pub struct MemoryReader<MV> {
pub struct MemoryReader<MV: MemoryView<Store>, Store: it_memory_traits::Store> {
pub(self) view: MV,
_phantom: PhantomData<Store>,
}
impl<MV: MemoryView> MemoryReader<MV> {
impl<MV: MemoryView<Store>, Store: it_memory_traits::Store> MemoryReader<MV, Store> {
pub fn new(view: MV) -> Self {
Self { view }
Self {
view,
_phantom: PhantomData,
}
}
/// 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<SequentialReader<'_, MV>> {
self.view.check_bounds(offset, size)?;
pub fn sequential_reader(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
offset: u32,
size: u32,
) -> LiResult<SequentialReader<'_, MV, Store>> {
self.view.check_bounds(store, offset, size)?;
let seq_reader = SequentialReader::new(&self, offset);
Ok(seq_reader)
}
pub fn read_raw_u8_array(&self, offset: u32, elements_count: u32) -> LiResult<Vec<u8>> {
let reader = self.sequential_reader(offset, elements_count)?;
pub fn read_raw_u8_array(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
offset: u32,
elements_count: u32,
) -> LiResult<Vec<u8>> {
let reader = self.sequential_reader(store, offset, elements_count)?;
let mut result = Vec::with_capacity(elements_count as usize);
for _ in 0..elements_count {
let value = reader.read_u8();
let value = reader.read_u8(store);
result.push(value);
}
Ok(result)
}
pub fn read_bool_array(&self, offset: u32, elements_count: u32) -> LiResult<Vec<IValue>> {
let reader = self.sequential_reader(offset, elements_count)?;
pub fn read_bool_array(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
offset: u32,
elements_count: u32,
) -> LiResult<Vec<IValue>> {
let reader = self.sequential_reader(store, offset, elements_count)?;
let mut result = Vec::with_capacity(elements_count as usize);
for _ in 0..elements_count {
let value = reader.read_u8();
let value = reader.read_u8(store);
result.push(IValue::Boolean(value != 0));
}
@ -79,21 +99,24 @@ impl<MV: MemoryView> MemoryReader<MV> {
read_array_ty!(read_f64_array, f64, F64);
}
pub struct SequentialReader<'r, MV: MemoryView> {
reader: &'r MemoryReader<MV>,
pub struct SequentialReader<'r, MV: MemoryView<Store>, Store: it_memory_traits::Store> {
reader: &'r MemoryReader<MV, Store>,
offset: Cell<u32>,
}
impl<'r, MV: MemoryView> SequentialReader<'r, MV> {
fn new(reader: &'r MemoryReader<MV>, offset: u32) -> Self {
impl<'r, MV: MemoryView<Store>, Store: it_memory_traits::Store> SequentialReader<'r, MV, Store> {
fn new(reader: &'r MemoryReader<MV, Store>, offset: u32) -> Self {
Self {
reader,
offset: Cell::new(offset),
}
}
pub fn read_bool(&self) -> bool {
self.read_u8() != 0
pub fn read_bool(
&self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
) -> bool {
self.read_u8(store) != 0
}
read_ty!(read_u8, u8, 1);

View File

@ -31,14 +31,19 @@ pub use it_memory_traits::MemoryView;
pub type LiResult<T> = std::result::Result<T, error::LiError>;
pub struct ILifter<'r, R: RecordResolvable, MV> {
pub reader: MemoryReader<MV>,
pub struct ILifter<'r, R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store> {
pub reader: MemoryReader<MV, Store>,
pub resolver: &'r R,
}
impl<'r, R: RecordResolvable, MV: MemoryView> ILifter<'r, R, MV> {
impl<'r, R: RecordResolvable, MV: MemoryView<Store>, Store: it_memory_traits::Store>
ILifter<'r, R, MV, Store>
{
pub fn new(view: MV, resolver: &'r R) -> Self {
let reader = MemoryReader::new(view);
Self { reader, resolver }
Self {
reader,
resolver,
}
}
}

View File

@ -38,8 +38,13 @@ impl LoweredArray {
}
}
pub fn array_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
lowerer: &ILowerer<'_, A, MV>,
pub fn array_lower_memory<
A: Allocatable<MV, Store>,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lowerer: &mut ILowerer<'_, A, MV, Store>,
array_values: Vec<IValue>,
) -> LoResult<LoweredArray> {
if array_values.is_empty() {
@ -49,45 +54,49 @@ pub fn array_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
let elements_count = array_values.len() as u32;
let size = ser_value_size(&array_values[0]) * elements_count;
let type_tag = type_tag_form_ivalue(&array_values[0]);
let seq_writer = lowerer.writer.sequential_writer(size, type_tag)?;
let seq_writer = lowerer.writer.sequential_writer(store, size, type_tag)?;
// 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(&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::Boolean(value) => seq_writer.write_u8(store, &lowerer.writer, value as _),
IValue::S8(value) => seq_writer.write_u8(store, &lowerer.writer, value as _),
IValue::S16(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::S32(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::S64(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::U8(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::U16(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::U32(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::U64(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::I32(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::I64(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::F32(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::F64(value) => seq_writer.write_bytes(store, &lowerer.writer, &value.to_le_bytes()),
IValue::String(value) => {
let offset = lowerer.writer.write_bytes(&value.as_bytes())? as u32;
let offset = lowerer.writer.write_bytes(store, &value.as_bytes())? as u32;
seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes());
seq_writer.write_bytes(&lowerer.writer, &(value.len() as u32).to_le_bytes());
seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
seq_writer.write_bytes(store, &lowerer.writer, &(value.len() as u32).to_le_bytes());
}
IValue::ByteArray(values) => {
let offset = lowerer.writer.write_bytes(&values)? as u32;
let offset = lowerer.writer.write_bytes(store, &values)? as u32;
seq_writer.write_bytes(&lowerer.writer, &offset.to_le_bytes());
seq_writer.write_bytes(&lowerer.writer, &(values.len() as u32).to_le_bytes());
seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
seq_writer.write_bytes(
store,
&lowerer.writer,
&(values.len() as u32).to_le_bytes(),
);
}
IValue::Array(values) => {
let LoweredArray { offset, size } = array_lower_memory(lowerer, values)?;
let LoweredArray { offset, size } = array_lower_memory(store, lowerer, values)?;
seq_writer.write_bytes(&lowerer.writer, &(offset as u32).to_le_bytes());
seq_writer.write_bytes(&lowerer.writer, &(size as u32).to_le_bytes());
seq_writer.write_bytes(store, &lowerer.writer, &(offset as u32).to_le_bytes());
seq_writer.write_bytes(store, &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(&lowerer.writer, &offset.to_le_bytes());
let offset = super::record_lower_memory(store, lowerer, values)? as u32;
seq_writer.write_bytes(store, &lowerer.writer, &offset.to_le_bytes());
}
}
}

View File

@ -23,8 +23,13 @@ use crate::NEVec;
use it_memory_traits::MemoryView;
pub fn record_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
lowerer: &ILowerer<'_, A, MV>,
pub fn record_lower_memory<
A: Allocatable<MV, Store>,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
>(
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
lowerer: &mut ILowerer<'_, A, MV, Store>,
values: NEVec<IValue>,
) -> LoResult<u32> {
let average_field_size = 4;
@ -47,34 +52,35 @@ pub fn record_lower_memory<A: Allocatable<MV>, MV: MemoryView>(
IValue::F32(value) => result.extend_from_slice(&value.to_le_bytes()),
IValue::F64(value) => result.extend_from_slice(&value.to_le_bytes()),
IValue::String(value) => {
let offset = lowerer.writer.write_bytes(value.as_bytes())?;
let offset = lowerer.writer.write_bytes(store, value.as_bytes())?;
result.extend_from_slice(&offset.to_le_bytes());
result.extend_from_slice(&(value.len() as u32).to_le_bytes());
}
IValue::ByteArray(value) => {
let offset = lowerer.writer.write_bytes(&value)?;
let offset = lowerer.writer.write_bytes(store, &value)?;
result.extend_from_slice(&offset.to_le_bytes());
result.extend_from_slice(&(value.len() as u32).to_le_bytes());
}
IValue::Array(values) => {
let LoweredArray { offset, size } = super::array_lower_memory(lowerer, values)?;
let LoweredArray { offset, size } =
super::array_lower_memory(store, lowerer, values)?;
result.extend_from_slice(&(offset).to_le_bytes());
result.extend_from_slice(&(size).to_le_bytes());
}
IValue::Record(values) => {
let offset = record_lower_memory(lowerer, values)?;
let offset = record_lower_memory(store, lowerer, values)?;
result.extend_from_slice(&offset.to_le_bytes());
}
}
}
let result_pointer = lowerer.writer.write_bytes(&result)?;
let result_pointer = lowerer.writer.write_bytes(store, &result)?;
Ok(result_pointer)
}

View File

@ -21,31 +21,50 @@ use crate::utils::type_tag_form_itype;
use it_memory_traits::MemoryView;
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;
pub struct MemoryWriter<'i, R: Allocatable<MV>, MV: MemoryView> {
heap_manager: &'i R,
pub struct MemoryWriter<
'i,
R: Allocatable<MV, Store>,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
> {
heap_manager: &'i mut R,
view: RefCell<MV>,
_store: PhantomData<Store>,
}
impl<'i, A: Allocatable<MV>, MV: MemoryView> MemoryWriter<'i, A, MV> {
pub fn new(view: MV, heap_manager: &'i A) -> LoResult<Self> {
impl<'i, A: Allocatable<MV, Store>, MV: MemoryView<Store>, Store: it_memory_traits::Store>
MemoryWriter<'i, A, MV, Store>
{
pub fn new(view: MV, heap_manager: &'i mut A) -> LoResult<Self> {
let writer = Self {
heap_manager,
view: RefCell::new(view),
_store: PhantomData,
};
Ok(writer)
}
pub fn write_bytes(&self, bytes: &[u8]) -> LoResult<u32> {
pub fn write_bytes(
&mut self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
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(&self, bytes);
let seq_writer = self.sequential_writer(store, bytes.len() as u32, byte_type_tag)?;
seq_writer.write_bytes(store, &self, bytes);
Ok(seq_writer.start_offset())
}
pub fn sequential_writer(&self, size: u32, type_tag: u32) -> LoResult<SequentialWriter> {
let (offset, view) = self.heap_manager.allocate(size, type_tag)?;
pub fn sequential_writer(
&mut self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
size: u32,
type_tag: u32,
) -> LoResult<SequentialWriter> {
let (offset, view) = self.heap_manager.allocate(store, size, type_tag)?;
self.view.replace(view);
let seq_writer = SequentialWriter::new(offset);
Ok(seq_writer)
@ -69,51 +88,72 @@ impl SequentialWriter {
self.start_offset
}
pub fn write_array<MV: MemoryView, A: Allocatable<MV>, const N: usize>(
pub fn write_array<
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
A: Allocatable<MV, Store>,
const N: usize,
>(
&self,
writer: &MemoryWriter<'_, A, MV>,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
writer: &MemoryWriter<'_, A, MV, Store>,
values: [u8; N],
) {
let offset = self.offset.get();
writer.view.borrow().write_bytes(offset, &values);
writer.view.borrow().write_bytes(store, offset, &values);
self.offset.set(offset + N as u32);
}
pub fn write_u8<MV: MemoryView, A: Allocatable<MV>>(
pub fn write_u8<
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
A: Allocatable<MV, Store>,
>(
&self,
writer: &MemoryWriter<'_, A, MV>,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
writer: &MemoryWriter<'_, A, MV, Store>,
value: u8,
) {
let offset = self.offset.get();
writer.view.borrow().write_byte(offset, value);
writer.view.borrow().write_byte(store, offset, value);
self.offset.set(offset + 1);
}
pub fn write_u32<MV: MemoryView, A: Allocatable<MV>>(
pub fn write_u32<
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
A: Allocatable<MV, Store>,
>(
&self,
writer: &MemoryWriter<'_, A, MV>,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
writer: &MemoryWriter<'_, A, MV, Store>,
value: u32,
) {
let offset = self.offset.get();
let value = value.to_le_bytes();
writer.view.borrow().write_bytes(offset, &value);
writer.view.borrow().write_bytes(store, offset, &value);
self.offset.set(offset + 4);
}
pub fn write_bytes<MV: MemoryView, A: Allocatable<MV>>(
pub fn write_bytes<
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
A: Allocatable<MV, Store>,
>(
&self,
writer: &MemoryWriter<'_, A, MV>,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
writer: &MemoryWriter<'_, A, MV, Store>,
bytes: &[u8],
) {
let offset = self.offset.get();
writer.view.borrow().write_bytes(offset, bytes);
writer.view.borrow().write_bytes(store, offset, bytes);
self.offset.set(offset + bytes.len() as u32);
}

View File

@ -31,12 +31,19 @@ pub use it_memory_traits::MemoryView;
pub type LoResult<T> = std::result::Result<T, error::LoError>;
pub struct ILowerer<'m, A: Allocatable<MV>, MV: MemoryView> {
pub writer: MemoryWriter<'m, A, MV>,
pub struct ILowerer<
'm,
A: Allocatable<MV, Store>,
MV: MemoryView<Store>,
Store: it_memory_traits::Store,
> {
pub writer: MemoryWriter<'m, A, MV, Store>,
}
impl<'m, A: Allocatable<MV>, MV: MemoryView> ILowerer<'m, A, MV> {
pub fn new(view: MV, allocatable: &'m A) -> LoResult<Self> {
impl<'m, A: Allocatable<MV, Store>, MV: MemoryView<Store>, Store: it_memory_traits::Store>
ILowerer<'m, A, MV, Store>
{
pub fn new(view: MV, allocatable: &'m mut A) -> LoResult<Self> {
let writer = MemoryWriter::new(view, allocatable)?;
let lowerer = Self { writer };

View File

@ -19,8 +19,13 @@ use thiserror::Error as ThisError;
pub const DEFAULT_MEMORY_INDEX: usize = 0;
pub trait Allocatable<MV: MemoryView> {
fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MV), AllocatableError>;
pub trait Allocatable<MV: MemoryView<Store>, Store: it_memory_traits::Store> {
fn allocate(
&mut self,
store: &mut <Store as it_memory_traits::Store>::ActualStore<'_>,
size: u32,
type_tag: u32,
) -> Result<(u32, MV), AllocatableError>;
}
#[derive(Debug, ThisError)]

View File

@ -18,44 +18,72 @@ mod errors;
pub use errors::MemoryAccessError;
pub trait MemoryReadable {
pub trait Store {
type ActualStore<'c>;
}
pub trait MemoryReadable<Store: self::Store> {
/// 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;
fn read_byte(&self, store: &mut <Store as self::Store>::ActualStore<'_>, 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];
fn read_array<const COUNT: usize>(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
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>;
fn read_vec(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
offset: u32,
size: u32,
) -> Vec<u8>;
}
pub trait MemoryWritable {
pub trait MemoryWritable<Store: self::Store> {
/// 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 write_byte(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
offset: u32,
value: u8,
);
/// 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]);
fn write_bytes(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
offset: u32,
bytes: &[u8],
);
}
pub trait MemoryView: MemoryWritable + MemoryReadable {
pub trait MemoryView<Store: self::Store>: MemoryWritable<Store> + MemoryReadable<Store> {
/// 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>;
fn check_bounds(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
offset: u32,
size: u32,
) -> Result<(), MemoryAccessError>;
}
pub trait Memory<View>
pub trait Memory<View, Store: self::Store>
where
View: MemoryView,
View: MemoryView<Store>,
{
fn view(&self) -> View;
}

View File

@ -5,8 +5,8 @@ use crate::{interpreter::Instruction, IRecordType, IType};
use serde::Deserialize;
use serde::Serialize;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
/// Represents the kind of type.
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
@ -38,10 +38,10 @@ pub enum Type {
/// ```
Function {
/// Types for the parameters (`(param (name i32))`).
arguments: Rc<Vec<FunctionArg>>,
arguments: Arc<Vec<FunctionArg>>,
/// Types for the results (`(result …)`).
output_types: Rc<Vec<IType>>,
output_types: Arc<Vec<IType>>,
},
/// A record type, like:
@ -49,7 +49,7 @@ pub enum Type {
/// ```wasm,ignore
/// (@interface type (record string i32))
/// ```
Record(Rc<IRecordType>),
Record(Arc<IRecordType>),
}
/// Represents an imported function.

View File

@ -8,8 +8,7 @@ use nom::{
error::{make_error, ErrorKind, ParseError},
Err, IResult,
};
use std::rc::Rc;
use std::{convert::TryFrom, str};
use std::{convert::TryFrom, str, sync::Arc};
/// Parse a type kind.
impl TryFrom<u8> for TypeKind {
@ -386,15 +385,15 @@ fn types<'input, E: ParseError<&'input [u8]>>(
consume!((input, output_types) = list(input, ty)?);
types.push(Type::Function {
arguments: Rc::new(arguments),
output_types: Rc::new(output_types),
arguments: Arc::new(arguments),
output_types: Arc::new(output_types),
});
}
TypeKind::Record => {
consume!((input, record_type) = record_type(input)?);
types.push(Type::Record(Rc::new(record_type)));
types.push(Type::Record(Arc::new(record_type)));
}
}
}

View File

@ -2,11 +2,13 @@
use crate::IType;
use crate::{ast::*, interpreter::Instruction};
use std::rc::Rc;
pub use wast::parser::ParseBuffer as Buffer;
use wast::parser::{self, Cursor, Parse, Parser, Peek, Result};
pub use wast::Error;
use std::sync::Arc;
mod keyword {
pub use wast::{
custom_keyword,
@ -491,11 +493,11 @@ impl<'a> Parse<'a> for Type {
}
Ok(Type::Function {
arguments: Rc::new(arguments),
output_types: Rc::new(output_types),
arguments: Arc::new(arguments),
output_types: Arc::new(output_types),
})
} else if lookahead.peek::<keyword::record>() {
Ok(Type::Record(Rc::new(parser.parse()?)))
Ok(Type::Record(Arc::new(parser.parse()?)))
} else {
Err(lookahead.error())
}

View File

@ -12,17 +12,30 @@ use it_lilo::lowerer::ILowerer;
use it_lilo::lowerer::LoweredArray;
use it_lilo::traits::DEFAULT_MEMORY_INDEX;
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView, Store>(
instruction: Instruction,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
MemoryView,
Store,
>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: crate::interpreter::wasm::structures::LocalImport<Store>,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView, Store>,
MemoryView: crate::interpreter::wasm::structures::MemoryView<Store>,
Instance: crate::interpreter::wasm::structures::Instance<
Export,
LocalImport,
Memory,
MemoryView,
Store,
>,
Store: crate::interpreter::wasm::structures::Store,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -61,8 +74,9 @@ where
let li_helper = lilo::LiHelper::new(&**instance);
let lifter = ILifter::new(memory_view, &li_helper);
let array = it_lilo::lifter::array_lift_memory(&lifter, &value_type, offset, size)
.map_err(|e| InstructionError::from_li(instruction.clone(), e))?;
let array =
it_lilo::lifter::array_lift_memory(runtime.store, &lifter, &value_type, offset, size)
.map_err(|e| InstructionError::from_li(instruction.clone(), e))?;
log::trace!("array.lift_memory: pushing {:?} on the stack", array);
runtime.stack.push(array);
@ -72,17 +86,30 @@ where
})
}
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView, Store>(
instruction: Instruction,
value_type: IType,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
MemoryView,
Store,
>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: crate::interpreter::wasm::structures::LocalImport<Store>,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView, Store>,
MemoryView: crate::interpreter::wasm::structures::MemoryView<Store>,
Instance: crate::interpreter::wasm::structures::Instance<
Export,
LocalImport,
Memory,
MemoryView,
Store,
>,
Store: crate::interpreter::wasm::structures::Store,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -117,12 +144,12 @@ where
})?
.view();
let lo_helper = lilo::LoHelper::new(&**instance);
let lowerer = ILowerer::new(memory_view, &lo_helper)
let mut lo_helper = lilo::LoHelper::new(&**instance);
let mut lowerer = ILowerer::new(memory_view, &mut lo_helper)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
let LoweredArray { offset, size } =
it_lilo::lowerer::array_lower_memory(&lowerer, values)
it_lilo::lowerer::array_lower_memory(runtime.store, &mut lowerer, values)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
log::trace!(
@ -136,7 +163,7 @@ where
Ok(())
}
IValue::ByteArray(bytearray) => {
let lo_helper = lilo::LoHelper::new(&**instance);
let mut lo_helper = lilo::LoHelper::new(&**instance);
let memory_index = DEFAULT_MEMORY_INDEX;
let memory_view = instance
.memory(memory_index)
@ -148,12 +175,12 @@ where
})?
.view();
let lowerer = ILowerer::new(memory_view, &lo_helper)
let mut lowerer = ILowerer::new(memory_view, &mut lo_helper)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
let offset = lowerer
.writer
.write_bytes(&bytearray)
.write_bytes(runtime.store, &bytearray)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
let size = bytearray.len();

View File

@ -42,10 +42,10 @@ executable_instruction!(
}
memory_view
.check_bounds(pointer, length)
.check_bounds(runtime.store, pointer, length)
.map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?;
let data = memory_view.read_vec(pointer, length);
let data = memory_view.read_vec(runtime.store, pointer, length);
log::debug!("byte_array.lift_memory: pushing {:?} on the stack", data);
runtime.stack.push(IValue::ByteArray(data));
@ -82,10 +82,10 @@ executable_instruction!(
.view();
memory_view
.check_bounds(array_pointer, array.len() as u32)
.check_bounds(runtime.store, array_pointer, array.len() as u32)
.map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?;
memory_view.write_bytes(array_pointer, &array);
memory_view.write_bytes(runtime.store, 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

@ -34,7 +34,7 @@ executable_instruction!(
log::debug!("call-core: calling {} with arguments: {:?}", local_or_import.name(), inputs);
let outputs = local_or_import.call(&inputs).map_err(|_| {
let outputs = local_or_import.call(runtime.store, &inputs).map_err(|_| {
InstructionError::from_error_kind(
instruction.clone(),
InstructionErrorKind::LocalOrImportCall {

View File

@ -6,29 +6,32 @@ use it_lilo::traits::RecordResolvableError;
use std::marker::PhantomData;
pub struct LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
pub struct LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView + 'i,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store> + 'i,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
pub(crate) instance: &'i Instance,
_export: PhantomData<Export>,
_local_import: PhantomData<LocalImport>,
_memory: PhantomData<Memory>,
_memory_view: PhantomData<MemoryView>,
_store: PhantomData<Store>,
}
impl<'i, Instance, Export, LocalImport, Memory, MemoryView>
LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
impl<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
pub(crate) fn new(instance: &'i Instance) -> Self {
Self {
@ -37,18 +40,20 @@ where
_local_import: PhantomData,
_memory: PhantomData,
_memory_view: PhantomData,
_store: PhantomData,
}
}
}
impl<'i, Instance, Export, LocalImport, Memory, MemoryView> RecordResolvable
for LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
impl<'i, Instance, Export, LocalImport, Memory, MemoryView, Store> RecordResolvable
for LiHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
fn resolve_record(&self, record_type_id: u64) -> Result<&IRecordType, RecordResolvableError> {
let record = self

View File

@ -8,29 +8,32 @@ use it_lilo::traits::DEFAULT_MEMORY_INDEX;
use std::marker::PhantomData;
pub struct LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
pub struct LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
pub(crate) instance: &'i Instance,
_export: PhantomData<Export>,
_local_import: PhantomData<LocalImport>,
_memory: PhantomData<Memory>,
_memory_view: PhantomData<MemoryView>,
_store: PhantomData<Store>,
}
impl<'i, Instance, Export, LocalImport, Memory, MemoryView>
LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
impl<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
pub(crate) fn new(instance: &'i Instance) -> Self {
Self {
@ -39,20 +42,27 @@ where
_local_import: PhantomData,
_memory: PhantomData,
_memory_view: PhantomData,
_store: PhantomData,
}
}
}
impl<'i, Instance, Export, LocalImport, Memory, MemoryView> Allocatable<MemoryView>
for LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView>
impl<'i, Instance, Export, LocalImport, Memory, MemoryView, Store> Allocatable<MemoryView, Store>
for LoHelper<'i, Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export + 'i,
LocalImport: wasm::structures::LocalImport + 'i,
Memory: wasm::structures::Memory<MemoryView> + 'i,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'i,
Memory: wasm::structures::Memory<MemoryView, Store> + 'i,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
fn allocate(&self, size: u32, type_tag: u32) -> Result<(u32, MemoryView), AllocatableError> {
fn allocate(
&mut self,
store: &mut <Store as wasm::structures::Store>::ActualStore<'_>,
size: u32,
type_tag: u32,
) -> Result<(u32, MemoryView), AllocatableError> {
use AllocatableError::*;
use crate::interpreter::instructions::ALLOCATE_FUNC_INDEX;
@ -76,7 +86,7 @@ where
.map_err(|_| AllocateFuncIncompatibleSignature)?;
let outcome = local_or_import
.call(&inputs)
.call(store, &inputs)
.map_err(|_| AllocateCallFailed)?;
if outcome.len() != 1 {

View File

@ -233,6 +233,7 @@ pub(crate) fn check_function_signature<
LocalImport,
Memory,
MemoryView,
Store,
>(
instance: &'instance Instance,
local_import: &LocalImport,
@ -240,10 +241,11 @@ pub(crate) fn check_function_signature<
) -> Result<(), InstructionErrorKind>
where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'instance,
Memory: wasm::structures::Memory<MemoryView, Store> + 'instance,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
let func_inputs = local_import.arguments();
@ -262,6 +264,7 @@ pub(crate) fn is_value_compatible_to_type<
LocalImport,
Memory,
MemoryView,
Store,
>(
instance: &'instance Instance,
interface_type: &IType,
@ -269,10 +272,11 @@ pub(crate) fn is_value_compatible_to_type<
) -> Result<(), InstructionErrorKind>
where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'instance,
Memory: wasm::structures::Memory<MemoryView, Store> + 'instance,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
match (&interface_type, interface_value) {
(IType::Boolean, IValue::Boolean(_)) => Ok(()),
@ -333,6 +337,7 @@ pub(crate) fn is_record_fields_compatible_to_type<
LocalImport,
Memory,
MemoryView,
Store,
>(
instance: &'instance Instance,
record_type_id: u64,
@ -340,10 +345,11 @@ pub(crate) fn is_record_fields_compatible_to_type<
) -> Result<(), InstructionErrorKind>
where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store> + 'instance,
Memory: wasm::structures::Memory<MemoryView, Store> + 'instance,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
let record_type = instance
.wit_record_by_id(record_type_id)
@ -453,7 +459,7 @@ pub(crate) mod tests {
}
}
impl wasm::structures::Memory<MemoryView> for Memory {
impl wasm::structures::Memory<MemoryView, Store> for Memory {
fn view(&self) -> MemoryView {
self.view.clone()
}

View File

@ -9,17 +9,30 @@ use it_lilo::lifter::ILifter;
use it_lilo::lowerer::ILowerer;
use it_lilo::traits::DEFAULT_MEMORY_INDEX;
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView, Store>(
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
MemoryView,
Store,
>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: crate::interpreter::wasm::structures::LocalImport<Store>,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView, Store>,
MemoryView: crate::interpreter::wasm::structures::MemoryView<Store>,
Instance: crate::interpreter::wasm::structures::Instance<
Export,
LocalImport,
Memory,
MemoryView,
Store,
>,
Store: crate::interpreter::wasm::structures::Store,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -62,7 +75,7 @@ where
let li_helper = lilo::LiHelper::new(&**instance);
let lifter = ILifter::new(memory_view, &li_helper);
let record = it_lilo::lifter::record_lift_memory(&lifter, record_type, offset)
let record = it_lilo::lifter::record_lift_memory(runtime.store, &lifter, record_type, offset)
.map_err(|e| InstructionError::from_li(instruction.clone(), e))?;
log::debug!("record.lift_memory: pushing {:?} on the stack", record);
@ -73,17 +86,30 @@ where
})
}
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
pub(crate) fn record_lower_memory<Instance, Export, LocalImport, Memory, MemoryView, Store>(
record_type_id: u64,
instruction: Instruction,
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
) -> crate::interpreter::ExecutableInstruction<
Instance,
Export,
LocalImport,
Memory,
MemoryView,
Store,
>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance:
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: crate::interpreter::wasm::structures::LocalImport<Store>,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView, Store>,
MemoryView: crate::interpreter::wasm::structures::MemoryView<Store>,
Instance: crate::interpreter::wasm::structures::Instance<
Export,
LocalImport,
Memory,
MemoryView,
Store,
>,
Store: crate::interpreter::wasm::structures::Store,
{
#[allow(unused_imports)]
use crate::interpreter::stack::Stackable;
@ -113,12 +139,15 @@ where
})?
.view();
let lo_helper = lilo::LoHelper::new(&**instance);
let memory_writer = ILowerer::new(memory_view, &lo_helper)
let mut lo_helper = lilo::LoHelper::new(&**instance);
let mut memory_writer = ILowerer::new(memory_view, &mut lo_helper)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
let offset =
it_lilo::lowerer::record_lower_memory(&memory_writer, record_fields)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
let offset = it_lilo::lowerer::record_lower_memory(
runtime.store,
&mut memory_writer,
record_fields,
)
.map_err(|e| InstructionError::from_lo(instruction.clone(), e))?;
log::debug!("record.lower_memory: pushing {} on the stack", offset);
runtime.stack.push(IValue::I32(offset as i32));

View File

@ -41,10 +41,10 @@ executable_instruction!(
}
memory_view
.check_bounds(pointer, length)
.check_bounds(runtime.store, pointer, length)
.map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?;
let data = memory_view.read_vec(pointer, length);
let data = memory_view.read_vec(runtime.store, pointer, length);
let string = String::from_utf8(data)
.map_err(|error| InstructionError::from_error_kind(instruction.clone(), InstructionErrorKind::String(error)))?;
@ -83,10 +83,10 @@ executable_instruction!(
})?;
memory_view
.check_bounds(string_pointer, string_length)
.check_bounds(runtime.store, string_pointer, string_length)
.map_err(|e| InstructionError::from_memory_access(instruction.clone(), e))?;
memory_view.write_bytes(string_pointer, string_bytes);
memory_view.write_bytes(runtime.store, 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,13 +13,25 @@ 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, MemoryView>
where
pub(crate) struct Runtime<
'invocation,
'instance,
'store_ref,
'store_param,
Instance,
Export,
LocalImport,
Memory,
MemoryView,
Store,
> where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView> + 'instance,
LocalImport: wasm::structures::LocalImport<Store> + 'instance,
Memory: wasm::structures::Memory<MemoryView, Store> + 'instance,
MemoryView: wasm::structures::MemoryView<Store>,
Instance:
wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store> + 'instance,
Store: wasm::structures::Store,
{
/// The invocation inputs are all the arguments received by an
/// adapter.
@ -31,17 +43,20 @@ where
/// The WebAssembly module instance. It is used by adapter's
/// instructions.
wasm_instance: &'instance mut Instance,
store: &'store_ref mut <Store as it_memory_traits::Store>::ActualStore<'store_param>,
/// Phantom data.
_phantom: PhantomData<(Export, LocalImport, Memory, MemoryView)>,
_phantom: PhantomData<(Export, LocalImport, Memory, MemoryView, Store)>,
}
/// 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, MemoryView> = Box<
dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory, MemoryView>) -> InstructionResult<()>
+ Send,
>;
pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView, Store> =
Box<
dyn Fn(&mut Runtime<Instance, Export, LocalImport, Memory, MemoryView, Store>, ) -> InstructionResult<()>
+ Send
+ Sync,
>;
/// An interpreter is the central piece of this crate. It is a set of
/// executable instructions. Each instruction takes the runtime as
@ -121,31 +136,33 @@ pub(crate) type ExecutableInstruction<Instance, Export, LocalImport, Memory, Mem
/// // 5. Read the stack to get the result.
/// assert_eq!(stack.as_slice(), &[IValue::I32(7)]);
/// ```
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
pub struct Interpreter<Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store>,
Memory: wasm::structures::Memory<MemoryView, Store>,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
executable_instructions:
Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>>,
Vec<ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView, Store>>,
}
impl<Instance, Export, LocalImport, Memory, MemoryView>
Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
impl<Instance, Export, LocalImport, Memory, MemoryView, Store>
Interpreter<Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store>,
Memory: wasm::structures::Memory<MemoryView, Store>,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
fn iter(
&self,
) -> impl Iterator<
Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>,
Item = &ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView, Store>,
> + '_ {
self.executable_instructions.iter()
}
@ -159,11 +176,13 @@ where
&self,
invocation_inputs: &[IValue],
wasm_instance: &mut Instance,
wasm_store: &mut <Store as wasm::structures::Store>::ActualStore<'_>,
) -> InterpreterResult<Stack<IValue>> {
let mut runtime = Runtime {
invocation_inputs,
stack: Stack::new(),
wasm_instance,
store: wasm_store,
_phantom: PhantomData,
};
@ -176,14 +195,15 @@ where
}
/// Transforms a `Vec<Instruction>` into an `Interpreter`.
impl<Instance, Export, LocalImport, Memory, MemoryView> TryFrom<Vec<Instruction>>
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView>
impl<Instance, Export, LocalImport, Memory, MemoryView, Store> TryFrom<Vec<Instruction>>
for Interpreter<Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: wasm::structures::Export,
LocalImport: wasm::structures::LocalImport,
Memory: wasm::structures::Memory<MemoryView>,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: wasm::structures::LocalImport<Store>,
Memory: wasm::structures::Memory<MemoryView, Store>,
MemoryView: wasm::structures::MemoryView<Store>,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: wasm::structures::Store,
{
type Error = ();

View File

@ -4,7 +4,7 @@ use crate::ast::FunctionArg;
use crate::IRecordType;
use crate::IType;
use crate::IValue;
use std::rc::Rc;
use std::sync::Arc;
pub use it_memory_traits::{Memory, MemoryAccessError, MemoryView};
use it_memory_traits::{MemoryReadable, MemoryWritable};
@ -54,27 +54,34 @@ pub trait Export {
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
}
pub trait LocalImport {
pub trait LocalImport<Store: self::Store> {
fn name(&self) -> &str;
fn inputs_cardinality(&self) -> usize;
fn outputs_cardinality(&self) -> usize;
fn arguments(&self) -> &[FunctionArg];
fn outputs(&self) -> &[IType];
fn call(&self, arguments: &[IValue]) -> Result<Vec<IValue>, ()>;
fn call(
&self,
store: &mut <Store as self::Store>::ActualStore<'_>,
arguments: &[IValue],
) -> Result<Vec<IValue>, ()>;
}
pub trait Instance<E, LI, M, MV>
pub use it_memory_traits::Store;
pub trait Instance<E, LI, M, MV, S>
where
E: Export,
LI: LocalImport,
M: Memory<MV>,
MV: MemoryView,
LI: LocalImport<S>,
M: Memory<MV, S>,
MV: MemoryView<S>,
S: Store,
{
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
fn memory(&self, index: usize) -> Option<&M>;
fn memory_view(&self, index: usize) -> Option<MV>;
fn wit_record_by_id(&self, index: u64) -> Option<&Rc<IRecordType>>;
fn wit_record_by_id(&self, index: u64) -> Option<&Arc<IRecordType>>;
}
impl Export for () {
@ -103,7 +110,7 @@ impl Export for () {
}
}
impl LocalImport for () {
impl<Store: self::Store> LocalImport<Store> for () {
fn name(&self) -> &str {
""
}
@ -124,35 +131,54 @@ impl LocalImport for () {
&[]
}
fn call(&self, _arguments: &[IValue]) -> Result<Vec<IValue>, ()> {
fn call(
&self,
_store: &mut <Store as self::Store>::ActualStore<'_>,
_arguments: &[IValue],
) -> Result<Vec<IValue>, ()> {
Err(())
}
}
pub(crate) struct EmptyMemoryView;
impl MemoryWritable for EmptyMemoryView {
fn write_byte(&self, _offset: u32, _value: u8) {}
impl<S: Store> MemoryWritable<S> for EmptyMemoryView {
fn write_byte(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32, _value: u8) {}
fn write_bytes(&self, _offset: u32, _bytes: &[u8]) {}
fn write_bytes(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32, _bytes: &[u8]) {
}
}
impl MemoryReadable for EmptyMemoryView {
fn read_byte(&self, _offset: u32) -> u8 {
impl<S: Store> MemoryReadable<S> for EmptyMemoryView {
fn read_byte(&self, _store: &mut <S as Store>::ActualStore<'_>, _offset: u32) -> u8 {
0
}
fn read_array<const COUNT: usize>(&self, _offset: u32) -> [u8; COUNT] {
fn read_array<const COUNT: usize>(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
_offset: u32,
) -> [u8; COUNT] {
[0; COUNT]
}
fn read_vec(&self, _offset: u32, _size: u32) -> Vec<u8> {
fn read_vec(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
_offset: u32,
_size: u32,
) -> Vec<u8> {
Vec::default()
}
}
impl MemoryView for EmptyMemoryView {
fn check_bounds(&self, offset: u32, size: u32) -> Result<(), MemoryAccessError> {
impl<S: Store> MemoryView<S> for EmptyMemoryView {
fn check_bounds(
&self,
_store: &mut <S as Store>::ActualStore<'_>,
offset: u32,
size: u32,
) -> Result<(), MemoryAccessError> {
Err(MemoryAccessError::OutOfBounds {
size,
offset,
@ -161,18 +187,19 @@ impl MemoryView for EmptyMemoryView {
}
}
impl Memory<EmptyMemoryView> for () {
impl<S: Store> Memory<EmptyMemoryView, S> for () {
fn view(&self) -> EmptyMemoryView {
EmptyMemoryView
}
}
impl<E, LI, M, MV> Instance<E, LI, M, MV> for ()
impl<E, LI, M, MV, S> Instance<E, LI, M, MV, S> for ()
where
E: Export,
LI: LocalImport,
M: Memory<MV>,
MV: MemoryView,
LI: LocalImport<S>,
M: Memory<MV, S>,
MV: MemoryView<S>,
S: Store,
{
fn export(&self, _export_name: &str) -> Option<&E> {
None
@ -190,7 +217,7 @@ where
None
}
fn wit_record_by_id(&self, _index: u64) -> Option<&Rc<IRecordType>> {
fn wit_record_by_id(&self, _index: u64) -> Option<&Arc<IRecordType>> {
None
}
}

View File

@ -67,15 +67,16 @@ 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, MemoryView>(
pub(crate) fn $name<Instance, Export, LocalImport, Memory, MemoryView, Store>(
$($argument_name: $argument_type),*
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView>
) -> crate::interpreter::ExecutableInstruction<Instance, Export, LocalImport, Memory, MemoryView, Store>
where
Export: crate::interpreter::wasm::structures::Export,
LocalImport: crate::interpreter::wasm::structures::LocalImport,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView>,
MemoryView: crate::interpreter::wasm::structures::MemoryView,
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
LocalImport: crate::interpreter::wasm::structures::LocalImport<Store>,
Memory: crate::interpreter::wasm::structures::Memory<MemoryView, Store>,
MemoryView: crate::interpreter::wasm::structures::MemoryView<Store>,
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView, Store>,
Store: crate::interpreter::wasm::structures::Store,
{
#[allow(unused_imports)]
use crate::interpreter::{stack::Stackable};