diff --git a/src/stack_limiter/max_height.rs b/src/stack_limiter/max_height.rs index 16dc165..055966d 100644 --- a/src/stack_limiter/max_height.rs +++ b/src/stack_limiter/max_height.rs @@ -5,6 +5,12 @@ use parity_wasm::elements::{self, BlockType, Type}; #[cfg(feature = "sign_ext")] 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. #[derive(Debug)] struct Frame { @@ -36,7 +42,7 @@ struct Stack { impl 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. @@ -431,7 +437,7 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 3); + assert_eq!(height, 3 + ACTIVATION_FRAME_COST); } #[test] @@ -448,7 +454,7 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 1); + assert_eq!(height, 1 + ACTIVATION_FRAME_COST); } #[test] @@ -466,7 +472,7 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 0); + assert_eq!(height, ACTIVATION_FRAME_COST); } #[test] @@ -501,7 +507,7 @@ mod tests { .expect("Failed to deserialize the module"); let height = compute(0, &module).unwrap(); - assert_eq!(height, 2); + assert_eq!(height, 2 + ACTIVATION_FRAME_COST); } #[test] @@ -525,7 +531,7 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 1); + assert_eq!(height, 1 + ACTIVATION_FRAME_COST); } #[test] @@ -547,7 +553,7 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 1); + assert_eq!(height, 1 + ACTIVATION_FRAME_COST); } #[test] @@ -573,6 +579,6 @@ mod tests { ); let height = compute(0, &module).unwrap(); - assert_eq!(height, 3); + assert_eq!(height, 3 + ACTIVATION_FRAME_COST); } } diff --git a/tests/diff.rs b/tests/diff.rs index fcaed5b..03425a2 100644 --- a/tests/diff.rs +++ b/tests/diff.rs @@ -92,6 +92,7 @@ mod stack_height { def_stack_height_test!(global); def_stack_height_test!(imports); def_stack_height_test!(many_locals); + def_stack_height_test!(empty_functions); } mod gas { diff --git a/tests/expectations/stack-height/empty_functions.wat b/tests/expectations/stack-height/empty_functions.wat new file mode 100644 index 0000000..20a71f4 --- /dev/null +++ b/tests/expectations/stack-height/empty_functions.wat @@ -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))) diff --git a/tests/expectations/stack-height/global.wat b/tests/expectations/stack-height/global.wat index 45b20c3..0289a50 100644 --- a/tests/expectations/stack-height/global.wat +++ b/tests/expectations/stack-height/global.wat @@ -17,7 +17,7 @@ local.get 1 local.get 0 global.get 1 - i32.const 2 + i32.const 4 i32.add global.set 1 global.get 1 @@ -28,7 +28,7 @@ end call 1 global.get 1 - i32.const 2 + i32.const 4 i32.sub global.set 1 drop) @@ -36,7 +36,7 @@ local.get 0 local.get 1 global.get 1 - i32.const 2 + i32.const 4 i32.add global.set 1 global.get 1 @@ -47,7 +47,7 @@ end call 1 global.get 1 - i32.const 2 + i32.const 4 i32.sub global.set 1) (global (;0;) (mut i32) (i32.const 1)) diff --git a/tests/expectations/stack-height/imports.wat b/tests/expectations/stack-height/imports.wat index eef8033..0098281 100644 --- a/tests/expectations/stack-height/imports.wat +++ b/tests/expectations/stack-height/imports.wat @@ -13,7 +13,7 @@ local.get 0 local.get 1 global.get 0 - i32.const 2 + i32.const 4 i32.add global.set 0 global.get 0 @@ -24,7 +24,7 @@ end call 2 global.get 0 - i32.const 2 + i32.const 4 i32.sub global.set 0) (global (;0;) (mut i32) (i32.const 0)) diff --git a/tests/expectations/stack-height/many_locals.wat b/tests/expectations/stack-height/many_locals.wat index e5fee38..c3202f7 100644 --- a/tests/expectations/stack-height/many_locals.wat +++ b/tests/expectations/stack-height/many_locals.wat @@ -4,7 +4,7 @@ (local i64 i64 i32)) (func (;1;) (type 0) global.get 0 - i32.const 3 + i32.const 5 i32.add global.set 0 global.get 0 @@ -15,7 +15,7 @@ end call 0 global.get 0 - i32.const 3 + i32.const 5 i32.sub global.set 0) (global (;0;) (mut i32) (i32.const 0))) diff --git a/tests/expectations/stack-height/simple.wat b/tests/expectations/stack-height/simple.wat index e44e7d5..6d1568f 100644 --- a/tests/expectations/stack-height/simple.wat +++ b/tests/expectations/stack-height/simple.wat @@ -5,7 +5,7 @@ drop) (func (;1;) (type 0) global.get 0 - i32.const 1 + i32.const 3 i32.add global.set 0 global.get 0 @@ -16,7 +16,7 @@ end call 0 global.get 0 - i32.const 1 + i32.const 3 i32.sub global.set 0) (global (;0;) (mut i32) (i32.const 0)) diff --git a/tests/expectations/stack-height/start.wat b/tests/expectations/stack-height/start.wat index 7a3e905..87e7ecb 100644 --- a/tests/expectations/stack-height/start.wat +++ b/tests/expectations/stack-height/start.wat @@ -8,7 +8,7 @@ (func (;2;) (type 1)) (func (;3;) (type 1) global.get 0 - i32.const 1 + i32.const 3 i32.add global.set 0 global.get 0 @@ -19,10 +19,25 @@ end call 1 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 global.set 0) (global (;0;) (mut i32) (i32.const 0)) - (export "exported_start" (func 3)) - (export "call" (func 2)) + (export "call" (func 4)) (start 3)) diff --git a/tests/expectations/stack-height/table.wat b/tests/expectations/stack-height/table.wat index 3b05d18..b345a5d 100644 --- a/tests/expectations/stack-height/table.wat +++ b/tests/expectations/stack-height/table.wat @@ -7,7 +7,7 @@ local.get 0 i32.const 0 global.get 0 - i32.const 2 + i32.const 4 i32.add global.set 0 global.get 0 @@ -18,7 +18,7 @@ end call 2 global.get 0 - i32.const 2 + i32.const 4 i32.sub global.set 0 drop) @@ -29,7 +29,7 @@ (func (;3;) (type 1) (param i32) local.get 0 global.get 0 - i32.const 2 + i32.const 4 i32.add global.set 0 global.get 0 @@ -40,14 +40,14 @@ end call 1 global.get 0 - i32.const 2 + i32.const 4 i32.sub global.set 0) (func (;4;) (type 2) (param i32 i32) (result i32) local.get 0 local.get 1 global.get 0 - i32.const 2 + i32.const 4 i32.add global.set 0 global.get 0 @@ -58,7 +58,7 @@ end call 2 global.get 0 - i32.const 2 + i32.const 4 i32.sub global.set 0) (table (;0;) 10 funcref) diff --git a/tests/fixtures/stack-height/empty_functions.wat b/tests/fixtures/stack-height/empty_functions.wat new file mode 100644 index 0000000..90c04b5 --- /dev/null +++ b/tests/fixtures/stack-height/empty_functions.wat @@ -0,0 +1,8 @@ +(module + (func (;0;) + call 0 + ) + (func (;1;) (export "main") + call 0 + ) +) \ No newline at end of file diff --git a/tests/fixtures/stack-height/global.wat b/tests/fixtures/stack-height/global.wat index bf0d600..64d978c 100644 --- a/tests/fixtures/stack-height/global.wat +++ b/tests/fixtures/stack-height/global.wat @@ -6,8 +6,8 @@ (func $i32.add (export "i32.add") (param i32 i32) (result i32) get_local 0 - get_local 1 - i32.add + get_local 1 + i32.add ) (func (param $arg i32) (local $tmp i32) @@ -15,7 +15,7 @@ global.get 0 i32.const 1 i32.add - tee_local $tmp + tee_local $tmp global.set $counter get_local $tmp diff --git a/tests/fixtures/stack-height/start.wat b/tests/fixtures/stack-height/start.wat index 595bdef..f8a560f 100644 --- a/tests/fixtures/stack-height/start.wat +++ b/tests/fixtures/stack-height/start.wat @@ -3,7 +3,7 @@ (import "env" "memory" (memory 1 1)) (start $start) - (func $start (export "exported_start") + (func $start (local i32) ) (func (export "call") diff --git a/tests/fixtures/stack-height/table.wat b/tests/fixtures/stack-height/table.wat index f17acdd..3911362 100644 --- a/tests/fixtures/stack-height/table.wat +++ b/tests/fixtures/stack-height/table.wat @@ -1,15 +1,15 @@ (module (import "env" "foo" (func $foo)) (func (param i32) - get_local 0 - i32.const 0 - call $i32.add - drop + get_local 0 + i32.const 0 + call $i32.add + drop ) (func $i32.add (export "i32.add") (param i32 i32) (result i32) get_local 0 - get_local 1 - i32.add + get_local 1 + i32.add ) (table 10 anyfunc)