grow-memory-in-branch.js 13.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// 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.
30 31
(function TestMemoryGrowInIfBranchNoElse() {
  print('TestMemoryGrowInIfBranchNoElse ...');
32 33 34 35 36 37 38
  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
39
          kExprMemoryGrow, kMemoryZero,         // grow memory
40 41 42 43 44 45 46 47 48 49 50 51 52 53
          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.
54 55
(function TestMemoryGrowInIfBranchWithElse() {
  print('TestMemoryGrowInIfBranchWithElse ...');
56 57 58 59 60 61 62 63 64 65
  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
66
          kExprMemoryGrow, kMemoryZero,         // grow memory
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
          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.
89 90
(function TestMemoryGrowInElseBranch() {
  print('TestMemoryGrowInElseBranch ...');
91 92 93 94 95 96 97 98 99 100 101 102 103 104
  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
105
          kExprMemoryGrow, kMemoryZero,         // grow memory
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
          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.
124 125
(function TestMemoryGrowInBothIfAndElse() {
  print('TestMemoryGrowInBothIfAndElse ...');
126 127 128 129 130 131 132 133
  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
134
          kExprMemoryGrow, kMemoryZero,         // grow memory
135 136 137
          kExprDrop,                            // drop the result of grow
        kExprElse,
          kExprI32Const, deltaPagesElse,        // put deltaPagesElse on stack
138
          kExprMemoryGrow, kMemoryZero,         // grow memory
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
          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.
155 156
(function TestMemoryGrowAndStoreInIfBranchNoElse() {
  print('TestMemoryGrowAndStoreInIfBranchNoElse ...');
157 158 159 160 161 162 163 164 165
  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
166
          kExprMemoryGrow, kMemoryZero,         // grow memory
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
          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.
187 188
(function TestMemoryGrowAndStoreInIfBranchWithElse() {
  print('TestMemoryGrowAndStoreInIfBranchWithElse ...');
189 190 191 192 193 194 195 196 197
  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
198
          kExprMemoryGrow, kMemoryZero,         // grow memory
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
          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.
222 223
(function TestMemoryGrowAndStoreInElseBranch() {
  print('TestMemoryGrowAndStoreInElseBranch ...');
224 225 226 227 228 229 230 231 232 233 234 235 236
  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
237
          kExprMemoryGrow, kMemoryZero,         // grow memory
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
          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.
257 258
(function TestMemoryGrowAndStoreInBothIfAndElse() {
  print('TestMemoryGrowAndStoreInBothIfAndElse ...');
259 260 261 262 263 264 265 266 267 268 269
  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
270
          kExprMemoryGrow, kMemoryZero,         // grow memory
271 272 273 274 275 276
          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
277
          kExprMemoryGrow, kMemoryZero,         // grow memory
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
          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));
})();