Bug 1303399 part 1 - Use InliningStatus as return value of inlineScriptedCall. r=h4writer
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Fri, 28 Oct 2016 12:45:31 +0000
changeset 320000 c0f71d17d65902b04f429e556bb8d709bcb32ce9
parent 319999 36deeea122f9f5898cfb8360cd7012e3d4a3fe03
child 320001 47e4fb57325d0766abbe7dd6260d339cb1e8f20f
push id20749
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:21:21 +0000
treeherderfx-team@1b170b39ed6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1303399
milestone52.0a1
Bug 1303399 part 1 - Use InliningStatus as return value of inlineScriptedCall. r=h4writer
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5152,46 +5152,46 @@ class AutoAccumulateReturns
         prev_ = graph_.returnAccumulator();
         graph_.setReturnAccumulator(&returns);
     }
     ~AutoAccumulateReturns() {
         graph_.setReturnAccumulator(prev_);
     }
 };
 
-bool
+IonBuilder::InliningStatus
 IonBuilder::inlineScriptedCall(CallInfo& callInfo, JSFunction* target)
 {
     MOZ_ASSERT(target->hasScript());
     MOZ_ASSERT(IsIonInlinablePC(pc));
 
     callInfo.setImplicitlyUsedUnchecked();
 
     // Ensure sufficient space in the slots: needed for inlining from FUNAPPLY.
     uint32_t depth = current->stackDepth() + callInfo.numFormals();
     if (depth > current->nslots()) {
         if (!current->increaseSlots(depth - current->nslots()))
-            return false;
+            return InliningStatus_Error;
     }
 
     // Create new |this| on the caller-side for inlined constructors.
     if (callInfo.constructing()) {
         MDefinition* thisDefn = createThis(target, callInfo.fun(), callInfo.getNewTarget());
         if (!thisDefn)
-            return false;
+            return InliningStatus_Error;
         callInfo.setThis(thisDefn);
     }
 
     // Capture formals in the outer resume point.
     callInfo.pushFormals(current);
 
     MResumePoint* outerResumePoint =
         MResumePoint::New(alloc(), current, pc, MResumePoint::Outer);
     if (!outerResumePoint)
-        return false;
+        return InliningStatus_Error;
     current->setOuterResumePoint(outerResumePoint);
 
     // Pop formals again, except leave |fun| on stack for duration of call.
     callInfo.popFormals(current);
     current->push(callInfo.fun());
 
     JSScript* calleeScript = target->nonLazyScript();
     BaselineInspector inspector(calleeScript);
@@ -5199,54 +5199,54 @@ IonBuilder::inlineScriptedCall(CallInfo&
     // Improve type information of |this| when not set.
     if (callInfo.constructing() &&
         !callInfo.thisArg()->resultTypeSet())
     {
         StackTypeSet* types = TypeScript::ThisTypes(calleeScript);
         if (types && !types->unknown()) {
             TemporaryTypeSet* clonedTypes = types->clone(alloc_->lifoAlloc());
             if (!clonedTypes)
-                return false;
+                return InliningStatus_Error;
             MTypeBarrier* barrier = MTypeBarrier::New(alloc(), callInfo.thisArg(), clonedTypes);
             current->add(barrier);
             if (barrier->type() == MIRType::Undefined)
                 callInfo.setThis(constant(UndefinedValue()));
             else if (barrier->type() == MIRType::Null)
                 callInfo.setThis(constant(NullValue()));
             else
                 callInfo.setThis(barrier);
         }
     }
 
     // Start inlining.
     LifoAlloc* lifoAlloc = alloc_->lifoAlloc();
     InlineScriptTree* inlineScriptTree =
         info().inlineScriptTree()->addCallee(alloc_, pc, calleeScript);
     if (!inlineScriptTree)
-        return false;
+        return InliningStatus_Error;
     CompileInfo* info = lifoAlloc->new_<CompileInfo>(calleeScript, target,
                                                      (jsbytecode*)nullptr,
                                                      this->info().analysisMode(),
                                                      /* needsArgsObj = */ false,
                                                      inlineScriptTree);
     if (!info)
-        return false;
+        return InliningStatus_Error;
 
     MIRGraphReturns returns(alloc());
     AutoAccumulateReturns aar(graph(), returns);
 
     // Build the graph.
     IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
                              &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
                              loopDepth_);
     if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
         if (analysisContext && analysisContext->isExceptionPending()) {
             JitSpew(JitSpew_IonAbort, "Inline builder raised exception.");
             abortReason_ = AbortReason_Error;
-            return false;
+            return InliningStatus_Error;
         }
 
         // Inlining the callee failed. Mark the callee as uninlineable only if
         // the inlining was aborted for a non-exception reason.
         if (inlineBuilder.abortReason_ == AbortReason_Disable) {
             calleeScript->setUninlineable();
             abortReason_ = AbortReason_Inlining;
         } else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
@@ -5256,47 +5256,50 @@ IonBuilder::inlineScriptedCall(CallInfo&
         } else if (inlineBuilder.abortReason_ == AbortReason_PreliminaryObjects) {
             const ObjectGroupVector& groups = inlineBuilder.abortedPreliminaryGroups();
             MOZ_ASSERT(!groups.empty());
             for (size_t i = 0; i < groups.length(); i++)
                 addAbortedPreliminaryGroup(groups[i]);
             abortReason_ = AbortReason_PreliminaryObjects;
         }
 
-        return false;
+        return InliningStatus_Error;
     }
 
     // Create return block.
     jsbytecode* postCall = GetNextPc(pc);
     MBasicBlock* returnBlock = newBlock(nullptr, postCall);
     if (!returnBlock)
