mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 22:55:23 +00:00
Bug 646597 - Make functions made by the Function constructor compile-and-go. Most of patch was originally written by jorendorff. (r=luke)
This commit is contained in:
parent
b0f0481c81
commit
2a348786f9
@ -330,7 +330,6 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
return false;
|
||||
}
|
||||
|
||||
options.setCompileAndGo(false);
|
||||
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true);
|
||||
if (!parser.init())
|
||||
return false;
|
||||
@ -413,9 +412,17 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
#endif
|
||||
|
||||
if (generateBytecode) {
|
||||
/*
|
||||
* The reason for checking fun->environment() below is that certain
|
||||
* consumers of JS::CompileFunction, namely
|
||||
* nsEventListenerManager::CompileEventHandlerInternal, passes in a
|
||||
* NULL environment. This compiled function is never used, but instead
|
||||
* is cloned immediately onto the right scope chain.
|
||||
*/
|
||||
BytecodeEmitter funbce(/* parent = */ NULL, &parser, funbox, script,
|
||||
/* evalCaller = */ NullPtr(),
|
||||
/* hasGlobalScope = */ false, options.lineno);
|
||||
fun->environment() && fun->environment()->isGlobal(),
|
||||
options.lineno);
|
||||
if (!funbce.init())
|
||||
return false;
|
||||
|
||||
|
@ -20,7 +20,7 @@ dbg.onNewScript = function (s) {
|
||||
};
|
||||
assertEq(g.eval("eval('2 + 3')"), 5);
|
||||
this.gczeal(hits, 2);
|
||||
var fn = g.Function("a", "return 5 + a;");
|
||||
var fn = g.evaluate("(function (a) { return 5 + a; })", {compileAndGo: false});
|
||||
var g2 = newGlobal('new-compartment');
|
||||
dbg.addDebuggee(g2, dbg);
|
||||
g2.clone(fn);
|
||||
|
@ -1,3 +1,8 @@
|
||||
// |jit-test| no-ion
|
||||
//
|
||||
// We can't guarantee error identity when functions are Ion-compiled due to
|
||||
// optimization.
|
||||
|
||||
function check_one(expected, f, err) {
|
||||
var failed = true;
|
||||
try {
|
||||
|
@ -19,9 +19,9 @@ function test(str, arg, result)
|
||||
Reflect.parse(got);
|
||||
|
||||
// test xdr by cloning a cross-compartment function
|
||||
otherGlobal.str = str;
|
||||
var c = clone(otherGlobal.eval("new Function('x', str)"));
|
||||
assertEq(c.toSource(), fun.toSource());
|
||||
var code = "(function (x) { " + str + " })";
|
||||
var c = clone(otherGlobal.evaluate(code, {compileAndGo: false}));
|
||||
assertEq(c.toSource(), eval(code).toSource());
|
||||
|
||||
var got = fun(arg);
|
||||
var expect = result;
|
||||
|
@ -1,24 +1,28 @@
|
||||
var g = newGlobal('new-compartment');
|
||||
|
||||
g.f = new Function('return function(x) { return x }');
|
||||
function cloneableFunction(body) {
|
||||
return evaluate("(function () { " + body + " })", {compileAndGo: false});
|
||||
}
|
||||
|
||||
g.f = cloneableFunction('return function(x) { return x };');
|
||||
assertEq(g.eval("clone(f)()(9)"), 9);
|
||||
|
||||
g.f = new Function('return function(x) { let(y = x+1) { return y } }');
|
||||
g.f = cloneableFunction('return function(x) { let(y = x+1) { return y } };');
|
||||
assertEq(g.eval("clone(f)()(9)"), 10);
|
||||
|
||||
g.f = new Function('return function(x) { let(y = x, z = 1) { return y+z } }');
|
||||
g.f = cloneableFunction('return function(x) { let(y = x, z = 1) { return y+z } };');
|
||||
assertEq(g.eval("clone(f)()(9)"), 10);
|
||||
|
||||
g.f = new Function('return function(x) { return x.search(/ponies/) }');
|
||||
g.f = cloneableFunction('return function(x) { return x.search(/ponies/) };');
|
||||
assertEq(g.eval("clone(f)()('123ponies')"), 3);
|
||||
|
||||
g.f = new Function('return function(x,y) { return x.search(/a/) + y.search(/b/) }');
|
||||
g.f = cloneableFunction('return function(x,y) { return x.search(/a/) + y.search(/b/) };');
|
||||
assertEq(g.eval("clone(f)()('12a','foo')"), 1);
|
||||
|
||||
g.f = new Function('return [function(x) x+2, function(y) let(z=y+1) z]');
|
||||
g.f = cloneableFunction('return [function(x) x+2, function(y) let(z=y+1) z];');
|
||||
assertEq(g.eval("let ([f,g] = clone(f)()) f(g(4))"), 7);
|
||||
|
||||
g.f = new Function('return function(x) { switch(x) { case "a": return "b"; case null: return "c" } }');
|
||||
g.f = cloneableFunction('return function(x) { switch(x) { case "a": return "b"; case null: return "c" } };');
|
||||
assertEq(g.eval("clone(f)()('a')"), "b");
|
||||
assertEq(g.eval("clone(f)()(null)"), "c");
|
||||
assertEq(g.eval("clone(f)()(3)"), undefined);
|
||||
|
@ -37,6 +37,7 @@ assertEq(fn(8), 13);
|
||||
assertEq(hits, 1);
|
||||
|
||||
// cloning functions across compartments
|
||||
fn = g.evaluate("(function(a) { return 5 + a; })", {compileAndGo: false});
|
||||
var g2 = newGlobal('new-compartment');
|
||||
dbg.addDebuggee(g2, dbg);
|
||||
hits = 0;
|
||||
|
@ -44,7 +44,7 @@ test(function () { g.eval("var obj = {get x() { return 1; }, set x(v) { print(v)
|
||||
test(function () { return g.Function("a", "b", "return b - a;"); });
|
||||
|
||||
// cloning a function with nested functions
|
||||
test(function () { g.clone(Function("x", "return x + 1")); });
|
||||
test(function () { g.clone(evaluate("(function(x) { return x + 1; })", {compileAndGo: false})); });
|
||||
|
||||
// eval declaring a generator
|
||||
test(function () { g.eval("function r(n) { for (var i=0;i<n;i++) yield i; }"); });
|
||||
|
@ -1296,7 +1296,8 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
|
||||
CompileOptions options(cx);
|
||||
options.setPrincipals(principals)
|
||||
.setOriginPrincipals(originPrincipals)
|
||||
.setFileAndLine(filename, lineno);
|
||||
.setFileAndLine(filename, lineno)
|
||||
.setCompileAndGo(true);
|
||||
|
||||
unsigned n = args.length() ? args.length() - 1 : 0;
|
||||
if (n > 0) {
|
||||
|
@ -28,14 +28,15 @@ var actualvalues = [];
|
||||
var expect= '';
|
||||
var expectedvalues = [];
|
||||
|
||||
var f = Function("x","y","\
|
||||
function h() { return h_peer(); } \
|
||||
function h_peer() { return (x + cnCOMMA + y); } \
|
||||
return h");
|
||||
|
||||
if (typeof clone == 'function')
|
||||
{
|
||||
status = inSection(1);
|
||||
var f = evaluate("(function(x, y) {\n" +
|
||||
" function h() { return h_peer(); }\n" +
|
||||
" function h_peer() { return (x + cnCOMMA + y); }\n" +
|
||||
" return h;\n" +
|
||||
"})",
|
||||
{compileAndGo: false});
|
||||
var g = clone(f);
|
||||
g.prototype = new Object;
|
||||
var h = g(5,6);
|
||||
|
@ -27,7 +27,7 @@ function test()
|
||||
else {
|
||||
expect = 'PASSED';
|
||||
|
||||
f = Function("return a * a;");
|
||||
f = evaluate("(function () { return a * a; })", {compileAndGo: false});
|
||||
g = clone(f, {a: 3});
|
||||
f = null;
|
||||
gc();
|
||||
|
@ -140,6 +140,8 @@ class Test:
|
||||
test.jitflags.append('--no-jm')
|
||||
elif name == 'ion-eager':
|
||||
test.jitflags.append('--ion-eager')
|
||||
elif name == 'no-ion':
|
||||
test.jitflags.append('--no-ion')
|
||||
elif name == 'dump-bytecode':
|
||||
test.jitflags.append('--dump-bytecode')
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user