summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/ion/array-push-multiple-frozen.js
blob: 271f6cb07a8d67a16bf795af0bed686c4f57c5a9 (plain)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// |jit-test| --no-threads; skip-if: !('oomAtAllocation' in this)

// This test case check's Ion ability to recover from an allocation failure in
// the inlining of Array.prototype.push, when given multiple arguments. Note,
// that the following are not equivalent in case of failures:
//
//   arr = [];
//   arr.push(1,2,3); // OOM ---> arr == []
//
//   arr = [];
//   arr.push(1);
//   arr.push(2); // OOM --> arr == [1]
//   arr.push(3);

function canIoncompile() {
  while (true) {
    var i = inIon();
    if (i)
      return i;
  }
}

if (canIoncompile() != true)
  quit();
if ("gczeal" in this)
  gczeal(0);

function pushLimits(limit, offset, arr, freeze) {
  arr = arr || [];
  arr.push(0,1,2,3,4,5,6,7,8,9);
  arr.length = offset;
  var l = arr.length;
  var was = inIon();
  oomAtAllocation(limit);
  try {
    for (var i = 0; i < 50; i++)
      arr.push(0,1,2,3,4,5,6,7,8,9);
    if (freeze)
      arr.frozen();
    for (var i = 0; i < 100; i++)
      arr.push(0,1,2,3,4,5,6,7,8,9);
  } catch (e) {
    // Catch OOM.
  }
  resetOOMFailure();
  assertEq(arr.length % 10, l);
  // Check for a bailout.
  var is = inIon();
  return was ? is ? 1 : 2 : 0;
}

// We need this limit to be high enough to be able to OSR in the for-loop of
// pushLimits.
var limit = 1024 * 1024 * 1024;
while(true) {
  var res = pushLimits(limit, 0);

  if (res == 0) {
    limit = 1024 * 1024 * 1024;
  } else if (res == 1) { // Started and finished in Ion.
    if (limit <= 1) // If we are not in the Jit.
      break;
    // We want to converge quickly to a state where the memory is limited
    // enough to cause failures in array.prototype.push.
    limit = (limit / 2) | 0;
  } else if (res == 2) { // Started in Ion, and finished in Baseline.
    if (limit < 10) {
      // This is used to offset the OOM location, such that we can test
      // each steps of the Array.push function, when it is jitted.
      for (var off = 1; off < 10; off++) {
        var arr = [];
        try {
          pushLimits(limit, off, arr, true);
        } catch (e) {
          // Cacth OOM produced while generating the error message.
        }
        if (arr.length > 10) assertEq(arr[arr.length - 1], 9);
        else assertEq(arr[arr.length - 1], arr.length - 1);
      }
    }
    if (limit == 1)
      break;
    limit--;
  }
}