gray-unmarking.js (2483B)
1 // Test interaction of gray marking / cross zone pointers / aborted GC marking. 2 3 gczeal(0); 4 5 gc(); 6 assertEq(grayBitsValid(), true); 7 8 // Create some globals in different zones. 9 let g1 = newGlobal({newCompartment: true}); 10 let g2 = newGlobal({newCompartment: true}); 11 let g3 = newGlobal({newCompartment: true}); 12 13 // Set up a linked list of objects in different zones: a --> b --> c 14 g1.eval('var a = {}'); 15 g2.eval('var b = {}'); 16 g3.eval('var c = {}'); 17 g1.a.next = g2.b; 18 g2.b.next = g3.c; 19 20 // Observe mark state of the objects and remove extra references from the globals. 21 g1.eval('addMarkObservers([a])'); 22 g2.eval('addMarkObservers([b])'); 23 g3.eval('addMarkObservers([c])'); 24 g2.b = undefined; 25 g3.c = undefined; 26 27 function checkMarks(a, b, c) { 28 assertEq(getMarks().join(", "), [a, b, c].join(", ")); 29 } 30 31 // Check GC initially marks everything black. 32 gc(); 33 checkMarks("black", "black", "black"); 34 35 // Replace root with a gray one and check GC marks everything gray. 36 g1.eval('grayRoot()[0] = a'); 37 g1.a = undefined; 38 gc(); 39 checkMarks("gray", "gray", "gray"); 40 41 // Read the gray root and check gray unmarking marks everything black again. 42 g1.eval('grayRoot()[0]'); 43 checkMarks("black", "black", "black"); 44 45 // Reset everything to gray. 46 gc(); 47 checkMarks("gray", "gray", "gray"); 48 49 // Start marking zone 2. 50 schedulezone(g2); 51 startgc(10); 52 while (gcstate() === "Prepare" || gcstate() === "MarkRoots") { 53 gcslice(10); 54 } 55 assertEq(gcstate(), "Mark"); 56 assertEq(gcstate(g1), "NoGC"); 57 assertEq(gcstate(g2), "MarkBlackOnly"); 58 assertEq(gcstate(g3), "NoGC"); 59 60 // Check zone 2's mark bits have been cleared. 61 checkMarks("gray", "unmarked", "gray"); 62 63 // Gray unmarking stops at the zone that is being mraked 64 g1.eval('grayRoot()[0]'); 65 checkMarks("black", "black", "gray"); 66 67 // GC marking handles the gray unmarking by propagaing b's mark state. 68 finishgc(); 69 assertEq(grayBitsValid(), true); 70 checkMarks("black", "black", "black"); 71 72 // Reset everything to gray. 73 gc(); 74 checkMarks("gray", "gray", "gray"); 75 76 // Repeat the previous test but abort marking after unmarking a. c is 77 // left as 'gray' (incorrect) but the gray marking state is marked as invalid. 78 schedulezone(g2); 79 startgc(10); 80 while (gcstate() === "Prepare" || gcstate() === "MarkRoots") { 81 gcslice(10); 82 } 83 assertEq(gcstate(), "Mark"); 84 checkMarks("gray", "unmarked", "gray"); 85 g1.eval('grayRoot()[0]'); 86 assertEq(grayBitsValid(), true); 87 abortgc(); 88 assertEq(grayBitsValid(), false); 89 checkMarks("black", "black", "gray"); 90 91 gc(); 92 checkMarks("gray", "gray", "gray");