a358c2eb42
Changes: - Add --wasm-loop-unrolling flag. Everything in this CL happens behind this flag. - In decoding, DoReturn does not take returned values as an argument. It is now the responsibility of graph-builder-interface.cc to extract these values. Note that this is what was already happening in Liftoff. - In pipeline.cc, add phase to remove loop exits after generating the turbofan graph. - Explicitly disallow calling FallThruTo() on loops. - Add loop assignments and loop header node to Control type in graph-builder-interface.cc. Assign them in Loop(). - Main change: Add loop exit nodes to wasm-generated graphs. For details, consult this design doc: https://docs.google.com/document/d/1AsUCqslMUB6fLdnGq0ZoPk2kn50jIJAWAL77lKXXP5g - Inline PrepareForLoop(). Bug: v8:11298 Change-Id: I65058f1b5df3f862f4a62f4dcb0bd7e1f1dcf4ee Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2621082 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#72094}
562 lines
16 KiB
JavaScript
562 lines
16 KiB
JavaScript
// Copyright 2017 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --experimental-wasm-mv --wasm-loop-unrolling
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
(function MultiBlockResultTest() {
|
|
print("MultiBlockResultTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_ii_v = builder.addType(kSig_ii_v);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprBlock, sig_ii_v,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprEnd,
|
|
kExprI32Add])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
})();
|
|
|
|
(function MultiBlockParamTest() {
|
|
print("MultiBlockParamTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprBlock, sig_i_ii,
|
|
kExprI32Add,
|
|
kExprEnd])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
})();
|
|
|
|
(function MultiBlockBrTest() {
|
|
print("MultiBlockBrTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_ii_v = builder.addType(kSig_ii_v);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprBlock, sig_ii_v,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprBr, 0,
|
|
kExprEnd,
|
|
kExprI32Add])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
})();
|
|
|
|
(function MultiBlockUnreachableTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_il_v = builder.addType(makeSig([], [kWasmI32, kWasmI64]));
|
|
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([
|
|
kExprBlock, sig_il_v,
|
|
kExprI32Const, 1,
|
|
kExprI64Const, 1,
|
|
kExprBr, 0,
|
|
kExprI32Const, 1,
|
|
kExprI64Const, 1,
|
|
kExprEnd,
|
|
kExprDrop])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 2), 1);
|
|
})();
|
|
|
|
(function MultiBlockUnreachableTypeErrorTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_il_v = builder.addType(makeSig([], [kWasmI32, kWasmI64]));
|
|
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([
|
|
kExprBlock, sig_il_v,
|
|
kExprI32Const, 1,
|
|
kExprI64Const, 1,
|
|
kExprBr, 0,
|
|
kExprI64Const, 1,
|
|
kExprI32Const, 1,
|
|
// Wrong order: expect i32, i64.
|
|
kExprEnd,
|
|
kExprDrop])
|
|
.exportAs("main");
|
|
|
|
assertThrows(() => new WebAssembly.Module(builder.toBuffer()),
|
|
WebAssembly.CompileError, /expected type i64, found i32.const/);
|
|
})();
|
|
|
|
(function MultiLoopResultTest() {
|
|
print("MultiLoopResultTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_ii_v = builder.addType(kSig_ii_v);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLoop, sig_ii_v,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprEnd,
|
|
kExprI32Add])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
})();
|
|
|
|
(function MultiLoopParamTest() {
|
|
print("MultiLoopParamTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLoop, sig_i_ii,
|
|
kExprI32Add,
|
|
kExprEnd])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
})();
|
|
|
|
(function MultiLoopBrTest() {
|
|
print("MultiLoopBrTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_ii_i = builder.addType(kSig_ii_i);
|
|
let sig_ii_ii = builder.addType(kSig_ii_ii);
|
|
|
|
builder.addFunction("dup", kSig_ii_i)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 0]);
|
|
builder.addFunction("swap", kSig_ii_ii)
|
|
.addBody([kExprLocalGet, 1, kExprLocalGet, 0]);
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLoop, sig_ii_ii,
|
|
kExprCallFunction, 1, // swap
|
|
kExprCallFunction, 0, // dup
|
|
kExprI32Add,
|
|
kExprCallFunction, 0, // dup
|
|
kExprI32Const, 20,
|
|
kExprI32LeU,
|
|
kExprBrIf, 0,
|
|
kExprEnd,
|
|
kExprDrop])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(0, instance.exports.main(0, 1));
|
|
assertEquals(16, instance.exports.main(1, 1));
|
|
assertEquals(4, instance.exports.main(3, 1));
|
|
assertEquals(4, instance.exports.main(4, 1));
|
|
assertEquals(0, instance.exports.main(0, 2));
|
|
assertEquals(16, instance.exports.main(1, 2));
|
|
assertEquals(8, instance.exports.main(3, 2));
|
|
assertEquals(8, instance.exports.main(4, 2));
|
|
assertEquals(0, instance.exports.main(0, 3));
|
|
assertEquals(8, instance.exports.main(1, 3));
|
|
assertEquals(12, instance.exports.main(3, 3));
|
|
assertEquals(12, instance.exports.main(4, 3));
|
|
assertEquals(0, instance.exports.main(0, 4));
|
|
assertEquals(8, instance.exports.main(1, 4));
|
|
assertEquals(16, instance.exports.main(3, 4));
|
|
assertEquals(16, instance.exports.main(4, 4));
|
|
assertEquals(3, instance.exports.main(100, 3));
|
|
assertEquals(6, instance.exports.main(3, 100));
|
|
})();
|
|
|
|
|
|
(function MultiIfResultTest() {
|
|
print("MultiIfResultTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_ii_v = builder.addType(kSig_ii_v);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprIf, sig_ii_v,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprElse,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 0,
|
|
kExprEnd,
|
|
kExprI32Sub])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(8, 3), 5);
|
|
assertEquals(instance.exports.main(0, 3), 3);
|
|
})();
|
|
|
|
(function MultiIfParamTest() {
|
|
print("MultiIfParamTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 0,
|
|
kExprIf, sig_i_ii,
|
|
kExprI32Add,
|
|
kExprElse,
|
|
kExprI32Sub,
|
|
kExprEnd])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(1, 4), 5);
|
|
assertEquals(instance.exports.main(0, 4), -4);
|
|
})();
|
|
|
|
(function MultiIfBrTest() {
|
|
print("MultiIfBrTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_ii_v = builder.addType(kSig_ii_v);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprIf, sig_ii_v,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprBr, 0,
|
|
kExprElse,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 0,
|
|
kExprBr, 0,
|
|
kExprEnd,
|
|
kExprI32Sub])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(8, 3), 5);
|
|
assertEquals(instance.exports.main(0, 3), 3);
|
|
})();
|
|
|
|
(function MultiIfParamOneArmedTest() {
|
|
print("MultiIfParamOneArmedTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
|
|
builder.addFunction("main", kSig_i_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprIf, sig_i_i,
|
|
kExprI32Const, 5,
|
|
kExprI32Add,
|
|
kExprEnd])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(0), 0);
|
|
assertEquals(instance.exports.main(1), 6);
|
|
})();
|
|
|
|
(function MultiIfOneArmedNoTypeCheckTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_l = builder.addType(kSig_i_l);
|
|
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([
|
|
kExprI64Const, 0,
|
|
kExprI32Const, 0,
|
|
kExprIf, sig_i_l,
|
|
kExprDrop,
|
|
kExprI32Const, 0,
|
|
kExprEnd]);
|
|
|
|
assertThrows(() => new WebAssembly.Module(builder.toBuffer()),
|
|
WebAssembly.CompileError, /expected i32, got i64/);
|
|
})();
|
|
|
|
(function MultiResultTest() {
|
|
print("MultiResultTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_ii = builder.addType(kSig_i_ii);
|
|
let sig_iii_ii = builder.addType(kSig_iii_ii);
|
|
|
|
builder.addFunction("callee", kSig_iii_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprI32Sub]);
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprCallFunction, 0,
|
|
kExprI32Mul,
|
|
kExprI32Add])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(0, 0), 0);
|
|
assertEquals(instance.exports.main(1, 0), 1);
|
|
assertEquals(instance.exports.main(2, 0), 2);
|
|
assertEquals(instance.exports.main(0, 1), -1);
|
|
assertEquals(instance.exports.main(0, 2), -4);
|
|
assertEquals(instance.exports.main(3, 4), -1);
|
|
assertEquals(instance.exports.main(4, 3), 7);
|
|
})();
|
|
|
|
(function MultiReturnTest() {
|
|
print("MultiReturnTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
let sig_ii_i = builder.addType(kSig_ii_i);
|
|
|
|
builder.addFunction("callee", kSig_ii_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Add,
|
|
kExprReturn]);
|
|
builder.addFunction("main", kSig_i_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprCallFunction, 0,
|
|
kExprI32Mul])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(0), 0);
|
|
assertEquals(instance.exports.main(1), 2);
|
|
assertEquals(instance.exports.main(2), 8);
|
|
assertEquals(instance.exports.main(10), 200);
|
|
})();
|
|
|
|
(function MultiBrReturnTest() {
|
|
print("MultiBrReturnTest");
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
let sig_ii_i = builder.addType(kSig_ii_i);
|
|
|
|
builder.addFunction("callee", kSig_ii_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Add,
|
|
kExprBr, 0]);
|
|
builder.addFunction("main", kSig_i_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprCallFunction, 0,
|
|
kExprI32Mul])
|
|
.exportAs("main");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.main(0), 0);
|
|
assertEquals(instance.exports.main(1), 2);
|
|
assertEquals(instance.exports.main(2), 8);
|
|
assertEquals(instance.exports.main(10), 200);
|
|
})();
|
|
|
|
(function MultiBrTableTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_ii_v = builder.addType(kSig_v_v);
|
|
|
|
builder.addFunction("main", kSig_ii_v)
|
|
.addBody([
|
|
kExprI32Const, 1, kExprI32Const, 2,
|
|
kExprI32Const, 0,
|
|
kExprBrTable, 1, 0, 0,
|
|
])
|
|
.exportAs("main");
|
|
|
|
let instance = builder.instantiate();
|
|
assertEquals(instance.exports.main(), [1, 2]);
|
|
})();
|
|
|
|
(function MultiUnreachablePolymorphicTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_v_i = builder.addType(kSig_v_i);
|
|
let sig_i_i = builder.addType(kSig_i_i);
|
|
|
|
builder.addFunction("block", kSig_v_v)
|
|
.addBody([
|
|
kExprReturn,
|
|
kExprBlock, sig_v_i,
|
|
kExprDrop,
|
|
kExprEnd
|
|
])
|
|
.exportAs("block");
|
|
builder.addFunction("if_else", kSig_v_v)
|
|
.addBody([
|
|
kExprReturn,
|
|
kExprIf, sig_v_i,
|
|
kExprDrop,
|
|
kExprElse,
|
|
kExprDrop,
|
|
kExprEnd
|
|
])
|
|
.exportAs("if_else");
|
|
builder.addFunction("loop", kSig_v_v)
|
|
.addBody([
|
|
kExprReturn,
|
|
kExprLoop, sig_i_i,
|
|
kExprEnd,
|
|
kExprDrop
|
|
])
|
|
.exportAs("loop");
|
|
// TODO(thibaudm): Create eh + mv mjsunit test and add try/catch case.
|
|
let instance = builder.instantiate();
|
|
instance.exports.block();
|
|
instance.exports.if_else();
|
|
instance.exports.loop();
|
|
})();
|
|
|
|
(function MultiWasmToJSReturnTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
let sig_fi_if = makeSig([kWasmI32, kWasmF32], [kWasmF32, kWasmI32]);
|
|
|
|
builder.addFunction("swap", sig_fi_if)
|
|
.addBody([
|
|
kExprLocalGet, 1,
|
|
kExprLocalGet, 0])
|
|
.exportAs("swap");
|
|
builder.addFunction("addsubmul", kSig_iii_i)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Add,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Sub,
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 0,
|
|
kExprI32Mul])
|
|
.exportAs("addsubmul");
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
let instance = new WebAssembly.Instance(module);
|
|
assertEquals(instance.exports.swap(0, 1.5), [1.5, 0]);
|
|
assertEquals(instance.exports.swap(2, 3.75), [3.75, 2]);
|
|
assertEquals(instance.exports.addsubmul(4), [8, 0, 16]);
|
|
assertEquals(instance.exports.addsubmul(5), [10, 0, 25]);
|
|
})();
|
|
|
|
(function MultiJSToWasmReturnTest() {
|
|
print(arguments.callee.name);
|
|
let builder = new WasmModuleBuilder();
|
|
function swap(x, y) { return [y, x]; }
|
|
function swap_proxy(x, y) {
|
|
return new Proxy([y, x], {
|
|
get: function(obj, prop) { return Reflect.get(obj, prop); },
|
|
});
|
|
}
|
|
function proxy_throw(x, y) {
|
|
return new Proxy([y, x], {
|
|
get: function(obj, prop) {
|
|
if (prop == 1) {
|
|
throw new Error("abc");
|
|
}
|
|
return Reflect.get(obj, prop); },
|
|
});
|
|
}
|
|
function drop_first(x, y) {
|
|
return [y];
|
|
}
|
|
function repeat(x, y) {
|
|
return [x, y, x, y];
|
|
}
|
|
function not_receiver(x, y) {
|
|
return 0;
|
|
}
|
|
function not_iterable(x, y) {
|
|
a = [x, y];
|
|
a[Symbol.iterator] = undefined;
|
|
return a;
|
|
}
|
|
function* generator(x, y) {
|
|
yield x;
|
|
yield y;
|
|
}
|
|
function* generator_throw(x, y) {
|
|
yield x;
|
|
throw new Error("def");
|
|
}
|
|
|
|
builder.addImport('imports', 'f', kSig_ii_ii);
|
|
builder.addFunction("main", kSig_ii_ii)
|
|
.addBody([
|
|
kExprLocalGet, 0,
|
|
kExprLocalGet, 1,
|
|
kExprCallFunction, 0])
|
|
.exportAs("main")
|
|
|
|
let module = new WebAssembly.Module(builder.toBuffer());
|
|
|
|
var instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : swap } });
|
|
assertEquals(instance.exports.main(1, 2), [2, 1]);
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : swap_proxy } });
|
|
assertEquals(instance.exports.main(1, 2), [2, 1]);
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : generator } });
|
|
assertEquals(instance.exports.main(1, 2), [1, 2]);
|
|
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : drop_first } });
|
|
assertThrows(() => instance.exports.main(1, 2), TypeError, "multi-return length mismatch");
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : repeat } });
|
|
assertThrows(() => instance.exports.main(1, 2), TypeError, "multi-return length mismatch");
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : proxy_throw } });
|
|
assertThrows(() => instance.exports.main(1, 2), Error, "abc");
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : not_receiver } });
|
|
assertThrows(() => instance.exports.main(1, 2), TypeError, /not iterable/);
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : not_iterable } });
|
|
assertThrows(() => instance.exports.main(1, 2), TypeError, /not iterable/);
|
|
instance = new WebAssembly.Instance(module, { 'imports' : { 'f' : generator_throw } });
|
|
assertThrows(() => instance.exports.main(1, 2), Error, "def");
|
|
})();
|