|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "jit/IonOptimizationLevels.h" |
|
8 |
|
9 #include "jsanalyze.h" |
|
10 #include "jsscript.h" |
|
11 |
|
12 using namespace js; |
|
13 using namespace js::jit; |
|
14 |
|
15 namespace js { |
|
16 namespace jit { |
|
17 |
|
18 OptimizationInfos js_IonOptimizations; |
|
19 |
|
20 void |
|
21 OptimizationInfo::initNormalOptimizationInfo() |
|
22 { |
|
23 level_ = Optimization_Normal; |
|
24 |
|
25 eaa_ = true; |
|
26 edgeCaseAnalysis_ = true; |
|
27 eliminateRedundantChecks_ = true; |
|
28 inlineInterpreted_ = true; |
|
29 inlineNative_ = true; |
|
30 gvn_ = true; |
|
31 gvnKind_ = GVN_Optimistic; |
|
32 licm_ = true; |
|
33 uce_ = true; |
|
34 rangeAnalysis_ = true; |
|
35 registerAllocator_ = RegisterAllocator_LSRA; |
|
36 |
|
37 inlineMaxTotalBytecodeLength_ = 1000; |
|
38 inliningMaxCallerBytecodeLength_ = 10000; |
|
39 maxInlineDepth_ = 3; |
|
40 smallFunctionMaxInlineDepth_ = 10; |
|
41 usesBeforeCompile_ = 1000; |
|
42 usesBeforeInliningFactor_ = 0.125; |
|
43 } |
|
44 |
|
45 void |
|
46 OptimizationInfo::initAsmjsOptimizationInfo() |
|
47 { |
|
48 // The AsmJS optimization level |
|
49 // Disables some passes that don't work well with asmjs. |
|
50 |
|
51 // Take normal option values for not specified values. |
|
52 initNormalOptimizationInfo(); |
|
53 |
|
54 level_ = Optimization_AsmJS; |
|
55 edgeCaseAnalysis_ = false; |
|
56 eliminateRedundantChecks_ = false; |
|
57 registerAllocator_ = RegisterAllocator_Backtracking; |
|
58 } |
|
59 |
|
60 uint32_t |
|
61 OptimizationInfo::usesBeforeCompile(JSScript *script, jsbytecode *pc) const |
|
62 { |
|
63 JS_ASSERT(pc == nullptr || pc == script->code() || JSOp(*pc) == JSOP_LOOPENTRY); |
|
64 |
|
65 if (pc == script->code()) |
|
66 pc = nullptr; |
|
67 |
|
68 uint32_t minUses = usesBeforeCompile_; |
|
69 if (js_JitOptions.forceDefaultIonUsesBeforeCompile) |
|
70 minUses = js_JitOptions.forcedDefaultIonUsesBeforeCompile; |
|
71 |
|
72 // If the script is too large to compile on the main thread, we can still |
|
73 // compile it off thread. In these cases, increase the use count threshold |
|
74 // to improve the compilation's type information and hopefully avoid later |
|
75 // recompilation. |
|
76 |
|
77 if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE) |
|
78 minUses = minUses * (script->length() / (double) MAX_MAIN_THREAD_SCRIPT_SIZE); |
|
79 |
|
80 uint32_t numLocalsAndArgs = analyze::TotalSlots(script); |
|
81 if (numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS) |
|
82 minUses = minUses * (numLocalsAndArgs / (double) MAX_MAIN_THREAD_LOCALS_AND_ARGS); |
|
83 |
|
84 if (!pc || js_JitOptions.eagerCompilation) |
|
85 return minUses; |
|
86 |
|
87 // It's more efficient to enter outer loops, rather than inner loops, via OSR. |
|
88 // To accomplish this, we use a slightly higher threshold for inner loops. |
|
89 // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR. |
|
90 uint32_t loopDepth = LoopEntryDepthHint(pc); |
|
91 JS_ASSERT(loopDepth > 0); |
|
92 return minUses + loopDepth * 100; |
|
93 } |
|
94 |
|
95 OptimizationInfos::OptimizationInfos() |
|
96 { |
|
97 infos_[Optimization_Normal - 1].initNormalOptimizationInfo(); |
|
98 infos_[Optimization_AsmJS - 1].initAsmjsOptimizationInfo(); |
|
99 |
|
100 #ifdef DEBUG |
|
101 OptimizationLevel level = firstLevel(); |
|
102 while (!isLastLevel(level)) { |
|
103 OptimizationLevel next = nextLevel(level); |
|
104 JS_ASSERT(level < next); |
|
105 level = next; |
|
106 } |
|
107 #endif |
|
108 } |
|
109 |
|
110 OptimizationLevel |
|
111 OptimizationInfos::nextLevel(OptimizationLevel level) const |
|
112 { |
|
113 JS_ASSERT(!isLastLevel(level)); |
|
114 switch (level) { |
|
115 case Optimization_DontCompile: |
|
116 return Optimization_Normal; |
|
117 default: |
|
118 MOZ_ASSUME_UNREACHABLE("Unknown optimization level."); |
|
119 } |
|
120 } |
|
121 |
|
122 OptimizationLevel |
|
123 OptimizationInfos::firstLevel() const |
|
124 { |
|
125 return nextLevel(Optimization_DontCompile); |
|
126 } |
|
127 |
|
128 bool |
|
129 OptimizationInfos::isLastLevel(OptimizationLevel level) const |
|
130 { |
|
131 return level == Optimization_Normal; |
|
132 } |
|
133 |
|
134 OptimizationLevel |
|
135 OptimizationInfos::levelForScript(JSScript *script, jsbytecode *pc) const |
|
136 { |
|
137 OptimizationLevel prev = Optimization_DontCompile; |
|
138 |
|
139 while (!isLastLevel(prev)) { |
|
140 OptimizationLevel level = nextLevel(prev); |
|
141 const OptimizationInfo *info = get(level); |
|
142 if (script->getUseCount() < info->usesBeforeCompile(script, pc)) |
|
143 return prev; |
|
144 |
|
145 prev = level; |
|
146 } |
|
147 |
|
148 return prev; |
|
149 } |
|
150 |
|
151 } // namespace jit |
|
152 } // namespace js |