421fd3929d
This brings our constants back in line with the changed spec text. We already use kExprTableGet and kExprTableSet, but for locals and globals we still use the old wording. This renaming is mostly mechanical. PS1 was created using: ag -l 'kExpr(Get|Set|Tee)Local' src test | \ xargs -L1 sed -E 's/kExpr(Get|Set|Tee)Local\b/kExprLocal\1/g' -i PS2 contains manual fixes. R=mstarzinger@chromium.org Bug: v8:9810 Change-Id: I1617f1b2a100685a3bf56218e76845a9481959c5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1847354 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#64161}
545 lines
16 KiB
JavaScript
545 lines
16 KiB
JavaScript
// Copyright 2016 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 --stress-compaction
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
|
|
function genMemoryGrowBuilder() {
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addFunction("grow_memory", kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprMemoryGrow, kMemoryZero])
|
|
.exportFunc();
|
|
builder.addFunction("load", kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprI32LoadMem, 0, 0])
|
|
.exportFunc();
|
|
builder.addFunction("store", kSig_i_ii)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32StoreMem, 0, 0,
|
|
kExprLocalGet, 1])
|
|
.exportFunc();
|
|
builder.addFunction("load16", kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprI32LoadMem16U, 0, 0])
|
|
.exportFunc();
|
|
builder.addFunction("store16", kSig_i_ii)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32StoreMem16, 0, 0,
|
|
kExprLocalGet, 1])
|
|
.exportFunc();
|
|
builder.addFunction("load8", kSig_i_i)
|
|
.addBody([kExprLocalGet, 0, kExprI32LoadMem8U, 0, 0])
|
|
.exportFunc();
|
|
builder.addFunction("store8", kSig_i_ii)
|
|
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprI32StoreMem8, 0, 0,
|
|
kExprLocalGet, 1])
|
|
.exportFunc();
|
|
return builder;
|
|
}
|
|
|
|
// V8 internal memory size limit.
|
|
var kV8MaxPages = 32767;
|
|
|
|
|
|
// TODO(gdeepti): Generate tests programatically for all the sizes instead of
|
|
// current implementation.
|
|
function testMemoryGrowReadWrite32() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 4); offset+=4) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = kPageSize - 3; offset < kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
for (offset = kPageSize; offset <= 4*kPageSize -4; offset+=4) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 4*kPageSize - 3; offset < 4*kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(4, growMem(15));
|
|
|
|
for (offset = 4*kPageSize - 3; offset <= 4*kPageSize + 4; offset+=4) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize - 10; offset <= 19*kPageSize - 4; offset+=4) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize - 3; offset < 19*kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowReadWrite32();
|
|
|
|
function testMemoryGrowReadWrite16() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load16(offset); }
|
|
function poke(value) { return module.exports.store16(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 2); offset+=2) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = kPageSize - 1; offset < kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
for (offset = kPageSize; offset <= 4*kPageSize -2; offset+=2) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 4*kPageSize - 1; offset < 4*kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(4, growMem(15));
|
|
|
|
for (offset = 4*kPageSize - 2; offset <= 4*kPageSize + 4; offset+=2) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize - 10; offset <= 19*kPageSize - 2; offset+=2) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize - 1; offset < 19*kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowReadWrite16();
|
|
|
|
function testMemoryGrowReadWrite8() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load8(offset); }
|
|
function poke(value) { return module.exports.store8(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= kPageSize - 1; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = kPageSize; offset < kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
for (offset = kPageSize; offset <= 4*kPageSize -1; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 4*kPageSize; offset < 4*kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
assertEquals(4, growMem(15));
|
|
|
|
for (offset = 4*kPageSize; offset <= 4*kPageSize + 4; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize - 10; offset <= 19*kPageSize - 1; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
for (offset = 19*kPageSize; offset < 19*kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowReadWrite8();
|
|
|
|
function testMemoryGrowZeroInitialSize() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(0, growMem(1));
|
|
|
|
for(offset = 0; offset <= kPageSize - 4; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
|
|
for(offset = kPageSize - 3; offset <= kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
|
|
offset = 3*kPageSize;
|
|
for (var i = 1; i < 4; i++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
assertEquals(i, growMem(1));
|
|
}
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
|
|
testMemoryGrowZeroInitialSize();
|
|
|
|
function testMemoryGrowZeroInitialSize32() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(0, growMem(1));
|
|
|
|
for(offset = 0; offset <= kPageSize - 4; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
|
|
for(offset = kPageSize - 3; offset <= kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowZeroInitialSize32();
|
|
|
|
function testMemoryGrowZeroInitialSize16() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load16(offset); }
|
|
function poke(value) { return module.exports.store16(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(0, growMem(1));
|
|
|
|
for(offset = 0; offset <= kPageSize - 2; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
|
|
for(offset = kPageSize - 1; offset <= kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowZeroInitialSize16();
|
|
|
|
function testMemoryGrowZeroInitialSize8() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset;
|
|
function peek() { return module.exports.load8(offset); }
|
|
function poke(value) { return module.exports.store8(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(0, growMem(1));
|
|
|
|
for(offset = 0; offset <= kPageSize - 1; offset++) {
|
|
poke(20);
|
|
assertEquals(20, peek());
|
|
}
|
|
|
|
for(offset = kPageSize; offset <= kPageSize + 5; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, peek);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowZeroInitialSize8();
|
|
|
|
function testMemoryGrowTrapMaxPagesZeroInitialMemory() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
assertEquals(-1, growMem(kV8MaxPages + 1));
|
|
}
|
|
|
|
testMemoryGrowTrapMaxPagesZeroInitialMemory();
|
|
|
|
function testMemoryGrowTrapMaxPages() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, 1, false);
|
|
var module = builder.instantiate();
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
assertEquals(-1, growMem(kV8MaxPages));
|
|
}
|
|
|
|
testMemoryGrowTrapMaxPages();
|
|
|
|
function testMemoryGrowTrapsWithNonSmiInput() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(0, undefined, false);
|
|
var module = builder.instantiate();
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
// The parameter of grow_memory is unsigned. Therefore -1 stands for
|
|
// UINT32_MIN, which cannot be represented as SMI.
|
|
assertEquals(-1, growMem(-1));
|
|
};
|
|
|
|
testMemoryGrowTrapsWithNonSmiInput();
|
|
|
|
function testMemoryGrowCurrentMemory() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
builder.addFunction("memory_size", kSig_i_v)
|
|
.addBody([kExprMemorySize, kMemoryZero])
|
|
.exportFunc();
|
|
var module = builder.instantiate();
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
function MemSize() { return module.exports.memory_size(); }
|
|
assertEquals(1, MemSize());
|
|
assertEquals(1, growMem(1));
|
|
assertEquals(2, MemSize());
|
|
}
|
|
|
|
testMemoryGrowCurrentMemory();
|
|
|
|
function testMemoryGrowPreservesDataMemOp32() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset, val;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 4); offset+=4) {
|
|
poke(100000 - offset);
|
|
assertEquals(100000 - offset, peek());
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
for(offset = 0; offset <= (kPageSize - 4); offset+=4) {
|
|
assertEquals(100000 - offset, peek());
|
|
}
|
|
}
|
|
|
|
testMemoryGrowPreservesDataMemOp32();
|
|
|
|
function testMemoryGrowPreservesDataMemOp16() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset, val;
|
|
function peek() { return module.exports.load16(offset); }
|
|
function poke(value) { return module.exports.store16(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 2); offset+=2) {
|
|
poke(65535 - offset);
|
|
assertEquals(65535 - offset, peek());
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
for(offset = 0; offset <= (kPageSize - 2); offset+=2) {
|
|
assertEquals(65535 - offset, peek());
|
|
}
|
|
}
|
|
|
|
testMemoryGrowPreservesDataMemOp16();
|
|
|
|
function testMemoryGrowPreservesDataMemOp8() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset, val = 0;
|
|
function peek() { return module.exports.load8(offset); }
|
|
function poke(value) { return module.exports.store8(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 1); offset++, val++) {
|
|
poke(val);
|
|
assertEquals(val, peek());
|
|
if (val == 255) val = 0;
|
|
}
|
|
|
|
assertEquals(1, growMem(3));
|
|
|
|
val = 0;
|
|
|
|
for(offset = 0; offset <= (kPageSize - 1); offset++, val++) {
|
|
assertEquals(val, peek());
|
|
if (val == 255) val = 0;
|
|
}
|
|
}
|
|
|
|
testMemoryGrowPreservesDataMemOp8();
|
|
|
|
function testMemoryGrowOutOfBoundsOffset() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset, val;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
offset = 3*kPageSize + 4;
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(1, growMem(1));
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(2, growMem(1));
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
|
|
assertEquals(3, growMem(1));
|
|
|
|
for (offset = 3*kPageSize; offset <= 4*kPageSize - 4; offset++) {
|
|
poke(0xaced);
|
|
assertEquals(0xaced, peek());
|
|
}
|
|
|
|
for (offset = 4*kPageSize - 3; offset <= 4*kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
}
|
|
}
|
|
|
|
testMemoryGrowOutOfBoundsOffset();
|
|
|
|
function testMemoryGrowOutOfBoundsOffset2() {
|
|
var builder = new WasmModuleBuilder();
|
|
builder.addMemory(16, 128, false);
|
|
builder.addFunction("main", kSig_v_v)
|
|
.addBody([
|
|
kExprI32Const, 20,
|
|
kExprI32Const, 29,
|
|
kExprMemoryGrow, kMemoryZero,
|
|
kExprI32StoreMem, 0, 0xFF, 0xFF, 0xFF, 0x3a
|
|
])
|
|
.exportAs("main");
|
|
var module = builder.instantiate();
|
|
assertTraps(kTrapMemOutOfBounds, module.exports.main);
|
|
}
|
|
|
|
testMemoryGrowOutOfBoundsOffset2();
|
|
|
|
function testMemoryGrowDeclaredMaxTraps() {
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, 16, false);
|
|
var module = builder.instantiate();
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
assertEquals(1, growMem(5));
|
|
assertEquals(6, growMem(5));
|
|
assertEquals(-1, growMem(6));
|
|
}
|
|
|
|
testMemoryGrowDeclaredMaxTraps();
|
|
|
|
function testMemoryGrowDeclaredSpecMaxTraps() {
|
|
// The spec maximum is higher than the internal V8 maximum. This test only
|
|
// checks that grow_memory does not grow past the internally defined maximum
|
|
// to reflect the current implementation.
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, kSpecMaxPages, false);
|
|
var module = builder.instantiate();
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
assertEquals(1, growMem(20));
|
|
assertEquals(-1, growMem(kV8MaxPages - 20));
|
|
}
|
|
|
|
testMemoryGrowDeclaredSpecMaxTraps();
|
|
|
|
function testMemoryGrow2Gb() {
|
|
print("testMemoryGrow2Gb");
|
|
var builder = genMemoryGrowBuilder();
|
|
builder.addMemory(1, undefined, false);
|
|
var module = builder.instantiate();
|
|
var offset, val;
|
|
function peek() { return module.exports.load(offset); }
|
|
function poke(value) { return module.exports.store(offset, value); }
|
|
function growMem(pages) { return module.exports.grow_memory(pages); }
|
|
|
|
for(offset = 0; offset <= (kPageSize - 4); offset+=4) {
|
|
poke(100000 - offset);
|
|
assertEquals(100000 - offset, peek());
|
|
}
|
|
|
|
let result = growMem(kV8MaxPages - 1);
|
|
if (result == 1 ){
|
|
for(offset = 0; offset <= (kPageSize - 4); offset+=4) {
|
|
assertEquals(100000 - offset, peek());
|
|
}
|
|
|
|
// Bounds check for large mem size
|
|
for(offset = (kV8MaxPages - 1) * kPageSize;
|
|
offset <= (kV8MaxPages * kPageSize - 4); offset+=4) {
|
|
poke(0xaced);
|
|
assertEquals(0xaced, peek());
|
|
}
|
|
|
|
for (offset = kV8MaxPages * kPageSize - 3;
|
|
offset <= kV8MaxPages * kPageSize + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
}
|
|
|
|
// Check traps around 3GB/4GB boundaries
|
|
let offset_3gb = 49152 * kPageSize;
|
|
let offset_4gb = 2 * kV8MaxPages * kPageSize;
|
|
for (offset = offset_3gb - 5; offset < offset_3gb + 4; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
}
|
|
for (offset = offset_4gb - 5; offset < offset_4gb; offset++) {
|
|
assertTraps(kTrapMemOutOfBounds, poke);
|
|
}
|
|
} else {
|
|
// Allocating big chunks of memory can fail on gc_stress, especially on 32
|
|
// bit platforms. When grow_memory fails, expected result is -1.
|
|
assertEquals(-1, result);
|
|
}
|
|
}
|
|
|
|
testMemoryGrow2Gb();
|