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
// 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)
16
      .addBody([kExprLocalGet, 0, kExprI32LoadMem, 0, 0])
17 18 19
      .exportFunc();
  builder.addFunction('store', kSig_i_ii)
      .addBody([
20 21
        kExprLocalGet, 0, kExprLocalGet, 1,
        kExprI32StoreMem, 0, 0, kExprLocalGet, 1
22 23 24 25 26 27 28
      ])
      .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
  let deltaPages = 4;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_i)
      .addBody([
35
        kExprLocalGet, 0,                       // get condition parameter
36 37
        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
  let index = 0;
  let oldValue = 21;
  let newValue = 42;
  let deltaPages = 4;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_i)
      .addBody([
62
        kExprLocalGet, 0,                       // get condition parameter
63 64
        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
  let index = 0;
  let oldValue = 21;
  let newValue = 42;
  let deltaPages = 4;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_i)
      .addBody([
97
        kExprLocalGet, 0,                       // get condition parameter
98 99 100 101 102 103
        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
  let deltaPagesIf = 1;
  let deltaPagesElse = 2;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_i)
      .addBody([
130
        kExprLocalGet, 0,                       // get condition parameter
131 132
        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
  let index = 2 * kPageSize - 4;
  let value = 42;
  let deltaPages = 1;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_ii)
      .addBody([
162
        kExprLocalGet, 0,                       // get condition parameter
163 164
        kExprIf, kWasmStmt,                     // if it's 1 then enter if
          kExprI32Const, deltaPages,            // put deltaPages on stack
165
          kExprMemoryGrow, kMemoryZero,         // grow memory
166
          kExprDrop,                            // drop the result of grow
167
          kExprLocalGet, 1,                     // get index parameter
168 169 170
          kExprI32Const, value,                 // put the value on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprEnd,
171
        kExprLocalGet, 1,                       // get index parameter
172 173 174 175 176 177 178 179 180 181 182 183 184 185
        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
  let index = 2 * kPageSize - 4;
  let value = 42;
  let deltaPages = 1;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_ii)
      .addBody([
194
        kExprLocalGet, 0,                       // get condition parameter
195 196
        kExprIf, kWasmStmt,                     // if it's 1 then enter if
          kExprI32Const, deltaPages,            // put deltaPages on stack
197
          kExprMemoryGrow, kMemoryZero,         // grow memory
198
          kExprDrop,                            // drop the result of grow
199
          kExprLocalGet, 1,                     // get index parameter
200 201 202
          kExprI32Const, value,                 // put the value on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprElse,
203
          kExprLocalGet, 1,                     // get index parameter
204 205 206
          kExprI32Const, value,                 // put the value on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprEnd,
207
        kExprLocalGet, 1,                       // get index parameter
208 209 210 211 212 213 214 215 216 217 218 219 220
        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
  let index = 2 * kPageSize - 4;
  let value = 42;
  let deltaPages = 1;
  let builder = generateBuilder();
  builder.addFunction('main', kSig_i_ii)
      .addBody([
229
        kExprLocalGet, 0,                       // get condition parameter
230
        kExprIf, kWasmStmt,                     // if it's 1 then enter if
231
          kExprLocalGet, 1,                     // get index parameter
232 233 234 235
          kExprI32Const, value,                 // put the value on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprElse,
          kExprI32Const, deltaPages,            // put deltaPages on stack
236
          kExprMemoryGrow, kMemoryZero,         // grow memory
237
          kExprDrop,                            // drop the result of grow
238
          kExprLocalGet, 1,                     // get index parameter
239 240 241
          kExprI32Const, value,                 // put the value on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprEnd,
242
        kExprLocalGet, 1,                       // get index parameter
243 244 245 246 247 248 249 250 251 252 253 254 255
        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
  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([
266
        kExprLocalGet, 0,                       // get condition parameter
267 268
        kExprIf, kWasmStmt,                     // if it's 1 then enter if
          kExprI32Const, deltaPagesIf,          // put deltaPagesIf on stack
269
          kExprMemoryGrow, kMemoryZero,         // grow memory
270
          kExprDrop,                            // drop the result of grow
271
          kExprLocalGet, 1,                     // get index parameter
272 273 274 275
          kExprI32Const, valueIf,               // put valueIf on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprElse,
          kExprI32Const, deltaPagesElse,        // put deltaPagesElse on stack
276
          kExprMemoryGrow, kMemoryZero,         // grow memory
277
          kExprDrop,                            // drop the result of grow
278
          kExprLocalGet, 1,                     // get index parameter
279 280 281
          kExprI32Const, valueElse,             // put valueElse on stack
          kExprI32StoreMem, 0, 0,               // store
        kExprEnd,
282
        kExprLocalGet, 1,                       // get index parameter
283 284 285 286 287 288 289 290 291
        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));
})();