summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorHenry Gressmann <mail@henrygressmann.de>2024-01-27 02:40:08 +0100
committerHenry Gressmann <mail@henrygressmann.de>2024-01-27 02:40:08 +0100
commit9d30a1b0d93b45c05f86e61df77359303aab449d (patch)
treea2a0e84ff5e548143593c84396908e2745726d85 /crates
parenta89f75ce42f83de09bad72c1baf697a007751b1b (diff)
pref: callstack/callframe improvements
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
Diffstat (limited to 'crates')
-rw-r--r--crates/parser/src/module.rs2
-rw-r--r--crates/tinywasm/src/runtime/interpreter/mod.rs3
-rw-r--r--crates/tinywasm/src/runtime/stack/blocks.rs5
-rw-r--r--crates/tinywasm/src/runtime/stack/call_stack.rs29
-rw-r--r--crates/tinywasm/src/runtime/stack/value_stack.rs4
-rw-r--r--crates/types/src/instructions.rs6
-rw-r--r--crates/types/src/lib.rs12
7 files changed, 24 insertions, 37 deletions
diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs
index e0fb0cc..5bc6a7e 100644
--- a/crates/parser/src/module.rs
+++ b/crates/parser/src/module.rs
@@ -5,7 +5,7 @@ use core::fmt::Debug;
use tinywasm_types::{Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, ValType};
use wasmparser::{Payload, Validator};
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Clone)]
pub struct CodeSection {
pub locals: Box<[ValType]>,
pub body: Box<[Instruction]>,
diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs
index 80fb3f9..285ba8d 100644
--- a/crates/tinywasm/src/runtime/interpreter/mod.rs
+++ b/crates/tinywasm/src/runtime/interpreter/mod.rs
@@ -115,6 +115,7 @@ macro_rules! break_to {
/// Run a single step of the interpreter
/// A seperate function is used so later, we can more easily implement
/// a step-by-step debugger (using generators once they're stable?)
+// TODO: perf: don't push then pop the call frame, just pass it via ExecResult::Call instead
#[inline(always)] // this improves performance by more than 20% in some cases
fn exec_one(
cf: &mut CallFrame,
@@ -611,7 +612,7 @@ fn exec_one(
let elem_idx = module.resolve_elem_addr(*elem_index);
let elem = store.get_elem(elem_idx as usize)?;
- if elem.kind != ElementKind::Passive {
+ if let ElementKind::Passive = elem.kind {
return Err(Trap::TableOutOfBounds { offset: 0, len: 0, max: 0 }.into());
}
diff --git a/crates/tinywasm/src/runtime/stack/blocks.rs b/crates/tinywasm/src/runtime/stack/blocks.rs
index 76252b5..ab2d28c 100644
--- a/crates/tinywasm/src/runtime/stack/blocks.rs
+++ b/crates/tinywasm/src/runtime/stack/blocks.rs
@@ -19,11 +19,6 @@ impl Labels {
#[inline]
/// get the label at the given index, where 0 is the top of the stack
pub(crate) fn get_relative_to_top(&self, index: usize) -> Option<&LabelFrame> {
- let len = self.0.len();
- if index >= len {
- return None;
- }
-
self.0.get(self.0.len() - index - 1)
}
diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs
index b19e332..46c745a 100644
--- a/crates/tinywasm/src/runtime/stack/call_stack.rs
+++ b/crates/tinywasm/src/runtime/stack/call_stack.rs
@@ -3,52 +3,45 @@ use crate::{
runtime::{BlockType, RawWasmValue},
Error, FunctionInstance, Result, Trap,
};
+use alloc::vec;
use alloc::{boxed::Box, rc::Rc, vec::Vec};
use tinywasm_types::{ValType, WasmValue};
use super::{blocks::Labels, LabelFrame};
// minimum call stack size
-const CALL_STACK_SIZE: usize = 128;
+const CALL_STACK_SIZE: usize = 256;
const CALL_STACK_MAX_SIZE: usize = 1024;
#[derive(Debug)]
pub(crate) struct CallStack {
stack: Vec<CallFrame>,
- top: usize,
}
impl Default for CallStack {
fn default() -> Self {
- Self { stack: Vec::with_capacity(CALL_STACK_SIZE), top: 0 }
+ Self { stack: Vec::with_capacity(CALL_STACK_SIZE) }
}
}
impl CallStack {
+ #[inline]
pub(crate) fn is_empty(&self) -> bool {
- self.top == 0
+ self.stack.is_empty()
}
+ #[inline]
pub(crate) fn pop(&mut self) -> Result<CallFrame> {
- assert!(self.top <= self.stack.len());
- if self.top == 0 {
- return Err(Error::CallStackEmpty);
- }
-
- self.top -= 1;
- Ok(self.stack.pop().unwrap())
+ self.stack.pop().ok_or_else(|| Error::CallStackEmpty)
}
#[inline]
pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> {
- assert!(self.top <= self.stack.len(), "stack is too small");
-
log::debug!("stack size: {}", self.stack.len());
if self.stack.len() >= CALL_STACK_MAX_SIZE {
return Err(Trap::CallStackOverflow.into());
}
- self.top += 1;
self.stack.push(call_frame);
Ok(())
}
@@ -79,7 +72,6 @@ impl CallFrame {
/// Break to a block at the given index (relative to the current frame)
/// Returns `None` if there is no block at the given index (e.g. if we need to return, this is handled by the caller)
pub(crate) fn break_to(&mut self, break_to_relative: u32, value_stack: &mut super::ValueStack) -> Option<()> {
- log::debug!("break_to_relative: {}", break_to_relative);
let break_to = self.labels.get_relative_to_top(break_to_relative as usize)?;
// instr_ptr points to the label instruction, but the next step
@@ -111,14 +103,15 @@ impl CallFrame {
Some(())
}
+ // TOOD: perf: this function is pretty hot
+ // Especially the two `extend` calls
pub(crate) fn new_raw(
func_instance_ptr: Rc<FunctionInstance>,
params: &[RawWasmValue],
local_types: Vec<ValType>,
) -> Self {
- let mut locals = Vec::with_capacity(local_types.len() + params.len());
- locals.extend(params.iter().cloned());
- locals.extend(local_types.iter().map(|_| RawWasmValue::default()));
+ let mut locals = vec![RawWasmValue::default(); local_types.len() + params.len()];
+ locals[..params.len()].copy_from_slice(params);
Self {
instr_ptr: 0,
diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs
index d36373b..e1c3107 100644
--- a/crates/tinywasm/src/runtime/stack/value_stack.rs
+++ b/crates/tinywasm/src/runtime/stack/value_stack.rs
@@ -98,9 +98,7 @@ impl ValueStack {
}
pub(crate) fn break_to(&mut self, new_stack_size: usize, result_count: usize) {
- let len = self.stack.len();
- self.stack.copy_within((len - result_count)..len, new_stack_size);
- self.stack.truncate(new_stack_size + result_count);
+ self.stack.drain(new_stack_size..(self.stack.len() - result_count));
}
#[inline]
diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs
index d5de50a..ba13979 100644
--- a/crates/types/src/instructions.rs
+++ b/crates/types/src/instructions.rs
@@ -10,7 +10,7 @@ pub enum BlockArgs {
}
/// Represents a memory immediate in a WebAssembly memory instruction.
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone)]
pub struct MemoryArg {
pub mem_addr: MemAddr,
pub align: u8,
@@ -23,7 +23,7 @@ type BrTableLen = usize;
type EndOffset = usize;
type ElseOffset = usize;
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy)]
pub enum ConstInstruction {
I32Const(i32),
I64Const(i64),
@@ -46,7 +46,7 @@ pub enum ConstInstruction {
/// This makes it easier to implement the label stack (we call it BlockFrameStack) iteratively.
///
/// See <https://webassembly.github.io/spec/core/binary/instructions.html>
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy)]
pub enum Instruction {
// Custom Instructions
BrLabel(LabelAddr),
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index 3729e1a..9af8e11 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -71,7 +71,7 @@ pub struct TinyWasmModule {
/// A WebAssembly value.
///
/// See <https://webassembly.github.io/spec/core/syntax/types.html#value-types>
-#[derive(Clone, PartialEq, Copy)]
+#[derive(Clone, Copy)]
pub enum WasmValue {
// Num types
/// A 32-bit integer.
@@ -253,7 +253,7 @@ impl WasmValue {
}
/// Type of a WebAssembly value.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValType {
/// A 32-bit integer.
I32,
@@ -380,13 +380,13 @@ pub struct Global {
pub init: ConstInstruction,
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub struct GlobalType {
pub mutable: bool,
pub ty: ValType,
}
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone)]
pub struct TableType {
pub element_type: ValType,
pub size_initial: u32,
@@ -406,7 +406,7 @@ impl TableType {
#[derive(Debug, Clone)]
/// Represents a memory's type.
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy)]
pub struct MemoryType {
pub arch: MemoryArch,
pub page_count_initial: u64,
@@ -480,7 +480,7 @@ pub struct Element {
pub ty: ValType,
}
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy)]
pub enum ElementKind {
Passive,
Active { table: TableAddr, offset: ConstInstruction },