Unreviewed, rolling out r154804.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPlan.cpp
1 /*
2  * Copyright (C) 2013 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 "DFGPlan.h"
28
29 #if ENABLE(DFG_JIT)
30
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>
58
59 #if ENABLE(FTL_JIT)
60 #include "FTLCapabilities.h"
61 #include "FTLCompile.h"
62 #include "FTLFail.h"
63 #include "FTLLink.h"
64 #include "FTLLowerDFGToLLVM.h"
65 #include "FTLState.h"
66 #endif
67
68 namespace JSC { namespace DFG {
69
70 static void dumpAndVerifyGraph(Graph& graph, const char* text)
71 {
72     GraphDumpMode modeForFinalValidate = DumpGraph;
73     if (verboseCompilationEnabled()) {
74         dataLog(text, "\n");
75         graph.dump();
76         modeForFinalValidate = DontDumpGraph;
77     }
78     if (validationEnabled())
79         validate(graph, modeForFinalValidate);
80 }
81
82 Plan::Plan(
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())
94     , isCompiled(false)
95 {
96 }
97
98 Plan::~Plan()
99 {
100 }
101
102 void Plan::compileInThread(LongLivedState& longLivedState)
103 {
104     double before = 0;
105     if (Options::reportCompileTimes())
106         before = currentTimeMS();
107     
108     SamplingRegion samplingRegion("DFG Compilation (Plan)");
109     CompilationScope compilationScope;
110
111     if (logCompilationChanges())
112         dataLog("DFG(Plan) compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
113
114     CompilationPath path = compileInThreadImpl(longLivedState);
115
116     RELEASE_ASSERT(finalizer);
117     
118     if (Options::reportCompileTimes()) {
119         const char* pathName;
120         switch (path) {
121         case FailPath:
122             pathName = "N/A (fail)";
123             break;
124         case DFGPath:
125             pathName = "DFG";
126             break;
127         case FTLPath:
128             pathName = "FTL";
129             break;
130         default:
131             RELEASE_ASSERT_NOT_REACHED();
132             pathName = "";
133             break;
134         }
135         double now = currentTimeMS();
136         dataLog("Optimized ", *codeBlock->alternative(), " with ", pathName, " in ", now - before, " ms");
137         if (path == FTLPath)
138             dataLog(" (DFG: ", beforeFTL - before, ", LLVM: ", now - beforeFTL, ")");
139         dataLog(".\n");
140     }
141 }
142
143 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
144 {
145     Graph dfg(vm, *this, longLivedState);
146     
147     if (!parse(dfg)) {
148         finalizer = adoptPtr(new FailedFinalizer(*this));
149         return FailPath;
150     }
151     
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);
157
158     if (validationEnabled())
159         validate(dfg);
160     
161     performCPSRethreading(dfg);
162     performUnification(dfg);
163     performPredictionInjection(dfg);
164     
165     if (validationEnabled())
166         validate(dfg);
167     
168     performBackwardsPropagation(dfg);
169     performPredictionPropagation(dfg);
170     performFixup(dfg);
171     performTypeCheckHoisting(dfg);
172     
173     unsigned count = 1;
174     dfg.m_fixpointState = FixpointNotConverged;
175     for (;; ++count) {
176         if (logCompilationChanges())
177             dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count);
178         bool changed = false;
179         
180         if (validationEnabled())
181             validate(dfg);
182         
183         performCFA(dfg);
184         changed |= performConstantFolding(dfg);
185         changed |= performArgumentsSimplification(dfg);
186         changed |= performCFGSimplification(dfg);
187         changed |= performCSE(dfg);
188         
189         if (!changed)
190             break;
191         
192         performCPSRethreading(dfg);
193     }
194     
195     if (logCompilationChanges())
196         dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count);
197
198     dfg.m_fixpointState = FixpointConverged;
199
200     performStoreElimination(dfg);
201     
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);
207     }
208
209 #if ENABLE(FTL_JIT)
210     if (Options::useExperimentalFTL()
211         && compileMode == CompileFunction
212         && FTL::canCompile(dfg)) {
213         
214         performCriticalEdgeBreaking(dfg);
215         performLoopPreHeaderCreation(dfg);
216         performCPSRethreading(dfg);
217         performSSAConversion(dfg);
218         performLivenessAnalysis(dfg);
219         performCFA(dfg);
220         performLICM(dfg);
221         performLivenessAnalysis(dfg);
222         performCFA(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);
227         
228         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
229         
230         // FIXME: Support OSR entry.
231         // https://bugs.webkit.org/show_bug.cgi?id=113625
232         
233         FTL::State state(dfg);
234         FTL::lowerDFGToLLVM(state);
235         
236         if (Options::reportCompileTimes())
237             beforeFTL = currentTimeMS();
238         
239         if (Options::llvmAlwaysFails()) {
240             FTL::fail(state);
241             return FTLPath;
242         }
243         
244         FTL::compile(state);
245         FTL::link(state);
246         return FTLPath;
247     }
248 #else
249     RELEASE_ASSERT(!Options::useExperimentalFTL());
250 #endif // ENABLE(FTL_JIT)
251     
252     performCPSRethreading(dfg);
253     performDCE(dfg);
254     performVirtualRegisterAllocation(dfg);
255     dumpAndVerifyGraph(dfg, "Graph after optimization:");
256
257     JITCompiler dataFlowJIT(dfg);
258     if (compileMode == CompileFunction) {
259         dataFlowJIT.compileFunction();
260         dataFlowJIT.linkFunction();
261     } else {
262         ASSERT(compileMode == CompileOther);
263         
264         dataFlowJIT.compile();
265         dataFlowJIT.link();
266     }
267     
268     return DFGPath;
269 }
270
271 bool Plan::isStillValid()
272 {
273     return watchpoints.areStillValid()
274         && chains.areStillValid();
275 }
276
277 void Plan::reallyAdd(CommonData* commonData)
278 {
279     watchpoints.reallyAdd();
280     identifiers.reallyAdd(vm, commonData);
281     weakReferences.reallyAdd(vm, commonData);
282     transitions.reallyAdd(vm, commonData);
283     writeBarriers.trigger(vm);
284 }
285
286 CompilationResult Plan::finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
287 {
288     if (!isStillValid())
289         return CompilationInvalidated;
290     
291     bool result;
292     if (compileMode == CompileFunction)
293         result = finalizer->finalizeFunction(jitCode, *jitCodeWithArityCheck);
294     else
295         result = finalizer->finalize(jitCode);
296     
297     if (!result)
298         return CompilationFailed;
299     
300     reallyAdd(jitCode->dfgCommon());
301     
302     return CompilationSuccessful;
303 }
304
305 CodeBlock* Plan::key()
306 {
307     return codeBlock->alternative();
308 }
309
310 } } // namespace JSC::DFG
311
312 #endif // ENABLE(DFG_JIT)
313