]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGJITCode.cpp
0d690791840211258d3b3f072ed23110da006e51
[apple/javascriptcore.git] / dfg / DFGJITCode.cpp
1 /*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "DFGJITCode.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlock.h"
32 #include "JSCInlines.h"
33
34 namespace JSC { namespace DFG {
35
36 JITCode::JITCode()
37 : DirectJITCode(DFGJIT)
38 #if ENABLE(FTL_JIT)
39 , osrEntryRetry(0)
40 , abandonOSREntry(false)
41 #endif // ENABLE(FTL_JIT)
42 {
43 }
44
45 JITCode::~JITCode()
46 {
47 }
48
49 CommonData* JITCode::dfgCommon()
50 {
51 return &common;
52 }
53
54 JITCode* JITCode::dfg()
55 {
56 return this;
57 }
58
59 void JITCode::shrinkToFit()
60 {
61 common.shrinkToFit();
62 osrEntry.shrinkToFit();
63 osrExit.shrinkToFit();
64 speculationRecovery.shrinkToFit();
65 minifiedDFG.prepareAndShrink();
66 variableEventStream.shrinkToFit();
67 }
68
69 void JITCode::reconstruct(
70 CodeBlock* codeBlock, CodeOrigin codeOrigin, unsigned streamIndex,
71 Operands<ValueRecovery>& result)
72 {
73 variableEventStream.reconstruct(
74 codeBlock, codeOrigin, minifiedDFG, streamIndex, result);
75 }
76
77 void JITCode::reconstruct(
78 ExecState* exec, CodeBlock* codeBlock, CodeOrigin codeOrigin, unsigned streamIndex,
79 Operands<JSValue>& result)
80 {
81 Operands<ValueRecovery> recoveries;
82 reconstruct(codeBlock, codeOrigin, streamIndex, recoveries);
83
84 result = Operands<JSValue>(OperandsLike, recoveries);
85 for (size_t i = result.size(); i--;) {
86 int operand = result.operandForIndex(i);
87
88 if (codeOrigin == CodeOrigin(0)
89 && operandIsArgument(operand)
90 && !VirtualRegister(operand).toArgument()
91 && codeBlock->codeType() == FunctionCode
92 && codeBlock->specializationKind() == CodeForConstruct) {
93 // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
94 // also never be used. It doesn't matter what we put into the value for this,
95 // but it has to be an actual value that can be grokked by subsequent DFG passes,
96 // so we sanitize it here by turning it into Undefined.
97 result[i] = jsUndefined();
98 continue;
99 }
100
101 result[i] = recoveries[i].recover(exec);
102 }
103 }
104
105 #if ENABLE(FTL_JIT)
106 bool JITCode::checkIfOptimizationThresholdReached(CodeBlock* codeBlock)
107 {
108 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
109 return tierUpCounter.checkIfThresholdCrossedAndSet(codeBlock->baselineVersion());
110 }
111
112 void JITCode::optimizeNextInvocation(CodeBlock* codeBlock)
113 {
114 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
115 if (Options::verboseOSR())
116 dataLog(*codeBlock, ": FTL-optimizing next invocation.\n");
117 tierUpCounter.setNewThreshold(0, codeBlock->baselineVersion());
118 }
119
120 void JITCode::dontOptimizeAnytimeSoon(CodeBlock* codeBlock)
121 {
122 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
123 if (Options::verboseOSR())
124 dataLog(*codeBlock, ": Not FTL-optimizing anytime soon.\n");
125 tierUpCounter.deferIndefinitely();
126 }
127
128 void JITCode::optimizeAfterWarmUp(CodeBlock* codeBlock)
129 {
130 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
131 if (Options::verboseOSR())
132 dataLog(*codeBlock, ": FTL-optimizing after warm-up.\n");
133 CodeBlock* baseline = codeBlock->baselineVersion();
134 tierUpCounter.setNewThreshold(
135 baseline->adjustedCounterValue(Options::thresholdForFTLOptimizeAfterWarmUp()),
136 baseline);
137 }
138
139 void JITCode::optimizeSoon(CodeBlock* codeBlock)
140 {
141 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
142 if (Options::verboseOSR())
143 dataLog(*codeBlock, ": FTL-optimizing soon.\n");
144 CodeBlock* baseline = codeBlock->baselineVersion();
145 tierUpCounter.setNewThreshold(
146 baseline->adjustedCounterValue(Options::thresholdForFTLOptimizeSoon()),
147 baseline);
148 }
149
150 void JITCode::forceOptimizationSlowPathConcurrently(CodeBlock* codeBlock)
151 {
152 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
153 if (Options::verboseOSR())
154 dataLog(*codeBlock, ": Forcing slow path concurrently for FTL entry.\n");
155 tierUpCounter.forceSlowPathConcurrently();
156 }
157
158 void JITCode::setOptimizationThresholdBasedOnCompilationResult(
159 CodeBlock* codeBlock, CompilationResult result)
160 {
161 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
162 switch (result) {
163 case CompilationSuccessful:
164 optimizeNextInvocation(codeBlock);
165 codeBlock->baselineVersion()->m_hasBeenCompiledWithFTL = true;
166 return;
167 case CompilationFailed:
168 dontOptimizeAnytimeSoon(codeBlock);
169 codeBlock->baselineVersion()->m_didFailFTLCompilation = true;
170 return;
171 case CompilationDeferred:
172 optimizeAfterWarmUp(codeBlock);
173 return;
174 case CompilationInvalidated:
175 // This is weird - it will only happen in cases when the DFG code block (i.e.
176 // the code block that this JITCode belongs to) is also invalidated. So it
177 // doesn't really matter what we do. But, we do the right thing anyway. Note
178 // that us counting the reoptimization actually means that we might count it
179 // twice. But that's generally OK. It's better to overcount reoptimizations
180 // than it is to undercount them.
181 codeBlock->baselineVersion()->countReoptimization();
182 optimizeAfterWarmUp(codeBlock);
183 return;
184 }
185 RELEASE_ASSERT_NOT_REACHED();
186 }
187 #endif // ENABLE(FTL_JIT)
188
189 } } // namespace JSC::DFG
190
191 #endif // ENABLE(DFG_JIT)