tor-browser

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

object-keys-04.js (7045B)


      1 load(libdir + 'array-compare.js'); // arraysEqual
      2 
      3 // Ion eager fails the test below because we have not yet created any
      4 // Cache IR IC in baseline before running the content of the top-level
      5 // function.
      6 if (getJitCompilerOptions()["ion.warmup.trigger"] <= 100)
      7    setJitCompilerOption("ion.warmup.trigger", 100);
      8 
      9 // This test case checks that we are capable of recovering the Object.keys array
     10 // even if we optimized it away. It also checks that we indeed optimize it away
     11 // as we would expect.
     12 
     13 // Prevent GC from cancelling/discarding Ion compilations.
     14 gczeal(0);
     15 
     16 function objKeysLength(obj, expected, i) {
     17    var keys = Object.keys(obj);
     18    let len = keys.length;
     19    assertRecoveredOnBailout(keys, true);
     20    if (i >= 99) {
     21        // bailout would hint Ion to remove everything after, making the keys
     22        // array appear like being only used by resume points.
     23        bailout();
     24        assertEq(arraysEqual(keys, expected), true);
     25    }
     26    return len;
     27 }
     28 
     29 function objKeysLengthDiffBlock(obj, expected, i) {
     30    var keys = Object.keys(obj);
     31    if (i >= 99) {
     32        // bailout would hint Ion to remove everything after, making the keys
     33        // array appear like being only used by resume points.
     34        bailout();
     35        assertEq(arraysEqual(keys, expected), true);
     36    }
     37    let len = keys.length;
     38    assertRecoveredOnBailout(keys, true);
     39    return len;
     40 }
     41 
     42 // Mutating the object in-between the call from Object.keys and the evaluation
     43 // of the length property should still allow the optimization to take place
     44 // since the iterator we held onto should be from the previous shape of the
     45 // object.
     46 function objKeysLengthMutate0(obj, expected, i) {
     47    var keys = Object.keys(obj);
     48    obj.foo = 42;
     49    let len = keys.length;
     50    assertRecoveredOnBailout(keys, true);
     51    if (i >= 99) {
     52        bailout();
     53        assertEq(arraysEqual(keys, expected), true);
     54    }
     55    return len;
     56 }
     57 
     58 function objKeysLengthMutate1(obj, expected, i) {
     59    var keys = Object.keys(obj);
     60    let len = keys.length;
     61    assertRecoveredOnBailout(keys, true);
     62    obj.foo = 42;
     63    if (i >= 99) {
     64        bailout();
     65        assertEq(arraysEqual(keys, expected), true);
     66    }
     67    return len;
     68 }
     69 
     70 function objKeysLengthMutate2(obj, expected, i) {
     71    var keys = Object.keys(obj);
     72    let len = keys.length;
     73    assertRecoveredOnBailout(keys, true);
     74    if (i >= 99) {
     75        bailout();
     76        assertEq(arraysEqual(keys, expected), true);
     77    }
     78    obj.foo = 42;
     79    return len;
     80 }
     81 
     82 function objKeysLengthMutate3(obj, expected, i) {
     83    var keys = Object.keys(obj);
     84    let len = keys.length;
     85    assertRecoveredOnBailout(keys, true);
     86    if (i >= 99) {
     87        obj.foo = 42;
     88        bailout();
     89        assertEq(arraysEqual(keys, expected), true);
     90    }
     91    return len;
     92 }
     93 
     94 function objKeysLengthMutate4(obj, expected, i) {
     95    obj.foo = 42;
     96    var keys = Object.keys(obj);
     97    let len = keys.length;
     98    assertRecoveredOnBailout(keys, true);
     99    if (i >= 99) {
    100        bailout();
    101        assertEq(arraysEqual(keys, expected), true);
    102    }
    103    return len;
    104 }
    105 
    106 
    107 function doNotInlineSideEffect() {
    108    eval("1");
    109 }
    110 
    111 function objKeysLengthSideEffect0(obj, expected, i) {
    112    var keys = Object.keys(obj);
    113    let len = keys.length;
    114    assertRecoveredOnBailout(keys, true);
    115    doNotInlineSideEffect();
    116    if (i >= 99) {
    117        bailout();
    118        assertEq(arraysEqual(keys, expected), true);
    119    }
    120    return len;
    121 }
    122 
    123 function objKeysLengthSideEffect1(obj, expected, i) {
    124    var keys = Object.keys(obj);
    125    let len = keys.length;
    126    assertRecoveredOnBailout(keys, true);
    127    if (i >= 99) {
    128        bailout();
    129        assertEq(arraysEqual(keys, expected), true);
    130    }
    131    doNotInlineSideEffect();
    132    return len;
    133 }
    134 
    135 function objKeysLengthSideEffect2(obj, expected, i) {
    136    var keys = Object.keys(obj);
    137    let len = keys.length;
    138    assertRecoveredOnBailout(keys, true);
    139    if (i >= 99) {
    140        // When branches are pruned, Warp/Ion is not aware and would recover the
    141        // keys on bailout, and this is fine.
    142        doNotInlineSideEffect();
    143        bailout();
    144        assertEq(arraysEqual(keys, expected), true);
    145    }
    146    return len;
    147 }
    148 
    149 function objKeysLengthSideEffect3(obj, expected, i) {
    150    doNotInlineSideEffect();
    151    var keys = Object.keys(obj);
    152    let len = keys.length;
    153    assertRecoveredOnBailout(keys, true);
    154    if (i >= 99) {
    155        bailout();
    156        assertEq(arraysEqual(keys, expected), true);
    157    }
    158    return len;
    159 }
    160 
    161 function objKeysLengthMutateElements0(obj, expected, i) {
    162    var keys = Object.keys(obj);
    163    obj[0] = 42;
    164    obj[1] = 42;
    165    obj[2] = 42;
    166    let len = keys.length;
    167    assertRecoveredOnBailout(keys, true);
    168    if (i >= 99) {
    169        bailout();
    170        assertEq(arraysEqual(keys, expected), true);
    171    }
    172    return len;
    173 }
    174 
    175 function objKeysLengthMutateElements1(obj, expected, i) {
    176    obj[0] = 42;
    177    var keys = Object.keys(obj);
    178    obj[1] = 42;
    179    obj[2] = 42;
    180    let len = keys.length;
    181    assertRecoveredOnBailout(keys, true);
    182    if (i >= 99) {
    183        bailout();
    184        assertEq(arraysEqual(keys, expected), true);
    185    }
    186    return len;
    187 }
    188 
    189 function objKeysLengthMutateElements2(obj, expected, i) {
    190    obj[0] = 42;
    191    obj[1] = 42;
    192    var keys = Object.keys(obj);
    193    obj[2] = 42;
    194    let len = keys.length;
    195    assertRecoveredOnBailout(keys, true);
    196    if (i >= 99) {
    197        bailout();
    198        assertEq(arraysEqual(keys, expected), true);
    199    }
    200    return len;
    201 }
    202 
    203 // Check what we are doing as optimizations when the object is fully known and
    204 // when it does not escape.
    205 //
    206 // Except that today, Object.keys(..) is still assumed to make side-effect
    207 // despite being removed later.
    208 function nonEscapedObjKeysLength(i) {
    209    let obj = {a: i};
    210    var keys = Object.keys(obj);
    211    let len = keys.length;
    212    assertRecoveredOnBailout(keys, true);
    213    assertRecoveredOnBailout(obj, false);
    214    if (i >= 99) {
    215        bailout();
    216        assertEq(arraysEqual(keys, ["a"]), true);
    217    }
    218    return len;
    219 }
    220 
    221 // Prevent compilation of the top-level.
    222 eval(`${arraysEqual}`);
    223 let obj = {a: 0, b: 1, c: 2, d: 3};
    224 
    225 for (let i = 0; i < 100; i++) {
    226    objKeysLength({...obj}, ["a", "b", "c", "d"], i);
    227    objKeysLengthDiffBlock({...obj}, ["a", "b", "c", "d"], i);
    228    objKeysLengthMutate0({...obj}, ["a", "b", "c", "d"], i);
    229    objKeysLengthMutate1({...obj}, ["a", "b", "c", "d"], i);
    230    objKeysLengthMutate2({...obj}, ["a", "b", "c", "d"], i);
    231    objKeysLengthMutate3({...obj}, ["a", "b", "c", "d"], i);
    232    objKeysLengthMutate4({...obj}, ["a", "b", "c", "d", "foo"], i);
    233    objKeysLengthSideEffect0({...obj}, ["a", "b", "c", "d"], i);
    234    objKeysLengthSideEffect1({...obj}, ["a", "b", "c", "d"], i);
    235    objKeysLengthSideEffect2({...obj}, ["a", "b", "c", "d"], i);
    236    objKeysLengthSideEffect3({...obj}, ["a", "b", "c", "d"], i);
    237    objKeysLengthMutateElements0({...obj}, ["a", "b", "c", "d"], i);
    238    objKeysLengthMutateElements1({...obj}, ["0", "a", "b", "c", "d"], i);
    239    objKeysLengthMutateElements2({...obj}, ["0", "1", "a", "b", "c", "d"], i);
    240    nonEscapedObjKeysLength(i);
    241 }