v8/test/mjsunit/wasm/grow-memory-in-branch.js
Enrico Bacis fe4d0686c9 [wasm] Add tests for grow_memory in conditional branches
This CL introduces 8 tests that verify that the effects of a grow_memory
instruction executed inside a conditional branch are visible also when
the branch is merged.

The tests verify the output of the current_memory instruction and the
result of loading a variable stored in the grown memory inside the
branch in the following cases:

 * the memory is grown inside the if branch (with no else branch);

 * the memory is grown inside the if branch (when an else branch exists);

 * the memory is grown inside the else branch;

 * the memory is grown by different amount of pages inside both the if
 and else branches.

R=ahaas@chromium.org,clemensh@chromium.org,gdeepti@chromium.org

Change-Id: I8127ebdf959eed5b7b5ca5aa6033a7ea41465f32
Reviewed-on: https://chromium-review.googlesource.com/617222
Reviewed-by: Deepti Gandluri <gdeepti@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Cr-Commit-Position: refs/heads/master@{#47452}
2017-08-19 10:33:11 +00:00

293 lines
13 KiB
JavaScript

// Copyright 2017 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-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
var initialMemoryPages = 1;
var maximumMemoryPages = 5;
function generateBuilder() {
let builder = new WasmModuleBuilder();
builder.addMemory(initialMemoryPages, maximumMemoryPages, true);
builder.addFunction('load', kSig_i_i)
.addBody([kExprGetLocal, 0, kExprI32LoadMem, 0, 0])
.exportFunc();
builder.addFunction('store', kSig_i_ii)
.addBody([
kExprGetLocal, 0, kExprGetLocal, 1,
kExprI32StoreMem, 0, 0, kExprGetLocal, 1
])
.exportFunc();
return builder;
}
// This test verifies that the effects of growing memory in an if branch
// affect the result of current_memory when the branch is merged.
(function TestGrowMemoryInIfBranchNoElse() {
print('TestGrowMemoryInIfBranchNoElse ...');
let deltaPages = 4;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_i)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprEnd,
kExprMemorySize, kMemoryZero // get the memory size
])
.exportFunc();
var instance = builder.instantiate();
// Avoid the if branch (not growing memory).
assertEquals(initialMemoryPages, instance.exports.main(0));
// Enter the if branch (growing memory).
assertEquals(initialMemoryPages + deltaPages, instance.exports.main(1));
})();
// This test verifies that the effects of growing memory in an if branch are
// retained when the branch is merged even when an else branch exists.
(function TestGrowMemoryInIfBranchWithElse() {
print('TestGrowMemoryInIfBranchWithElse ...');
let index = 0;
let oldValue = 21;
let newValue = 42;
let deltaPages = 4;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_i)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprElse,
kExprI32Const, index, // put index on stack
kExprI32Const, newValue, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprEnd,
kExprMemorySize, kMemoryZero // get the memory size
])
.exportFunc();
var instance = builder.instantiate();
// Initialize the memory location with oldValue.
instance.exports.store(index, oldValue);
assertEquals(oldValue, instance.exports.load(index));
// Verify that the else branch (not growing) is reachable.
assertEquals(initialMemoryPages, instance.exports.main(0));
assertEquals(newValue, instance.exports.load(index));
// Enter the if branch (growing memory).
assertEquals(initialMemoryPages + deltaPages, instance.exports.main(1));
})();
// This test verifies that the effects of growing memory in an else branch
// affect the result of current_memory when the branch is merged.
(function TestGrowMemoryInElseBranch() {
print('TestGrowMemoryInElseBranch ...');
let index = 0;
let oldValue = 21;
let newValue = 42;
let deltaPages = 4;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_i)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, index, // put index on stack
kExprI32Const, newValue, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprElse,
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprEnd,
kExprMemorySize, kMemoryZero // get the memory size
])
.exportFunc();
var instance = builder.instantiate();
// Initialize the memory location with oldValue.
instance.exports.store(index, oldValue);
assertEquals(oldValue, instance.exports.load(index));
// Verify that the if branch (not growing) is reachable.
assertEquals(initialMemoryPages, instance.exports.main(1));
assertEquals(newValue, instance.exports.load(index));
// Enter the else branch (growing memory).
assertEquals(initialMemoryPages + deltaPages, instance.exports.main(0));
})();
// This test verifies that the effects of growing memory in an if/else
// branch affect the result of current_memory when the branches are merged.
(function TestGrowMemoryInBothIfAndElse() {
print('TestGrowMemoryInBothIfAndElse ...');
let deltaPagesIf = 1;
let deltaPagesElse = 2;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_i)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPagesIf, // put deltaPagesIf on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprElse,
kExprI32Const, deltaPagesElse, // put deltaPagesElse on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprEnd,
kExprMemorySize, kMemoryZero // get the memory size
])
.exportFunc();
var instance = builder.instantiate();
// Enter the if branch (growing memory by 1 page).
assertEquals(initialMemoryPages + deltaPagesIf, instance.exports.main(1));
// Create a new instance for the testing the else branch.
var instance = builder.instantiate();
// Enter the else branch (growing memory by 2 pages).
assertEquals(initialMemoryPages + deltaPagesElse, instance.exports.main(0));
})();
// This test verifies that the effects of growing memory in an if branch are
// retained when the branch is merged.
(function TestGrowMemoryAndStoreInIfBranchNoElse() {
print('TestGrowMemoryAndStoreInIfBranchNoElse ...');
let index = 2 * kPageSize - 4;
let value = 42;
let deltaPages = 1;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_ii)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprGetLocal, 1, // get index parameter
kExprI32Const, value, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprEnd,
kExprGetLocal, 1, // get index parameter
kExprI32LoadMem, 0, 0 // load from grown memory
])
.exportFunc();
var instance = builder.instantiate();
// Avoid the if branch (not growing memory). This should trap when executing
// the kExprI32LoadMem instruction at the end of main.
assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(0, index));
// Enter the if branch (growing memory).
assertEquals(value, instance.exports.main(1, index));
})();
// This test verifies that the effects of growing memory in an if branch are
// retained when the branch is merged even when an else branch exists.
(function TestGrowMemoryAndStoreInIfBranchWithElse() {
print('TestGrowMemoryAndStoreInIfBranchWithElse ...');
let index = 2 * kPageSize - 4;
let value = 42;
let deltaPages = 1;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_ii)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprGetLocal, 1, // get index parameter
kExprI32Const, value, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprElse,
kExprGetLocal, 1, // get index parameter
kExprI32Const, value, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprEnd,
kExprGetLocal, 1, // get index parameter
kExprI32LoadMem, 0, 0 // load from grown memory
])
.exportFunc();
var instance = builder.instantiate();
// Avoid the if branch (not growing memory). This should trap when executing
// the kExprI32StoreMem instruction in the if branch.
assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(0, index));
// Enter the if branch (growing memory).
assertEquals(value, instance.exports.main(1, index));
})();
// This test verifies that the effects of growing memory in an else branch are
// retained when the branch is merged.
(function TestGrowMemoryAndStoreInElseBranch() {
print('TestGrowMemoryAndStoreInElseBranch ...');
let index = 2 * kPageSize - 4;
let value = 42;
let deltaPages = 1;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_ii)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprGetLocal, 1, // get index parameter
kExprI32Const, value, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprElse,
kExprI32Const, deltaPages, // put deltaPages on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprGetLocal, 1, // get index parameter
kExprI32Const, value, // put the value on stack
kExprI32StoreMem, 0, 0, // store
kExprEnd,
kExprGetLocal, 1, // get index parameter
kExprI32LoadMem, 0, 0 // load from grown memory
])
.exportFunc();
var instance = builder.instantiate();
// Avoid the else branch (not growing memory). This should trap when executing
// the kExprI32StoreMem instruction in the else branch.
assertTraps(kTrapMemOutOfBounds, () => instance.exports.main(1, index));
// Enter the else branch (growing memory).
assertEquals(value, instance.exports.main(0, index));
})();
// This test verifies that the effects of growing memory in an if/else branch
// are retained when the branch is merged.
(function TestGrowMemoryAndStoreInBothIfAndElse() {
print('TestGrowMemoryAndStoreInBothIfAndElse ...');
let index = 0;
let valueIf = 21;
let valueElse = 42;
let deltaPagesIf = 1;
let deltaPagesElse = 2;
let builder = generateBuilder();
builder.addFunction('main', kSig_i_ii)
.addBody([
kExprGetLocal, 0, // get condition parameter
kExprIf, kWasmStmt, // if it's 1 then enter if
kExprI32Const, deltaPagesIf, // put deltaPagesIf on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprGetLocal, 1, // get index parameter
kExprI32Const, valueIf, // put valueIf on stack
kExprI32StoreMem, 0, 0, // store
kExprElse,
kExprI32Const, deltaPagesElse, // put deltaPagesElse on stack
kExprGrowMemory, kMemoryZero, // grow memory
kExprDrop, // drop the result of grow
kExprGetLocal, 1, // get index parameter
kExprI32Const, valueElse, // put valueElse on stack
kExprI32StoreMem, 0, 0, // store
kExprEnd,
kExprGetLocal, 1, // get index parameter
kExprI32LoadMem, 0, 0 // load from grown memory
])
.exportFunc();
var instance = builder.instantiate();
// Enter the if branch (growing memory by 1 page).
assertEquals(valueIf, instance.exports.main(1, index));
// Enter the else branch (growing memory by 2 pages).
assertEquals(valueElse, instance.exports.main(0, index));
})();