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