2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
31 #include "DFGArgumentsSimplificationPhase.h"
32 #include "DFGBackwardsPropagationPhase.h"
33 #include "DFGByteCodeParser.h"
34 #include "DFGCFAPhase.h"
35 #include "DFGCFGSimplificationPhase.h"
36 #include "DFGCPSRethreadingPhase.h"
37 #include "DFGCSEPhase.h"
38 #include "DFGConstantFoldingPhase.h"
39 #include "DFGCriticalEdgeBreakingPhase.h"
40 #include "DFGDCEPhase.h"
41 #include "DFGFailedFinalizer.h"
42 #include "DFGFlushLivenessAnalysisPhase.h"
43 #include "DFGFixupPhase.h"
44 #include "DFGJITCompiler.h"
45 #include "DFGLICMPhase.h"
46 #include "DFGLivenessAnalysisPhase.h"
47 #include "DFGLoopPreHeaderCreationPhase.h"
48 #include "DFGOSRAvailabilityAnalysisPhase.h"
49 #include "DFGPredictionInjectionPhase.h"
50 #include "DFGPredictionPropagationPhase.h"
51 #include "DFGSSAConversionPhase.h"
52 #include "DFGTypeCheckHoistingPhase.h"
53 #include "DFGUnificationPhase.h"
54 #include "DFGValidate.h"
55 #include "DFGVirtualRegisterAllocationPhase.h"
56 #include "Operations.h"
57 #include <wtf/CurrentTime.h>
60 #include "FTLCapabilities.h"
61 #include "FTLCompile.h"
64 #include "FTLLowerDFGToLLVM.h"
68 namespace JSC { namespace DFG {
70 static void dumpAndVerifyGraph(Graph& graph, const char* text)
72 GraphDumpMode modeForFinalValidate = DumpGraph;
73 if (verboseCompilationEnabled()) {
76 modeForFinalValidate = DontDumpGraph;
78 if (validationEnabled())
79 validate(graph, modeForFinalValidate);
83 PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
84 unsigned numVarsWithValues)
85 : vm(*passedCodeBlock->vm())
86 , codeBlock(passedCodeBlock)
87 , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
88 , numVarsWithValues(numVarsWithValues)
89 , mustHandleValues(codeBlock->numParameters(), numVarsWithValues)
90 , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0)
91 , identifiers(codeBlock.get())
92 , weakReferences(codeBlock.get())
101 void Plan::compileInThread(LongLivedState& longLivedState)
104 if (Options::reportCompileTimes())
105 before = currentTimeMS();
107 SamplingRegion samplingRegion("DFG Compilation (Plan)");
108 CompilationScope compilationScope;
110 if (logCompilationChanges())
111 dataLog("DFG(Plan) compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
113 CompilationPath path = compileInThreadImpl(longLivedState);
115 RELEASE_ASSERT(finalizer);
117 if (Options::reportCompileTimes()) {
118 const char* pathName;
121 pathName = "N/A (fail)";
130 RELEASE_ASSERT_NOT_REACHED();
134 double now = currentTimeMS();
135 dataLog("Optimized ", *codeBlock->alternative(), " with ", pathName, " in ", now - before, " ms");
137 dataLog(" (DFG: ", beforeFTL - before, ", LLVM: ", now - beforeFTL, ")");
142 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
144 Graph dfg(vm, *this, longLivedState);
147 finalizer = adoptPtr(new FailedFinalizer(*this));
151 // By this point the DFG bytecode parser will have potentially mutated various tables
152 // in the CodeBlock. This is a good time to perform an early shrink, which is more
153 // powerful than a late one. It's safe to do so because we haven't generated any code
154 // that references any of the tables directly, yet.
155 codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
157 if (validationEnabled())
160 performCPSRethreading(dfg);
161 performUnification(dfg);
162 performPredictionInjection(dfg);
164 if (validationEnabled())
167 performBackwardsPropagation(dfg);
168 performPredictionPropagation(dfg);
170 performTypeCheckHoisting(dfg);
173 dfg.m_fixpointState = FixpointNotConverged;
175 if (logCompilationChanges())
176 dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count);
177 bool changed = false;
179 if (validationEnabled())
183 changed |= performConstantFolding(dfg);
184 changed |= performArgumentsSimplification(dfg);
185 changed |= performCFGSimplification(dfg);
186 changed |= performCSE(dfg);
191 performCPSRethreading(dfg);
194 if (logCompilationChanges())
195 dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count);
197 dfg.m_fixpointState = FixpointConverged;
199 performStoreElimination(dfg);
201 // If we're doing validation, then run some analyses, to give them an opportunity
202 // to self-validate. Now is as good a time as any to do this.
203 if (validationEnabled()) {
204 dfg.m_dominators.computeIfNecessary(dfg);
205 dfg.m_naturalLoops.computeIfNecessary(dfg);
209 if (Options::useExperimentalFTL()
210 && codeBlock->codeType() == FunctionCode
211 && FTL::canCompile(dfg)) {
213 performCriticalEdgeBreaking(dfg);
214 performLoopPreHeaderCreation(dfg);
215 performCPSRethreading(dfg);
216 performSSAConversion(dfg);
217 performLivenessAnalysis(dfg);
220 performLivenessAnalysis(dfg);
222 performDCE(dfg); // We rely on this to convert dead SetLocals into the appropriate hint, and to kill dead code that won't be recognized as dead by LLVM.
223 performLivenessAnalysis(dfg);
224 performFlushLivenessAnalysis(dfg);
225 performOSRAvailabilityAnalysis(dfg);
227 dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
229 // FIXME: Support OSR entry.
230 // https://bugs.webkit.org/show_bug.cgi?id=113625
232 FTL::State state(dfg);
233 FTL::lowerDFGToLLVM(state);
235 if (Options::reportCompileTimes())
236 beforeFTL = currentTimeMS();
238 if (Options::llvmAlwaysFails()) {
248 RELEASE_ASSERT(!Options::useExperimentalFTL());
249 #endif // ENABLE(FTL_JIT)
251 performCPSRethreading(dfg);
253 performVirtualRegisterAllocation(dfg);
254 dumpAndVerifyGraph(dfg, "Graph after optimization:");
256 JITCompiler dataFlowJIT(dfg);
257 if (codeBlock->codeType() == FunctionCode) {
258 dataFlowJIT.compileFunction();
259 dataFlowJIT.linkFunction();
261 dataFlowJIT.compile();
268 bool Plan::isStillValid()
270 return watchpoints.areStillValid()
271 && chains.areStillValid();
274 void Plan::reallyAdd(CommonData* commonData)
276 watchpoints.reallyAdd();
277 identifiers.reallyAdd(vm, commonData);
278 weakReferences.reallyAdd(vm, commonData);
279 transitions.reallyAdd(vm, commonData);
280 writeBarriers.trigger(vm);
283 void Plan::notifyReady()
285 callback->compilationDidBecomeReadyAsynchronously(codeBlock.get());
289 CompilationResult Plan::finalizeWithoutNotifyingCallback()
292 return CompilationInvalidated;
295 if (codeBlock->codeType() == FunctionCode)
296 result = finalizer->finalizeFunction();
298 result = finalizer->finalize();
301 return CompilationFailed;
303 reallyAdd(codeBlock->jitCode()->dfgCommon());
305 return CompilationSuccessful;
308 void Plan::finalizeAndNotifyCallback()
310 callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
313 CodeBlock* Plan::key()
315 return codeBlock->alternative();
318 } } // namespace JSC::DFG
320 #endif // ENABLE(DFG_JIT)