fourthTier: FTL shouldn't use the LLVM global context, and should instead create...
[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 "DFGDCEPhase.h"
40 #include "DFGFailedFinalizer.h"
41 #include "DFGFixupPhase.h"
42 #include "DFGJITCompiler.h"
43 #include "DFGPredictionInjectionPhase.h"
44 #include "DFGPredictionPropagationPhase.h"
45 #include "DFGTypeCheckHoistingPhase.h"
46 #include "DFGUnificationPhase.h"
47 #include "DFGValidate.h"
48 #include "DFGVirtualRegisterAllocationPhase.h"
49 #include "FTLCapabilities.h"
50 #include "FTLCompile.h"
51 #include "FTLLink.h"
52 #include "FTLLowerDFGToLLVM.h"
53 #include "FTLState.h"
54 #include "Operations.h"
55 #include <wtf/CurrentTime.h>
56
57 namespace JSC { namespace DFG {
58
59 static void dumpAndVerifyGraph(Graph& graph, const char* text)
60 {
61     GraphDumpMode modeForFinalValidate = DumpGraph;
62     if (verboseCompilationEnabled()) {
63         dataLog(text, "\n");
64         graph.dump();
65         modeForFinalValidate = DontDumpGraph;
66     }
67     if (validationEnabled())
68         validate(graph, modeForFinalValidate);
69 }
70
71 Plan::Plan(
72     CompileMode compileMode, PassRefPtr<CodeBlock> passedCodeBlock, unsigned osrEntryBytecodeIndex,
73     unsigned numVarsWithValues)
74     : compileMode(compileMode)
75     , vm(*passedCodeBlock->vm())
76     , codeBlock(passedCodeBlock)
77     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
78     , numVarsWithValues(numVarsWithValues)
79     , mustHandleValues(codeBlock->numParameters(), numVarsWithValues)
80     , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0)
81     , identifiers(codeBlock.get())
82     , isCompiled(false)
83 {
84 }
85
86 Plan::~Plan()
87 {
88 }
89
90 void Plan::compileInThread(LongLivedState& longLivedState)
91 {
92     double before = 0;
93     if (Options::reportCompileTimes())
94         before = currentTimeMS();
95     
96     SamplingRegion samplingRegion("DFG Compilation (Plan)");
97     CompilationScope compilationScope;
98
99     if (logCompilationChanges())
100         dataLog("DFG(Plan) compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
101
102     CompilationPath path = compileInThreadImpl(longLivedState);
103
104     RELEASE_ASSERT(finalizer);
105     
106     if (Options::reportCompileTimes()) {
107         const char* pathName;
108         switch (path) {
109         case FailPath:
110             pathName = "N/A (fail)";
111             break;
112         case DFGPath:
113             pathName = "DFG";
114             break;
115         case FTLPath:
116             pathName = "FTL";
117             break;
118         }
119         dataLog("Compiled ", *codeBlock, " with ", pathName, " in ", currentTimeMS() - before, " ms.\n");
120     }
121 }
122
123 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
124 {
125     Graph dfg(vm, *this, longLivedState);
126     
127     if (!parse(dfg)) {
128         finalizer = adoptPtr(new FailedFinalizer(*this));
129         return FailPath;
130     }
131     
132     // By this point the DFG bytecode parser will have potentially mutated various tables
133     // in the CodeBlock. This is a good time to perform an early shrink, which is more
134     // powerful than a late one. It's safe to do so because we haven't generated any code
135     // that references any of the tables directly, yet.
136     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
137
138     if (validationEnabled())
139         validate(dfg);
140     
141     performCPSRethreading(dfg);
142     performUnification(dfg);
143     performPredictionInjection(dfg);
144     
145     if (validationEnabled())
146         validate(dfg);
147     
148     performBackwardsPropagation(dfg);
149     performPredictionPropagation(dfg);
150     performFixup(dfg);
151     performTypeCheckHoisting(dfg);
152     
153     dfg.m_fixpointState = FixpointNotConverged;
154
155     performCSE(dfg);
156     performArgumentsSimplification(dfg);
157     performCPSRethreading(dfg); // This should usually be a no-op since CSE rarely dethreads, and arguments simplification rarely does anything.
158     performCFA(dfg);
159     performConstantFolding(dfg);
160     performCFGSimplification(dfg);
161
162     dfg.m_fixpointState = FixpointConverged;
163
164     performStoreElimination(dfg);
165     performCPSRethreading(dfg);
166     performDCE(dfg);
167
168 #if ENABLE(FTL_JIT)
169     if (Options::useExperimentalFTL()
170         && compileMode == CompileFunction
171         && FTL::canCompile(dfg)) {
172         
173         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
174         
175         // FIXME: Support OSR entry.
176         // https://bugs.webkit.org/show_bug.cgi?id=113625
177         
178         FTL::State state(dfg);
179         FTL::lowerDFGToLLVM(state);
180         FTL::compile(state);
181         FTL::link(state);
182         return FTLPath;
183     }
184 #endif // ENABLE(FTL_JIT)
185     
186     performVirtualRegisterAllocation(dfg);
187     dumpAndVerifyGraph(dfg, "Graph after optimization:");
188
189     JITCompiler dataFlowJIT(dfg);
190     if (compileMode == CompileFunction) {
191         dataFlowJIT.compileFunction();
192         dataFlowJIT.linkFunction();
193     } else {
194         ASSERT(compileMode == CompileOther);
195         
196         dataFlowJIT.compile();
197         dataFlowJIT.link();
198     }
199     
200     return DFGPath;
201 }
202
203 bool Plan::isStillValid()
204 {
205     return watchpoints.areStillValid()
206         && chains.areStillValid();
207 }
208
209 void Plan::reallyAdd()
210 {
211     watchpoints.reallyAdd();
212     identifiers.reallyAdd(vm);
213 }
214
215 CompilationResult Plan::finalize(RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck)
216 {
217     if (!isStillValid())
218         return CompilationInvalidated;
219     
220     bool result;
221     if (compileMode == CompileFunction)
222         result = finalizer->finalizeFunction(jitCode, *jitCodeWithArityCheck);
223     else
224         result = finalizer->finalize(jitCode);
225     
226     if (!result)
227         return CompilationFailed;
228     
229     reallyAdd();
230     
231     return CompilationSuccessful;
232 }
233
234 CodeBlock* Plan::key()
235 {
236     return codeBlock->alternative();
237 }
238
239 } } // namespace JSC::DFG
240
241 #endif // ENABLE(DFG_JIT)
242