mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 1003161 - Don't optimize arguments usage in scripts with aliased arguments, r=jandem.
This commit is contained in:
parent
766404390f
commit
d9df1214c0
8
js/src/jit-test/tests/basic/bug1003161.js
Normal file
8
js/src/jit-test/tests/basic/bug1003161.js
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
function foo(a, b) {
|
||||
function bar() {
|
||||
return b;
|
||||
}
|
||||
return arguments[0] + arguments[1] + bar();
|
||||
}
|
||||
foo(1, 2);
|
@ -2371,7 +2371,8 @@ jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
|
||||
}
|
||||
|
||||
static bool
|
||||
ArgumentsUseCanBeLazy(JSContext *cx, JSScript *script, MInstruction *ins, size_t index)
|
||||
ArgumentsUseCanBeLazy(JSContext *cx, JSScript *script, MInstruction *ins, size_t index,
|
||||
bool *argumentsContentsObserved)
|
||||
{
|
||||
// We can read the frame's arguments directly for f.apply(x, arguments).
|
||||
if (ins->isCall()) {
|
||||
@ -2379,13 +2380,16 @@ ArgumentsUseCanBeLazy(JSContext *cx, JSScript *script, MInstruction *ins, size_t
|
||||
ins->toCall()->numActualArgs() == 2 &&
|
||||
index == MCall::IndexOfArgument(1))
|
||||
{
|
||||
*argumentsContentsObserved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// arguments[i] can read fp->canonicalActualArg(i) directly.
|
||||
if (ins->isCallGetElement() && index == 0)
|
||||
if (ins->isCallGetElement() && index == 0) {
|
||||
*argumentsContentsObserved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// arguments.length length can read fp->numActualArgs() directly.
|
||||
if (ins->isCallGetProperty() && index == 0 && ins->toCallGetProperty()->name() == cx->names().length)
|
||||
@ -2408,6 +2412,26 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
// and also simplifies handling of early returns.
|
||||
script->setNeedsArgsObj(true);
|
||||
|
||||
// Always construct arguments objects when in debug mode and for generator
|
||||
// scripts (generators can be suspended when speculation fails).
|
||||
//
|
||||
// FIXME: Don't build arguments for ES6 generator expressions.
|
||||
if (cx->compartment()->debugMode() || script->isGenerator())
|
||||
return true;
|
||||
|
||||
// If the script has dynamic name accesses which could reach 'arguments',
|
||||
// the parser will already have checked to ensure there are no explicit
|
||||
// uses of 'arguments' in the function. If there are such uses, the script
|
||||
// will be marked as definitely needing an arguments object.
|
||||
//
|
||||
// New accesses on 'arguments' can occur through 'eval' or the debugger
|
||||
// statement. In the former case, we will dynamically detect the use and
|
||||
// mark the arguments optimization as having failed.
|
||||
if (script->bindingsAccessedDynamically()) {
|
||||
script->setNeedsArgsObj(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!jit::IsIonEnabled(cx) || !script->compileAndGo())
|
||||
return true;
|
||||
|
||||
@ -2470,6 +2494,8 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
|
||||
MDefinition *argumentsValue = graph.begin()->getSlot(info.argsObjSlot());
|
||||
|
||||
bool argumentsContentsObserved = false;
|
||||
|
||||
for (MUseDefIterator uses(argumentsValue); uses; uses++) {
|
||||
MDefinition *use = uses.def();
|
||||
|
||||
@ -2477,10 +2503,20 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
if (!use->isInstruction())
|
||||
return true;
|
||||
|
||||
if (!ArgumentsUseCanBeLazy(cx, script, use->toInstruction(), uses.index()))
|
||||
if (!ArgumentsUseCanBeLazy(cx, script, use->toInstruction(), uses.index(),
|
||||
&argumentsContentsObserved))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If a script explicitly accesses the contents of 'arguments', and has
|
||||
// formals which may be stored as part of a call object, don't use lazy
|
||||
// arguments. The compiler can then assume that accesses through
|
||||
// arguments[i] will be on unaliased variables.
|
||||
if (script->funHasAnyAliasedFormal() && argumentsContentsObserved)
|
||||
return true;
|
||||
|
||||
script->setNeedsArgsObj(false);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user