Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
364 changes: 217 additions & 147 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ keywords = ["wasm", "webassembly", "interpreter", "vm"]
categories = ["wasm", "no-std", "virtualization"]

[dependencies]
wasmparser = { version = "0.100.1", package = "wasmparser-nostd", default-features = false }
wasmparser = { version = "=0.235.0", default-features = false, features = ["validate", "features"] }
hashbrown = { version = "0.15.2", features = ["alloc"] }
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
paste = { version = "1.0", default-features = false }
Expand All @@ -21,15 +21,16 @@ bincode = { version = "2.0.1", default-features = false, features = ["alloc", "d
num-traits = { version = "0.2", default-features = false }
bitvec = { version = "1.0.1", default-features = false, features = ["alloc"] }
libm = "0.2.1"
wasmtime = { git = "https://github.com/fluentlabs-xyz/wasmtime", branch = "devel", optional = true, features = ["disable-fpu", "cache"] }
wasmtime = { git = "https://github.com/fluentlabs-xyz/wasmtime", branch = "feat/gas-meter", optional = true, features = ["disable-fpu", "cache"] }
#wasmtime = { path = "../wasmtime/crates/wasmtime", optional = true, features = ["disable-fpu"] }
serde = { version = "1.0.219", features = ["derive"], optional = true }
smallvec = "1.15.0"
anyhow = { version = "1.0.98", default-features = false, optional = true }
directories = { version = "6.0.0", optional = true }
wasmi = { version = "0.47.0", default-features = false }
wasmi = { version = "0.48.0", default-features = false }
num-derive = "0.4.2"
once_cell = { version = "1.21.3", optional = true }
rwasm-gas-injector = { path = "./gas-injector" }

[dev-dependencies]
rand = "0.9.1"
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "fib"
name = "rwasm-benchmarks"
version = "0.1.0"
edition = "2021"

Expand Down
2 changes: 1 addition & 1 deletion benchmarks/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.PHONY: build
build:
RUSTFLAGS="-C link-arg=-zstack-size=0" cargo b --target=wasm32-unknown-unknown --release --no-default-features
cp ./target/wasm32-unknown-unknown/release/fib.wasm ./lib.wasm
cp ./target/wasm32-unknown-unknown/release/rwasm_benchmarks.wasm ./lib.wasm
wasm2wat ./lib.wasm > ./lib.wat || true
1 change: 1 addition & 0 deletions e2e/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
[dependencies]
rwasm = { path = "..", features = ["fpu"] }
anyhow = "1.0.71"
wasmparser = { version = "0.235.0", default-features = false, features = ["validate", "features"] }
wast = "=64.0"

[features]
Expand Down
41 changes: 9 additions & 32 deletions e2e/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
use super::{TestDescriptor, TestError, TestProfile, TestSpan};
use crate::handler::{
testing_context_syscall_handler,
TestingContext,
FUNC_ENTRYPOINT,
FUNC_PRINT,
FUNC_PRINT_F32,
FUNC_PRINT_F64,
FUNC_PRINT_I32,
FUNC_PRINT_I32_F32,
FUNC_PRINT_I64,
FUNC_PRINT_I64_F64,
testing_context_syscall_handler, TestingContext, FUNC_ENTRYPOINT, FUNC_PRINT, FUNC_PRINT_F32,
FUNC_PRINT_F64, FUNC_PRINT_I32, FUNC_PRINT_I32_F32, FUNC_PRINT_I64, FUNC_PRINT_I64_F64,
};
use anyhow::Result;
use rwasm::{
instruction_set,
split_i64_to_i32_arr,
CallStack,
CompilationConfig,
ExecutorConfig,
FuncType,
ImportLinker,
ImportLinkerEntity,
ImportName,
InstructionSet,
ModuleParser,
Opcode,
RwasmExecutor,
RwasmModule,
RwasmStore,
StateRouterConfig,
Store,
ValType,
Value,
ValueStack,
instruction_set, split_i64_to_i32_arr, CallStack, CompilationConfig, ExecutorConfig, FuncType,
ImportLinker, ImportLinkerEntity, ImportName, InstructionSet, ModuleParser, Opcode,
RwasmExecutor, RwasmModule, RwasmStore, StateRouterConfig, Store, ValType, Value, ValueStack,
F64,
};
use std::{cell::RefCell, collections::HashMap, rc::Rc};
Expand Down Expand Up @@ -410,8 +385,10 @@ impl TestContext<'_> {
let value = (hi << 32) | lo;
Value::F64(F64::from_bits(value))
}
ValType::FuncRef => Value::FuncRef(popped_value.into()),
ValType::ExternRef => Value::ExternRef(popped_value.into()),
ValType::Ref(wasmparser::RefType::FUNCREF) => Value::FuncRef(popped_value.into()),
ValType::Ref(wasmparser::RefType::EXTERNREF) => {
Value::ExternRef(popped_value.into())
}
_ => unreachable!("unsupported result type: {:?}", val_type),
};
}
Expand Down
8 changes: 1 addition & 7 deletions e2e/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ use wast::{
lexer::Lexer,
parser::ParseBuffer,
token::Span,
QuoteWat,
Wast,
WastDirective,
WastExecute,
WastInvoke,
WastRet,
Wat,
QuoteWat, Wast, WastDirective, WastExecute, WastInvoke, WastRet, Wat,
};

