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 CompileMode compileMode, PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
84 unsigned numVarsWithValues)
85 : compileMode(compileMode)
86 , vm(*passedCodeBlock->vm())
87 , codeBlock(passedCodeBlock)
88 , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
89 , numVarsWithValues(numVarsWithValues)
90 , mustHandleValues(codeBlock->numParameters(), numVarsWithValues)
91 , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0)
92 , identifiers(codeBlock.get())
93 , weakReferences(codeBlock.get())
102 void Plan::compileInThread(LongLivedState& longLivedState)
105 if (Options::reportCompileTimes())
106 before = currentTimeMS();
108 SamplingRegion samplingRegion("DFG Compilation (Plan)");
109 CompilationScope compilationScope;
111 if (logCompilationChanges())
112 dataLog("DFG(Plan) compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
114 CompilationPath path = compileInThreadImpl(longLivedState);
116 RELEASE_ASSERT(finalizer);
118 if (Options::reportCompileTimes()) {
119 const char* pathName;
122 pathName = "N/A (fail)";
131 RELEASE_ASSERT_NOT_REACHED();
135 double now = currentTimeMS();
136 dataLog("Optimized ", *codeBlock->alternative(), " with ", pathName, " in ", now - before, " ms");
138 dataLog(" (DFG: ", beforeFTL - before, ", LLVM: ", now - beforeFTL, ")");
143 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
145 Graph dfg(vm, *this, longLivedState);
148 finalizer = adoptPtr(new FailedFinalizer(*this));
152 // By this point the DFG bytecode parser will have potentially mutated various tables
153 // in the CodeBlock. This is a good time to perform an early shrink, which is more
154 // powerful than a late one. It's safe to do so because we haven't generated any code
155 // that references any of the tables directly, yet.
156 codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
158 if (validationEnabled())
161 performCPSRethreading(dfg);
162 performUnification(dfg);
163 performPredictionInjection(dfg);
165 if (validationEnabled())
168 performBackwardsPropagation(dfg);
169 performPredictionPropagation(dfg);
171 performTypeCheckHoisting(dfg);
174 dfg.m_fixpointState = FixpointNotConverged;
176 if (logCompilationChanges())
177 dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count);
178 bool changed = false;
180 if (validationEnabled())
184 changed |= performConstantFolding(dfg);
185 changed |= performArgumentsSimplification(dfg);
186 changed |= performCFGSimplification(dfg);
187 changed |= performCSE(dfg);
192 performCPSRethreading(dfg);
195 if (logCompilationChanges())
196 dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count);
198 dfg.m_fixpointState = FixpointConverged;
200 performStoreElimination(dfg);
202 // If we're doing validation, then run some analyses, to give them an opportunity
203 // to self-validate. Now is as good a time as any to do this.
204 if (validationEnabled()) {
205 dfg.m_dominators.computeIfNecessary(dfg);
206 dfg.m_naturalLoops.computeIfNecessary(dfg);
210 if (Options::useExperimentalFTL()
211 && compileMode == CompileFunction
212 && FTL::canCompile(dfg)) {
214 performCriticalEdgeBreaking(dfg);
215 performLoopPreHeaderCreation(dfg);
216 performCPSRethreading(dfg);
217 performSSAConversion(dfg);
218 performLivenessAnalysis(dfg);
221 performLivenessAnalysis(dfg);
223 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.
224 performLivenessAnalysis(dfg);
225 performFlushLivenessAnalysis(dfg);
226 performOSRAvailabilityAnalysis(dfg);
228 dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
230 // FIXME: Support OSR entry.
231 // https://bugs.webkit.org/show_bug.cgi?id=113625
233 FTL::State state(dfg);
234 FTL::lowerDFGToLLVM(state);
236 if (Options::reportCompileTimes())
237 beforeFTL = currentTimeMS();
239 if (Options::llvmAlwaysFails()) {
249 RELEASE_ASSERT(!Options::useExperimentalFTL());
250 #endif // ENABLE(FTL_JIT)
252 performCPSRethreading(dfg);
254 performVirtualRegisterAllocation(dfg);
255 dumpAndVerifyGraph(dfg, "Graph after optimization:");
257 JITCompiler dataFlowJIT(dfg);
258 if (compileMode == CompileFunction) {
259 dataFlowJIT.compileFunction();
260 dataFlowJIT.linkFunction();
262 ASSERT(compileMode == CompileOther);
264 dataFlowJIT.compile();
271 bool Plan::isStillValid()
273 return watchpoints.areStillValid()
274 && chains.areStillValid();
277 void Plan::reallyAdd(CommonData* commonData)
279 watchpoints.reallyAdd();
280 identifiers.reallyAdd(vm, commonData);
281 weakReferences.reallyAdd(vm, commonData);
282 transitions.reallyAdd(vm, commonData);
283 writeBarriers.trigger(vm);
286 CompilationResult Plan::finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
289 return CompilationInvalidated;
292 if (compileMode == CompileFunction)
293 result = finalizer->finalizeFunction(jitCode, *jitCodeWithArityCheck);
295 result = finalizer->finalize(jitCode);
298 return CompilationFailed;
300 reallyAdd(jitCode->dfgCommon());
302 return CompilationSuccessful;
305 CodeBlock* Plan::key()
307 return codeBlock->alternative();
310 } } // namespace JSC::DFG
312 #endif // ENABLE(DFG_JIT)