[wasm] Refactor mjsunit atomics tests into smaller tests

Tests were monolithic, with large loops, and slow on ARM64. Refactor to
small tests so they can be sharded better, reduce page size to 1 to
keep the loops small.

BUG=v8:6532

Change-Id: I712551564d4a70fc12acdf114922feb614aeb271
Reviewed-on: https://chromium-review.googlesource.com/611614
Reviewed-by: Ben Smith <binji@chromium.org>
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47353}
This commit is contained in:
Deepti Gandluri 2017-08-14 15:31:59 -07:00 committed by Commit Bot
parent f6e20fcbba
commit 3a30f60d05
2 changed files with 121 additions and 282 deletions

View File

@ -324,7 +324,6 @@
'unicodelctest-no-optimization': [PASS, SLOW],
'unicodelctest': [PASS, SLOW],
'unicode-test': [PASS, SLOW],
'wasm/atomics': [PASS, SLOW],
'whitespaces': [PASS, SLOW],
}], # 'arch == arm64'

View File

@ -7,330 +7,170 @@
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
function VerifyBoundsCheck(buffer, funcs, max) {
kPageSize = 65536;
// Test out of bounds at boundary
for (j = 0; j < funcs.length; j++) {
for (i = buffer.byteLength - funcs[j].memtype_size + 1;
i < buffer.byteLength + funcs[j].memtype_size + 4; i++) {
assertTraps(kTrapMemOutOfBounds, () => funcs[j].func(i, 5));
}
// Test out of bounds at maximum + 1
assertTraps(kTrapMemOutOfBounds, () =>
funcs[j].func((max + 1) * kPageSize, 5));
}
}
const kMemtypeSize32 = 4;
const kMemtypeSize16 = 2;
const kMemtypeSize8 = 1;
(function TestAtomicAdd() {
print("TestAtomicAdd");
let memory = new WebAssembly.Memory({initial: 1, maximum: 10, shared: true});
function Add(a, b) { return a + b; }
function Sub(a, b) { return a - b; }
function And(a, b) { return a & b; }
function Or(a, b) { return a | b; }
function Xor(a, b) { return a ^ b; }
let maxSize = 10;
let memory = new WebAssembly.Memory({initial: 1, maximum: maxSize, shared: true});
function GetAtomicBinOpFunction(wasmExpression) {
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem");
builder.addFunction("atomic_add", kSig_i_ii)
builder.addFunction("main", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAdd])
.exportAs("atomic_add");
builder.addFunction("atomic_add16", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAdd16U])
.exportAs("atomic_add16");
builder.addFunction("atomic_add8", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAdd8U])
.exportAs("atomic_add8");
wasmExpression])
.exportAs("main");
// Instantiate module, get function exports
let module = new WebAssembly.Module(builder.toBuffer());
let instance = (new WebAssembly.Instance(module,
{m: {imported_mem: memory}}));
return instance.exports.main;
}
// 32-bit Add
function VerifyBoundsCheck(func, memtype_size) {
const kPageSize = 65536;
// Test out of bounds at boundary
for (let i = memory.buffer.byteLength - memtype_size + 1;
i < memory.buffer.byteLength + memtype_size + 4; i++) {
assertTraps(kTrapMemOutOfBounds, () => func(i, 5));
}
// Test out of bounds at maximum + 1
assertTraps(kTrapMemOutOfBounds, () => func((maxSize + 1) * kPageSize, 5));
}
function Test32Op(operation, func) {
let i32 = new Uint32Array(memory.buffer);
for (i = 0; i < i32.length; i++) {
i32[i] = i;
assertEquals(i, instance.exports.atomic_add(i * 4, 0xACEDACED));
assertEquals(i + 0xACEDACED, i32[i]);
for (let i = 0; i < i32.length; i++) {
let expected = 0x9cedf00d;
let value = 0x11111111;
i32[i] = expected;
assertEquals(expected, func(i * kMemtypeSize32, value) >>> 0);
assertEquals(operation(expected, value) >>> 0, i32[i]);
}
VerifyBoundsCheck(func, kMemtypeSize32);
}
// 16-bit Add
function Test16Op(operation, func) {
let i16 = new Uint16Array(memory.buffer);
for (i = 0; i < i16.length; i++) {
i16[i] = i;
assertEquals(i, instance.exports.atomic_add16(i * 2, 0x1234));
assertEquals(i + 0x1234, i16[i]);
for (let i = 0; i < i16.length; i++) {
let expected = 0xd00d;
let value = 0x1111;
i16[i] = expected;
assertEquals(expected, func(i * kMemtypeSize16, value));
assertEquals(operation(expected, value), i16[i]);
}
VerifyBoundsCheck(func, kMemtypeSize16);
}
// 8-bit Add
function Test8Op(operation, func) {
let i8 = new Uint8Array(memory.buffer);
for (i = 0; i < i8.length; i++) {
i8[i] = 0x11;
assertEquals(0x11, instance.exports.atomic_add8(i, 0xee));
assertEquals(0x11 + 0xee, i8[i]);
for (let i = 0; i < i8.length; i++) {
let expected = 0xbe;
let value = 0x12;
i8[i] = expected;
assertEquals(expected, func(i * kMemtypeSize8, value));
assertEquals(operation(expected, value), i8[i]);
}
VerifyBoundsCheck(func, kMemtypeSize8, 10);
}
var adds = [{func: instance.exports.atomic_add, memtype_size: 4},
{func: instance.exports.atomic_add16, memtype_size: 2},
{func: instance.exports.atomic_add8, memtype_size: 1}];
(function TestAtomicAdd() {
print("TestAtomicAdd");
let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd);
Test32Op(Add, wasmAdd);
})();
VerifyBoundsCheck(memory.buffer, adds, 10);
(function TestAtomicAdd16U() {
print("TestAtomicAdd16U");
let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd16U);
Test16Op(Add, wasmAdd);
})();
(function TestAtomicAdd8U() {
print("TestAtomicAdd8U");
let wasmAdd = GetAtomicBinOpFunction(kExprI32AtomicAdd8U);
Test8Op(Add, wasmAdd);
})();
(function TestAtomicSub() {
print("TestAtomicSub");
let memory = new WebAssembly.Memory({initial: 5, maximum: 20, shared: true});
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem");
builder.addFunction("atomic_sub", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicSub])
.exportAs("atomic_sub");
builder.addFunction("atomic_sub16", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicSub16U])
.exportAs("atomic_sub16");
builder.addFunction("atomic_sub8", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicSub8U])
.exportAs("atomic_sub8");
let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub);
Test32Op(Sub, wasmSub);
})();
let module = new WebAssembly.Module(builder.toBuffer());
let instance = (new WebAssembly.Instance(module,
{m: {imported_mem: memory}}));
// 32-bit Sub
let i32 = new Uint32Array(memory.buffer);
for (i = 0; i < i32.length; i++) {
i32[i] = i32.length;
assertEquals(i32.length, instance.exports.atomic_sub(i * 4, i));
assertEquals(i32.length - i, i32[i]);
}
// 16-bit Sub
let i16 = new Uint16Array(memory.buffer);
for (i = 0; i < i16.length; i++) {
i16[i] = 0xffff;
assertEquals(0xffff, instance.exports.atomic_sub16(i * 2, 0x1234));
assertEquals(0xffff - 0x1234, i16[i]);
}
// 8-bit Sub
let i8 = new Uint8Array(memory.buffer);
for (i = 0; i < i8.length; i++) {
i8[i] = 0xff;
assertEquals(0xff, instance.exports.atomic_sub8(i, i % 0xff));
assertEquals(0xff - i % 0xff, i8[i]);
}
var subs = [{func: instance.exports.atomic_sub, memtype_size: 4},
{func: instance.exports.atomic_sub16, memtype_size: 2},
{func: instance.exports.atomic_sub8, memtype_size: 1}];
VerifyBoundsCheck(memory.buffer, subs, 20);
(function TestAtomicSub16U() {
print("TestAtomicSub16U");
let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub16U);
Test16Op(Sub, wasmSub);
})();
(function TestAtomicSub8U() {
print("TestAtomicSub8U");
let wasmSub = GetAtomicBinOpFunction(kExprI32AtomicSub8U);
Test8Op(Sub, wasmSub);
})();
(function TestAtomicAnd() {
print("TestAtomicAnd");
let memory = new WebAssembly.Memory({initial: 5, maximum: 20, shared: true});
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem");
builder.addFunction("atomic_and", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAnd])
.exportAs("atomic_and");
builder.addFunction("atomic_and16", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAnd16U])
.exportAs("atomic_and16");
builder.addFunction("atomic_and8", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicAnd8U])
.exportAs("atomic_and8");
let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd);
Test32Op(And, wasmAnd);
})();
let module = new WebAssembly.Module(builder.toBuffer());
let instance = (new WebAssembly.Instance(module,
{m: {imported_mem: memory}}));
(function TestAtomicAnd16U() {
print("TestAtomicAnd16U");
let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd16U);
Test16Op(And, wasmAnd);
})();
// 32-bit And
let i32 = new Uint32Array(memory.buffer);
for (i = 0; i < i32.length; i++) {
i32[i] = i32.length;
assertEquals(i32.length, instance.exports.atomic_and(i * 4, i));
assertEquals(i32.length & i, i32[i]);
}
// 16-bit And
let i16 = new Uint16Array(memory.buffer);
for (i = 0; i < i16.length; i++) {
i16[i] = 0xffff;
assertEquals(0xffff, instance.exports.atomic_and16(i * 2, 0x1234));
assertEquals(0xffff & 0x1234, i16[i]);
}
// 8-bit And
let i8 = new Uint8Array(memory.buffer);
for (i = 0; i < i8.length; i++) {
i8[i] = 0xff;
assertEquals(0xff, instance.exports.atomic_and8(i, i % 0xff));
assertEquals(0xff & i % 0xff, i8[i]);
}
var ands = [{func: instance.exports.atomic_and, memtype_size: 4},
{func: instance.exports.atomic_and16, memtype_size: 2},
{func: instance.exports.atomic_and8, memtype_size: 1}];
VerifyBoundsCheck(memory.buffer, ands, 20);
(function TestAtomicAnd8U() {
print("TestAtomicAnd8U");
let wasmAnd = GetAtomicBinOpFunction(kExprI32AtomicAnd8U);
Test8Op(And, wasmAnd);
})();
(function TestAtomicOr() {
print("TestAtomicOr");
let memory = new WebAssembly.Memory({initial: 5, maximum: 20, shared: true});
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem");
builder.addFunction("atomic_or", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicOr])
.exportAs("atomic_or");
builder.addFunction("atomic_or16", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicOr16U])
.exportAs("atomic_or16");
builder.addFunction("atomic_or8", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicOr8U])
.exportAs("atomic_or8");
let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr);
Test32Op(Or, wasmOr);
})();
let module = new WebAssembly.Module(builder.toBuffer());
let instance = (new WebAssembly.Instance(module,
{m: {imported_mem: memory}}));
// 32-bit Or
let i32 = new Uint32Array(memory.buffer);
for (i = 0; i < i32.length; i++) {
i32[i] = i32.length;
assertEquals(i32.length, instance.exports.atomic_or(i * 4, i));
assertEquals(i32.length | i, i32[i]);
}
// 16-bit Or
let i16 = new Uint16Array(memory.buffer);
for (i = 0; i < i16.length; i++) {
i16[i] = 0xffff;
assertEquals(0xffff, instance.exports.atomic_or16(i * 2, 0x1234));
assertEquals(0xffff | 0x1234, i16[i]);
}
// 8-bit Or
let i8 = new Uint8Array(memory.buffer);
for (i = 0; i < i8.length; i++) {
i8[i] = 0xff;
assertEquals(0xff, instance.exports.atomic_or8(i, i % 0xff));
assertEquals(0xff | i % 0xff, i8[i]);
}
var ors = [{func: instance.exports.atomic_or, memtype_size: 4},
{func: instance.exports.atomic_or16, memtype_size: 2},
{func: instance.exports.atomic_or8, memtype_size: 1}];
VerifyBoundsCheck(memory.buffer, ors, 20);
(function TestAtomicOr16U() {
print("TestAtomicOr16U");
let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr16U);
Test16Op(Or, wasmOr);
})();
(function TestAtomicOr8U() {
print("TestAtomicOr8U");
let wasmOr = GetAtomicBinOpFunction(kExprI32AtomicOr8U);
Test8Op(Or, wasmOr);
})();
(function TestAtomicXor() {
print("TestAtomicXor");
let memory = new WebAssembly.Memory({initial: 5, maximum: 20, shared: true});
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem");
builder.addFunction("atomic_xor", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicXor])
.exportAs("atomic_xor");
builder.addFunction("atomic_xor16", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicXor16U])
.exportAs("atomic_xor16");
builder.addFunction("atomic_xor8", kSig_i_ii)
.addBody([
kExprGetLocal, 0,
kExprGetLocal, 1,
kAtomicPrefix,
kExprI32AtomicXor8U])
.exportAs("atomic_xor8");
let module = new WebAssembly.Module(builder.toBuffer());
let instance = (new WebAssembly.Instance(module,
{m: {imported_mem: memory}}));
// 32-bit Xor
let i32 = new Uint32Array(memory.buffer);
for (i = 0; i < i32.length; i++) {
i32[i] = i32.length;
assertEquals(i32.length, instance.exports.atomic_xor(i * 4, i));
assertEquals(i32.length ^ i, i32[i]);
}
// 16-bit Xor
let i16 = new Uint16Array(memory.buffer);
for (i = 0; i < i16.length; i++) {
i16[i] = 0xffff;
assertEquals(0xffff, instance.exports.atomic_xor16(i * 2, 0x5678));
assertEquals(0xffff ^ 0x5678, i16[i]);
}
// 8-bit Xor
let i8 = new Uint8Array(memory.buffer);
for (i = 0; i < i8.length; i++) {
i8[i] = 0xff;
assertEquals(0xff, instance.exports.atomic_xor8(i, i % 0xff));
assertEquals(0xff ^ i % 0xff, i8[i]);
}
var xors = [{func: instance.exports.atomic_xor, memtype_size: 4},
{func: instance.exports.atomic_xor16, memtype_size: 2},
{func: instance.exports.atomic_xor8, memtype_size: 1}];
VerifyBoundsCheck(memory.buffer, xors, 20);
let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor);
Test32Op(Xor, wasmXor);
})();
(function TestAtomicXor16U() {
print("TestAtomicXor16U");
let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor16U);
Test16Op(Xor, wasmXor);
})();
(function TestAtomicXor8U() {
print("TestAtomicXor8U");
let wasmXor = GetAtomicBinOpFunction(kExprI32AtomicXor8U);
Test8Op(Xor, wasmXor);
})();