v8/test/mjsunit/wasm/memory_4gb_oob.js
Ben L. Titzer 352e408b0e [wasm] Support 4GiB memories in Liftoff
Add codegen support for up to 4GiB memories in Liftoff code.

This CL also adds three new mjsunit tests that stress large WASM
memories (1, 2, and 4 GiB) and checks that accesses near these
boundaries properly generate traps.

Note there is still some trickiness around the setting of:
  1.) the flag --wasm-max-mem-pages
  2.) wasm-limits.h kSpecMaxWasmMemoryPages = 65536
  3.) wasm-limits.h kV8MaxWasmMemoryPages = 32767

In particular, the allocation of memories is still limited to
3.) and the runtime flag can only lower this limit.

The above means that the tests for 2GiB and 4GiB memories will silently
OOM by design until 3.) is changed (though they currently pass with
manual testing). I argue it is better to include these tests up front,
since they will immediately trigger if their memory allocation succeeds.

Therefore the plan is to lift the restriction on 3.) after removing
all other other internal V8 limitations including array buffers and views.

R=clemensh@chromium.org
CC=mstarzinger@chromium.org
BUG=v8:7881

Change-Id: I3205ac2daf5c9a84364c670a2c3ef2258e5649f6
Reviewed-on: https://chromium-review.googlesource.com/1151309
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54754}
2018-07-27 14:20:00 +00:00

98 lines
3.4 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.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
const k1MiB = 1 * 1024 * 1024;
const k1GiB = 1 * 1024 * 1024 * 1024;
const k2GiB = 2 * k1GiB;
const k3GiB = 3 * k1GiB;
const k4GiB = 4 * k1GiB;
const kMaxMemory = k4GiB;
// Indexes (and offsets) used to systematically probe the memory.
const indexes = (() => {
const a = k1GiB, b = k2GiB, c = k3GiB, d = k4GiB;
return [
0, 1, 2, 3, 4, 5, 7, 8, 9, // near 0
a-8, a-4, a+0, a+1, a+2, a+3, a+4, a+5, a+7, a+8, a+9, // near 1GiB
b-8, b-4, b+0, b+1, b+2, b+3, b+4, b+5, b+7, b+8, b+9, // near 2GiB
c-8, c-4, c+0, c+1, c+2, c+3, c+4, c+5, c+7, c+8, c+9, // near 3GiB
d-9, d-8, d-7, d-5, d-4, d-3, d-2, d-1 // near 4GiB
];
})();
(function Test() {
var memory;
function BuildAccessors(type, load_opcode, store_opcode, offset) {
builder = new WasmModuleBuilder();
builder.addImportedMemory("i", "mem");
const h = 0x80;
const m = 0x7f;
let offset_bytes = [h|((offset >>> 0) & m), // LEB encoding of offset
h|((offset >>> 7) & m),
h|((offset >>> 14) & m),
h|((offset >>> 21) & m),
0|((offset >>> 28) & m)];
builder.addFunction("load", makeSig([kWasmI32], [type]))
.addBody([ // --
kExprGetLocal, 0, // --
load_opcode, 0, ...offset_bytes, // --
]) // --
.exportFunc();
builder.addFunction("store", makeSig([kWasmI32, type], []))
.addBody([ // --
kExprGetLocal, 0, // --
kExprGetLocal, 1, // --
store_opcode, 0, ...offset_bytes, // --
]) // --
.exportFunc();
let i = builder.instantiate({i: {mem: memory}});
return {offset: offset, load: i.exports.load, store: i.exports.store};
}
function probe(a, size, offset, f) {
print(`size=${size} offset=${offset}`);
for (let i of indexes) {
let oob = (i + size + offset) > kMaxMemory;
if (oob) {
// print(` ${i} + ${offset} OOB`);
assertThrows(() => a.store(i, f(i)));
assertThrows(() => a.load(i));
} else {
// print(` ${i} = ${f(i)}`);
a.store(i, f(i));
assertEquals(f(i), a.load(i));
}
}
}
try {
let kPages = kMaxMemory / kPageSize;
memory = new WebAssembly.Memory({initial: kPages, maximum: kPages});
} catch (e) {
print("OOM: sorry, best effort max memory size test.");
return;
}
assertEquals(kMaxMemory, memory.buffer.byteLength);
for (let offset of indexes) {
let a = BuildAccessors(kWasmI32, kExprI32LoadMem, kExprI32StoreMem, offset);
probe(a, 4, offset, i => (0xaabbccee ^ ((i >> 11) * 0x110005)) | 0);
}
for (let offset of indexes) {
let a = BuildAccessors(kWasmI32, kExprI32LoadMem8U, kExprI32StoreMem8, offset);
probe(a, 1, offset, i => (0xee ^ ((i >> 11) * 0x05)) & 0xFF);
}
for (let offset of indexes) {
let a = BuildAccessors(kWasmF64, kExprF64LoadMem, kExprF64StoreMem, offset);
probe(a, 8, offset, i => 0xaabbccee ^ ((i >> 11) * 0x110005));
}
})();