v8/test/mjsunit/wasm/exceptions-global.js
Michael Starzinger 4902e91a82 [wasm] Fix reference type global initialization by index.
This fixes initialization of reference type global variables (i.e.
anyref and except_ref) based on an index of another global. It extends
the existing support to exception types, fixes the logic, and also fixes
a missing write barrier.

R=ahaas@chromium.org
TEST=mjsunit/wasm/exceptions-global
BUG=v8:8091

Change-Id: Ia91f1ea03be24fadf3023a5acdd073badb8dcd93
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1539581
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60525}
2019-03-29 12:39:40 +00:00

155 lines
6.1 KiB
JavaScript

// Copyright 2019 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: --expose-wasm --experimental-wasm-eh --allow-natives-syntax
// Note that this test does not pass --experimental-wasm-anyref on purpose so
// that we make sure the two flags can be controlled separately/independently.
load("test/mjsunit/wasm/wasm-module-builder.js");
// First we just test that "except_ref" global variables are allowed.
(function TestGlobalExceptRefSupported() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g = builder.addGlobal(kWasmExceptRef);
builder.addFunction("push_and_drop_except_ref", kSig_v_v)
.addBody([
kExprGetGlobal, g.index,
kExprDrop,
]).exportFunc();
let instance = builder.instantiate();
assertDoesNotThrow(instance.exports.push_and_drop_except_ref);
})();
// Test default value that global "except_ref" variables are initialized with.
(function TestGlobalExceptRefDefaultValue() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g = builder.addGlobal(kWasmExceptRef);
builder.addFunction('push_and_return_except_ref', kSig_e_v)
.addBody([kExprGetGlobal, g.index])
.exportFunc();
let instance = builder.instantiate();
assertEquals(null, instance.exports.push_and_return_except_ref());
})();
// Test storing a caught exception into an exported mutable "except_ref" global.
(function TestGlobalExceptRefSetCaught() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_i);
let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn");
builder.addFunction('catch_and_set_except_ref', kSig_v_i)
.addBody([
kExprTry, kWasmStmt,
kExprGetLocal, 0,
kExprThrow, except,
kExprCatch,
kExprSetGlobal, g.index,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
assertDoesNotThrow(() => instance.exports.catch_and_set_except_ref(23));
let exception = instance.exports.exn.value; // Exported mutable global.
assertInstanceof(exception, WebAssembly.RuntimeError);
assertEquals(except, %GetWasmExceptionId(exception, instance));
})();
// Test storing a parameter into an exported mutable "except_ref" global.
(function TestGlobalExceptRefSetParameter() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn");
builder.addFunction('set_param_except_ref', kSig_v_e)
.addBody([
kExprTry, kWasmStmt,
kExprGetLocal, 0,
kExprRethrow,
kExprCatch,
kExprSetGlobal, g.index,
kExprEnd,
]).exportFunc();
let exception = "my fancy exception";
let instance = builder.instantiate();
assertDoesNotThrow(() => instance.exports.set_param_except_ref(exception));
assertEquals(exception, instance.exports.exn.value);
})();
// Test loading an imported "except_ref" global and re-throwing the exception.
(function TestGlobalExceptRefGetImportedAndRethrow() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef);
builder.addFunction('rethrow_except_ref', kSig_v_v)
.addBody([
kExprGetGlobal, g_index,
kExprRethrow,
]).exportFunc();
let exception = "my fancy exception";
let instance = builder.instantiate({ "m": { "exn": exception }});
assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception);
})();
// Test loading an exported mutable "except_ref" being changed from the outside.
(function TestGlobalExceptRefGetExportedMutableAndRethrow() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g = builder.addGlobal(kWasmExceptRef, true).exportAs("exn");
builder.addFunction('rethrow_except_ref', kSig_v_v)
.addBody([
kExprGetGlobal, g.index,
kExprRethrow,
]).exportFunc();
let instance = builder.instantiate();
let exception1 = instance.exports.exn.value = "my fancy exception";
assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1);
let exception2 = instance.exports.exn.value = "an even fancier exception";
assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2);
})();
// TODO(mstarzinger): Add the following test once proposal makes it clear how
// far interaction with the mutable globals proposal is intended to go.
// Test loading an imported mutable "except_ref" being changed from the outside.
/*(function TestGlobalExceptRefGetImportedMutableAndRethrow() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef, true);
builder.addFunction('rethrow_except_ref', kSig_v_v)
.addBody([
kExprGetGlobal, g_index,
kExprRethrow,
]).exportFunc();
let exception1 = "my fancy exception";
let desc = { value: 'except_ref', mutable: true };
let mutable_global = new WebAssembly.Global(desc, exception1);
let instance = builder.instantiate({ "m": { "exn": mutable_global }});
assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception1);
let exception2 = mutable_global.value = "an even fancier exception";
assertThrowsEquals(() => instance.exports.rethrow_except_ref(), exception2);
})();*/
// Test custom initialization index for a global "except_ref" variable.
(function TestGlobalExceptRefInitIndex() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let g1_index = builder.addImportedGlobal("m", "exn", kWasmExceptRef);
let g2 = builder.addGlobal(kWasmExceptRef);
g2.init_index = g1_index; // Initialize {g2} to equal {g1}.
builder.addFunction('push_and_return_except_ref', kSig_e_v)
.addBody([kExprGetGlobal, g2.index])
.exportFunc();
let exception = { x: "my fancy exception" };
let instance = builder.instantiate({ "m": { "exn": exception }});
assertSame(exception, instance.exports.push_and_return_except_ref());
})();