blob: 3dd580d269e42008b241fe7e7c277bb95cc9d205 [file] [log] [blame]
// 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 --expose-gc --stress-compaction --allow-natives-syntax
load("test/mjsunit/wasm/wasm-module-builder.js");
var kMemSize = 65536;
function genModule(memory) {
var builder = new WasmModuleBuilder();
builder.addImportedMemory("", "memory", 1);
builder.exportMemoryAs("memory");
builder.addFunction("main", kSig_i_i)
.addBody([
// main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
// TODO(titzer): this manual bytecode has a copy of test-run-wasm.cc
/**/ kExprLoop, kWasmStmt, // --
/* */ kExprGetLocal, 0, // --
/* */ kExprIf, kWasmStmt, // --
/* */ kExprGetLocal, 0, // --
/* */ kExprI32LoadMem, 0, 0, // --
/* */ kExprIf, kWasmStmt, // --
/* */ kExprI32Const, 127, // --
/* */ kExprReturn, // --
/* */ kExprEnd, // --
/* */ kExprGetLocal, 0, // --
/* */ kExprI32Const, 4, // --
/* */ kExprI32Sub, // --
/* */ kExprSetLocal, 0, // --
/* */ kExprBr, 1, // --
/* */ kExprEnd, // --
/* */ kExprEnd, // --
/**/ kExprI32Const, 0 // --
])
.exportFunc();
var module = builder.instantiate({"": {memory:memory}});
assertTrue(module.exports.memory instanceof WebAssembly.Memory);
if (memory != null) assertEquals(memory.buffer, module.exports.memory.buffer);
return module;
}
function testPokeMemory() {
print("testPokeMemory");
var module = genModule(new WebAssembly.Memory({initial: 1}));
var buffer = module.exports.memory.buffer;
var main = module.exports.main;
assertEquals(kMemSize, buffer.byteLength);
var array = new Int8Array(buffer);
assertEquals(kMemSize, array.length);
for (var i = 0; i < kMemSize; i++) {
assertEquals(0, array[i]);
}
for (var i = 0; i < 10; i++) {
assertEquals(0, main(kMemSize - 4));
array[kMemSize/2 + i] = 1;
assertEquals(0, main(kMemSize/2 - 4));
assertEquals(-1, main(kMemSize - 4));
array[kMemSize/2 + i] = 0;
assertEquals(0, main(kMemSize - 4));
}
}
testPokeMemory();
function genAndGetMain(buffer) {
return genModule(buffer).exports.main; // to prevent intermediates living
}
function testSurvivalAcrossGc() {
var checker = genAndGetMain(new WebAssembly.Memory({initial: 1}));
for (var i = 0; i < 3; i++) {
print("gc run ", i);
assertEquals(0, checker(kMemSize - 4));
gc();
}
}
testSurvivalAcrossGc();
testSurvivalAcrossGc();
testSurvivalAcrossGc();
testSurvivalAcrossGc();
function testPokeOuterMemory() {
print("testPokeOuterMemory");
var buffer = new WebAssembly.Memory({initial: kMemSize / kPageSize});
var module = genModule(buffer);
var main = module.exports.main;
assertEquals(kMemSize, buffer.buffer.byteLength);
var array = new Int8Array(buffer.buffer);
assertEquals(kMemSize, array.length);
for (var i = 0; i < kMemSize; i++) {
assertEquals(0, array[i]);
}
for (var i = 0; i < 10; i++) {
assertEquals(0, main(kMemSize - 4));
array[kMemSize/2 + i] = 1;
assertEquals(0, main(kMemSize/2 - 4));
assertEquals(-1, main(kMemSize - 4));
array[kMemSize/2 + i] = 0;
assertEquals(0, main(kMemSize - 4));
}
}
testPokeOuterMemory();
function testOuterMemorySurvivalAcrossGc() {
var buffer = new WebAssembly.Memory({initial: kMemSize / kPageSize});
var checker = genAndGetMain(buffer);
for (var i = 0; i < 3; i++) {
print("gc run ", i);
assertEquals(0, checker(kMemSize - 4));
gc();
}
}
testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();
function testOOBThrows() {
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
builder.addFunction("geti", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kExprI32LoadMem, 0, 0,
kExprI32StoreMem, 0, 0,
kExprGetLocal, 1,
kExprI32LoadMem, 0, 0,
])
.exportFunc();
var module = builder.instantiate();
var offset;
function read() { return module.exports.geti(0, offset); }
function write() { return module.exports.geti(offset, 0); }
for (offset = 0; offset < 65533; offset++) {
assertEquals(0, read());
assertEquals(0, write());
}
// Note that this test might be run concurrently in multiple Isolates, which
// makes an exact comparison of the expected trap count unreliable. But is is
// still possible to check the lower bound for the expected trap count.
for (offset = 65534; offset < 66536; offset++) {
const trap_count = %GetWasmRecoveredTrapCount();
assertTraps(kTrapMemOutOfBounds, read);
assertTraps(kTrapMemOutOfBounds, write);
if (%IsWasmTrapHandlerEnabled()) {
assertTrue(trap_count + 2 <= %GetWasmRecoveredTrapCount());
}
}
}
testOOBThrows();
function testAddressSpaceLimit() {
// 1TiB + 4 GiB, see wasm-memory.h
const kMaxAddressSpace = 1 * 1024 * 1024 * 1024 * 1024
+ 4 * 1024 * 1024 * 1024;
const kAddressSpacePerMemory = 10 * 1024 * 1024 * 1024;
let last_memory;
try {
let memories = [];
let address_space = 0;
while (address_space <= kMaxAddressSpace + 1) {
last_memory = new WebAssembly.Memory({initial: 1})
memories.push(last_memory);
address_space += kAddressSpacePerMemory;
}
} catch (e) {
assertTrue(e instanceof RangeError);
return;
}
assertUnreachable("should have reached the address space limit");
}
if(%IsWasmTrapHandlerEnabled()) {
testAddressSpaceLimit();
}