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
93
|
// Check that we switch to allocating in the tenured 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);
gcparam('semispaceNurseryEnabled', 0);
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);
|