From 138801e0d0857247128702f15d3061f8724000a5 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Fri, 10 May 2013 14:49:58 +0200 Subject: [PATCH] Bug 768288: IonMonkey: Inline small functions with loops, r=djvj r=shu --- js/src/ion/IonBuilder.cpp | 30 +++++++++++++++++++++--------- js/src/ion/MIRGraph.cpp | 10 ++++++++++ js/src/jsanalyze.cpp | 2 +- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 8a40ee3a987..713b874f2a9 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -237,7 +237,8 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo) RootedScript inlineScript(cx, target->nonLazyScript()); ExecutionMode executionMode = info().executionMode(); if (!CanIonCompile(inlineScript, executionMode)) { - IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation"); + IonSpew(IonSpew_Inlining, "%s:%d Cannot inline due to disable Ion compilation", + inlineScript->filename(), inlineScript->lineno); return false; } @@ -246,7 +247,8 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo) ion::IsBaselineEnabled(cx) && !inlineScript->hasBaselineScript()) { - IonSpew(IonSpew_Inlining, "Cannot inline target with no baseline jitcode"); + IonSpew(IonSpew_Inlining, "%s:%d Cannot inline target with no baseline jitcode", + inlineScript->filename(), inlineScript->lineno); return false; } @@ -254,18 +256,20 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo) IonBuilder *builder = callerBuilder_; while (builder) { if (builder->script() == inlineScript) { - IonSpew(IonSpew_Inlining, "Not inlining recursive call"); + IonSpew(IonSpew_Inlining, "%s:%d Not inlining recursive call", + inlineScript->filename(), inlineScript->lineno); return false; } builder = builder->callerBuilder_; } if (!canEnterInlinedFunction(target)) { - IonSpew(IonSpew_Inlining, "Cannot inline due to analysis data %d", script()->lineno); + IonSpew(IonSpew_Inlining, "%s:%d Cannot inline due to oracle veto %d", + inlineScript->filename(), inlineScript->lineno, + script()->lineno); return false; } - IonSpew(IonSpew_Inlining, "Inlining good to go!"); return true; } @@ -3429,6 +3433,12 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target) // Accumulate return values. MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator(); + if (exits.length() == 0) { + // Inlining of functions that have no exit is not supported. + calleeScript->analysis()->setIonUninlineable(); + abortReason_ = AbortReason_Inlining; + return false; + } MDefinition *retvalDefn = patchInlinedReturns(callInfo, exits, returnBlock); if (!retvalDefn) return false; @@ -3537,11 +3547,13 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo) targetScript->filename(), targetScript->lineno); return false; } - } - // Always inline the empty script up to the inlining depth. - if (targetScript->length == 1) - return true; + if (targetScript->analysis()->hasLoops()) { + IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: big function that contains a loop", + targetScript->filename(), targetScript->lineno); + return false; + } + } // Callee must not be excessively large. // This heuristic also applies to the callsite as a whole. diff --git a/js/src/ion/MIRGraph.cpp b/js/src/ion/MIRGraph.cpp index 9fbd4625cce..75deb7c9c9a 100644 --- a/js/src/ion/MIRGraph.cpp +++ b/js/src/ion/MIRGraph.cpp @@ -76,6 +76,16 @@ MIRGraph::removeBlocksAfter(MBasicBlock *start) if (block == osrBlock_) osrBlock_ = NULL; + + if (exitAccumulator_) { + size_t i = 0; + while (i < exitAccumulator_->length()) { + if ((*exitAccumulator_)[i] == block) + exitAccumulator_->erase(exitAccumulator_->begin() + i); + else + i++; + } + } block->discardAllInstructions(); block->discardAllPhis(); block->discardAllResumePoints(); diff --git a/js/src/jsanalyze.cpp b/js/src/jsanalyze.cpp index 14c8200551a..32e836ab5dd 100644 --- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -65,7 +65,7 @@ ScriptAnalysis::addJump(JSContext *cx, unsigned offset, if (offset < *currentOffset) { /* Scripts containing loops are never inlined. */ - isJaegerInlineable = isIonInlineable = false; + isJaegerInlineable = false; hasLoops_ = true; if (code->analyzed) {