module-memory.js 5.48 KB
Newer Older
1 2 3 4
// Copyright 2015 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.

5
// Flags: --expose-wasm --expose-gc --stress-compaction --allow-natives-syntax
6 7

load("test/mjsunit/wasm/wasm-constants.js");
8
load("test/mjsunit/wasm/wasm-module-builder.js");
9

10
var kMemSize = 65536;
11 12

function genModule(memory) {
13 14
  var builder = new WasmModuleBuilder();

15
  builder.addImportedMemory("", "memory", 1);
mtrofin's avatar
mtrofin committed
16
  builder.exportMemoryAs("memory");
17
  builder.addFunction("main", kSig_i_i)
18
    .addBody([
19 20
      // main body: while(i) { if(mem[i]) return -1; i -= 4; } return 0;
      // TODO(titzer): this manual bytecode has a copy of test-run-wasm.cc
21
      /**/ kExprLoop, kWasmStmt,           // --
22
      /*  */ kExprGetLocal, 0,             // --
23
      /*  */ kExprIf, kWasmStmt,           // --
24 25
      /*    */ kExprGetLocal, 0,           // --
      /*    */ kExprI32LoadMem, 0, 0,      // --
26 27
      /*    */ kExprIf, kWasmStmt,         // --
      /*      */ kExprI32Const, 127,       // --
28 29 30
      /*      */ kExprReturn,              // --
      /*      */ kExprEnd,                 // --
      /*    */ kExprGetLocal, 0,           // --
31
      /*    */ kExprI32Const, 4,           // --
32 33 34 35 36
      /*    */ kExprI32Sub,                // --
      /*    */ kExprSetLocal, 0,           // --
      /*    */ kExprBr, 1,                 // --
      /*    */ kExprEnd,                   // --
      /*  */ kExprEnd,                     // --
37
      /**/ kExprI32Const, 0                // --
38
    ])
39
    .exportFunc();
mtrofin's avatar
mtrofin committed
40
  var module = builder.instantiate({"": {memory:memory}});
41
  assertTrue(module.exports.memory instanceof WebAssembly.Memory);
42
  if (memory != null) assertEquals(memory.buffer, module.exports.memory.buffer);
43
  return module;
44 45 46
}

function testPokeMemory() {
47
  print("testPokeMemory");
mtrofin's avatar
mtrofin committed
48
  var module = genModule(new WebAssembly.Memory({initial: 1}));
49
  var buffer = module.exports.memory.buffer;
50
  var main = module.exports.main;
51 52 53 54 55 56 57 58 59 60
  assertEquals(kMemSize, buffer.byteLength);

  var array = new Int8Array(buffer);
  assertEquals(kMemSize, array.length);

  for (var i = 0; i < kMemSize; i++) {
    assertEquals(0, array[i]);
  }

  for (var i = 0; i < 10; i++) {
61
    assertEquals(0, main(kMemSize - 4));
62 63

    array[kMemSize/2 + i] = 1;
64 65
    assertEquals(0, main(kMemSize/2 - 4));
    assertEquals(-1, main(kMemSize - 4));
66 67

    array[kMemSize/2 + i] = 0;
68
    assertEquals(0, main(kMemSize - 4));
69 70 71 72 73
  }
}

testPokeMemory();

74 75 76 77
function genAndGetMain(buffer) {
  return genModule(buffer).exports.main;  // to prevent intermediates living
}

78
function testSurvivalAcrossGc() {
mtrofin's avatar
mtrofin committed
79
  var checker = genAndGetMain(new WebAssembly.Memory({initial: 1}));
80
  for (var i = 0; i < 3; i++) {
81 82 83 84 85 86 87 88 89 90 91 92 93
    print("gc run ", i);
    assertEquals(0, checker(kMemSize - 4));
    gc();
  }
}

testSurvivalAcrossGc();
testSurvivalAcrossGc();
testSurvivalAcrossGc();
testSurvivalAcrossGc();


function testPokeOuterMemory() {
94 95
  print("testPokeOuterMemory");
  var buffer = new WebAssembly.Memory({initial: kMemSize / kPageSize});
96
  var module = genModule(buffer);
97
  var main = module.exports.main;
98
  assertEquals(kMemSize, buffer.buffer.byteLength);
99

100
  var array = new Int8Array(buffer.buffer);
101 102 103 104 105 106 107
  assertEquals(kMemSize, array.length);

  for (var i = 0; i < kMemSize; i++) {
    assertEquals(0, array[i]);
  }

  for (var i = 0; i < 10; i++) {
108
    assertEquals(0, main(kMemSize - 4));
109 110

    array[kMemSize/2 + i] = 1;
111 112
    assertEquals(0, main(kMemSize/2 - 4));
    assertEquals(-1, main(kMemSize - 4));
113 114

    array[kMemSize/2 + i] = 0;
115
    assertEquals(0, main(kMemSize - 4));
116 117 118 119 120 121
  }
}

testPokeOuterMemory();

function testOuterMemorySurvivalAcrossGc() {
122
  var buffer = new WebAssembly.Memory({initial: kMemSize / kPageSize});
123 124
  var checker = genAndGetMain(buffer);
  for (var i = 0; i < 3; i++) {
125 126 127 128 129 130 131 132 133 134 135 136 137
    print("gc run ", i);
    assertEquals(0, checker(kMemSize - 4));
    gc();
  }
}

testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();
testOuterMemorySurvivalAcrossGc();


function testOOBThrows() {
138 139 140
  var builder = new WasmModuleBuilder();

  builder.addMemory(1, 1, true);
141
  builder.addFunction("geti", kSig_i_ii)
142
    .addBody([
143 144 145
      kExprGetLocal, 0,
      kExprGetLocal, 1,
      kExprI32LoadMem, 0, 0,
146 147 148
      kExprI32StoreMem, 0, 0,
      kExprGetLocal, 1,
      kExprI32LoadMem, 0, 0,
149 150 151 152
    ])
    .exportFunc();

  var module = builder.instantiate();
153 154
  var offset;

155 156
  function read() { return module.exports.geti(0, offset); }
  function write() { return module.exports.geti(offset, 0); }
157

158
  for (offset = 0; offset < 65533; offset++) {
159 160 161 162 163
    assertEquals(0, read());
    assertEquals(0, write());
  }


164
  for (offset = 65534; offset < 66536; offset++) {
165
    const trap_count = %GetWasmRecoveredTrapCount();
166 167
    assertTraps(kTrapMemOutOfBounds, read);
    assertTraps(kTrapMemOutOfBounds, write);
168 169 170
    if (%IsWasmTrapHandlerEnabled()) {
      assertEquals(trap_count + 2, %GetWasmRecoveredTrapCount());
    }
171 172 173 174
  }
}

testOOBThrows();
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

function testAddressSpaceLimit() {
  // 1TiB, see wasm-memory.h
  const kMaxAddressSpace = 1 * 1024 * 1024 * 1024 * 1024;
  const kAddressSpacePerMemory = 8 * 1024 * 1024 * 1024;

  try {
    let memories = [];
    let address_space = 0;
    while (address_space <= kMaxAddressSpace + 1) {
      memories.push(new WebAssembly.Memory({initial: 1}));
      address_space += kAddressSpacePerMemory;
    }
  } catch (e) {
    assertTrue(e instanceof RangeError);
    return;
  }
  failWithMessage("allocated too much memory");
}

if(%IsWasmTrapHandlerEnabled()) {
  testAddressSpaceLimit();
}