summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-03-04 13:21:39 -0800
committerGitHub <noreply@github.com>2020-03-04 13:21:39 -0800
commit57a81a04f7a49593438dcae4ca8cbad8e465dc2e (patch)
tree02f8732873e8ef2608a94610857e2fb13de813ca
parent2a0f6a513c6d6a99d16ca31de3e76a63b1490b4c (diff)
downloadbinaryen-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.
-rw-r--r--src/passes/Asyncify.cpp17
-rw-r--r--test/passes/asyncify.txt16
-rw-r--r--test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt4
-rw-r--r--test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt5
-rw-r--r--test/passes/asyncify_mod-asyncify-never-unwind.txt4
-rw-r--r--test/passes/asyncify_mod-asyncify-never-unwind_O.txt5
-rw-r--r--test/passes/asyncify_optimize-level=1.txt6
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-whitelist@waka.txt4
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt5
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt4
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt4
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt11
-rw-r--r--test/passes/asyncify_pass-arg=asyncify-whitelist@foo,bar.txt5
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)
+ )
)