summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/passes/bysyncify.txt89
-rw-r--r--test/passes/bysyncify.wast5
-rw-r--r--test/passes/bysyncify_optimize-level=1.txt10
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt (renamed from test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt)58
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.wast (renamed from test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast)0
-rw-r--r--test/unit/input/bysyncify-coroutine.wast44
-rw-r--r--test/unit/input/bysyncify-sleep.wast (renamed from test/unit/input/bysyncify.wast)0
-rw-r--r--test/unit/input/bysyncify.js352
-rw-r--r--test/unit/test_bysyncify.py3
9 files changed, 409 insertions, 152 deletions
diff --git a/test/passes/bysyncify.txt b/test/passes/bysyncify.txt
index 1ec35057e..2ab682149 100644
--- a/test/passes/bysyncify.txt
+++ b/test/passes/bysyncify.txt
@@ -6,6 +6,7 @@
(global $__bysyncify_state (mut i32) (i32.const 0))
(global $__bysyncify_data (mut i32) (i32.const 0))
(export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_stop_unwind" (func $bysyncify_stop_unwind))
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $do_sleep (; 0 ;) (type $FUNCSIG$v)
@@ -151,16 +152,40 @@
(i32.const 2)
)
)
- (if
- (i32.eq
- (global.get $__bysyncify_state)
- (i32.const 0)
- )
- (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
(global.set $sleeping
(i32.const 0)
)
- (call $bysyncify_stop_rewind)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $bysyncify_stop_rewind)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
)
)
)
@@ -458,6 +483,31 @@
)
)
(block
+ (call $bysyncify_stop_unwind)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 0)
+ )
+ )
+ )
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $1)
+ (i32.const 1)
+ )
+ )
+ (block
(call $bysyncify_start_rewind
(i32.const 4)
)
@@ -467,7 +517,7 @@
(i32.const 1)
)
(br $__bysyncify_unwind
- (i32.const 0)
+ (i32.const 1)
)
)
)
@@ -481,7 +531,7 @@
(i32.const 1)
(i32.eq
(local.get $1)
- (i32.const 1)
+ (i32.const 2)
)
)
(block
@@ -492,7 +542,7 @@
(i32.const 1)
)
(br $__bysyncify_unwind
- (i32.const 1)
+ (i32.const 2)
)
)
)
@@ -546,7 +596,12 @@
(local.get $0)
)
)
- (func $bysyncify_start_rewind (; 7 ;) (param $0 i32)
+ (func $bysyncify_stop_unwind (; 7 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
@@ -565,7 +620,7 @@
(local.get $0)
)
)
- (func $bysyncify_stop_rewind (; 8 ;)
+ (func $bysyncify_stop_rewind (; 9 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
@@ -583,6 +638,7 @@
(global $__bysyncify_state (mut i32) (i32.const 0))
(global $__bysyncify_data (mut i32) (i32.const 0))
(export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_stop_unwind" (func $bysyncify_stop_unwind))
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $calls-import (; 3 ;) (type $FUNCSIG$v)
@@ -2683,7 +2739,12 @@
(local.get $0)
)
)
- (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (func $bysyncify_stop_unwind (; 20 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
@@ -2702,7 +2763,7 @@
(local.get $0)
)
)
- (func $bysyncify_stop_rewind (; 21 ;)
+ (func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
diff --git a/test/passes/bysyncify.wast b/test/passes/bysyncify.wast
index 7c92bd86f..00ecc7fde 100644
--- a/test/passes/bysyncify.wast
+++ b/test/passes/bysyncify.wast
@@ -2,6 +2,7 @@
(module
(memory 1 2)
(import "bysyncify" "start_unwind" (func $bysyncify_start_unwind (param i32)))
+ (import "bysyncify" "stop_unwind" (func $bysyncify_stop_unwind))
(import "bysyncify" "start_rewind" (func $bysyncify_start_rewind (param i32)))
(import "bysyncify" "stop_rewind" (func $bysyncify_stop_rewind))
(global $sleeping (mut i32) (i32.const 0))
@@ -34,8 +35,10 @@
;; work will sleep, so we exit through here while it is paused
)
;; the second event called from the main event loop: to resume $work,
- ;; initiate a rewind, and then do the call to start things back up
+ ;; stop the unwind, then prepare a rewind, and initiate it by doing
+ ;; the call to rewind the call stack back up to where it was
(func $second_event
+ (call $bysyncify_stop_unwind)
(call $bysyncify_start_rewind (i32.const 4))
(call $work)
)
diff --git a/test/passes/bysyncify_optimize-level=1.txt b/test/passes/bysyncify_optimize-level=1.txt
index 6eb7217e4..73456a7ae 100644
--- a/test/passes/bysyncify_optimize-level=1.txt
+++ b/test/passes/bysyncify_optimize-level=1.txt
@@ -10,6 +10,7 @@
(global $__bysyncify_state (mut i32) (i32.const 0))
(global $__bysyncify_data (mut i32) (i32.const 0))
(export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_stop_unwind" (func $bysyncify_stop_unwind))
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $calls-import (; 3 ;) (type $FUNCSIG$v)
@@ -1514,7 +1515,12 @@
(local.get $0)
)
)
- (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (func $bysyncify_stop_unwind (; 20 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
@@ -1533,7 +1539,7 @@
(local.get $0)
)
)
- (func $bysyncify_stop_rewind (; 21 ;)
+ (func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt
index e850da6cf..81a37a643 100644
--- a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.txt
+++ b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt
@@ -6,6 +6,7 @@
(global $__bysyncify_state (mut i32) (i32.const 0))
(global $__bysyncify_data (mut i32) (i32.const 0))
(export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_stop_unwind" (func $bysyncify_stop_unwind))
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $do_sleep (; 0 ;) (type $FUNCSIG$v)
@@ -151,16 +152,40 @@
(i32.const 2)
)
)
- (if
- (i32.eq
- (global.get $__bysyncify_state)
- (i32.const 0)
- )
- (block
+ (block
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
(global.set $sleeping
(i32.const 0)
)
- (call $bysyncify_stop_rewind)
+ )
+ (if
+ (if (result i32)
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 0)
+ )
+ (i32.const 1)
+ (i32.eq
+ (local.get $3)
+ (i32.const 1)
+ )
+ )
+ (block
+ (call $bysyncify_stop_rewind)
+ (if
+ (i32.eq
+ (global.get $__bysyncify_state)
+ (i32.const 1)
+ )
+ (br $__bysyncify_unwind
+ (i32.const 1)
+ )
+ )
+ )
)
)
)
@@ -546,7 +571,12 @@
(local.get $0)
)
)
- (func $bysyncify_start_rewind (; 7 ;) (param $0 i32)
+ (func $bysyncify_stop_unwind (; 7 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
@@ -565,7 +595,7 @@
(local.get $0)
)
)
- (func $bysyncify_stop_rewind (; 8 ;)
+ (func $bysyncify_stop_rewind (; 9 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
@@ -583,6 +613,7 @@
(global $__bysyncify_state (mut i32) (i32.const 0))
(global $__bysyncify_data (mut i32) (i32.const 0))
(export "bysyncify_start_unwind" (func $bysyncify_start_unwind))
+ (export "bysyncify_stop_unwind" (func $bysyncify_stop_unwind))
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $calls-import (; 3 ;) (type $FUNCSIG$v)
@@ -1971,7 +2002,12 @@
(local.get $0)
)
)
- (func $bysyncify_start_rewind (; 20 ;) (param $0 i32)
+ (func $bysyncify_stop_unwind (; 20 ;)
+ (global.set $__bysyncify_state
+ (i32.const 0)
+ )
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
@@ -1990,7 +2026,7 @@
(local.get $0)
)
)
- (func $bysyncify_stop_rewind (; 21 ;)
+ (func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.wast
index 7c92bd86f..7c92bd86f 100644
--- a/test/passes/bysyncify_pass-arg=bysyncify@env.import,env.import2.wast
+++ b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.wast
diff --git a/test/unit/input/bysyncify-coroutine.wast b/test/unit/input/bysyncify-coroutine.wast
new file mode 100644
index 000000000..ace97c6e6
--- /dev/null
+++ b/test/unit/input/bysyncify-coroutine.wast
@@ -0,0 +1,44 @@
+(module
+ (memory 1 2)
+ ;; import a "yield" function that receives the current value,
+ ;; then pauses execution until it is resumed later.
+ (import "env" "yield" (func $yield (param i32)))
+ (export "memory" (memory 0))
+ ;; simple linear progression in a loop
+ (func "linear" (result i32)
+ (local $x i32)
+ (loop $l
+ (call $yield (local.get $x))
+ (local.set $x
+ (i32.add (local.get $x) (i32.const 10))
+ )
+ (br $l)
+ )
+ )
+ ;; exponential in a loop
+ (func "exponential" (result i32)
+ (local $x i32)
+ (local.set $x
+ (i32.const 1)
+ )
+ (loop $l
+ (call $yield (local.get $x))
+ (local.set $x
+ (i32.mul (local.get $x) (i32.const 2))
+ )
+ (br $l)
+ )
+ )
+ ;; just some weird numbers, no loop
+ (func "weird" (result i32)
+ (call $yield (i32.const 42))
+ (call $yield (i32.const 1337))
+ (call $yield (i32.const 0))
+ (call $yield (i32.const -1000))
+ (call $yield (i32.const 42))
+ (call $yield (i32.const 314159))
+ (call $yield (i32.const 21828))
+ (unreachable)
+ )
+)
+
diff --git a/test/unit/input/bysyncify.wast b/test/unit/input/bysyncify-sleep.wast
index 91fb5a327..91fb5a327 100644
--- a/test/unit/input/bysyncify.wast
+++ b/test/unit/input/bysyncify-sleep.wast
diff --git a/test/unit/input/bysyncify.js b/test/unit/input/bysyncify.js
index 97d7a0da5..4fd6f4b84 100644
--- a/test/unit/input/bysyncify.js
+++ b/test/unit/input/bysyncify.js
@@ -5,151 +5,257 @@ function assert(x, y) {
var fs = require('fs');
-// Get and compile the wasm.
-
-var binary = fs.readFileSync('a.wasm');
-
-var module = new WebAssembly.Module(binary);
-
-var DATA_ADDR = 4;
-
-var sleeps = 0;
-
-var sleeping = false;
-
-var instance = new WebAssembly.Instance(module, {
- env: {
- sleep: function() {
- logMemory();
-assert(view[0] == 0);
- if (!sleeping) {
- // We are called in order to start a sleep/unwind.
- console.log('sleep...');
- sleeps++;
- // Unwinding.
- exports.bysyncify_start_unwind(DATA_ADDR);
- // Fill in the data structure. The first value has the stack location,
- // which for simplicity we can start right after the data structure itself.
- view[DATA_ADDR >> 2] = DATA_ADDR + 8;
- // The end of the stack will not be reached here anyhow.
- view[DATA_ADDR + 4 >> 2] = 1024;
- sleeping = true;
- } else {
- // We are called as part of a resume/rewind. Stop sleeping.
- console.log('resume...');
- exports.bysyncify_stop_rewind();
- // The stack should have been all used up, and so returned to the original state.
- assert(view[DATA_ADDR >> 2] == DATA_ADDR + 8);
- assert(view[DATA_ADDR + 4 >> 2] == 1024);
- sleeping = false;
+function sleepTests() {
+ console.log('\nsleep tests\n\n');
+
+ // Get and compile the wasm.
+
+ var binary = fs.readFileSync('a.wasm');
+
+ var module = new WebAssembly.Module(binary);
+
+ var DATA_ADDR = 4;
+
+ var sleeps = 0;
+
+ var sleeping = false;
+
+ var instance = new WebAssembly.Instance(module, {
+ env: {
+ sleep: function() {
+ logMemory();
+ if (!sleeping) {
+ // We are called in order to start a sleep/unwind.
+ console.log('sleep...');
+ sleeps++;
+ // Unwinding.
+ exports.bysyncify_start_unwind(DATA_ADDR);
+ // Fill in the data structure. The first value has the stack location,
+ // which for simplicity we can start right after the data structure itself.
+ view[DATA_ADDR >> 2] = DATA_ADDR + 8;
+ // The end of the stack will not be reached here anyhow.
+ view[DATA_ADDR + 4 >> 2] = 1024;
+ sleeping = true;
+ } else {
+ // We are called as part of a resume/rewind. Stop sleeping.
+ console.log('resume...');
+ exports.bysyncify_stop_rewind();
+ // The stack should have been all used up, and so returned to the original state.
+ assert(view[DATA_ADDR >> 2] == DATA_ADDR + 8);
+ assert(view[DATA_ADDR + 4 >> 2] == 1024);
+ sleeping = false;
+ }
+ logMemory();
+ },
+ tunnel: function(x) {
+ console.log('tunneling, sleep == ' + sleeping);
+ return exports.end_tunnel(x);
}
- logMemory();
- },
- tunnel: function(x) {
- console.log('tunneling, sleep == ' + sleeping);
- return exports.end_tunnel(x);
}
- }
-});
+ });
-var exports = instance.exports;
-var view = new Int32Array(exports.memory.buffer);
+ var exports = instance.exports;
+ var view = new Int32Array(exports.memory.buffer);
-function logMemory() {
- // Log the relevant memory locations for debugging purposes.
- console.log('memory: ', view[0 >> 2], view[4 >> 2], view[8 >> 2], view[12 >> 2], view[16 >> 2], view[20 >> 2], view[24 >> 2]);
-}
+ function logMemory() {
+ // Log the relevant memory locations for debugging purposes.
+ console.log('memory: ', view[0 >> 2], view[4 >> 2], view[8 >> 2], view[12 >> 2], view[16 >> 2], view[20 >> 2], view[24 >> 2]);
+ }
-function runTest(name, expectedSleeps, expectedResult, params) {
- params = params || [];
+ function runTest(name, expectedSleeps, expectedResult, params) {
+ params = params || [];
- console.log('\n==== testing ' + name + ' ====');
+ console.log('\n==== testing ' + name + ' ====');
- sleeps = 0;
+ sleeps = 0;
- logMemory();
+ logMemory();
- // Run until the sleep.
- var result = exports[name].apply(null, params);
- logMemory();
+ // Run until the sleep.
+ var result = exports[name].apply(null, params);
+ logMemory();
- if (expectedSleeps > 0) {
- assert(!result, 'results during sleep are meaningless, just 0');
+ if (expectedSleeps > 0) {
+ assert(!result, 'results during sleep are meaningless, just 0');
+ exports.bysyncify_stop_unwind(DATA_ADDR);
+
+ for (var i = 0; i < expectedSleeps - 1; i++) {
+ console.log('rewind, run until the next sleep');
+ exports.bysyncify_start_rewind(DATA_ADDR);
+ result = exports[name](); // no need for params on later times
+ assert(!result, 'results during sleep are meaningless, just 0');
+ logMemory();
+ exports.bysyncify_stop_unwind(DATA_ADDR);
+ }
- for (var i = 0; i < expectedSleeps - 1; i++) {
- console.log('rewind, run until the next sleep');
+ console.log('rewind and run til the end.');
exports.bysyncify_start_rewind(DATA_ADDR);
- result = exports[name](); // no need for params on later times
- assert(!result, 'results during sleep are meaningless, just 0');
- assert(!result, 'bad first sleep result');
- logMemory();
+ result = exports[name]();
}
- console.log('rewind and run til the end.');
- exports.bysyncify_start_rewind(DATA_ADDR);
- result = exports[name]();
- }
+ console.log('final result: ' + result);
+ assert(result == expectedResult, 'bad final result');
+ logMemory();
- console.log('final result: ' + result);
- assert(result == expectedResult, 'bad final result');
- logMemory();
+ assert(sleeps == expectedSleeps, 'expectedSleeps');
+ }
- assert(sleeps == expectedSleeps, 'expectedSleeps');
+ //================
+ // Tests
+ //================
+
+ // A minimal single sleep.
+ runTest('minimal', 1, 21);
+
+ // Two sleeps.
+ runTest('repeat', 2, 42);
+
+ // A value in a local is preserved across a sleep.
+ runTest('local', 1, 10);
+
+ // A local with more operations done on it.
+ runTest('local2', 1, 22);
+
+ // A local with more operations done on it.
+ runTest('params', 1, 18);
+ runTest('params', 1, 21, [1, 2]);
+
+ // Calls to multiple other functions, only one of whom
+ // sleeps, and keep locals and globals valid throughout.
+ runTest('deeper', 0, 27, [0]);
+ runTest('deeper', 1, 3, [1]);
+
+ // A recursive factorial, that sleeps on each iteration
+ // above 1.
+ runTest('factorial-recursive', 0, 1, [1]);
+ runTest('factorial-recursive', 1, 2, [2]);
+ runTest('factorial-recursive', 2, 6, [3]);
+ runTest('factorial-recursive', 3, 24, [4]);
+ runTest('factorial-recursive', 4, 120, [5]);
+
+ // A looping factorial, that sleeps on each iteration
+ // above 1.
+ runTest('factorial-loop', 0, 1, [1]);
+ runTest('factorial-loop', 1, 2, [2]);
+ runTest('factorial-loop', 2, 6, [3]);
+ runTest('factorial-loop', 3, 24, [4]);
+ runTest('factorial-loop', 4, 120, [5]);
+
+ // Test calling into JS in the middle (which can work if
+ // the JS just forwards the call and has no side effects or
+ // state of its own that needs to be saved).
+ runTest('do_tunnel', 2, 72, [1]);
+
+ // Test indirect function calls.
+ runTest('call_indirect', 3, 432, [1, 2]);
+
+ // Test indirect function calls.
+ runTest('if_else', 3, 1460, [1, 1000]);
+ runTest('if_else', 3, 2520, [2, 2000]);
}
-//================
-// Tests
-//================
-
-// A minimal single sleep.
-runTest('minimal', 1, 21);
-
-// Two sleeps.
-runTest('repeat', 2, 42);
-
-// A value in a local is preserved across a sleep.
-runTest('local', 1, 10);
-
-// A local with more operations done on it.
-runTest('local2', 1, 22);
-
-// A local with more operations done on it.
-runTest('params', 1, 18);
-runTest('params', 1, 21, [1, 2]);
-
-// Calls to multiple other functions, only one of whom
-// sleeps, and keep locals and globals valid throughout.
-runTest('deeper', 0, 27, [0]);
-runTest('deeper', 1, 3, [1]);
-
-// A recursive factorial, that sleeps on each iteration
-// above 1.
-runTest('factorial-recursive', 0, 1, [1]);
-runTest('factorial-recursive', 1, 2, [2]);
-runTest('factorial-recursive', 2, 6, [3]);
-runTest('factorial-recursive', 3, 24, [4]);
-runTest('factorial-recursive', 4, 120, [5]);
+function coroutineTests() {
+ console.log('\ncoroutine tests\n\n');
+
+ // Get and compile the wasm.
+
+ var binary = fs.readFileSync('b.wasm');
+
+ var module = new WebAssembly.Module(binary);
+
+ // Create a coroutine, for a specific export to
+ // call, and whose unwind/rewind data is in
+ // a specific range.
+ function Coroutine(name, dataStart, dataEnd) {
+ this.name = name;
+ this.start = function() {
+ exports[name]();
+ };
+ this.startUnwind = function() {
+ // Initialize the data.
+ view[dataStart >> 2] = dataStart + 8;
+ view[dataStart + 4 >> 2] = dataEnd;
+ exports.bysyncify_start_unwind(dataStart);
+ // (With C etc. coroutines we would also have
+ // a C stack to pause and resume here.)
+ };
+ this.stopUnwind = function() {
+ exports.bysyncify_stop_unwind();
+ };
+ this.startRewind = function() {
+ exports.bysyncify_start_rewind(dataStart);
+ exports[name]();
+ };
+ this.stopRewind = function() {
+ exports.bysyncify_stop_rewind();
+ };
+ }
-// A looping factorial, that sleeps on each iteration
-// above 1.
-runTest('factorial-loop', 0, 1, [1]);
-runTest('factorial-loop', 1, 2, [2]);
-runTest('factorial-loop', 2, 6, [3]);
-runTest('factorial-loop', 3, 24, [4]);
-runTest('factorial-loop', 4, 120, [5]);
+ var Runtime = {
+ coroutines: [
+ new Coroutine('linear', 1000, 2000),
+ new Coroutine('exponential', 2000, 3000),
+ new Coroutine('weird', 3000, 4000)
+ ],
+ active: null,
+ rewinding: false,
+ run: function(iters) {
+ Runtime.coroutines.forEach(function(coroutine) {
+ console.log('starting ' + coroutine.name);
+ Runtime.active = coroutine;
+ coroutine.start();
+ coroutine.stopUnwind();
+ Runtime.active = null;
+ });
+ for (var i = 0; i < iters; i++) {
+ Runtime.coroutines.forEach(function(coroutine) {
+ console.log('resuming ' + coroutine.name);
+ Runtime.active = coroutine;
+ Runtime.rewinding = true;
+ coroutine.startRewind();
+ Runtime.active = null;
+ });
+ }
+ },
+ values: [],
+ yield: function(value) {
+ console.log('yield reached', Runtime.rewinding, value);
+ var coroutine = Runtime.active;
+ if (Runtime.rewinding) {
+ coroutine.stopRewind();
+ Runtime.rewinding = false;
+ } else {
+ Runtime.values.push(value);
+ coroutine.startUnwind();
+ console.log('pausing ' + coroutine.name);
+ }
+ },
+ };
-// Test calling into JS in the middle (which can work if
-// the JS just forwards the call and has no side effects or
-// state of its own that needs to be saved).
-runTest('do_tunnel', 2, 72, [1]);
+ var instance = new WebAssembly.Instance(module, {
+ env: {
+ yield: Runtime.yield
+ }
+ });
+
+ var exports = instance.exports;
+ var view = new Int32Array(exports.memory.buffer);
+
+ Runtime.run(4);
+ console.log(Runtime.values);
+ assert(JSON.stringify(Runtime.values) === JSON.stringify([
+ 0, 1, 42,
+ 10, 2, 1337,
+ 20, 4, 0,
+ 30, 8, -1000,
+ 40, 16, 42
+ ]), 'check yielded values')
+}
-// Test indirect function calls.
-runTest('call_indirect', 3, 432, [1, 2]);
+// Main
-// Test indirect function calls.
-runTest('if_else', 3, 1460, [1, 1000]);
-runTest('if_else', 3, 2520, [2, 2000]);
+sleepTests();
+coroutineTests();
-// All done.
console.log('\ntests completed successfully');
diff --git a/test/unit/test_bysyncify.py b/test/unit/test_bysyncify.py
index 5373a4def..29a8ae7cb 100644
--- a/test/unit/test_bysyncify.py
+++ b/test/unit/test_bysyncify.py
@@ -8,7 +8,8 @@ class BysyncifyTest(BinaryenTestCase):
def test_bysyncify(self):
def test(args):
print(args)
- run_process(WASM_OPT + args + [self.input_path('bysyncify.wast'), '--bysyncify', '-o', 'a.wasm'])
+ run_process(WASM_OPT + args + [self.input_path('bysyncify-sleep.wast'), '--bysyncify', '-o', 'a.wasm'])
+ run_process(WASM_OPT + args + [self.input_path('bysyncify-coroutine.wast'), '--bysyncify', '-o', 'b.wasm'])
print(' file size: %d' % os.path.getsize('a.wasm'))
run_process([NODEJS, self.input_path('bysyncify.js')])