Skip to content

Commit

Permalink
implement table.init execution
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop committed Aug 22, 2023
1 parent 8d79f31 commit b46273c
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 9 deletions.
30 changes: 22 additions & 8 deletions crates/wasmi/src/engine/regmach/executor/instrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,28 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
Instr::TableCopyFromToExact { dst, src, len } => {
self.execute_table_copy_from_to_exact(dst, src, len)?
}
Instr::TableInit { dst, src, len } => todo!(),
Instr::TableInitTo { dst, src, len } => todo!(),
Instr::TableInitFrom { dst, src, len } => todo!(),
Instr::TableInitFromTo { dst, src, len } => todo!(),
Instr::TableInitExact { dst, src, len } => todo!(),
Instr::TableInitToExact { dst, src, len } => todo!(),
Instr::TableInitFromExact { dst, src, len } => todo!(),
Instr::TableInitFromToExact { dst, src, len } => todo!(),
Instr::TableInit { dst, src, len } => self.execute_table_init(dst, src, len)?,
Instr::TableInitTo { dst, src, len } => {
self.execute_table_init_to(dst, src, len)?
}
Instr::TableInitFrom { dst, src, len } => {
self.execute_table_init_from(dst, src, len)?
}
Instr::TableInitFromTo { dst, src, len } => {
self.execute_table_init_from_to(dst, src, len)?
}
Instr::TableInitExact { dst, src, len } => {
self.execute_table_init_exact(dst, src, len)?
}
Instr::TableInitToExact { dst, src, len } => {
self.execute_table_init_to_exact(dst, src, len)?
}
Instr::TableInitFromExact { dst, src, len } => {
self.execute_table_init_from_exact(dst, src, len)?
}
Instr::TableInitFromToExact { dst, src, len } => {
self.execute_table_init_from_to_exact(dst, src, len)?
}
Instr::TableFill { dst, len, value } => todo!(),
Instr::TableFillAt { dst, len, value } => todo!(),
Instr::TableFillExact { dst, len, value } => todo!(),
Expand Down
154 changes: 153 additions & 1 deletion crates/wasmi/src/engine/regmach/executor/instrs/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::Executor;
use crate::{
core::TrapCode,
engine::{
bytecode::TableIdx,
bytecode::{ElementSegmentIdx, TableIdx},
bytecode2::{Const16, Const32, Instruction, Register},
code_map::InstructionPtr2 as InstructionPtr,
},
Expand All @@ -20,6 +20,16 @@ impl<'engine, 'ctx> Executor<'engine, 'ctx> {
}
}

/// Returns the [`Instruction::ElementSegmentIdx`] parameter for an [`Instruction`].
fn fetch_element_segment_index(&self, offset: usize) -> ElementSegmentIdx {
let mut addr: InstructionPtr = self.ip;
addr.add(offset);
match *addr.get() {
Instruction::ElementSegmentIdx(segment_index) => segment_index,
_ => unreachable!("expected an Instruction::ElementSegmentIdx instruction word"),
}
}

/// Executes an [`Instruction::TableGet`].
#[inline(always)]
pub fn execute_table_get(&mut self, result: Register, index: Register) -> Result<(), TrapCode> {
Expand Down Expand Up @@ -237,4 +247,146 @@ impl<'engine, 'ctx> Executor<'engine, 'ctx> {
)?;
self.try_next_instr_at(3)
}

/// Executes an [`Instruction::TableInit`].
#[inline(always)]
pub fn execute_table_init(
&mut self,
dst: Register,
src: Register,
len: Register,
) -> Result<(), TrapCode> {
let dst: u32 = self.get_register_as(dst);
let src: u32 = self.get_register_as(src);
let len: u32 = self.get_register_as(len);
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitTo`].
#[inline(always)]
pub fn execute_table_init_to(
&mut self,
dst: Const16<u32>,
src: Register,
len: Register,
) -> Result<(), TrapCode> {
let dst: u32 = dst.into();
let src: u32 = self.get_register_as(src);
let len: u32 = self.get_register_as(len);
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitFrom`].
#[inline(always)]
pub fn execute_table_init_from(
&mut self,
dst: Register,
src: Const16<u32>,
len: Register,
) -> Result<(), TrapCode> {
let dst: u32 = self.get_register_as(dst);
let src: u32 = src.into();
let len: u32 = self.get_register_as(len);
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitFromTo`].
#[inline(always)]
pub fn execute_table_init_from_to(
&mut self,
dst: Const16<u32>,
src: Const16<u32>,
len: Register,
) -> Result<(), TrapCode> {
let dst: u32 = dst.into();
let src: u32 = src.into();
let len: u32 = self.get_register_as(len);
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitExact`].
#[inline(always)]
pub fn execute_table_init_exact(
&mut self,
dst: Register,
src: Register,
len: Const16<u32>,
) -> Result<(), TrapCode> {
let dst: u32 = self.get_register_as(dst);
let src: u32 = self.get_register_as(src);
let len: u32 = len.into();
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitToExact`].
#[inline(always)]
pub fn execute_table_init_to_exact(
&mut self,
dst: Const16<u32>,
src: Register,
len: Const16<u32>,
) -> Result<(), TrapCode> {
let dst: u32 = dst.into();
let src: u32 = self.get_register_as(src);
let len: u32 = len.into();
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitFromExact`].
#[inline(always)]
pub fn execute_table_init_from_exact(
&mut self,
dst: Register,
src: Const16<u32>,
len: Const16<u32>,
) -> Result<(), TrapCode> {
let dst: u32 = self.get_register_as(dst);
let src: u32 = src.into();
let len: u32 = len.into();
self.execute_table_init_impl(dst, src, len)
}

/// Executes an [`Instruction::TableInitFromToExact`].
#[inline(always)]
pub fn execute_table_init_from_to_exact(
&mut self,
dst: Const16<u32>,
src: Const16<u32>,
len: Const16<u32>,
) -> Result<(), TrapCode> {
let dst: u32 = dst.into();
let src: u32 = src.into();
let len: u32 = len.into();
self.execute_table_init_impl(dst, src, len)
}

/// Executes a generic `table.init` instruction.
fn execute_table_init_impl(
&mut self,
dst_index: u32,
src_index: u32,
len: u32,
) -> Result<(), TrapCode> {
if len == 0 {
// Case: copying no elements means there is nothing to do
return Ok(());
}
let table_index = self.fetch_table_index(1);
let element_index = self.fetch_element_segment_index(2);
self.consume_fuel_with(
|costs| costs.fuel_for_elements(u64::from(len)),
|this| {
let (instance, table, element) =
this.cache
.get_table_and_element_segment(this.ctx, table_index, element_index);
table.init(dst_index, element, src_index, len, |func_index| {
instance
.get_func(func_index)
.unwrap_or_else(|| panic!("missing function at index {func_index}"))
})?;
Ok(())
},
)?;
self.try_next_instr_at(3)
}
}

0 comments on commit b46273c

Please sign in to comment.