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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// These tests will be using object literals as keys, and we want some of them
// to be dead after being inserted into a WeakMap. That means we must wrap
// everything in functions because it seems like the toplevel script hangs onto
// its object literals.
// Cross-compartment WeakMap keys work by storing a cross-compartment wrapper
// in the WeakMap, and the actual "delegate" object in the target compartment
// is the thing whose liveness is checked.
var g2 = newGlobal();
g2.eval('function genObj(name) { return {"name": name} }');
function basicSweeping() {
var wm1 = new WeakMap();
wm1.set({'name': 'obj1'}, {'name': 'val1'});
var hold = g2.genObj('obj2');
wm1.set(hold, {'name': 'val2'});
wm1.set({'name': 'obj3'}, {'name': 'val3'});
var obj4 = g2.genObj('obj4');
wm1.set(obj4, {'name': 'val3'});
obj4 = undefined;
startgc(100000, 'shrinking');
gcslice();
assertEq(wm1.get(hold).name, 'val2');
assertEq(nondeterministicGetWeakMapKeys(wm1).length, 1);
}
basicSweeping();
// Same, but behind an additional WM layer, to avoid ordering problems (not
// that I've checked that basicSweeping even has any problems.)
function basicSweeping2() {
var wm1 = new WeakMap();
wm1.set({'name': 'obj1'}, {'name': 'val1'});
var hold = g2.genObj('obj2');
wm1.set(hold, {'name': 'val2'});
wm1.set({'name': 'obj3'}, {'name': 'val3'});
var obj4 = g2.genObj('obj4');
wm1.set(obj4, {'name': 'val3'});
obj4 = undefined;
var base1 = {'name': 'base1'};
var base2 = {'name': 'base2'};
var wm_base1 = new WeakMap();
var wm_base2 = new WeakMap();
wm_base1.set(base1, wm_base2);
wm_base2.set(base2, wm1);
wm1 = wm_base2 = undefined;
startgc(100000, 'shrinking');
gcslice();
assertEq(nondeterministicGetWeakMapKeys(wm_base1).length, 1);
wm_base2 = wm_base1.get(base1);
assertEq(nondeterministicGetWeakMapKeys(wm_base2).length, 1);
assertEq(nondeterministicGetWeakMapKeys(wm_base1)[0], base1);
assertEq(nondeterministicGetWeakMapKeys(wm_base2)[0], base2);
wm_base2 = wm_base1.get(base1);
wm1 = wm_base2.get(base2);
assertEq(wm1.get(hold).name, 'val2');
assertEq(nondeterministicGetWeakMapKeys(wm1).length, 1);
}
basicSweeping2();
// Scatter the weakmap, the keys, and the values among different compartments.
function tripleZoneMarking() {
var g1 = newGlobal();
var g2 = newGlobal();
var g3 = newGlobal();
var wm = g1.eval("new WeakMap()");
var key = g2.eval("({'name': 'obj1'})");
var value = g3.eval("({'name': 'val1'})");
g1 = g2 = g3 = undefined;
wm.set(key, value);
// Make all of it only reachable via a weakmap in the main test compartment,
// so that all of this happens during weak marking mode. Use the weakmap as
// its own key, so we know that the weakmap will get traced before the key
// and therefore will populate the weakKeys table and all of that jazz.
var base_wm = new WeakMap();
base_wm.set(base_wm, [ wm, key ]);
wm = key = value = undefined;
startgc(100000, 'shrinking');
gcslice();
var keys = nondeterministicGetWeakMapKeys(base_wm);
assertEq(keys.length, 1);
var [ wm, key ] = base_wm.get(keys[0]);
assertEq(key.name, "obj1");
value = wm.get(key);
assertEq(value.name, "val1");
}
tripleZoneMarking();
function enbugger() {
var g = newGlobal();
var dbg = new Debugger;
g.eval("function debuggee_f() { return 1; }");
g.eval("function debuggee_g() { return 1; }");
dbg.addDebuggee(g);
var [ s ] = dbg.findScripts({global: g}).filter(s => s.displayName == "debuggee_f");
var [ s2 ] = dbg.findScripts({global: g}).filter(s => s.displayName == "debuggee_g");
g.eval("debuggee_f = null");
gc();
dbg.removeAllDebuggees();
gc();
assertEq(s.displayName, "debuggee_f");
var wm = new WeakMap;
var obj = Object.create(null);
var obj2 = Object.create(null);
wm.set(obj, s);
wm.set(obj2, obj);
wm.set(s2, obj2);
s = s2 = obj = obj2 = null;
gc();
}
enbugger();
|