v8/test/mjsunit/wasm/import-mutable-global.js
Ben Smith 2747d0e6da [wasm] Fix some bugs in mut global implementation
* If the mutability of the global object doesn't match the module, then
  it should throw a LinkError.
* There was a missing `return` when importing a Number as a mutable
  global.
* All globals were being exported as immutable.
* Attempting to set the value of an immutable global should throw a
  TypeError.
* The length of the setter function should be 1.

Bug: v8:7625
Change-Id: I08d6a428506a18db15eecadf4cbcee89e0658924
Reviewed-on: https://chromium-review.googlesource.com/1031626
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Ben Smith <binji@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52865}
2018-04-27 19:14:36 +00:00

194 lines
6.1 KiB
JavaScript

// Copyright 2018 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-mut-global --expose-gc
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
(function TestBasic() {
let global = new WebAssembly.Global({type: 'i32'}, 1);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmI32);
builder.addFunction("main", kSig_i_v)
.addBody([kExprGetGlobal, 0])
.exportAs("main");
let main = builder.instantiate({mod: {g: global}}).exports.main;
assertEquals(1, main());
})();
(function TestTypeMismatch() {
let global = new WebAssembly.Global({type: 'f32'}, 1);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmI32);
assertThrows(() => builder.instantiate({mod: {g: global}}));
})();
(function TestMutableMismatch() {
let global = new WebAssembly.Global({type: 'f64'}, 1);
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmF64, true);
assertThrows(() => builder.instantiate({mod: {g: global}}));
global = new WebAssembly.Global({type: 'i32', mutable: true}, 1);
builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmI32);
assertThrows(() => builder.instantiate({mod: {g: global}}));
})();
(function TestImportMutableAsNumber() {
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmF32, true);
assertThrows(() => builder.instantiate({mod: {g: 1234}}));
})();
(function TestImportI64AsNumber() {
let builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", "g", kWasmI64);
assertThrows(() => builder.instantiate({mod: {g: 1234}}));
})();
function addGlobalGetterAndSetter(builder, index, name, type) {
builder.addFunction('get' + name, makeSig([], [type]))
.addBody([kExprGetGlobal, index])
.exportFunc();
builder.addFunction('set' + name, makeSig([type], []))
.addBody([kExprGetLocal, 0, kExprSetGlobal, index])
.exportFunc();
}
(function TestImportMutableGlobal() {
const globalDesc = [
{name: 'i32', type: kWasmI32},
{name: 'f32', type: kWasmF32},
{name: 'f64', type: kWasmF64},
];
let globals = {};
let builder = new WasmModuleBuilder();
for (let [index, {name, type}] of globalDesc.entries()) {
globals[name] = new WebAssembly.Global({type: name, mutable: true});
builder.addImportedGlobal("mod", name, type, true);
addGlobalGetterAndSetter(builder, index, name, type);
}
let inst = builder.instantiate(
{mod: {i32: globals.i32, f32: globals.f32, f64: globals.f64}});
for (let type of ['i32', 'f32', 'f64']) {
let global = globals[type];
let get = inst.exports['get' + type];
let set = inst.exports['set' + type];
assertEquals(get(), global.value, type);
set(1234567);
assertEquals(1234567, global.value, type);
global.value = 7654321;
assertEquals(7654321, get(), type);
}
})();
(function TestImportExportedMutableGlobal() {
const globalDesc = [
{name: 'i32', type: kWasmI32},
{name: 'f32', type: kWasmF32},
{name: 'f64', type: kWasmF64},
];
let builder1 = new WasmModuleBuilder();
let builder2 = new WasmModuleBuilder();
for (let [index, {name, type}] of globalDesc.entries()) {
builder1.addGlobal(type, true).exportAs(name);
addGlobalGetterAndSetter(builder1, index, name, type);
builder2.addImportedGlobal("mod", name, type, true);
addGlobalGetterAndSetter(builder2, index, name, type);
}
let inst1 = builder1.instantiate();
let inst2 = builder2.instantiate({
mod: {
i32: inst1.exports.i32,
f32: inst1.exports.f32,
f64: inst1.exports.f64
}
});
for (let type of ['i32', 'f32', 'f64']) {
let get1 = inst1.exports['get' + type];
let get2 = inst2.exports['get' + type];
let set1 = inst1.exports['set' + type];
let set2 = inst2.exports['set' + type];
assertEquals(get1(), get2(), type);
set1(1234567);
assertEquals(1234567, get2(), type);
set2(7654321);
assertEquals(7654321, get1(), type);
}
})();
(function TestImportExportedMutableGlobalI64() {
function addGettersAndSetters(builder) {
const index = 0;
builder.addFunction('geti64_hi', makeSig([], [kWasmI32]))
.addBody([
kExprGetGlobal, index,
kExprI64Const, 32, kExprI64ShrU,
kExprI32ConvertI64])
.exportFunc();
builder.addFunction('geti64_lo', makeSig([], [kWasmI32]))
.addBody([kExprGetGlobal, index, kExprI32ConvertI64])
.exportFunc();
builder.addFunction("seti64", makeSig([kWasmI32, kWasmI32], []))
.addBody([
kExprGetLocal, 1, kExprI64UConvertI32,
kExprGetLocal, 0, kExprI64UConvertI32,
kExprI64Const, 32, kExprI64Shl,
kExprI64Ior,
kExprSetGlobal, index])
.exportFunc();
};
let builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI64, true).exportAs('i64');
addGettersAndSetters(builder);
let inst1 = builder.instantiate();
builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", 'i64', kWasmI64, true);
addGettersAndSetters(builder);
let inst2 = builder.instantiate({ mod: { i64: inst1.exports.i64 } });
assertEquals(inst1.exports.geti64_lo(), inst2.exports.geti64_lo());
assertEquals(inst1.exports.geti64_hi(), inst2.exports.geti64_hi());
inst1.exports.seti64(13579, 24680);
assertEquals(13579, inst2.exports.geti64_hi());
assertEquals(24680, inst2.exports.geti64_lo());
inst2.exports.seti64(97531, 86420);
assertEquals(97531, inst1.exports.geti64_hi());
assertEquals(86420, inst1.exports.geti64_lo());
})();
(function TestImportMutableAcrossGc() {
let builder = new WasmModuleBuilder();
builder.addGlobal(kWasmI32, true).exportAs('i32');
let inst1 = builder.instantiate();
builder = new WasmModuleBuilder();
builder.addImportedGlobal("mod", 'i32', kWasmI32, true);
addGlobalGetterAndSetter(builder, 0, 'i32', kWasmI32);
let inst2 = builder.instantiate({ mod: { i32: inst1.exports.i32 } });
delete inst1;
gc();
inst2.exports.seti32(0x789abcde);
assertEquals(0x789abcde, inst2.exports.geti32());
})();