mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
refactoring
This commit is contained in:
parent
41555d4d32
commit
51af2df63e
@ -127,8 +127,8 @@ pub enum InstructionErrorKind {
|
||||
|
||||
/// The memory doesn't exist.
|
||||
MemoryIsMissing {
|
||||
/// The memory indeX.
|
||||
memory_index: u32,
|
||||
/// The memory index.
|
||||
memory_index: usize,
|
||||
},
|
||||
|
||||
/// Tried to read out of bounds of the memory.
|
||||
|
@ -1,9 +1,17 @@
|
||||
mod lift_array;
|
||||
mod lower_array;
|
||||
mod read_arrays;
|
||||
mod utils;
|
||||
mod write_arrays;
|
||||
|
||||
pub(crate) use lift_array::array_lift_memory_impl;
|
||||
pub(crate) use lower_array::array_lower_memory_impl;
|
||||
|
||||
use super::allocate;
|
||||
use super::read_from_instance_mem;
|
||||
use super::record_lift_memory_;
|
||||
use super::record_lower_memory_;
|
||||
use super::write_to_instance_mem;
|
||||
use read_arrays::*;
|
||||
|
||||
use crate::instr_error;
|
||||
use crate::interpreter::instructions::to_native;
|
||||
@ -15,60 +23,6 @@ use crate::{
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
pub(super) fn array_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
value_type: &IType,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
instruction: Instruction,
|
||||
) -> Result<IValue, InstructionError>
|
||||
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>
|
||||
+ 'instance,
|
||||
{
|
||||
if elements_count == 0 {
|
||||
return Ok(IValue::Array(vec![]));
|
||||
}
|
||||
|
||||
match value_type {
|
||||
IType::Boolean => read_bool_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S8 => read_s8_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S16 => read_s16_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S32 => read_s32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S64 => read_s64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::I32 => read_i32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::I64 => read_i64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U8 => read_u8_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U16 => read_u16_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U32 => read_u32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U64 => read_u64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::F32 => read_f32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::F64 => read_f64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::String => read_string_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::Record(record_type_id) => read_record_array(
|
||||
instance,
|
||||
instruction.clone(),
|
||||
*record_type_id,
|
||||
offset,
|
||||
elements_count,
|
||||
),
|
||||
IType::ByteArray => read_array_array(
|
||||
instance,
|
||||
instruction.clone(),
|
||||
&IType::ByteArray,
|
||||
offset,
|
||||
elements_count,
|
||||
),
|
||||
IType::Array(ty) => {
|
||||
read_array_array(instance, instruction.clone(), &ty, offset, elements_count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: IType,
|
||||
@ -110,7 +64,7 @@ where
|
||||
);
|
||||
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let array = array_lift_memory_(
|
||||
let array = array_lift_memory_impl(
|
||||
*instance,
|
||||
&value_type,
|
||||
offset as _,
|
||||
@ -126,72 +80,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn array_lower_memory_<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
array_values: Vec<IValue>,
|
||||
) -> Result<(usize, usize), InstructionError>
|
||||
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>,
|
||||
{
|
||||
let mut result: Vec<u64> = Vec::with_capacity(array_values.len());
|
||||
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
IValue::S8(value) => result.push(value as _),
|
||||
IValue::S16(value) => result.push(value as _),
|
||||
IValue::S32(value) => result.push(value as _),
|
||||
IValue::S64(value) => result.push(value as _),
|
||||
IValue::U8(value) => result.push(value as _),
|
||||
IValue::U16(value) => result.push(value as _),
|
||||
IValue::U32(value) => result.push(value as _),
|
||||
IValue::U64(value) => result.push(value as _),
|
||||
IValue::I32(value) => result.push(value as _),
|
||||
IValue::I64(value) => result.push(value as _),
|
||||
IValue::F32(value) => result.push(value as _),
|
||||
IValue::F64(value) => result.push(value.to_bits()),
|
||||
IValue::String(value) => {
|
||||
let string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
result.push(string_pointer as _);
|
||||
result.push(value.len() as _);
|
||||
}
|
||||
|
||||
IValue::Array(values) => {
|
||||
let (array_offset, array_size) = if !values.is_empty() {
|
||||
array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
result.push(array_offset as _);
|
||||
result.push(array_size as _);
|
||||
}
|
||||
|
||||
IValue::Record(values) => {
|
||||
let record_offset =
|
||||
super::record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
result.push(record_offset as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = safe_transmute::transmute_to_bytes::<u64>(&result);
|
||||
let result_pointer = write_to_instance_mem(instance, instruction, &result)?;
|
||||
|
||||
Ok((result_pointer as _, result.len() as _))
|
||||
}
|
||||
|
||||
pub(crate) fn array_lower_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instruction: Instruction,
|
||||
value_type: IType,
|
||||
@ -230,7 +118,7 @@ where
|
||||
}
|
||||
|
||||
let (offset, size) =
|
||||
array_lower_memory_(*instance, instruction.clone(), values)?;
|
||||
array_lower_memory_impl(*instance, instruction.clone(), values)?;
|
||||
|
||||
log::trace!(
|
||||
"array.lower_memory: pushing {}, {} on the stack",
|
||||
|
57
wasmer-it/src/interpreter/instructions/arrays/lift_array.rs
Normal file
57
wasmer-it/src/interpreter/instructions/arrays/lift_array.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use super::read_arrays::*;
|
||||
|
||||
use crate::{errors::InstructionError, interpreter::Instruction, IType, IValue};
|
||||
|
||||
pub(crate) fn array_lift_memory_impl<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
value_type: &IType,
|
||||
offset: usize,
|
||||
elements_count: usize,
|
||||
instruction: Instruction,
|
||||
) -> Result<IValue, InstructionError>
|
||||
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>
|
||||
+ 'instance,
|
||||
{
|
||||
if elements_count == 0 {
|
||||
return Ok(IValue::Array(vec![]));
|
||||
}
|
||||
|
||||
match value_type {
|
||||
IType::Boolean => read_bool_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S8 => read_s8_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S16 => read_s16_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S32 => read_s32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::S64 => read_s64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::I32 => read_i32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::I64 => read_i64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U8 => read_u8_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U16 => read_u16_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U32 => read_u32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::U64 => read_u64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::F32 => read_f32_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::F64 => read_f64_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::String => read_string_array(instance, instruction.clone(), offset, elements_count),
|
||||
IType::Record(record_type_id) => read_record_array(
|
||||
instance,
|
||||
instruction.clone(),
|
||||
*record_type_id,
|
||||
offset,
|
||||
elements_count,
|
||||
),
|
||||
IType::ByteArray => read_array_array(
|
||||
instance,
|
||||
instruction.clone(),
|
||||
&IType::ByteArray,
|
||||
offset,
|
||||
elements_count,
|
||||
),
|
||||
IType::Array(ty) => {
|
||||
read_array_array(instance, instruction.clone(), &ty, offset, elements_count)
|
||||
}
|
||||
}
|
||||
}
|
107
wasmer-it/src/interpreter/instructions/arrays/lower_array.rs
Normal file
107
wasmer-it/src/interpreter/instructions/arrays/lower_array.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use super::utils::MemoryWriter;
|
||||
use super::write_to_instance_mem;
|
||||
|
||||
use crate::{
|
||||
errors::{InstructionError, InstructionErrorKind},
|
||||
interpreter::Instruction,
|
||||
IValue,
|
||||
};
|
||||
|
||||
pub(crate) fn array_lower_memory_impl<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &mut Instance,
|
||||
instruction: Instruction,
|
||||
array_values: Vec<IValue>,
|
||||
) -> Result<(usize, usize), InstructionError>
|
||||
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>,
|
||||
{
|
||||
if array_values.is_empty() {
|
||||
return Ok((0, 0));
|
||||
}
|
||||
|
||||
let size_to_allocate = value_size(&array_values[0]) * array_values.len();
|
||||
let offset = super::allocate(instance, instruction.clone(), size_to_allocate)?;
|
||||
|
||||
let memory_index = 0;
|
||||
let memory_view = &instance
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::MemoryIsMissing { memory_index },
|
||||
)
|
||||
})?
|
||||
.view();
|
||||
let writer = MemoryWriter::new(memory_view, offset);
|
||||
|
||||
let values_count = array_values.len();
|
||||
|
||||
// here it's known that all interface values have the same type
|
||||
for value in array_values {
|
||||
match value {
|
||||
IValue::Boolean(value) => writer.write_u8(value as _),
|
||||
IValue::S8(value) => writer.write_u8(value as _),
|
||||
IValue::S16(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::S32(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::S64(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::U8(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::U16(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::U32(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::U64(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::I32(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::I64(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::F32(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::F64(value) => writer.write_array(value.to_le_bytes()),
|
||||
IValue::String(value) => {
|
||||
let string_pointer =
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?;
|
||||
|
||||
writer.write_array(string_pointer.to_le_bytes());
|
||||
writer.write_array(value.len().to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(values) => writer.write_slice(&values),
|
||||
IValue::Array(values) => {
|
||||
let (array_offset, array_size) =
|
||||
array_lower_memory_impl(instance, instruction.clone(), values)?;
|
||||
|
||||
writer.write_array(array_offset.to_le_bytes());
|
||||
writer.write_array(array_size.to_le_bytes());
|
||||
}
|
||||
|
||||
IValue::Record(values) => {
|
||||
let record_offset =
|
||||
super::record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
writer.write_array(record_offset.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((offset as _, values_count as _))
|
||||
}
|
||||
|
||||
fn value_size(value: &IValue) -> usize {
|
||||
match value {
|
||||
IValue::Boolean(_) => 1,
|
||||
IValue::S8(_) => 1,
|
||||
IValue::S16(_) => 2,
|
||||
IValue::S32(_) => 4,
|
||||
IValue::S64(_) => 8,
|
||||
IValue::U8(_) => 1,
|
||||
IValue::U16(_) => 2,
|
||||
IValue::U32(_) => 4,
|
||||
IValue::U64(_) => 8,
|
||||
IValue::F32(_) => 4,
|
||||
IValue::F64(_) => 8,
|
||||
IValue::String(_) => 4,
|
||||
IValue::ByteArray(_) => 4,
|
||||
IValue::Array(_) => 4,
|
||||
IValue::I32(_) => 4,
|
||||
IValue::I64(_) => 8,
|
||||
IValue::Record(_) => 4,
|
||||
}
|
||||
}
|
@ -55,9 +55,9 @@ where
|
||||
MemoryView: wasm::structures::MemoryView + 'instance,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let memory_index: u32 = 0;
|
||||
let memory_index = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
@ -112,7 +112,7 @@ def_read_func!(read_s8_array, (i8, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i8::from_be_bytes([Cell::get(&memory_view[element_id])]);
|
||||
let value = i8::from_le_bytes([Cell::get(&memory_view[element_id])]);
|
||||
result.push(IValue::S8(value));
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ def_read_func!(read_u16_array, (u16, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = u16::from_be_bytes([
|
||||
let value = u16::from_le_bytes([
|
||||
Cell::get(&memory_view[2 * element_id]),
|
||||
Cell::get(&memory_view[2 * element_id + 1]),
|
||||
]);
|
||||
@ -139,7 +139,7 @@ def_read_func!(read_s16_array, (i16, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i16::from_be_bytes([
|
||||
let value = i16::from_le_bytes([
|
||||
Cell::get(&memory_view[2 * element_id]),
|
||||
Cell::get(&memory_view[2 * element_id + 1]),
|
||||
]);
|
||||
@ -154,7 +154,7 @@ def_read_func!(read_u32_array, (u32, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = u32::from_be_bytes([
|
||||
let value = u32::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -171,7 +171,7 @@ def_read_func!(read_f32_array, (f32, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = f32::from_be_bytes([
|
||||
let value = f32::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -188,7 +188,7 @@ def_read_func!(read_s32_array, (i32, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i32::from_be_bytes([
|
||||
let value = i32::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -205,7 +205,7 @@ def_read_func!(read_i32_array, (i32, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i32::from_be_bytes([
|
||||
let value = i32::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -222,7 +222,7 @@ def_read_func!(read_u64_array, (u64, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = u64::from_be_bytes([
|
||||
let value = u64::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -243,7 +243,7 @@ def_read_func!(read_f64_array, (f64, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = f64::from_be_bytes([
|
||||
let value = f64::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -264,7 +264,7 @@ def_read_func!(read_s64_array, (i64, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i64::from_be_bytes([
|
||||
let value = i64::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -285,7 +285,7 @@ def_read_func!(read_i64_array, (i64, elements_count), {
|
||||
|memory_view: &[Cell<u8>]| {
|
||||
let mut result = Vec::with_capacity(elements_count);
|
||||
for element_id in 0..elements_count {
|
||||
let value = i64::from_be_bytes([
|
||||
let value = i64::from_le_bytes([
|
||||
Cell::get(&memory_view[4 * element_id]),
|
||||
Cell::get(&memory_view[4 * element_id + 1]),
|
||||
Cell::get(&memory_view[4 * element_id + 2]),
|
||||
@ -459,7 +459,7 @@ where
|
||||
)?;
|
||||
IValue::ByteArray(value)
|
||||
}
|
||||
_ => super::array_lift_memory_(
|
||||
_ => super::array_lift_memory_impl(
|
||||
instance,
|
||||
&*ty,
|
||||
*array_offset as _,
|
||||
|
47
wasmer-it/src/interpreter/instructions/arrays/utils.rs
Normal file
47
wasmer-it/src/interpreter/instructions/arrays/utils.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::cell::Cell;
|
||||
|
||||
pub(super) struct MemoryWriter<'m> {
|
||||
memory_view: &'m [Cell<u8>],
|
||||
offset: Cell<usize>,
|
||||
}
|
||||
|
||||
impl<'m> MemoryWriter<'m> {
|
||||
pub(crate) fn new(memory_view: &'m [Cell<u8>], offset: usize) -> Self {
|
||||
let offset = Cell::new(offset);
|
||||
|
||||
Self {
|
||||
memory_view,
|
||||
offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn write_u8(&self, value: u8) {
|
||||
let offset = self.offset.get();
|
||||
self.memory_view[offset].set(value);
|
||||
self.offset.set(offset + 1);
|
||||
}
|
||||
|
||||
pub(crate) fn write_slice(&self, values: &[u8]) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
for (id, value) in values.iter().enumerate() {
|
||||
// don't check for memory overflow here for optimization purposes
|
||||
// assuming that caller site work well
|
||||
self.memory_view[offset + id].set(*value);
|
||||
}
|
||||
|
||||
self.offset.set(offset + values.len());
|
||||
}
|
||||
|
||||
pub(crate) fn write_array<const N: usize>(&self, values: [u8; N]) {
|
||||
let offset = self.offset.get();
|
||||
|
||||
for id in 0..N {
|
||||
// don't check for memory overflow here for optimization purposes
|
||||
// assuming that caller site work well
|
||||
self.memory_view[offset + id].set(values[id]);
|
||||
}
|
||||
|
||||
self.offset.set(offset + values.len());
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
|
@ -14,93 +14,6 @@ use crate::{
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
/*
|
||||
/// Build an `IValue::Record` based on values on the stack.
|
||||
///
|
||||
/// To fill a record, every field `field_1` to `field_n` must get its
|
||||
/// value from the stack with `value_1` to `value_n`. It is not
|
||||
/// possible to use `Stack::pop` because the one-pass algorithm does
|
||||
/// not know exactly the number of values to read from the stack
|
||||
/// ahead-of-time, so `Stack::pop1` is used. It implies that values
|
||||
/// are read one after the other from the stack, in a natural reverse
|
||||
/// order, from `value_n` to `value_1`. Thus, the `values` vector must
|
||||
/// be filled from the end to the beginning. It is not safely possible
|
||||
/// to fill the `values` vector with empty values though (so that it
|
||||
/// is possible to access to last positions). So a `VecDeque` type is
|
||||
/// used: it is a double-ended queue.
|
||||
fn record_lift_(
|
||||
stack: &mut Stack<IValue>,
|
||||
record_type: &RecordType,
|
||||
) -> Result<IValue, InstructionErrorKind> {
|
||||
let length = record_type.fields.len();
|
||||
let mut values = VecDeque::with_capacity(length);
|
||||
for field in record_type.fields.iter().rev() {
|
||||
match field {
|
||||
IType::Record(record_type) => {
|
||||
values.push_front(record_lift_(stack, &record_type)?)
|
||||
}
|
||||
ty => {
|
||||
let value = stack.pop1().unwrap();
|
||||
let value_type = (&value).into();
|
||||
if ty != &value_type {
|
||||
return Err(InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: ty.clone(),
|
||||
received_type: value_type,
|
||||
});
|
||||
}
|
||||
values.push_front(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(IValue::Record(
|
||||
NEVec::new(values.into_iter().collect())
|
||||
.expect("Record must have at least one field, zero given"),
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn record_lift<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
type_index: u32,
|
||||
instruction: Instruction,
|
||||
) -> 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<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;
|
||||
Box::new({
|
||||
move |runtime| -> _ {
|
||||
let instance = &runtime.wasm_instance;
|
||||
let record_type = match instance.wit_type(type_index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::TypeIsMissing { type_index },
|
||||
)
|
||||
})? {
|
||||
Type::Record(record_type) => record_type,
|
||||
Type::Function { .. } => {
|
||||
return Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidTypeKind {
|
||||
expected_kind: TypeKind::Record,
|
||||
received_kind: TypeKind::Function,
|
||||
},
|
||||
))
|
||||
}
|
||||
};
|
||||
let record = record_lift_(&mut runtime.stack, &record_type)
|
||||
.map_err(|k| InstructionError::new(instruction.clone(), k))?;
|
||||
runtime.stack.push(record);
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
pub(super) fn record_lift_memory_<'instance, Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
instance: &'instance Instance,
|
||||
record_type: &IRecordType,
|
||||
@ -115,33 +28,18 @@ where
|
||||
Instance: crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>
|
||||
+ 'instance,
|
||||
{
|
||||
fn record_size(record_type: &IRecordType) -> usize {
|
||||
let mut record_size = 0;
|
||||
|
||||
for field_type in record_type.fields.iter() {
|
||||
let params_count = match field_type.ty {
|
||||
IType::String | IType::Array(_) => 2,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
record_size += std::mem::size_of::<u64>() * params_count;
|
||||
}
|
||||
|
||||
record_size
|
||||
}
|
||||
|
||||
let length = record_type.fields.len();
|
||||
let mut values = Vec::with_capacity(length);
|
||||
let size = record_size(record_type);
|
||||
let data = read_from_instance_mem(instance, instruction.clone(), offset, size)?;
|
||||
// TODO: add error handling
|
||||
let data =
|
||||
safe_transmute::transmute_many::<u64, safe_transmute::SingleManyGuard>(&data).unwrap();
|
||||
|
||||
let mut field_id = 0;
|
||||
for field in (*record_type.fields).iter() {
|
||||
let value = data[field_id];
|
||||
match &field.ty {
|
||||
IType::Boolean => {
|
||||
values.push(IValue::Boolean(value as _));
|
||||
}
|
||||
IType::S8 => {
|
||||
values.push(IValue::S8(value as _));
|
||||
}
|
||||
@ -202,7 +100,7 @@ where
|
||||
let array_size = data[field_id];
|
||||
|
||||
if array_size != 0 {
|
||||
let array = super::array_lift_memory_(
|
||||
let array = super::array_lift_memory_impl(
|
||||
instance,
|
||||
&**ty,
|
||||
array_offset as _,
|
||||
@ -243,6 +141,29 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns record size in bytes.
|
||||
fn record_size(record_type: &IRecordType) -> usize {
|
||||
let mut record_size = 0;
|
||||
|
||||
for field_type in record_type.fields.iter() {
|
||||
record_size += match field_type.ty {
|
||||
IType::Boolean | IType::S8 | IType::U8 => 1,
|
||||
IType::S16 | IType::U16 => 2,
|
||||
IType::S32
|
||||
| IType::U32
|
||||
| IType::I32
|
||||
| IType::F32
|
||||
| IType::String
|
||||
| IType::ByteArray
|
||||
| IType::Array(_)
|
||||
| IType::Record(_) => 32,
|
||||
IType::S64 | IType::U64 | IType::I64 | IType::F64 => 64,
|
||||
};
|
||||
}
|
||||
|
||||
record_size
|
||||
}
|
||||
|
||||
pub(crate) fn record_lift_memory<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
record_type_id: u64,
|
||||
instruction: Instruction,
|
||||
@ -310,53 +231,53 @@ where
|
||||
Instance:
|
||||
crate::interpreter::wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let mut result: Vec<u64> = Vec::with_capacity(values.len());
|
||||
let mut result: Vec<u8> = Vec::with_capacity(values.len());
|
||||
|
||||
for value in values.into_vec() {
|
||||
match value {
|
||||
IValue::Boolean(value) => result.push(value as _),
|
||||
IValue::S8(value) => result.push(value as _),
|
||||
IValue::S16(value) => result.push(value as _),
|
||||
IValue::S32(value) => result.push(value as _),
|
||||
IValue::S64(value) => result.push(value as _),
|
||||
IValue::U8(value) => result.push(value as _),
|
||||
IValue::U16(value) => result.push(value as _),
|
||||
IValue::U32(value) => result.push(value as _),
|
||||
IValue::U64(value) => result.push(value as _),
|
||||
IValue::I32(value) => result.push(value as _),
|
||||
IValue::I64(value) => result.push(value as _),
|
||||
IValue::F32(value) => result.push(value as _),
|
||||
IValue::F64(value) => result.push(value.to_bits()),
|
||||
IValue::S16(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::S32(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::S64(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::U8(value) => result.push(value),
|
||||
IValue::U16(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::U32(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::U64(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::I32(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
IValue::I64(value) => result.extend_from_slice(&value.to_le_bytes()),
|
||||
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 string_pointer = if !value.is_empty() {
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let string_pointer =
|
||||
write_to_instance_mem(instance, instruction.clone(), value.as_bytes())?;
|
||||
|
||||
result.push(string_pointer as _);
|
||||
result.push(value.len() as _);
|
||||
result.extend_from_slice(&string_pointer.to_le_bytes());
|
||||
result.extend_from_slice(&value.len().to_le_bytes());
|
||||
}
|
||||
IValue::ByteArray(value) => {
|
||||
let array_pointer = write_to_instance_mem(instance, instruction.clone(), &value)?;
|
||||
|
||||
result.extend_from_slice(&array_pointer.to_le_bytes());
|
||||
result.extend_from_slice(&value.len().to_le_bytes());
|
||||
}
|
||||
|
||||
IValue::Array(values) => {
|
||||
let (offset, size) = if !values.is_empty() {
|
||||
super::array_lower_memory_(instance, instruction.clone(), values)?
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
let (offset, size) =
|
||||
super::array_lower_memory_impl(instance, instruction.clone(), values)?;
|
||||
|
||||
result.push(offset as _);
|
||||
result.push(size as _);
|
||||
result.extend_from_slice(&offset.to_le_bytes());
|
||||
result.extend_from_slice(&size.to_le_bytes());
|
||||
}
|
||||
|
||||
IValue::Record(values) => {
|
||||
let record_ptr = record_lower_memory_(instance, instruction.clone(), values)?;
|
||||
|
||||
result.push(record_ptr as _);
|
||||
result.extend_from_slice(&record_ptr.to_le_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = safe_transmute::transmute_to_bytes::<u64>(&result);
|
||||
let result_pointer = write_to_instance_mem(instance, instruction, &result)?;
|
||||
|
||||
Ok(result_pointer as _)
|
||||
@ -414,65 +335,3 @@ where
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
pub(crate) fn record_lower<Instance, Export, LocalImport, Memory, MemoryView>(
|
||||
type_index: u32,
|
||||
instruction: Instruction,
|
||||
) -> 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<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;
|
||||
Box::new({
|
||||
move |runtime| -> _ {
|
||||
let instance = &runtime.wasm_instance;
|
||||
let record_type = match instance.wit_type(type_index).ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::TypeIsMissing { type_index },
|
||||
)
|
||||
})? {
|
||||
Type::Record(record_type) => record_type,
|
||||
Type::Function { .. } => {
|
||||
return Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidTypeKind {
|
||||
expected_kind: TypeKind::Record,
|
||||
received_kind: TypeKind::Function,
|
||||
},
|
||||
))
|
||||
}
|
||||
};
|
||||
match runtime.stack.pop1() {
|
||||
Some(IValue::Record(record_values))
|
||||
if record_type == &(&*record_values).into() =>
|
||||
{
|
||||
let values = FlattenIValueIterator::new(&record_values);
|
||||
for value in values {
|
||||
runtime.stack.push(value.clone());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Some(value) => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::InvalidValueOnTheStack {
|
||||
expected_type: IType::Record(record_type.clone()),
|
||||
received_type: (&value).into(),
|
||||
},
|
||||
)),
|
||||
None => Err(InstructionError::new(
|
||||
instruction.clone(),
|
||||
InstructionErrorKind::StackIsTooSmall { needed: 1 },
|
||||
)),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
@ -19,10 +19,10 @@ executable_instruction!(
|
||||
)
|
||||
})?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_index = 0;
|
||||
let memory = runtime
|
||||
.wasm_instance
|
||||
.memory(memory_index as usize)
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
@ -96,9 +96,9 @@ executable_instruction!(
|
||||
})?;
|
||||
|
||||
let instance = &mut runtime.wasm_instance;
|
||||
let memory_index: u32 = 0;
|
||||
let memory_index = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
|
@ -24,9 +24,9 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
let memory_index: u32 = 0;
|
||||
let memory_index = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
@ -66,11 +66,15 @@ where
|
||||
MemoryView: wasm::structures::MemoryView,
|
||||
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
|
||||
{
|
||||
if bytes.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let offset = allocate(instance, instruction.clone(), bytes.len() as _)?;
|
||||
|
||||
let memory_index: u32 = 0;
|
||||
let memory_index = 0;
|
||||
let memory_view = instance
|
||||
.memory(memory_index as usize)
|
||||
.memory(memory_index)
|
||||
.ok_or_else(|| {
|
||||
InstructionError::new(
|
||||
instruction.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user