diff options
Diffstat (limited to 'js/src/jit-test/tests/xdr')
-rw-r--r-- | js/src/jit-test/tests/xdr/asm.js | 18 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/async-lazy.js | 24 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/async.js | 32 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/bug1108603.js | 9 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/bug1186973.js | 15 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/classes.js | 7 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/debug-lazy.js | 19 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/function-flags.js | 40 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/lazy.js | 164 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/scope.js | 19 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/tagged-template-literals-2.js | 4 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/tagged-template-literals.js | 4 | ||||
-rw-r--r-- | js/src/jit-test/tests/xdr/trivial.js | 42 |
13 files changed, 397 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/xdr/asm.js b/js/src/jit-test/tests/xdr/asm.js new file mode 100644 index 000000000..f584ea20e --- /dev/null +++ b/js/src/jit-test/tests/xdr/asm.js @@ -0,0 +1,18 @@ +load(libdir + 'bytecode-cache.js'); + +var test = (function () { + function f() { + var x = function inner() { + "use asm"; + function g() {} + return g; + }; + }; + return f.toSource(); +})(); + +try { + evalWithCache(test, {}); +} catch (x) { + assertEq(x.message.includes("Asm.js is not supported by XDR"), true); +} diff --git a/js/src/jit-test/tests/xdr/async-lazy.js b/js/src/jit-test/tests/xdr/async-lazy.js new file mode 100644 index 000000000..8f8c5accc --- /dev/null +++ b/js/src/jit-test/tests/xdr/async-lazy.js @@ -0,0 +1,24 @@ +async function f1(a, b) { + let x = await 10; + return x; +}; +var toStringResult = f1.toString(); + +async function f2(a, b) { + // arguments.callee gets wrapped function from unwrapped function. + return arguments.callee; +}; + +relazifyFunctions(); + +// toString gets unwrapped function from wrapped function. +assertEq(f1.toString(), toStringResult); + +var ans = 0; +f1().then(x => { ans = x; }); +drainJobQueue(); +assertEq(ans, 10); + +f2().then(x => { ans = x; }); +drainJobQueue(); +assertEq(ans, f2); diff --git a/js/src/jit-test/tests/xdr/async.js b/js/src/jit-test/tests/xdr/async.js new file mode 100644 index 000000000..5be39237b --- /dev/null +++ b/js/src/jit-test/tests/xdr/async.js @@ -0,0 +1,32 @@ +load(libdir + 'bytecode-cache.js'); + +async function f1(a, b) { + let x = await 10; + return x; +}; +var toStringResult = f1.toString(); + +var test = ` +async function f1(a, b) { + let x = await 10; + return x; +}; +// toString gets unwrapped function from wrapped function. +assertEq(f1.toString(), \`${toStringResult}\`); + +var ans = 0; +f1().then(x => { ans = x; }); +drainJobQueue(); +assertEq(ans, 10); + +async function f2(a, b) { + // arguments.callee gets wrapped function from unwrapped function. + return arguments.callee; +}; + +f2().then(x => { ans = x; }); +drainJobQueue(); +assertEq(ans, f2); +`; + +evalWithCache(test, { assertEqBytecode: true, checkFrozen: true}); diff --git a/js/src/jit-test/tests/xdr/bug1108603.js b/js/src/jit-test/tests/xdr/bug1108603.js new file mode 100644 index 000000000..54ba21e79 --- /dev/null +++ b/js/src/jit-test/tests/xdr/bug1108603.js @@ -0,0 +1,9 @@ +var caught = false; +try { + evaluate(cacheEntry(""), {saveBytecode: {value: true}, global: this}); + [[0]]; +} catch (err) { + caught = true; + assertEq(err.message, "compartment cannot save singleton anymore."); +} +assertEq(caught, true);
\ No newline at end of file diff --git a/js/src/jit-test/tests/xdr/bug1186973.js b/js/src/jit-test/tests/xdr/bug1186973.js new file mode 100644 index 000000000..780ef55dc --- /dev/null +++ b/js/src/jit-test/tests/xdr/bug1186973.js @@ -0,0 +1,15 @@ +// |jit-test| error: cache does not have the same size +load(libdir + 'bytecode-cache.js'); + +var test = (function () { + function f(x) { + function ifTrue() {}; + function ifFalse() {}; + + if (generation % 2 == 0) + return ifTrue(); + return ifFalse(); + } + return f.toSource() + "; f()"; +})(); +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); diff --git a/js/src/jit-test/tests/xdr/classes.js b/js/src/jit-test/tests/xdr/classes.js new file mode 100644 index 000000000..a5dc527f1 --- /dev/null +++ b/js/src/jit-test/tests/xdr/classes.js @@ -0,0 +1,7 @@ +load(libdir + 'bytecode-cache.js'); + +var test = "new class extends class { } { constructor() { super(); } }()"; +evalWithCache(test, { assertEqBytecode : true }); + +var test = "new class { method() { super.toString(); } }().method()"; +evalWithCache(test, { assertEqBytecode : true }); diff --git a/js/src/jit-test/tests/xdr/debug-lazy.js b/js/src/jit-test/tests/xdr/debug-lazy.js new file mode 100644 index 000000000..c6dec561b --- /dev/null +++ b/js/src/jit-test/tests/xdr/debug-lazy.js @@ -0,0 +1,19 @@ +load(libdir + 'bytecode-cache.js'); + +// Ensure that if a function is encoded when non-lazy but relazifiable, then +// decoded, the resulting LazyScript is marked as being non-lazy so that when +// the debugger tries to delazify things it doesn't get all confused. We just +// use findScripts() to trigger debugger delazification; we don't really care +// about the scripts themselves. +function checkAfter(ctx) { + var dbg = new Debugger(ctx.global); + var allScripts = dbg.findScripts(); + assertEq(allScripts.length == 0, false); +} + +test = ` + function f() { return true; }; + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true, + checkAfter: checkAfter }); diff --git a/js/src/jit-test/tests/xdr/function-flags.js b/js/src/jit-test/tests/xdr/function-flags.js new file mode 100644 index 000000000..62c69752b --- /dev/null +++ b/js/src/jit-test/tests/xdr/function-flags.js @@ -0,0 +1,40 @@ +load(libdir + 'bytecode-cache.js'); + +var test; + +// Ensure that if a function is encoded we don't encode its "name +// resolved" flag. +test = ` + function f() { delete f.name; return f.hasOwnProperty('name'); } + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); + +test = ` + function f() { return f.hasOwnProperty('name'); } + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); + +// Ensure that if a function is encoded we don't encode its "length +// resolved" flag. +test = ` + function f() { delete f.length; return f.hasOwnProperty('length'); } + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); + +test = ` + function f() { return f.hasOwnProperty('length'); } + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); + +// And make sure our bytecode is actually not reflecting the flags, +// not that we ignore them on decode. +test = ` + function f() { return f.hasOwnProperty('length') || f.hasOwnProperty('name'); } + f(); + ` +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); + 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}); diff --git a/js/src/jit-test/tests/xdr/scope.js b/js/src/jit-test/tests/xdr/scope.js new file mode 100644 index 000000000..417a402d2 --- /dev/null +++ b/js/src/jit-test/tests/xdr/scope.js @@ -0,0 +1,19 @@ +load(libdir + 'bytecode-cache.js'); +var test = ""; + +// code a function which has both used and unused inner functions. +test = (function () { + function f() { + var x = 3; + (function() { + with(obj) { + (function() { + assertEq(x, 2); + })(); + } + })(); + }; + + return "var obj = { x : 2 };" + f.toSource() + "; f()"; +})(); +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); diff --git a/js/src/jit-test/tests/xdr/tagged-template-literals-2.js b/js/src/jit-test/tests/xdr/tagged-template-literals-2.js new file mode 100644 index 000000000..10326eece --- /dev/null +++ b/js/src/jit-test/tests/xdr/tagged-template-literals-2.js @@ -0,0 +1,4 @@ +var code = cacheEntry("(x => x.toSource())`bar`;"); +var g = newGlobal({ cloneSingletons: true }); +assertEq("[\"bar\"]", evaluate(code, { global: g, saveBytecode: true })); +assertEq("[\"bar\"]", evaluate(code, { global: g, loadBytecode: true })); diff --git a/js/src/jit-test/tests/xdr/tagged-template-literals.js b/js/src/jit-test/tests/xdr/tagged-template-literals.js new file mode 100644 index 000000000..27a8c40ed --- /dev/null +++ b/js/src/jit-test/tests/xdr/tagged-template-literals.js @@ -0,0 +1,4 @@ +var code = cacheEntry("assertEq('bar', String.raw`bar`);"); +var g = newGlobal({ cloneSingletons: true }); +evaluate(code, { global: g, saveBytecode: true }); +evaluate(code, { global: g, loadBytecode: true }) diff --git a/js/src/jit-test/tests/xdr/trivial.js b/js/src/jit-test/tests/xdr/trivial.js new file mode 100644 index 000000000..8cb54bea5 --- /dev/null +++ b/js/src/jit-test/tests/xdr/trivial.js @@ -0,0 +1,42 @@ +load(libdir + 'bytecode-cache.js'); +var test = ""; + +// code a constant. +test = "1;"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code a string constant. +test = "'string';"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code a global variable access. +test = "generation;"; +evalWithCache(test, { assertEqBytecode: true }); + +// code an object constant. +test = "var obj = { a: 1, b: 2 };"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code object literal with mutations. +test = "var obj = { a: 1, b: 2 }; obj.a++; assertEq(obj.a, 2);"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code object literals with mutations. +test = "var obj = { a: 1, b: { c: 3, d: 4 } }; obj.b.c++; assertEq(obj.b.c, 4);"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code a function which is used. +test = "function f() { return 1; }; f();"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code a function which is not used. +test = "function f() { return 1; }; 1;"; +evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); + +// code a function which has an object literal. +test = "function f() { return { x: 2 }; }; f();"; +evalWithCache(test, { assertEqBytecode: true }); + +// code call site object +test = "function f(a) { return a; }; f`a${4}b`;"; +evalWithCache(test, { assertEqBytecode: true, checkFrozen: true}); |