Bug 877936 - IonMonkey: Disable compilation and inlining when too many arguments are specified, r=dvander

This commit is contained in:
Hannes Verschore 2013-10-25 12:28:50 +02:00
parent 9831a6963e
commit 44dad161aa
8 changed files with 84 additions and 11 deletions

View File

@ -0,0 +1,5 @@
rex = RegExp("()()()()()()()()()()(z)?(y)");
a = ["sub"];
a[230] = '' + "a"
f = Function.apply(null, a);
"xyz".replace(rex, f);

View File

@ -0,0 +1,44 @@
try{} catch(e){}
function test(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) {
return 0;
}
test();
test();
/////////////////////
function test2() {
return 0;
}
var a = 1;
test2(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a);
test2(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a);
/////////////////////
function test4() {
test3()
}
function test3(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a) {
return 0;
}
test4();
/////////////////////
function test6() {
test5.apply({}, [])
}
function test5() {
return 0;
}
test6();
test6();

View File

@ -24,6 +24,7 @@ StartArgSlot(JSScript *script, JSFunction *fun)
// When needed:
// Slot 2: Argumentsobject.
// Note: when updating this, please also update the assert in SnapshotWriter::startFrame
return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
}
@ -34,6 +35,8 @@ CountArgSlots(JSScript *script, JSFunction *fun)
// Slot x + 1: Argument 1.
// ...
// Slot x + n: Argument n.
// Note: when updating this, please also update the assert in SnapshotWriter::startFrame
return StartArgSlot(script, fun) + (fun ? fun->nargs + 1 : 0);
}

View File

@ -1656,12 +1656,6 @@ IonCompile(JSContext *cx, JSScript *script,
return success ? AbortReason_NoAbort : AbortReason_Disable;
}
static bool
TooManyArguments(unsigned nargs)
{
return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
}
static bool
CheckFrame(BaselineFrame *frame)
{
@ -1902,6 +1896,12 @@ jit::CanEnter(JSContext *cx, RunState &state)
return Method_CantCompile;
}
if (TooManyArguments(invoke.args().callee().as<JSFunction>().nargs)) {
IonSpew(IonSpew_Abort, "too many args");
ForbidCompilation(cx, script);
return Method_CantCompile;
}
if (invoke.constructing() && invoke.args().thisv().isPrimitive()) {
RootedScript scriptRoot(cx, script);
RootedObject callee(cx, &invoke.args().callee());

View File

@ -384,6 +384,12 @@ IsIonInlinablePC(jsbytecode *pc) {
return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc);
}
inline bool
TooManyArguments(unsigned nargs)
{
return (nargs >= SNAPSHOT_MAX_NARGS || nargs > js_IonOptions.maxStackArgs);
}
void ForbidCompilation(JSContext *cx, JSScript *script);
void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode);
uint32_t UsesBeforeIonRecompile(JSScript *script, jsbytecode *pc);

View File

@ -266,7 +266,7 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
}
bool
IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
{
if (!target->isInterpreted()) {
IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
@ -297,7 +297,7 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false;
}
if (constructing && !target->isInterpretedConstructor()) {
if (callInfo.constructing() && !target->isInterpretedConstructor()) {
IonSpew(IonSpew_Inlining, "Cannot inline because callee is not a constructor");
return false;
}
@ -317,6 +317,18 @@ IonBuilder::canInlineTarget(JSFunction *target, bool constructing)
return false;
}
if (TooManyArguments(target->nargs)) {
IonSpew(IonSpew_Inlining, "%s:%d Cannot inline too many args",
inlineScript->filename(), inlineScript->lineno);
return false;
}
if (TooManyArguments(callInfo.argc())) {
IonSpew(IonSpew_Inlining, "%s:%d Cannot inline too many args",
inlineScript->filename(), inlineScript->lineno);
return false;
}
// Allow inlining of recursive calls, but only one level deep.
IonBuilder *builder = callerBuilder_;
while (builder) {
@ -3947,7 +3959,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return true;
// Determine whether inlining is possible at callee site
if (!canInlineTarget(target, callInfo.constructing()))
if (!canInlineTarget(target, callInfo))
return false;
// Heuristics!

View File

@ -231,7 +231,7 @@ class IonBuilder : public MIRGenerator
JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
ObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
bool canInlineTarget(JSFunction *target, bool constructing);
bool canInlineTarget(JSFunction *target, CallInfo &callInfo);
void popCfgStack();
DeferredEdge *filterDeadDeferredEdges(DeferredEdge *edge);

View File

@ -301,7 +301,10 @@ SnapshotWriter::startSnapshot(uint32_t frameCount, BailoutKind kind, bool resume
void
SnapshotWriter::startFrame(JSFunction *fun, JSScript *script, jsbytecode *pc, uint32_t exprStack)
{
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS);
// Test if we honor the maximum of arguments at all times.
// This is a sanity check and not an algorithm limit. So check might be a bit too loose.
// +4 to account for scope chain, return value, this value and maybe arguments_object.
JS_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
uint32_t implicit = StartArgSlot(script, fun);
uint32_t formalArgs = CountArgSlots(script, fun);