summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/structured-clone/tenuring.js
blob: 0fffa064fa9875d0f28e7e0c6ac0b6f84b8c646a (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
86
87
88
89
90
91
92
// Check that we switch to allocating in the tenure heap after the first
// nursery collection.

function buildObjectTree(depth) {
  if (depth === 0) {
    return "leaf";
  }

  return {
    left: buildObjectTree(depth - 1),
    right: buildObjectTree(depth - 1)
  };
}

function buildArrayTree(depth) {
  if (depth === 0) {
    return [];
  }

  return [
    buildArrayTree(depth - 1),
    buildArrayTree(depth - 1)
  ];
}

function testRoundTrip(depth, objectTree, expectedNurseryAllocated) {
  const input = objectTree ? buildObjectTree(depth) : buildArrayTree(depth);

  gc();
  const initialMinorNumber = gcparam('minorGCNumber');

  const output = deserialize(serialize(input));
  checkHeap(output, depth, objectTree, expectedNurseryAllocated);

  const minorCollections = gcparam('minorGCNumber') - initialMinorNumber;
  const expectedMinorCollections = expectedNurseryAllocated ? 0 : 1;
  assertEq(minorCollections, expectedMinorCollections);
}

function checkHeap(tree, depth, objectTree, expectedNurseryAllocated) {
  const counts = countHeapLocations(tree, objectTree);

  const total = counts.nursery + counts.tenured;
  assertEq(total, (2 ** (depth + 1)) - 1);

  if (expectedNurseryAllocated) {
    assertEq(counts.tenured, 0);
    assertEq(counts.nursery >= 1, true);
  } else {
    assertEq(counts.tenured >= 1, true);
    // We get a single nursery allocation when we trigger minor GC.
    assertEq(counts.nursery <= 1, true);
  }
}

function countHeapLocations(tree, objectTree, counts) {
  if (!counts) {
    counts = {nursery: 0, tenured: 0};
  }

  if (isNurseryAllocated(tree)) {
    counts.nursery++;
  } else {
    counts.tenured++;
  }

  if (objectTree) {
    if (tree !== "leaf") {
      countHeapLocations(tree.left, objectTree, counts);
      countHeapLocations(tree.right, objectTree, counts);
    }
  } else {
    if (tree.length !== 0) {
      countHeapLocations(tree[0], objectTree, counts);
      countHeapLocations(tree[1], objectTree, counts);
    }
  }

  return counts;
}

gczeal(0);
gcparam('minNurseryBytes', 1024 * 1024);
gcparam('maxNurseryBytes', 1024 * 1024);
gc();

testRoundTrip(1, true, true);
testRoundTrip(1, false, true);
testRoundTrip(4, true, true);
testRoundTrip(4, false, true);
testRoundTrip(15, true, false);
testRoundTrip(15, false, false);