summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/xdr/lazy.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/xdr/lazy.js')
-rw-r--r--js/src/jit-test/tests/xdr/lazy.js164
1 files changed, 164 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/xdr/lazy.js b/js/src/jit-test/tests/xdr/lazy.js
new file mode 100644
index 000000000..da9d745fc
--- /dev/null
+++ b/js/src/jit-test/tests/xdr/lazy.js
@@ -0,0 +1,164 @@
+load(libdir + 'bytecode-cache.js');
+var test = "";
+var checkAfter;
+
+// code a function which has both used and unused inner functions.
+test = (function () {
+ function f(x) {
+ function ifTrue() {
+ return true;
+ };
+ function ifFalse() {
+ return false;
+ };
+
+ if (x) return ifTrue();
+ else return ifFalse();
+ }
+
+ return f.toSource() + "; f(true)";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// code a function which uses different inner functions based on the generation.
+test = (function () {
+ function f(x) {
+ function ifTrue() {
+ return true;
+ };
+ function ifFalse() {
+ return false;
+ };
+
+ if (x) return ifTrue();
+ else return ifFalse();
+ }
+
+ return f.toSource() + "; f((generation % 2) == 0)";
+})();
+evalWithCache(test, { });
+
+// Code a function which has an enclosing scope.
+test = (function () {
+ function f() {
+ var upvar = "";
+ function g() { upvar += ""; return upvar; }
+ return g;
+ }
+
+ return f.toSource() + "; f()();";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// Code a lazy function which has an enclosing scope.
+test = (function () {
+ function f() {
+ var upvar = "";
+ function g() { upvar += ""; return upvar; }
+ return g;
+ }
+
+ return f.toSource() + "; f();";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// (basic/bug535930) Code an enclosing scope which is a Call object.
+test = (function () {
+ return "(" + (function () {
+ p = function () {
+ Set()
+ };
+ var Set = function () {};
+ for (var x = 0; x < 5; x++) {
+ Set = function (z) {
+ return function () {
+ [z]
+ }
+ } (x)
+ }
+ }).toSource() + ")()";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// Code an arrow function, and execute it.
+test = (function () {
+ function f() {
+ var g = (a) => a + a;
+ return g;
+ }
+
+ return f.toSource() + "; f()(1);";
+})();
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// Code an arrow function, and do not execute it.
+test = (function () {
+ function f() {
+ var g = (a) => a + a;
+ return g;
+ }
+
+ return f.toSource() + "; f();";
+})();
+evalWithCache(test, { assertEqBytecode: true });
+
+// Extra zeal GCs can cause isRelazifiableFunction() to become true after we
+// record its value by throwing away JIT code for the function.
+gczeal(0);
+
+// Ensure that decoded functions can be relazified.
+test = "function f() { }; f();"
+ + "assertEq(isLazyFunction(f), false);"
+ + "var expect = isRelazifiableFunction(f);";
+checkAfter = function (ctx) {
+ gc(ctx.global.f, "shrinking"); // relazify f, if possible.
+ evaluate("assertEq(isLazyFunction(f), expect);", ctx);
+};
+evalWithCache(test, {
+ assertEqBytecode: true, // Check that we re-encode the same thing.
+ assertEqResult: true, // The function should remain relazifiable, if it was
+ // during the first run.
+ checkAfter: checkAfter // Check that relazifying the restored function works
+ // if the original was relazifiable.
+});
+
+// Ensure that decoded functions can be relazified, even if they have free
+// variables.
+test = "function f() { return isRelazifiableFunction(f) }; var expect = f();"
+ + "assertEq(isLazyFunction(f), false);"
+ + "expect";
+checkAfter = function (ctx) {
+ gc(ctx.global.f, "shrinking"); // relazify f, if possible.
+ evaluate("assertEq(isLazyFunction(f), expect);", ctx);
+};
+evalWithCache(test, {
+ assertEqBytecode: true, // Check that we re-encode the same thing.
+ assertEqResult: true, // The function should remain relazifiable, if it was
+ // during the first run.
+ checkAfter: checkAfter // Check that relazifying the restored function works
+ // if the original was relazifiable.
+});
+
+// Ensure that if a function is encoded when non-lazy but relazifiable, then
+// decoded, relazified, and then delazified, the result actually works.
+test = `
+ function f() { return true; };
+ var canBeLazy = isRelazifiableFunction(f) || isLazyFunction(f);
+ relazifyFunctions();
+ assertEq(isLazyFunction(f), canBeLazy);
+ f()`
+evalWithCache(test, { assertEqBytecode: true, assertEqResult: true });
+
+// And more of the same, in a slightly different way
+var g1 = newGlobal({ cloneSingletons: true });
+var g2 = newGlobal();
+var res = "function f(){}";
+var code = cacheEntry(res + "; f();");
+evaluate(code, {global:g1, compileAndGo: true, saveBytecode: {value: true}});
+evaluate(code, {global:g2, loadBytecode: true});
+gc();
+assertEq(g2.f.toString(), res);
+
+// Another relazification case.
+var src = "function f() { return 3; }; f(); relazifyFunctions(); 4";
+evalWithCache(src, {assertEqBytecode: true, assertEqResult: true});