Bug 835877: Increase inline depth for small functions, r=dvander
authorHannes Verschore <hv1989@gmail.com>
Tue, 29 Jan 2013 22:17:50 +0100
changeset 130151 84597bf0120dfb31d7aae1ac2c4056a05e49e67a
parent 130150 3c95ca16eb66bc33ef3a307b1da157afcce5768e
child 130153 962cf4a5231c1f64a572b0c09c533fa29c7dd47b
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs835877
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 835877: Increase inline depth for small functions, r=dvander
js/src/ion/Ion.h
js/src/ion/IonBuilder.cpp
--- a/js/src/ion/Ion.h
+++ b/js/src/ion/Ion.h
@@ -107,16 +107,26 @@ struct IonOptions
     // Default: 4,096
     uint32_t maxStackArgs;
 
     // The maximum inlining depth.
     //
     // Default: 3
     uint32_t maxInlineDepth;
 
+    // The maximum inlining depth for functions.
+    //
+    // Inlining small functions has almost no compiling overhead
+    // and removes the otherwise needed call overhead.
+    // The value is currently very low.
+    // Actually it is only needed to make sure we don't blow out the stack.
+    //
+    // Default: 10
+    uint32_t smallFunctionMaxInlineDepth;
+
     // The bytecode length limit for small function.
     //
     // The default for this was arrived at empirically via benchmarking.
     // We may want to tune it further after other optimizations have gone
     // in.
     //
     // Default: 100
     uint32_t smallFunctionMaxBytecodeLength;
@@ -186,16 +196,17 @@ struct IonOptions
         rangeAnalysis(true),
         uce(true),
         parallelCompilation(false),
         usesBeforeCompile(10240),
         usesBeforeCompileNoJaeger(40),
         usesBeforeInlining(usesBeforeCompile),
         maxStackArgs(4096),
         maxInlineDepth(3),
+        smallFunctionMaxInlineDepth(10),
         smallFunctionMaxBytecodeLength(100),
         smallFunctionUsesBeforeInlining(usesBeforeInlining / 4),
         polyInlineMax(4),
         inlineMaxTotalBytecodeLength(800),
         inlineUseCountRatio(128),
         eagerCompilation(false),
         slowCallLimit(512),
         slowCallIncUseCount(5)
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3092,34 +3092,32 @@ IonBuilder::jsop_call_inline(HandleFunct
     return true;
 }
 
 bool
 IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc)
 {
     AssertCanGC();
 
-    if (inliningDepth >= js_IonOptions.maxInlineDepth)
-        return false;
-
     // For "small" functions, we should be more aggressive about inlining.
     // This is based on the following intuition:
     //  1. The call overhead for a small function will likely be a much
     //     higher proportion of the runtime of the function than for larger
     //     functions.
     //  2. The cost of inlining (in terms of size expansion of the SSA graph),
     //     and size expansion of the ultimately generated code, will be
     //     less significant.
     //  3. Do not inline functions which are not called as frequently as their
     //     callers.
 
     uint32_t callerUses = script()->getUseCount();
 
     uint32_t totalSize = 0;
     uint32_t checkUses = js_IonOptions.usesBeforeInlining;
+    uint32_t maxInlineDepth = js_IonOptions.maxInlineDepth;
     bool allFunctionsAreSmall = true;
     RootedFunction target(cx);
     RootedScript targetScript(cx);
     for (size_t i = 0; i < targets.length(); i++) {
         target = targets[i]->toFunction();
         if (!target->isInterpreted())
             return false;
 
@@ -3133,18 +3131,23 @@ IonBuilder::makeInliningDecision(AutoObj
         if (targetScript->length > js_IonOptions.smallFunctionMaxBytecodeLength)
             allFunctionsAreSmall = false;
 
         if (calleeUses * js_IonOptions.inlineUseCountRatio < callerUses) {
             IonSpew(IonSpew_Inlining, "Not inlining, callee is not hot");
             return false;
         }
     }
-    if (allFunctionsAreSmall)
+    if (allFunctionsAreSmall) {
         checkUses = js_IonOptions.smallFunctionUsesBeforeInlining;
+        maxInlineDepth = js_IonOptions.smallFunctionMaxInlineDepth;
+    }
+
+    if (inliningDepth >= maxInlineDepth)
+        return false;
 
     if (script()->getUseCount() < checkUses) {
         IonSpew(IonSpew_Inlining, "Not inlining, caller is not hot");
         return false;
     }
 
     RootedScript scriptRoot(cx, script());
     if (!oracle->canInlineCall(scriptRoot, pc)) {