diff options
author | Alon Zakai <azakai@google.com> | 2020-03-04 13:21:39 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-04 13:21:39 -0800 |
commit | 57a81a04f7a49593438dcae4ca8cbad8e465dc2e (patch) | |
tree | 02f8732873e8ef2608a94610857e2fb13de813ca | |
parent | 2a0f6a513c6d6a99d16ca31de3e76a63b1490b4c (diff) | |
download | binaryen-57a81a04f7a49593438dcae4ca8cbad8e465dc2e.tar.gz binaryen-57a81a04f7a49593438dcae4ca8cbad8e465dc2e.tar.bz2 binaryen-57a81a04f7a49593438dcae4ca8cbad8e465dc2e.zip |
Expose asyncify state via a getter (#2679)
Normally, a wrapper has to track state separately to know when to
unwind/rewind and when to actually call import functions.
Exposing Asyncify state can help avoid this duplication and avoid
subtle bugs when internal and wrapper state get out of sync.
Since this is a tiny function and it's useful for any Asyncify
embedder, I've decided to expose it by default rather than hide behind an option.
13 files changed, 86 insertions, 4 deletions
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index a4ff5794b..c1cec4a36 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -127,7 +127,7 @@ // proper place, and the end to the proper end based on how much memory // you reserved. Note that asyncify will grow the stack up. // -// The pass will also create four functions that let you control unwinding +// The pass will also create five functions that let you control unwinding // and rewinding: // // * asyncify_start_unwind(data : i32): call this to start unwinding the @@ -150,6 +150,12 @@ // * asyncify_stop_rewind(): call this to note that rewinding has // concluded, and normal execution can resume. // +// * asyncify_get_state(): call this to get the current value of the +// internal "__asyncify_state" variable as described above. +// It can be used to distinguish between unwinding/rewinding and normal +// calls, so that you know when to start an asynchronous operation and +// when to propagate results back. +// // These four functions are exported so that you can call them from the // outside. If you want to manage things from inside the wasm, then you // couldn't have called them before they were created by this pass. To work @@ -269,6 +275,7 @@ namespace wasm { namespace { static const Name ASYNCIFY_STATE = "__asyncify_state"; +static const Name ASYNCIFY_GET_STATE = "asyncify_get_state"; static const Name ASYNCIFY_DATA = "__asyncify_data"; static const Name ASYNCIFY_START_UNWIND = "asyncify_start_unwind"; static const Name ASYNCIFY_STOP_UNWIND = "asyncify_stop_unwind"; @@ -1336,6 +1343,14 @@ private: makeFunction(ASYNCIFY_STOP_UNWIND, false, State::Normal); makeFunction(ASYNCIFY_START_REWIND, true, State::Rewinding); makeFunction(ASYNCIFY_STOP_REWIND, false, State::Normal); + + module->addFunction( + builder.makeFunction(ASYNCIFY_GET_STATE, + Signature(Type::none, Type::i32), + {}, + builder.makeGlobalGet(ASYNCIFY_STATE, Type::i32))); + module->addExport(builder.makeExport( + ASYNCIFY_GET_STATE, ASYNCIFY_GET_STATE, ExternalKind::Function)); } }; diff --git a/test/passes/asyncify.txt b/test/passes/asyncify.txt index 3c121c029..8e349a637 100644 --- a/test/passes/asyncify.txt +++ b/test/passes/asyncify.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 1 2) (global $sleeping (mut i32) (i32.const 0)) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -9,6 +10,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $do_sleep (; 0 ;) (local $0 i32) (local $1 i32) @@ -313,12 +315,15 @@ (unreachable) ) ) + (func $asyncify_get_state (; 10 ;) (result i32) + (global.get $__asyncify_state) + ) ) (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "import" (func $import)) (import "env" "import2" (func $import2 (result i32))) (import "env" "import3" (func $import3 (param i32))) @@ -329,6 +334,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local $1 i32) @@ -2648,10 +2654,14 @@ (unreachable) ) ) + (func $asyncify_get_state (; 23 ;) (result i32) + (global.get $__asyncify_state) + ) ) (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 1 1) (global $__asyncify_state (mut i32) (i32.const 0)) (global $__asyncify_data (mut i32) (i32.const 0)) @@ -2659,6 +2669,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $asyncify_start_unwind (; 0 ;) (param $0 i32) (global.set $__asyncify_state (i32.const 1) @@ -2729,4 +2740,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 4 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt b/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt index f5c1ed1c0..4c37eaa14 100644 --- a/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt +++ b/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt @@ -12,6 +12,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local $1 i32) @@ -497,4 +498,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 11 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt b/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt index 68359770d..aa8a7bd40 100644 --- a/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt +++ b/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "import" (func $import)) (memory $0 1 2) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -13,6 +14,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 1 ;) (; has Stack IR ;) (local $0 i32) (call $import) @@ -86,4 +88,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 5 ;) (; has Stack IR ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_mod-asyncify-never-unwind.txt b/test/passes/asyncify_mod-asyncify-never-unwind.txt index b0ba19de0..62e3b0f4d 100644 --- a/test/passes/asyncify_mod-asyncify-never-unwind.txt +++ b/test/passes/asyncify_mod-asyncify-never-unwind.txt @@ -12,6 +12,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local $1 i32) @@ -515,4 +516,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 11 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_mod-asyncify-never-unwind_O.txt b/test/passes/asyncify_mod-asyncify-never-unwind_O.txt index 2390d6e93..7b6fe717b 100644 --- a/test/passes/asyncify_mod-asyncify-never-unwind_O.txt +++ b/test/passes/asyncify_mod-asyncify-never-unwind_O.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "import" (func $import)) (memory $0 1 2) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -13,6 +14,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 1 ;) (; has Stack IR ;) (if (select @@ -101,4 +103,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 5 ;) (; has Stack IR ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_optimize-level=1.txt b/test/passes/asyncify_optimize-level=1.txt index 9922e4f41..b0eae1971 100644 --- a/test/passes/asyncify_optimize-level=1.txt +++ b/test/passes/asyncify_optimize-level=1.txt @@ -1,8 +1,8 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "import" (func $import)) (import "env" "import2" (func $import2 (result i32))) (import "env" "import3" (func $import3 (param i32))) @@ -13,6 +13,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local.set $0 @@ -1634,4 +1635,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 23 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-whitelist@waka.txt b/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-whitelist@waka.txt index 2df8ccae6..fe67c47a7 100644 --- a/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-whitelist@waka.txt +++ b/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-whitelist@waka.txt @@ -14,6 +14,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local.set $0 @@ -198,4 +199,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 11 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt b/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt index 538060f41..ed2870d7c 100644 --- a/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt +++ b/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "import" (func $import)) (memory $0 1 2) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -9,6 +10,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $foo (; 1 ;) (call $import) ) @@ -262,4 +264,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 10 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt b/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt index d38e97626..8c0d3c801 100644 --- a/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt +++ b/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt @@ -14,6 +14,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (call $import) ) @@ -262,4 +263,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 11 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt b/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt index 7b75800bd..88203a505 100644 --- a/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt +++ b/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt @@ -14,6 +14,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local $1 i32) @@ -545,4 +546,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 11 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt b/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt index a6a0a8b1d..69a555cf8 100644 --- a/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt +++ b/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 1 2) (global $sleeping (mut i32) (i32.const 0)) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -9,6 +10,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $do_sleep (; 0 ;) (local $0 i32) (local $1 i32) @@ -312,12 +314,15 @@ (unreachable) ) ) + (func $asyncify_get_state (; 10 ;) (result i32) + (global.get $__asyncify_state) + ) ) (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "import" (func $import)) (import "env" "import2" (func $import2 (result i32))) (import "env" "import3" (func $import3 (param i32))) @@ -328,6 +333,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $calls-import (; 3 ;) (local $0 i32) (local $1 i32) @@ -1855,4 +1861,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 23 ;) (result i32) + (global.get $__asyncify_state) + ) ) diff --git a/test/passes/asyncify_pass-arg=asyncify-whitelist@foo,bar.txt b/test/passes/asyncify_pass-arg=asyncify-whitelist@foo,bar.txt index d8512cd7e..ea0975afd 100644 --- a/test/passes/asyncify_pass-arg=asyncify-whitelist@foo,bar.txt +++ b/test/passes/asyncify_pass-arg=asyncify-whitelist@foo,bar.txt @@ -1,6 +1,7 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "import" (func $import)) (memory $0 1 2) (global $__asyncify_state (mut i32) (i32.const 0)) @@ -9,6 +10,7 @@ (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) (export "asyncify_start_rewind" (func $asyncify_start_rewind)) (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) (func $foo (; 1 ;) (local $0 i32) (local $1 i32) @@ -262,4 +264,7 @@ (unreachable) ) ) + (func $asyncify_get_state (; 10 ;) (result i32) + (global.get $__asyncify_state) + ) ) |