-        return false;
+        return InliningStatus_Error;
     returnBlock->setCallerResumePoint(callerResumePoint_);
 
     // Inherit the slots from current and pop |fun|.
     returnBlock->inheritSlots(current);
     returnBlock->pop();
 
     // Accumulate return values.
     if (returns.empty()) {
         // Inlining of functions that have no exit is not supported.
         calleeScript->setUninlineable();
         abortReason_ = AbortReason_Inlining;
-        return false;
+        return InliningStatus_Error;
     }
     MDefinition* retvalDefn = patchInlinedReturns(callInfo, returns, returnBlock);
     if (!retvalDefn)
-        return false;
+        return InliningStatus_Error;
     returnBlock->push(retvalDefn);
 
     // Initialize entry slots now that the stack has been fixed up.
     if (!returnBlock->initEntrySlots(alloc()))
-        return false;
-
-    return setCurrentAndSpecializePhis(returnBlock);
+        return InliningStatus_Error;
+
+    if (!setCurrentAndSpecializePhis(returnBlock))
+        return InliningStatus_Error;
+
+    return InliningStatus_Inlined;
 }
 
 MDefinition*
 IonBuilder::patchInlinedReturn(CallInfo& callInfo, MBasicBlock* exit, MBasicBlock* bottom)
 {
     // Replaces the MReturn in the exit block with an MGoto.
     MDefinition* rdef = exit->lastIns()->toReturn()->input();
     exit->discardLastIns();
@@ -5740,19 +5743,17 @@ IonBuilder::inlineSingleCall(CallInfo& c
         InliningStatus status = inlineNativeCall(callInfo, target);
         trackInlineSuccess(status);
         return status;
     }
 
     // Track success now, as inlining a scripted call makes a new return block
     // which has a different pc than the current call pc.
     trackInlineSuccess();
-    if (!inlineScriptedCall(callInfo, target))
-        return InliningStatus_Error;
-    return InliningStatus_Inlined;
+    return inlineScriptedCall(callInfo, target);
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineCallsite(const ObjectVector& targets, CallInfo& callInfo)
 {
     if (targets.empty()) {
         trackOptimizationAttempt(TrackedStrategy::Call_Inline);
         trackOptimizationOutcome(TrackedOutcome::CantInlineNoTarget);
@@ -6521,18 +6522,23 @@ IonBuilder::jsop_funcall(uint32_t argc)
         InliningDecision decision = makeInliningDecision(target, callInfo);
         switch (decision) {
           case InliningDecision_Error:
             return false;
           case InliningDecision_DontInline:
           case InliningDecision_WarmUpCountTooLow:
             break;
           case InliningDecision_Inline:
-            if (target->isInterpreted())
-                return inlineScriptedCall(callInfo, target);
+            if (target->isInterpreted()) {
+                InliningStatus status = inlineScriptedCall(callInfo, target);
+                if (status == InliningStatus_Inlined)
+                    return true;
+                if (status == InliningStatus_Error)
+                    return false;
+            }
             break;
         }
     }
 
     // Call without inlining.
     return makeCall(target, callInfo);
 }
 
@@ -6710,18 +6716,23 @@ IonBuilder::jsop_funapplyarguments(uint3
     InliningDecision decision = makeInliningDecision(target, callInfo);
     switch (decision) {
       case InliningDecision_Error:
         return false;
       case InliningDecision_DontInline:
       case InliningDecision_WarmUpCountTooLow:
         break;
       case InliningDecision_Inline:
-        if (target->isInterpreted())
-            return inlineScriptedCall(callInfo, target);
+        if (target->isInterpreted()) {
+            InliningStatus status = inlineScriptedCall(callInfo, target);
+            if (status == InliningStatus_Inlined)
+                return true;
+            if (status == InliningStatus_Error)
+                return false;
+        }
     }
 
     return makeCall(target, callInfo);
 }
 
 bool
 IonBuilder::jsop_call(uint32_t argc, bool constructing)
 {
@@ -12233,21 +12244,26 @@ IonBuilder::getPropTryCommonGetter(bool*
     if (commonGetter->isInterpreted()) {
         InliningDecision decision = makeInliningDecision(commonGetter, callInfo);
         switch (decision) {
           case InliningDecision_Error:
             return false;
           case InliningDecision_DontInline:
           case InliningDecision_WarmUpCountTooLow:
             break;
-          case InliningDecision_Inline:
-            if (!inlineScriptedCall(callInfo, commonGetter))
+          case InliningDecision_Inline: {
+            InliningStatus status = inlineScriptedCall(callInfo, commonGetter);
+            if (status == InliningStatus_Inlined) {
+                *emitted = true;
+                return true;
+            }
+            if (status == InliningStatus_Error)
                 return false;
-            *emitted = true;
-            return true;
+            break;
+          }
         }
     }
 
     if (!makeCall(commonGetter, callInfo))
         return false;
 
     // If the getter could have been inlined, don't track success. The call to
     // makeInliningDecision above would have tracked a specific reason why we
@@ -12763,21 +12779,25 @@ IonBuilder::setPropTryCommonSetter(bool*
     if (commonSetter->isInterpreted()) {
         InliningDecision decision = makeInliningDecision(commonSetter, callInfo);
         switch (decision) {
           case InliningDecision_Error:
             return false;
           case InliningDecision_DontInline:
           case InliningDecision_WarmUpCountTooLow:
             break;
-          case InliningDecision_Inline:
-            if (!inlineScriptedCall(callInfo, commonSetter))
+          case InliningDecision_Inline: {
+            InliningStatus status = inlineScriptedCall(callInfo, commonSetter);
+            if (status == InliningStatus_Inlined) {
+                *emitted = true;
+                return true;
+            }
+            if (status == InliningStatus_Error)
                 return false;
-            *emitted = true;
-            return true;
+          }
         }
     }
 
     MCall* call = makeCallHelper(commonSetter, callInfo);
     if (!call)
         return false;
 
     current->push(value);
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -976,17 +976,17 @@ class IonBuilder
 
     // Bind function.
     InliningStatus inlineBoundFunction(CallInfo& callInfo, JSFunction* target);
 
     // Main inlining functions
     InliningStatus inlineNativeCall(CallInfo& callInfo, JSFunction* target);
     InliningStatus inlineNativeGetter(CallInfo& callInfo, JSFunction* target);
     InliningStatus inlineNonFunctionCall(CallInfo& callInfo, JSObject* target);
-    MOZ_MUST_USE bool inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
+    InliningStatus inlineScriptedCall(CallInfo& callInfo, JSFunction* target);
     InliningStatus inlineSingleCall(CallInfo& callInfo, JSObject* target);
 
     // Call functions
     InliningStatus inlineCallsite(const ObjectVector& targets, CallInfo& callInfo);
     MOZ_MUST_USE bool inlineCalls(CallInfo& callInfo, const ObjectVector& targets,
                                   BoolVector& choiceSet, MGetPropertyCache* maybeCache);
 
     // Inlining helpers.