mirror of
https://github.com/pezkuwichain/wasm-instrument.git
synced 2026-06-13 09:21:11 +00:00
Consider activation frame for stack height metering (#2)
* Charge a base cost for calling a function * Added regression test for empty functions * Satisfy clippy
This commit is contained in:
committed by
GitHub
parent
4e3e6b598a
commit
57da96fb50
@@ -5,6 +5,12 @@ use parity_wasm::elements::{self, BlockType, Type};
|
|||||||
#[cfg(feature = "sign_ext")]
|
#[cfg(feature = "sign_ext")]
|
||||||
use parity_wasm::elements::SignExtInstruction;
|
use parity_wasm::elements::SignExtInstruction;
|
||||||
|
|
||||||
|
// The cost in stack items that should be charged per call of a function. This is
|
||||||
|
// is a static cost that is added to each function call. This makes sense because even
|
||||||
|
// if a function does not use any parameters or locals some stack space on the host
|
||||||
|
// machine might be consumed to hold some context.
|
||||||
|
const ACTIVATION_FRAME_COST: u32 = 2;
|
||||||
|
|
||||||
/// Control stack frame.
|
/// Control stack frame.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Frame {
|
struct Frame {
|
||||||
@@ -36,7 +42,7 @@ struct Stack {
|
|||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
fn new() -> Stack {
|
fn new() -> Stack {
|
||||||
Stack { height: 0, control_stack: Vec::new() }
|
Stack { height: ACTIVATION_FRAME_COST, control_stack: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns current height of the value stack.
|
/// Returns current height of the value stack.
|
||||||
@@ -431,7 +437,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 3);
|
assert_eq!(height, 3 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -448,7 +454,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 1);
|
assert_eq!(height, 1 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -466,7 +472,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 0);
|
assert_eq!(height, ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -501,7 +507,7 @@ mod tests {
|
|||||||
.expect("Failed to deserialize the module");
|
.expect("Failed to deserialize the module");
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 2);
|
assert_eq!(height, 2 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -525,7 +531,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 1);
|
assert_eq!(height, 1 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -547,7 +553,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 1);
|
assert_eq!(height, 1 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -573,6 +579,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let height = compute(0, &module).unwrap();
|
let height = compute(0, &module).unwrap();
|
||||||
assert_eq!(height, 3);
|
assert_eq!(height, 3 + ACTIVATION_FRAME_COST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ mod stack_height {
|
|||||||
def_stack_height_test!(global);
|
def_stack_height_test!(global);
|
||||||
def_stack_height_test!(imports);
|
def_stack_height_test!(imports);
|
||||||
def_stack_height_test!(many_locals);
|
def_stack_height_test!(many_locals);
|
||||||
|
def_stack_height_test!(empty_functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod gas {
|
mod gas {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
(module
|
||||||
|
(type (;0;) (func))
|
||||||
|
(func (;0;) (type 0)
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.add
|
||||||
|
global.set 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 1024
|
||||||
|
i32.gt_u
|
||||||
|
if ;; label = @1
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.sub
|
||||||
|
global.set 0)
|
||||||
|
(func (;1;) (type 0)
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.add
|
||||||
|
global.set 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 1024
|
||||||
|
i32.gt_u
|
||||||
|
if ;; label = @1
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.sub
|
||||||
|
global.set 0)
|
||||||
|
(func (;2;) (type 0)
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.add
|
||||||
|
global.set 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 1024
|
||||||
|
i32.gt_u
|
||||||
|
if ;; label = @1
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call 1
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.sub
|
||||||
|
global.set 0)
|
||||||
|
(global (;0;) (mut i32) (i32.const 0))
|
||||||
|
(export "main" (func 2)))
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
local.get 1
|
local.get 1
|
||||||
local.get 0
|
local.get 0
|
||||||
global.get 1
|
global.get 1
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 1
|
global.set 1
|
||||||
global.get 1
|
global.get 1
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
end
|
end
|
||||||
call 1
|
call 1
|
||||||
global.get 1
|
global.get 1
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 1
|
global.set 1
|
||||||
drop)
|
drop)
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
local.get 0
|
local.get 0
|
||||||
local.get 1
|
local.get 1
|
||||||
global.get 1
|
global.get 1
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 1
|
global.set 1
|
||||||
global.get 1
|
global.get 1
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
end
|
end
|
||||||
call 1
|
call 1
|
||||||
global.get 1
|
global.get 1
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 1)
|
global.set 1)
|
||||||
(global (;0;) (mut i32) (i32.const 1))
|
(global (;0;) (mut i32) (i32.const 1))
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
local.get 0
|
local.get 0
|
||||||
local.get 1
|
local.get 1
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
end
|
end
|
||||||
call 2
|
call 2
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(global (;0;) (mut i32) (i32.const 0))
|
(global (;0;) (mut i32) (i32.const 0))
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
(local i64 i64 i32))
|
(local i64 i64 i32))
|
||||||
(func (;1;) (type 0)
|
(func (;1;) (type 0)
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 3
|
i32.const 5
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
end
|
end
|
||||||
call 0
|
call 0
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 3
|
i32.const 5
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(global (;0;) (mut i32) (i32.const 0)))
|
(global (;0;) (mut i32) (i32.const 0)))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
drop)
|
drop)
|
||||||
(func (;1;) (type 0)
|
(func (;1;) (type 0)
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 1
|
i32.const 3
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
end
|
end
|
||||||
call 0
|
call 0
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 1
|
i32.const 3
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(global (;0;) (mut i32) (i32.const 0))
|
(global (;0;) (mut i32) (i32.const 0))
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
(func (;2;) (type 1))
|
(func (;2;) (type 1))
|
||||||
(func (;3;) (type 1)
|
(func (;3;) (type 1)
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 1
|
i32.const 3
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -19,10 +19,25 @@
|
|||||||
end
|
end
|
||||||
call 1
|
call 1
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 1
|
i32.const 3
|
||||||
|
i32.sub
|
||||||
|
global.set 0)
|
||||||
|
(func (;4;) (type 1)
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
|
i32.add
|
||||||
|
global.set 0
|
||||||
|
global.get 0
|
||||||
|
i32.const 1024
|
||||||
|
i32.gt_u
|
||||||
|
if ;; label = @1
|
||||||
|
unreachable
|
||||||
|
end
|
||||||
|
call 2
|
||||||
|
global.get 0
|
||||||
|
i32.const 2
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(global (;0;) (mut i32) (i32.const 0))
|
(global (;0;) (mut i32) (i32.const 0))
|
||||||
(export "exported_start" (func 3))
|
(export "call" (func 4))
|
||||||
(export "call" (func 2))
|
|
||||||
(start 3))
|
(start 3))
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
local.get 0
|
local.get 0
|
||||||
i32.const 0
|
i32.const 0
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
end
|
end
|
||||||
call 2
|
call 2
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0
|
global.set 0
|
||||||
drop)
|
drop)
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
(func (;3;) (type 1) (param i32)
|
(func (;3;) (type 1) (param i32)
|
||||||
local.get 0
|
local.get 0
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -40,14 +40,14 @@
|
|||||||
end
|
end
|
||||||
call 1
|
call 1
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(func (;4;) (type 2) (param i32 i32) (result i32)
|
(func (;4;) (type 2) (param i32 i32) (result i32)
|
||||||
local.get 0
|
local.get 0
|
||||||
local.get 1
|
local.get 1
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
global.set 0
|
global.set 0
|
||||||
global.get 0
|
global.get 0
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
end
|
end
|
||||||
call 2
|
call 2
|
||||||
global.get 0
|
global.get 0
|
||||||
i32.const 2
|
i32.const 4
|
||||||
i32.sub
|
i32.sub
|
||||||
global.set 0)
|
global.set 0)
|
||||||
(table (;0;) 10 funcref)
|
(table (;0;) 10 funcref)
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
(module
|
||||||
|
(func (;0;)
|
||||||
|
call 0
|
||||||
|
)
|
||||||
|
(func (;1;) (export "main")
|
||||||
|
call 0
|
||||||
|
)
|
||||||
|
)
|
||||||
+3
-3
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
(func $i32.add (export "i32.add") (param i32 i32) (result i32)
|
(func $i32.add (export "i32.add") (param i32 i32) (result i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
get_local 1
|
get_local 1
|
||||||
i32.add
|
i32.add
|
||||||
)
|
)
|
||||||
(func (param $arg i32)
|
(func (param $arg i32)
|
||||||
(local $tmp i32)
|
(local $tmp i32)
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
global.get 0
|
global.get 0
|
||||||
i32.const 1
|
i32.const 1
|
||||||
i32.add
|
i32.add
|
||||||
tee_local $tmp
|
tee_local $tmp
|
||||||
global.set $counter
|
global.set $counter
|
||||||
|
|
||||||
get_local $tmp
|
get_local $tmp
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
(import "env" "memory" (memory 1 1))
|
(import "env" "memory" (memory 1 1))
|
||||||
|
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $start (export "exported_start")
|
(func $start
|
||||||
(local i32)
|
(local i32)
|
||||||
)
|
)
|
||||||
(func (export "call")
|
(func (export "call")
|
||||||
|
|||||||
+6
-6
@@ -1,15 +1,15 @@
|
|||||||
(module
|
(module
|
||||||
(import "env" "foo" (func $foo))
|
(import "env" "foo" (func $foo))
|
||||||
(func (param i32)
|
(func (param i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
i32.const 0
|
i32.const 0
|
||||||
call $i32.add
|
call $i32.add
|
||||||
drop
|
drop
|
||||||
)
|
)
|
||||||
(func $i32.add (export "i32.add") (param i32 i32) (result i32)
|
(func $i32.add (export "i32.add") (param i32 i32) (result i32)
|
||||||
get_local 0
|
get_local 0
|
||||||
get_local 1
|
get_local 1
|
||||||
i32.add
|
i32.add
|
||||||
)
|
)
|
||||||
(table 10 anyfunc)
|
(table 10 anyfunc)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user