tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

collect-gray.js (5755B)


      1 // |reftest| skip-if(!xulRuntime.shell)
      2 // Any copyright is dedicated to the Public Domain.
      3 // http://creativecommons.org/licenses/publicdomain/
      4 
      5 //-----------------------------------------------------------------------------
      6 var BUGNUMBER = 1337209;
      7 var summary =
      8  "Test gray marking";
      9 
     10 print(BUGNUMBER + ": " + summary);
     11 
     12 if (typeof gczeal !== 'undefined')
     13    gczeal(0);
     14 
     15 function test() {
     16  grayRoot().x = Object.create(null);
     17  addMarkObservers([grayRoot(), grayRoot().x, this, Object.create(null)]);
     18  gc();
     19  let marks = getMarks();
     20  assertEq(marks[0], 'gray', 'gray root');
     21  assertEq(marks[1], 'gray', 'object reachable from gray root');
     22  assertEq(marks[2], 'black', 'global');
     23  assertEq(marks[3], 'dead', 'dead object should have been collected');
     24 
     25  grayRoot().x = 7; // Overwrite the object
     26  gc();
     27  marks = getMarks();
     28  assertEq(marks[0], 'gray', 'gray root');
     29  assertEq(marks[1], 'dead', 'object no longer reachable from gray root');
     30  assertEq(marks[2], 'black', 'global');
     31  assertEq(marks[3], 'dead', 'dead object should have been collected');
     32 
     33  var wm = new WeakMap();
     34  var global = newGlobal({newCompartment: true});
     35 
     36  var wrapper1 = global.eval("Object.create(null)");
     37  wrapper1.name = "wrapper1";
     38  var value1 = Object.create(null);
     39  wm.set(wrapper1, value1);
     40 
     41  var wrapper2 = global.eval("Object.create(null)");
     42  wrapper2.name = "wrapper2";
     43  var value2 = global.eval("Object.create(null)");
     44  wm.set(wrapper2, value2);
     45 
     46  grayRoot().root1 = wrapper1;
     47  grayRoot().root2 = wrapper2;
     48  clearMarkObservers();
     49  addMarkObservers([wrapper1, value1, wrapper2, value2]);
     50  wrapper1 = wrapper2 = null;
     51  value1 = value2 = null;
     52  gc();
     53  marks = getMarks();
     54  assertEq(marks[0], 'gray', 'gray key 1');
     55  assertEq(marks[1], 'gray', 'black map, gray key => gray value');
     56  assertEq(marks[2], 'gray', 'gray key 2');
     57  assertEq(marks[3], 'gray', 'black map, gray key => gray value');
     58 
     59  // Blacken one of the keys
     60  wrapper1 = grayRoot().root1;
     61  gc();
     62  marks = getMarks();
     63  assertEq(marks[0], 'black', 'black key 1');
     64  assertEq(marks[1], 'black', 'black map, black key => black value');
     65  assertEq(marks[2], 'gray', 'gray key 2');
     66  assertEq(marks[3], 'gray', 'black map, gray key => gray value');
     67 
     68  // Test edges from map&delegate => key and map&key => value.
     69  //
     70  // In general, when a&b => x, then if both a and b are black, then x must be
     71  // black. If either is gray and the other is marked (gray or black), then x
     72  // must be gray (unless otherwise reachable from black.) If neither a nor b is
     73  // marked at all, then they will not keep x alive.
     74 
     75  clearMarkObservers();
     76 
     77  // Black map, gray delegate => gray key
     78 
     79  // wm is in a variable, so is black.
     80  wm = new WeakMap();
     81 
     82  let key = Object.create(null);
     83  // delegate unwraps key in the 'global' compartment
     84  global.grayRoot().delegate = key;
     85 
     86  // Create a value and map to it from a gray key, then make the value a gray
     87  // root.
     88  let value = Object.create(null);
     89  wm.set(key, value);
     90  grayRoot().value = value;
     91 
     92  // We are interested in the mark bits of the map, key, and value, as well as
     93  // the mark bits of the wrapped versions in the other compartment. Note that
     94  // the other-compartment key is the known as the key's delegate with respect to
     95  // the weakmap.
     96  global.addMarkObservers([wm, key, value]);
     97  addMarkObservers([wm, key, value]);
     98 
     99  // Key is otherwise dead in main compartment.
    100  key = null;
    101  // Don't want value to be marked black.
    102  value = null;
    103 
    104  gc(); // Update mark bits.
    105  let [
    106    other_map_mark, other_key_mark, other_value_mark,
    107    map_mark, key_mark, value_mark
    108  ] = getMarks();
    109  assertEq(other_map_mark, 'dead', 'nothing points to wm in other compartment');
    110  assertEq(other_key_mark, 'gray', 'delegate should be gray');
    111  assertEq(other_value_mark, 'dead', 'nothing points to value wrapper in other compartment');
    112  assertEq(map_mark, 'black', 'map in var => black');
    113  assertEq(key_mark, 'gray', 'black map, gray delegate => gray key');
    114  assertEq(value_mark, 'gray', 'black map, gray delegate/key => gray value');
    115 
    116  // Black map, black delegate => black key
    117 
    118  // Blacken the delegate by pointing to it from the other global.
    119  global.delegate = global.grayRoot().delegate;
    120 
    121  gc();
    122  [
    123    other_map_mark, other_key_mark, other_value_mark,
    124    map_mark, key_mark, value_mark
    125  ] = getMarks();
    126  assertEq(other_map_mark, 'dead', 'nothing points to wm in other compartment');
    127  assertEq(other_key_mark, 'black', 'delegate held in global.delegate');
    128  assertEq(other_value_mark, 'dead', 'nothing points to value wrapper in other compartment');
    129  assertEq(map_mark, 'black', 'map in var => black');
    130  assertEq(key_mark, 'black', 'black map, black delegate => black key');
    131  assertEq(value_mark, 'black', 'black map, black key => black value');
    132 
    133  // Gray map, black delegate => gray key. Unfortunately, there's no way to test
    134  // this, because a WeakMap key's delegate is its wrapper, and there is a strong
    135  // edge from wrappers to wrappees. The jsapi-test in testGCGrayMarking, inside
    136  // TestWeakMaps, *does* test this case.
    137 
    138  grayRoot().map = wm;
    139  wm = null;
    140 
    141  gc();
    142  [
    143    other_map_mark, other_key_mark, other_value_mark,
    144    map_mark, key_mark, value_mark
    145  ] = getMarks();
    146  assertEq(other_map_mark, 'dead', 'nothing points to wm in other compartment');
    147  assertEq(other_key_mark, 'black', 'delegate held in global.delegate');
    148  assertEq(other_value_mark, 'dead', 'nothing points to value wrapper in other compartment');
    149  assertEq(map_mark, 'gray', 'map is a gray root');
    150  assertEq(key_mark, 'black', 'black delegate marks its key black');
    151  assertEq(value_mark, 'gray', 'gray map, black key => gray value');
    152 }
    153 test();
    154 
    155 if (typeof reportCompare === "function")
    156  reportCompare(true, true);