| // 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-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 TestMemoryGrowInIfBranchNoElse() { |
| print('TestMemoryGrowInIfBranchNoElse ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowInIfBranchWithElse() { |
| print('TestMemoryGrowInIfBranchWithElse ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowInElseBranch() { |
| print('TestMemoryGrowInElseBranch ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowInBothIfAndElse() { |
| print('TestMemoryGrowInBothIfAndElse ...'); |
| 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 |
| kExprMemoryGrow, kMemoryZero, // grow memory |
| kExprDrop, // drop the result of grow |
| kExprElse, |
| kExprI32Const, deltaPagesElse, // put deltaPagesElse on stack |
| kExprMemoryGrow, 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 TestMemoryGrowAndStoreInIfBranchNoElse() { |
| print('TestMemoryGrowAndStoreInIfBranchNoElse ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowAndStoreInIfBranchWithElse() { |
| print('TestMemoryGrowAndStoreInIfBranchWithElse ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowAndStoreInElseBranch() { |
| print('TestMemoryGrowAndStoreInElseBranch ...'); |
| 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 |
| kExprMemoryGrow, 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 TestMemoryGrowAndStoreInBothIfAndElse() { |
| print('TestMemoryGrowAndStoreInBothIfAndElse ...'); |
| 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 |
| kExprMemoryGrow, 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 |
| kExprMemoryGrow, 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)); |
| })(); |