Line data Source code
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 "jsscript.h"
10 :
11 : #include "jit/Ion.h"
12 :
13 : using namespace js;
14 : using namespace js::jit;
15 :
16 : namespace js {
17 : namespace jit {
18 :
19 3 : OptimizationLevelInfo IonOptimizations;
20 :
21 : void
22 6 : OptimizationInfo::initNormalOptimizationInfo()
23 : {
24 6 : level_ = OptimizationLevel::Normal;
25 :
26 6 : autoTruncate_ = true;
27 6 : eaa_ = true;
28 6 : eagerSimdUnbox_ = true;
29 6 : edgeCaseAnalysis_ = true;
30 6 : eliminateRedundantChecks_ = true;
31 6 : inlineInterpreted_ = true;
32 6 : inlineNative_ = true;
33 6 : licm_ = true;
34 6 : loopUnrolling_ = true;
35 6 : gvn_ = true;
36 6 : rangeAnalysis_ = true;
37 6 : reordering_ = true;
38 6 : sincos_ = true;
39 6 : sink_ = true;
40 :
41 6 : registerAllocator_ = RegisterAllocator_Backtracking;
42 :
43 6 : inlineMaxBytecodePerCallSiteActiveCooperatingThread_ = 550;
44 6 : inlineMaxBytecodePerCallSiteHelperThread_ = 1100;
45 6 : inlineMaxCalleeInlinedBytecodeLength_ = 3550;
46 6 : inlineMaxTotalBytecodeLength_ = 85000;
47 6 : inliningMaxCallerBytecodeLength_ = 1600;
48 6 : maxInlineDepth_ = 3;
49 6 : scalarReplacement_ = true;
50 6 : smallFunctionMaxInlineDepth_ = 10;
51 6 : compilerWarmUpThreshold_ = CompilerWarmupThreshold;
52 6 : compilerSmallFunctionWarmUpThreshold_ = CompilerSmallFunctionWarmupThreshold;
53 6 : inliningWarmUpThresholdFactor_ = 0.125;
54 6 : inliningRecompileThresholdFactor_ = 4;
55 6 : }
56 :
57 : void
58 3 : OptimizationInfo::initWasmOptimizationInfo()
59 : {
60 : // The Wasm optimization level
61 : // Disables some passes that don't work well with wasm.
62 :
63 : // Take normal option values for not specified values.
64 3 : initNormalOptimizationInfo();
65 :
66 3 : level_ = OptimizationLevel::Wasm;
67 :
68 3 : ama_ = true;
69 3 : autoTruncate_ = false;
70 3 : eagerSimdUnbox_ = false; // wasm has no boxing / unboxing.
71 3 : edgeCaseAnalysis_ = false;
72 3 : eliminateRedundantChecks_ = false;
73 3 : scalarReplacement_ = false; // wasm has no objects.
74 3 : sincos_ = false;
75 3 : sink_ = false;
76 3 : }
77 :
78 : uint32_t
79 7872 : OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) const
80 : {
81 7872 : MOZ_ASSERT(pc == nullptr || pc == script->code() || JSOp(*pc) == JSOP_LOOPENTRY);
82 :
83 7872 : if (pc == script->code())
84 620 : pc = nullptr;
85 :
86 7872 : uint32_t warmUpThreshold = compilerWarmUpThreshold_;
87 7872 : if (JitOptions.forcedDefaultIonWarmUpThreshold.isSome())
88 0 : warmUpThreshold = JitOptions.forcedDefaultIonWarmUpThreshold.ref();
89 :
90 7872 : if (JitOptions.isSmallFunction(script)) {
91 3748 : warmUpThreshold = compilerSmallFunctionWarmUpThreshold_;
92 3748 : if (JitOptions.forcedDefaultIonSmallFunctionWarmUpThreshold.isSome())
93 0 : warmUpThreshold = JitOptions.forcedDefaultIonSmallFunctionWarmUpThreshold.ref();
94 : }
95 :
96 : // If the script is too large to compile on the active thread, we can still
97 : // compile it off thread. In these cases, increase the warm-up counter
98 : // threshold to improve the compilation's type information and hopefully
99 : // avoid later recompilation.
100 :
101 7872 : if (script->length() > MAX_ACTIVE_THREAD_SCRIPT_SIZE)
102 40 : warmUpThreshold *= (script->length() / (double) MAX_ACTIVE_THREAD_SCRIPT_SIZE);
103 :
104 7872 : uint32_t numLocalsAndArgs = NumLocalsAndArgs(script);
105 7872 : if (numLocalsAndArgs > MAX_ACTIVE_THREAD_LOCALS_AND_ARGS)
106 0 : warmUpThreshold *= (numLocalsAndArgs / (double) MAX_ACTIVE_THREAD_LOCALS_AND_ARGS);
107 :
108 7872 : if (!pc || JitOptions.eagerCompilation)
109 7622 : return warmUpThreshold;
110 :
111 : // It's more efficient to enter outer loops, rather than inner loops, via OSR.
112 : // To accomplish this, we use a slightly higher threshold for inner loops.
113 : // Note that the loop depth is always > 0 so we will prefer non-OSR over OSR.
114 250 : uint32_t loopDepth = LoopEntryDepthHint(pc);
115 250 : MOZ_ASSERT(loopDepth > 0);
116 250 : return warmUpThreshold + loopDepth * 100;
117 : }
118 :
119 3 : OptimizationLevelInfo::OptimizationLevelInfo()
120 : {
121 3 : infos_[OptimizationLevel::Normal].initNormalOptimizationInfo();
122 3 : infos_[OptimizationLevel::Wasm].initWasmOptimizationInfo();
123 :
124 : #ifdef DEBUG
125 3 : OptimizationLevel level = firstLevel();
126 3 : while (!isLastLevel(level)) {
127 0 : OptimizationLevel next = nextLevel(level);
128 0 : MOZ_ASSERT_IF(level != OptimizationLevel::DontCompile, level < next);
129 0 : level = next;
130 : }
131 : #endif
132 3 : }
133 :
134 : OptimizationLevel
135 7875 : OptimizationLevelInfo::nextLevel(OptimizationLevel level) const
136 : {
137 7875 : MOZ_ASSERT(!isLastLevel(level));
138 7875 : switch (level) {
139 : case OptimizationLevel::DontCompile:
140 15750 : return OptimizationLevel::Normal;
141 : case OptimizationLevel::Normal:
142 : case OptimizationLevel::Wasm:
143 : case OptimizationLevel::Count:;
144 : }
145 0 : MOZ_CRASH("Unknown optimization level.");
146 : }
147 :
148 : OptimizationLevel
149 868 : OptimizationLevelInfo::firstLevel() const
150 : {
151 868 : return nextLevel(OptimizationLevel::DontCompile);
152 : }
153 :
154 : bool
155 15232 : OptimizationLevelInfo::isLastLevel(OptimizationLevel level) const
156 : {
157 15232 : return level == OptimizationLevel::Normal;
158 : }
159 :
160 : OptimizationLevel
161 7007 : OptimizationLevelInfo::levelForScript(JSScript* script, jsbytecode* pc) const
162 : {
163 7007 : OptimizationLevel prev = OptimizationLevel::DontCompile;
164 :
165 7105 : while (!isLastLevel(prev)) {
166 7007 : OptimizationLevel level = nextLevel(prev);
167 7007 : const OptimizationInfo* info = get(level);
168 7007 : if (script->getWarmUpCount() < info->compilerWarmUpThreshold(script, pc))
169 6958 : return prev;
170 :
171 49 : prev = level;
172 : }
173 :
174 49 : return prev;
175 : }
176 :
177 : } // namespace jit
178 : } // namespace js
|