fourthTier: Landing the initial FTL logic in a single commit to avoid spurious
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGDriver.cpp
1 /*
2  * Copyright (C) 2011, 2012, 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 "DFGDriver.h"
28
29 #include "JSObject.h"
30 #include "JSString.h"
31
32
33 #if ENABLE(DFG_JIT)
34
35 #include "DFGArgumentsSimplificationPhase.h"
36 #include "DFGBackwardsPropagationPhase.h"
37 #include "DFGByteCodeParser.h"
38 #include "DFGCFAPhase.h"
39 #include "DFGCFGSimplificationPhase.h"
40 #include "DFGCPSRethreadingPhase.h"
41 #include "DFGCSEPhase.h"
42 #include "DFGConstantFoldingPhase.h"
43 #include "DFGDCEPhase.h"
44 #include "DFGFixupPhase.h"
45 #include "DFGJITCompiler.h"
46 #include "DFGPredictionInjectionPhase.h"
47 #include "DFGPredictionPropagationPhase.h"
48 #include "DFGTypeCheckHoistingPhase.h"
49 #include "DFGUnificationPhase.h"
50 #include "DFGValidate.h"
51 #include "DFGVirtualRegisterAllocationPhase.h"
52 #include "FTLCapabilities.h"
53 #include "FTLCompile.h"
54 #include "FTLLowerDFGToLLVM.h"
55 #include "FTLState.h"
56 #include "Operations.h"
57 #include "Options.h"
58
59 namespace JSC { namespace DFG {
60
61 static unsigned numCompilations;
62
63 unsigned getNumCompilations()
64 {
65     return numCompilations;
66 }
67
68 static void dumpAndVerifyGraph(Graph& graph, const char* text)
69 {
70     GraphDumpMode modeForFinalValidate = DumpGraph;
71     if (verboseCompilationEnabled()) {
72         dataLog(text, "\n");
73         graph.dump();
74         modeForFinalValidate = DontDumpGraph;
75     }
76     if (validationEnabled())
77         validate(graph, modeForFinalValidate);
78 }
79
80 enum CompileMode { CompileFunction, CompileOther };
81 static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
82 {
83     SamplingRegion samplingRegion("DFG Compilation (Driver)");
84     
85     numCompilations++;
86     
87     ASSERT(codeBlock);
88     ASSERT(codeBlock->alternative());
89     ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
90     
91     ASSERT(osrEntryBytecodeIndex != UINT_MAX);
92
93     if (!Options::useDFGJIT())
94         return false;
95
96     if (!Options::bytecodeRangeToDFGCompile().isInRange(codeBlock->instructionCount()))
97         return false;
98
99     if (logCompilationChanges())
100         dataLog("DFG compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
101     
102     // Derive our set of must-handle values. The compilation must be at least conservative
103     // enough to allow for OSR entry with these values.
104     unsigned numVarsWithValues;
105     if (osrEntryBytecodeIndex)
106         numVarsWithValues = codeBlock->m_numVars;
107     else
108         numVarsWithValues = 0;
109     Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
110     for (size_t i = 0; i < mustHandleValues.size(); ++i) {
111         int operand = mustHandleValues.operandForIndex(i);
112         if (operandIsArgument(operand)
113             && !operandToArgument(operand)
114             && compileMode == CompileFunction
115             && codeBlock->specializationKind() == CodeForConstruct) {
116             // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
117             // also never be used. It doesn't matter what we put into the value for this,
118             // but it has to be an actual value that can be grokked by subsequent DFG passes,
119             // so we sanitize it here by turning it into Undefined.
120             mustHandleValues[i] = jsUndefined();
121         } else
122             mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
123     }
124     
125     Graph dfg(exec->vm(), codeBlock, osrEntryBytecodeIndex, mustHandleValues);
126     if (!parse(exec, dfg))
127         return false;
128     
129     // By this point the DFG bytecode parser will have potentially mutated various tables
130     // in the CodeBlock. This is a good time to perform an early shrink, which is more
131     // powerful than a late one. It's safe to do so because we haven't generated any code
132     // that references any of the tables directly, yet.
133     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
134
135     if (validationEnabled())
136         validate(dfg);
137     
138     performCPSRethreading(dfg);
139     performUnification(dfg);
140     performPredictionInjection(dfg);
141     
142     if (validationEnabled())
143         validate(dfg);
144     
145     performBackwardsPropagation(dfg);
146     performPredictionPropagation(dfg);
147     performFixup(dfg);
148     performTypeCheckHoisting(dfg);
149     
150     dfg.m_fixpointState = FixpointNotConverged;
151
152     performCSE(dfg);
153     performArgumentsSimplification(dfg);
154     performCPSRethreading(dfg); // This should usually be a no-op since CSE rarely dethreads, and arguments simplification rarely does anything.
155     performCFA(dfg);
156     performConstantFolding(dfg);
157     performCFGSimplification(dfg);
158
159     dfg.m_fixpointState = FixpointConverged;
160
161     performStoreElimination(dfg);
162     performCPSRethreading(dfg);
163     performDCE(dfg);
164
165 #if ENABLE(FTL_JIT)
166     if (Options::useExperimentalFTL()
167         && compileMode == CompileFunction
168         && FTL::canCompile(dfg)) {
169         
170         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
171         
172         // FIXME: Support OSR entry.
173         // https://bugs.webkit.org/show_bug.cgi?id=113625
174         
175         FTL::State state(dfg);
176         FTL::lowerDFGToLLVM(state);
177         FTL::compile(state, jitCode, *jitCodeWithArityCheck);
178         
179         // FIXME: Need to add support for the case where JIT memory allocation failed.
180         // https://bugs.webkit.org/show_bug.cgi?id=113620
181         
182         return true;
183     }
184 #endif // ENABLE(FTL_JIT)
185     
186     performVirtualRegisterAllocation(dfg);
187     dumpAndVerifyGraph(dfg, "Graph after optimization:");
188
189     JITCompiler dataFlowJIT(dfg);
190     bool result;
191     if (compileMode == CompileFunction) {
192         ASSERT(jitCodeWithArityCheck);
193         
194         result = dataFlowJIT.compileFunction(jitCode, *jitCodeWithArityCheck);
195     } else {
196         ASSERT(compileMode == CompileOther);
197         ASSERT(!jitCodeWithArityCheck);
198         
199         result = dataFlowJIT.compile(jitCode);
200     }
201     
202     return result;
203 }
204
205 bool tryCompile(ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, unsigned bytecodeIndex)
206 {
207     return compile(CompileOther, exec, codeBlock, jitCode, 0, bytecodeIndex);
208 }
209
210 bool tryCompileFunction(ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, unsigned bytecodeIndex)
211 {
212     return compile(CompileFunction, exec, codeBlock, jitCode, &jitCodeWithArityCheck, bytecodeIndex);
213 }
214
215 } } // namespace JSC::DFG
216
217 #endif // ENABLE(DFG_JIT)
218