/// Runs the Wasm test spec identified by the given name.
Expand Down
13 changes: 13 additions & 0 deletions gas-injector/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "rwasm-gas-injector"
version = "0.1.0"
edition = "2021"

[dependencies]
wasmparser = { version = "0.235.0", default-features = false, features = ["validate", "features"] }
wasm-encoder = { version = "0.235.0", features = ["wasmparser"] }

[dev-dependencies]
wasmprinter = { version = "0.235.0", default-features = false }
wat = "1.230.0"
hex-literal = "1.0.0"
87 changes: 87 additions & 0 deletions gas-injector/src/cost_model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use crate::BASE_FUEL_COST;
use wasmparser::Operator;

#[derive(Debug, PartialEq, Eq)]
pub enum ShouldInject {
InjectCost(u64),
None,
}

pub trait CostModel {
fn cost_for(&self, op: &Operator) -> u64;
}

#[derive(Default)]
pub struct DefaultCostModel;

impl CostModel for DefaultCostModel {
fn cost_for(&self, op: &Operator) -> u64 {
use Operator::*;
match op {
// Control flow may create branches, but is generally inexpensive and
// free, so don't consume fuel.
// Note the lack of `if` since some
// cost is incurred with the conditional check.
Block { .. } | Loop { .. } | Unreachable | Return | Else | End => 0,

// Most other ops cost base
_ => BASE_FUEL_COST as u64,
}
}
}

/// GasMeter state (cumulative counter, threshold, cost model)
pub struct GasMeter<T: CostModel> {
gas_spent: u64,
model: T,
}

impl<T: CostModel + Default> Default for GasMeter<T> {
fn default() -> Self {
Self::new(Default::default())
}
}

impl<T: CostModel> GasMeter<T> {
pub fn new(model: T) -> Self {
Self {
gas_spent: 0,
model,
}
}

pub fn charge_gas_for(&mut self, op: &Operator) -> ShouldInject {
use Operator::*;
// List of control operators
let is_control = matches!(
op,
Unreachable
| Block { .. }
| Loop { .. }
| If { .. }
| Else
| End
| Br { .. }
| BrIf { .. }
| BrTable { .. }
| Return
| Call { .. }
| CallIndirect { .. }
| ReturnCall { .. }
| ReturnCallIndirect { .. }
);
let cost = self.model.cost_for(op);
self.gas_spent += cost;
if is_control && self.gas_spent > 0 {
let total = self.gas_spent;
self.gas_spent = 0;
ShouldInject::InjectCost(total)
} else {
ShouldInject::None
}
}

pub fn gas_spent(&self) -> u64 {
self.gas_spent
}
}
Loading