tor-browser

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

lazy.js (4776B)


      1 load(libdir + 'bytecode-cache.js');
      2 var test = "";
      3 var checkAfter;
      4 
      5 // code a function which has both used and unused inner functions.
      6 test = (function () {
      7  function f(x) {
      8    function ifTrue() {
      9      return true;
     10    };
     11    function ifFalse() {
     12      return false;
     13    };
     14 
     15    if (x) return ifTrue();
     16    else return ifFalse();
     17  }
     18 
     19  return f.toString() + "; f(true)";
     20 })();
     21 evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
     22 
     23 // code a function which uses different inner functions based on the generation.
     24 test = (function () {
     25  function f(x) {
     26    function ifTrue() {
     27      return true;
     28    };
     29    function ifFalse() {
     30      return false;
     31    };
     32 
     33    if (x) return ifTrue();
     34    else return ifFalse();
     35  }
     36 
     37  return f.toString() + "; f((generation % 2) == 0)";
     38 })();
     39 evalWithCache(test, { });
     40 
     41 // Code a function which has an enclosing scope.
     42 test = (function () {
     43  function f() {
     44    var upvar = "";
     45    function g() { upvar += ""; return upvar; }
     46    return g;
     47  }
     48 
     49  return f.toString() + "; f()();";
     50 })();
     51 evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
     52 
     53 // Code a lazy function which has an enclosing scope.
     54 test = (function () {
     55  function f() {
     56    var upvar = "";
     57    function g() { upvar += ""; return upvar; }
     58    return g;
     59  }
     60 
     61  return f.toString() + "; f();";
     62 })();
     63 evalWithCache(test, { assertEqBytecode: true });
     64 
     65 // (basic/bug535930) Code an enclosing scope which is a Call object.
     66 test = (function () {
     67  return "(" + (function () {
     68    p = function () {
     69        Set()
     70    };
     71    var Set = function () {};
     72    for (var x = 0; x < 5; x++) {
     73      Set = function (z) {
     74        return function () {
     75          [z]
     76        }
     77      } (x)
     78    }
     79  }).toString() + ")()";
     80 })();
     81 evalWithCache(test, { assertEqBytecode: true });
     82 
     83 // Code an arrow function, and execute it.
     84 test = (function () {
     85  function f() {
     86    var g = (a) => a + a;
     87    return g;
     88  }
     89 
     90  return f.toString() + "; f()(1);";
     91 })();
     92 evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
     93 
     94 // Code an arrow function, and do not execute it.
     95 test = (function () {
     96  function f() {
     97    var g = (a) => a + a;
     98    return g;
     99  }
    100 
    101  return f.toString() + "; f();";
    102 })();
    103 evalWithCache(test, { assertEqBytecode: true });
    104 
    105 // Extra zeal GCs can cause isRelazifiableFunction() to become true after we
    106 // record its value by throwing away JIT code for the function.
    107 gczeal(0);
    108 
    109 // Ensure that decoded functions can be relazified.
    110 test = "function f() { }; f();"
    111     + "assertEq(isLazyFunction(f), false);"
    112     + "var expect = isRelazifiableFunction(f);";
    113 checkAfter = function (ctx) {
    114  relazifyFunctions(); // relazify f, if possible.
    115  evaluate("assertEq(isLazyFunction(f), expect);", ctx);
    116 };
    117 evalWithCache(test, {
    118  assertEqBytecode: true,  // Check that we re-encode the same thing.
    119  assertEqResult: true,    // The function should remain relazifiable, if it was
    120                           // during the first run.
    121  checkAfter: checkAfter   // Check that relazifying the restored function works
    122                           // if the original was relazifiable.
    123 });
    124 
    125 // Ensure that decoded functions can be relazified, even if they have free
    126 // variables.
    127 test = "function f() { return isRelazifiableFunction(f) }; var expect = f();"
    128     + "assertEq(isLazyFunction(f), false);"
    129     + "expect";
    130 checkAfter = function (ctx) {
    131  relazifyFunctions(); // relazify f, if possible.
    132  evaluate("assertEq(isLazyFunction(f), expect);", ctx);
    133 };
    134 evalWithCache(test, {
    135  assertEqBytecode: true,  // Check that we re-encode the same thing.
    136  assertEqResult: true,    // The function should remain relazifiable, if it was
    137                           // during the first run.
    138  checkAfter: checkAfter   // Check that relazifying the restored function works
    139                           // if the original was relazifiable.
    140 });
    141 
    142 // Ensure that if a function is encoded when non-lazy but relazifiable, then
    143 // decoded, relazified, and then delazified, the result actually works.
    144 test = `
    145  function f() { return true; };
    146  var canBeLazy = isRelazifiableFunction(f) || isLazyFunction(f);
    147  relazifyFunctions();
    148  assertEq(isLazyFunction(f), canBeLazy);
    149  f()`
    150 evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
    151 
    152 // And more of the same, in a slightly different way
    153 var g1 = newGlobal({ cloneSingletons: true });
    154 var g2 = newGlobal();
    155 var res = "function f(){}";
    156 var code = cacheEntry(res + "; f();");
    157 evaluate(code, {global:g1, saveBytecodeWithDelazifications: {value: true}});
    158 evaluate(code, {global:g2, loadBytecode: true});
    159 gc();
    160 assertEq(g2.f.toString(), res);
    161 
    162 // Another relazification case.
    163 var src = "function f() { return 3; }; f(); relazifyFunctions(); 4";
    164 evalWithCache(src, {assertEqBytecode: true, assertEqResult: true});