c96ac82c50
This makes stack checks in WasmCode independent of the underlying Isolate by loading the limit address from the WasmInstanceObject instead of embedding it into the instruction stream. It hence removes the last use of the Isolate field from WasmGraphBuilder. Additionally this introduces the notion of a "runtime stub" which represents stub code global to the NativeModule that can be directly called from each WasmCode in the same module. These stubs can act as trampolines via which Isolate-independent WasmCode can enter other V8 builtins or runtime functions that remain Isolate-dependent. They will eventually replace the current "trampoline" in a NativeModule. R=titzer@chromium.org BUG=v8:7424 Change-Id: Ie1f5582ee656b1ab7716ea06316d6e21a0268e74 Reviewed-on: https://chromium-review.googlesource.com/1078732 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#53487}
280 lines
9.1 KiB
JavaScript
280 lines
9.1 KiB
JavaScript
// Copyright 2015 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 --allow-natives-syntax --expose-gc
|
|
|
|
load("test/mjsunit/wasm/wasm-constants.js");
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
(function SerializeAndDeserializeModule() {
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addImportedMemory("", "memory", 1);
|
|
var kSig_v_i = makeSig([kWasmI32], []);
|
|
var signature = builder.addType(kSig_v_i);
|
|
builder.addImport("", "some_value", kSig_i_v);
|
|
builder.addImport("", "writer", signature);
|
|
|
|
builder.addFunction("main", kSig_i_i)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprI32LoadMem, 0, 0,
|
|
kExprI32Const, 1,
|
|
kExprCallIndirect, signature, kTableZero,
|
|
kExprGetLocal,0,
|
|
kExprI32LoadMem,0, 0,
|
|
kExprCallFunction, 0,
|
|
kExprI32Add
|
|
]).exportFunc();
|
|
|
|
// writer(mem[i]);
|
|
// return mem[i] + some_value();
|
|
builder.addFunction("_wrap_writer", signature)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprCallFunction, 1]);
|
|
builder.appendToTable([2, 3]);
|
|
|
|
var wire_bytes = builder.toBuffer();
|
|
var module = new WebAssembly.Module(wire_bytes);
|
|
var mem_1 = new WebAssembly.Memory({initial: 1});
|
|
var view_1 = new Int32Array(mem_1.buffer);
|
|
view_1[0] = 42;
|
|
var outval_1;
|
|
var i1 = new WebAssembly.Instance(module, {"":
|
|
{some_value: () => 1,
|
|
writer: (x) => outval_1 = x ,
|
|
memory: mem_1}
|
|
});
|
|
|
|
assertEquals(43, i1.exports.main(0));
|
|
|
|
assertEquals(42, outval_1);
|
|
var buff = %SerializeWasmModule(module);
|
|
module = null;
|
|
gc();
|
|
module = %DeserializeWasmModule(buff, wire_bytes);
|
|
|
|
var mem_2 = new WebAssembly.Memory({initial: 2});
|
|
var view_2 = new Int32Array(mem_2.buffer);
|
|
|
|
view_2[0] = 50;
|
|
|
|
var outval_2;
|
|
var i2 = new WebAssembly.Instance(module, {"":
|
|
{some_value: () => 1,
|
|
writer: (x) => outval_2 = x ,
|
|
memory: mem_2}
|
|
});
|
|
|
|
assertEquals(51, i2.exports.main(0));
|
|
|
|
assertEquals(50, outval_2);
|
|
// The instances don't share memory through deserialization.
|
|
assertEquals(43, i1.exports.main(0));
|
|
})();
|
|
|
|
(function DeserializeInvalidObject() {
|
|
var invalid_buffer = new ArrayBuffer(10);
|
|
|
|
module = %DeserializeWasmModule(invalid_buffer, invalid_buffer);
|
|
assertEquals(module, undefined);
|
|
})();
|
|
|
|
(function RelationBetweenModuleAndClone() {
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([kExprI32Const, 42])
|
|
.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer();
|
|
var compiled_module = new WebAssembly.Module(wire_bytes);
|
|
var serialized = %SerializeWasmModule(compiled_module);
|
|
var clone = %DeserializeWasmModule(serialized, wire_bytes);
|
|
|
|
assertNotNull(clone);
|
|
assertFalse(clone == undefined);
|
|
assertFalse(clone == compiled_module);
|
|
assertEquals(clone.constructor, compiled_module.constructor);
|
|
})();
|
|
|
|
(function SerializeWrappersWithSameSignature() {
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([kExprI32Const, 42])
|
|
.exportFunc();
|
|
builder.addFunction("main_same_signature", kSig_i_v)
|
|
.addBody([kExprI32Const, 23])
|
|
.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer();
|
|
var compiled_module = new WebAssembly.Module(wire_bytes);
|
|
var serialized = %SerializeWasmModule(compiled_module);
|
|
var clone = %DeserializeWasmModule(serialized, wire_bytes);
|
|
|
|
assertNotNull(clone);
|
|
assertFalse(clone == undefined);
|
|
assertFalse(clone == compiled_module);
|
|
assertEquals(clone.constructor, compiled_module.constructor);
|
|
})();
|
|
|
|
(function SerializeAfterInstantiation() {
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([kExprI32Const, 42])
|
|
.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer()
|
|
var compiled_module = new WebAssembly.Module(wire_bytes);
|
|
var instance1 = new WebAssembly.Instance(compiled_module);
|
|
var instance2 = new WebAssembly.Instance(compiled_module);
|
|
var serialized = %SerializeWasmModule(compiled_module);
|
|
var clone = %DeserializeWasmModule(serialized, wire_bytes);
|
|
|
|
assertNotNull(clone);
|
|
assertFalse(clone == undefined);
|
|
assertFalse(clone == compiled_module);
|
|
assertEquals(clone.constructor, compiled_module.constructor);
|
|
var instance3 = new WebAssembly.Instance(clone);
|
|
assertFalse(instance3 == undefined);
|
|
})();
|
|
|
|
|
|
(function SerializeAfterInstantiationWithMemory() {
|
|
let builder = new WasmModuleBuilder();
|
|
builder.addImportedMemory("", "memory", 1);
|
|
builder.addFunction("main", kSig_i_v)
|
|
.addBody([kExprI32Const, 42])
|
|
.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer()
|
|
var compiled_module = new WebAssembly.Module(wire_bytes);
|
|
var mem_1 = new WebAssembly.Memory({initial: 1});
|
|
var ffi = {"":{memory:mem_1}};
|
|
var instance1 = new WebAssembly.Instance(compiled_module, ffi);
|
|
var serialized = %SerializeWasmModule(compiled_module);
|
|
var clone = %DeserializeWasmModule(serialized, wire_bytes);
|
|
|
|
assertNotNull(clone);
|
|
assertFalse(clone == undefined);
|
|
assertFalse(clone == compiled_module);
|
|
assertEquals(clone.constructor, compiled_module.constructor);
|
|
var instance2 = new WebAssembly.Instance(clone, ffi);
|
|
assertFalse(instance2 == undefined);
|
|
})();
|
|
|
|
(function GlobalsArePrivateBetweenClones() {
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addGlobal(kWasmI32, true);
|
|
builder.addFunction("read", kSig_i_v)
|
|
.addBody([
|
|
kExprGetGlobal, 0])
|
|
.exportFunc();
|
|
|
|
builder.addFunction("write", kSig_v_i)
|
|
.addBody([
|
|
kExprGetLocal, 0,
|
|
kExprSetGlobal, 0])
|
|
.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer();
|
|
var module = new WebAssembly.Module(wire_bytes);
|
|
var i1 = new WebAssembly.Instance(module);
|
|
// serialize and replace module
|
|
var buff = %SerializeWasmModule(module);
|
|
var module_clone = %DeserializeWasmModule(buff, wire_bytes);
|
|
var i2 = new WebAssembly.Instance(module_clone);
|
|
i1.exports.write(1);
|
|
i2.exports.write(2);
|
|
assertEquals(1, i1.exports.read());
|
|
assertEquals(2, i2.exports.read());
|
|
})();
|
|
|
|
(function SharedTableTest() {
|
|
let kTableSize = 3;
|
|
var sig_index1;
|
|
|
|
function MakeTableExportingModule(constant) {
|
|
// A module that defines a table and exports it.
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addType(kSig_i_i);
|
|
builder.addType(kSig_i_ii);
|
|
sig_index1 = builder.addType(kSig_i_v);
|
|
var f1 = builder.addFunction("f1", sig_index1)
|
|
.addBody([kExprI32Const, constant]);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprGetLocal, 0, // --
|
|
kExprCallIndirect, sig_index1, kTableZero]) // --
|
|
.exportAs("main");
|
|
|
|
builder.setFunctionTableBounds(kTableSize, kTableSize);
|
|
builder.addFunctionTableInit(0, false, [f1.index]);
|
|
builder.addExportOfKind("table", kExternalTable, 0);
|
|
|
|
return new WebAssembly.Module(builder.toBuffer());
|
|
}
|
|
var m1 = MakeTableExportingModule(11);
|
|
|
|
// Module {m2} imports the table and adds {f2}.
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addType(kSig_i_ii);
|
|
var sig_index2 = builder.addType(kSig_i_v);
|
|
var f2 = builder.addFunction("f2", sig_index2)
|
|
.addBody([kExprI32Const, 22]);
|
|
|
|
builder.addFunction("main", kSig_i_ii)
|
|
.addBody([
|
|
kExprGetLocal, 0, // --
|
|
kExprCallIndirect, sig_index2, kTableZero]) // --
|
|
.exportAs("main");
|
|
|
|
builder.addImportedTable("z", "table", kTableSize, kTableSize);
|
|
builder.addFunctionTableInit(1, false, [f2.index], true);
|
|
var m2_bytes = builder.toBuffer();
|
|
var m2 = new WebAssembly.Module(m2_bytes);
|
|
|
|
assertFalse(sig_index1 == sig_index2);
|
|
|
|
var i1 = new WebAssembly.Instance(m1);
|
|
var i2 = new WebAssembly.Instance(m2, {z: {table: i1.exports.table}});
|
|
|
|
var serialized_m2 = %SerializeWasmModule(m2);
|
|
var m2_clone = %DeserializeWasmModule(serialized_m2, m2_bytes);
|
|
|
|
var m3 = MakeTableExportingModule(33);
|
|
var i3 = new WebAssembly.Instance(m3);
|
|
var i2_prime = new WebAssembly.Instance(m2_clone,
|
|
{z: {table: i3.exports.table}});
|
|
|
|
assertEquals(11, i1.exports.main(0));
|
|
assertEquals(11, i2.exports.main(0));
|
|
|
|
assertEquals(22, i1.exports.main(1));
|
|
assertEquals(22, i2.exports.main(1));
|
|
|
|
assertEquals(33, i3.exports.main(0));
|
|
assertEquals(33, i2_prime.exports.main(0));
|
|
|
|
assertThrows(() => i1.exports.main(2));
|
|
assertThrows(() => i2.exports.main(2));
|
|
assertThrows(() => i1.exports.main(3));
|
|
assertThrows(() => i2.exports.main(3));
|
|
})();
|
|
|
|
(function StackOverflowAfterSerialization() {
|
|
const builder = new WasmModuleBuilder();
|
|
var fun = builder.addFunction('main', kSig_v_v);
|
|
fun.addBody([kExprCallFunction, fun.index]);
|
|
fun.exportFunc();
|
|
|
|
var wire_bytes = builder.toBuffer();
|
|
var module = new WebAssembly.Module(wire_bytes);
|
|
var buffer = %SerializeWasmModule(module);
|
|
module = %DeserializeWasmModule(buffer, wire_bytes);
|
|
var instance = new WebAssembly.Instance(module);
|
|
|
|
assertThrows(instance.exports.main, RangeError);
|
|
})();
|