6 Commits

Author SHA1 Message Date
Dmitry Sinyavin 10fd3529f2 Add conditional br count 2022-08-22 18:36:42 +02:00
Dmitry Sinyavin 32ae9f8478 Additional metrics 2022-08-19 12:24:52 +02:00
Dmitry Sinyavin 8bfdb41d01 Return detailed stats 2022-08-09 16:01:05 +02:00
Dmitry Sinyavin 659d3bf12c Reworked stack computation 2022-08-04 21:47:32 +02:00
Dmitry Sinyavin 5b2f75a066 Fix param count and rearrange code 2022-08-02 19:29:06 +02:00
dependabot[bot] 25ff883bbd Update wasmparser requirement from 0.87 to 0.88 (#26)
Updates the requirements on [wasmparser](https://github.com/bytecodealliance/wasm-tools) to permit the latest version.
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/compare/wasmparser-0.87.0...wasmparser-0.88.0)

---
updated-dependencies:
- dependency-name: wasmparser
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-30 17:39:07 +02:00
4 changed files with 415 additions and 487 deletions
+2 -5
View File
@@ -22,9 +22,7 @@ codegen-units = 1
[dependencies]
parity-wasm = { version = "0.45", default-features = false }
log = { version = "0.4.8", default-features = false, optional = true }
test-log = { version = "0.2", optional = true }
env_logger = { version = "0.9", optional = true }
log = "0.4"
[dev-dependencies]
binaryen = "0.12"
@@ -32,11 +30,10 @@ criterion = "0.3"
diff = "0.1"
rand = "0.8"
wat = "1"
wasmparser = "0.87"
wasmparser = "0.88"
wasmprinter = "0.2"
[features]
default = ["std"]
std = ["parity-wasm/std"]
sign_ext = ["parity-wasm/sign_ext"]
trace-log = ["dep:log", "dep:test-log", "dep:env_logger"]
+3 -3
View File
@@ -1,6 +1,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[macro_use]
extern crate log;
mod export_globals;
pub mod gas_metering;
@@ -8,6 +10,4 @@ mod stack_limiter;
pub use export_globals::export_mutable_globals;
pub use parity_wasm;
pub use stack_limiter::{
compute_stack_cost, compute_stack_height_weight, inject as inject_stack_limiter,
};
pub use stack_limiter::{compute_stack_cost, inject as inject_stack_limiter};
File diff suppressed because it is too large Load Diff
+10 -36
View File
@@ -6,6 +6,7 @@ use parity_wasm::{
builder,
elements::{self, Instruction, Instructions, Type},
};
pub use max_height::StackHeightStats;
/// Macro to generate preamble and postamble.
macro_rules! instrument_call {
@@ -40,7 +41,7 @@ mod thunk;
pub struct Context {
stack_height_global_idx: u32,
func_stack_costs: Vec<u32>,
func_stack_costs: Vec<StackHeightStats>,
stack_limit: u32,
}
@@ -52,7 +53,11 @@ impl Context {
/// Returns `stack_cost` for `func_idx`.
fn stack_cost(&self, func_idx: u32) -> Option<u32> {
self.func_stack_costs.get(func_idx as usize).cloned()
if let Some(stats) = self.func_stack_costs.get(func_idx as usize) {
Some(stats.total_cost)
} else {
None
}
}
/// Returns stack limit specified by the rules.
@@ -154,7 +159,7 @@ fn generate_stack_height_global(module: &mut elements::Module) -> u32 {
/// Calculate stack costs for all functions.
///
/// Returns a vector with a stack cost for each function, including imports.
pub fn compute_stack_costs(module: &elements::Module) -> Result<Vec<u32>, &'static str> {
fn compute_stack_costs(module: &elements::Module) -> Result<Vec<StackHeightStats>, &'static str> {
let func_imports = module.import_count(elements::ImportCountType::Function);
// TODO: optimize!
@@ -162,7 +167,7 @@ pub fn compute_stack_costs(module: &elements::Module) -> Result<Vec<u32>, &'stat
.map(|func_idx| {
if func_idx < func_imports {
// We can't calculate stack_cost of the import functions.
Ok(0)
Ok(Default::default())
} else {
compute_stack_cost(func_idx as u32, module)
}
@@ -173,7 +178,7 @@ pub fn compute_stack_costs(module: &elements::Module) -> Result<Vec<u32>, &'stat
/// Stack cost of the given *defined* function is the sum of it's locals count (that is,
/// number of arguments plus number of local variables) and the maximal stack
/// height.
pub fn compute_stack_cost(func_idx: u32, module: &elements::Module) -> Result<u32, &'static str> {
pub fn compute_stack_cost(func_idx: u32, module: &elements::Module) -> Result<StackHeightStats, &'static str> {
// To calculate the cost of a function we need to convert index from
// function index space to defined function spaces.
let func_imports = module.import_count(elements::ImportCountType::Function) as u32;
@@ -181,37 +186,6 @@ pub fn compute_stack_cost(func_idx: u32, module: &elements::Module) -> Result<u3
.checked_sub(func_imports)
.ok_or("This should be a index of a defined function")?;
let code_section =
module.code_section().ok_or("Due to validation code section should exists")?;
let body = &code_section
.bodies()
.get(defined_func_idx as usize)
.ok_or("Function body is out of bounds")?;
let mut locals_count: u32 = 0;
for local_group in body.locals() {
locals_count =
locals_count.checked_add(local_group.count()).ok_or("Overflow in local count")?;
}
let (max_stack_height, _max_stack_weight) = max_height::compute(defined_func_idx, module)?;
locals_count
.checked_add(max_stack_height)
.ok_or("Overflow in adding locals_count and max_stack_height")
}
/// Stack height is the measurement maximum wasm stack height reached during function execution.
/// Stack weight is weighted value which approximates a real stack size on x64 architecture.
pub fn compute_stack_height_weight(
func_idx: u32,
module: &elements::Module,
) -> Result<(u32, u32), &'static str> {
let func_imports = module.import_count(elements::ImportCountType::Function) as u32;
let defined_func_idx = func_idx
.checked_sub(func_imports)
.ok_or("This should be a index of a defined function")?;
max_height::compute(defined_func_idx, module)
}