Unreviewed, rolling out r189938, r189952, and r189956.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGJITCompiler.h
1 /*
2  * Copyright (C) 2011, 2013-2015 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 #ifndef DFGJITCompiler_h
27 #define DFGJITCompiler_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CCallHelpers.h"
32 #include "CodeBlock.h"
33 #include "DFGDisassembler.h"
34 #include "DFGGraph.h"
35 #include "DFGInlineCacheWrapper.h"
36 #include "DFGJITCode.h"
37 #include "DFGOSRExitCompilationInfo.h"
38 #include "DFGRegisterBank.h"
39 #include "FPRInfo.h"
40 #include "GPRInfo.h"
41 #include "JITCode.h"
42 #include "JITInlineCacheGenerator.h"
43 #include "LinkBuffer.h"
44 #include "MacroAssembler.h"
45 #include "TempRegisterSet.h"
46
47 namespace JSC {
48
49 class AbstractSamplingCounter;
50 class CodeBlock;
51 class VM;
52
53 namespace DFG {
54
55 class JITCodeGenerator;
56 class NodeToRegisterMap;
57 class OSRExitJumpPlaceholder;
58 class SlowPathGenerator;
59 class SpeculativeJIT;
60 class SpeculationRecovery;
61
62 struct EntryLocation;
63 struct OSRExit;
64
65 // === CallLinkRecord ===
66 //
67 // A record of a call out from JIT code that needs linking to a helper function.
68 // Every CallLinkRecord contains a reference to the call instruction & the function
69 // that it needs to be linked to.
70 struct CallLinkRecord {
71     CallLinkRecord(MacroAssembler::Call call, FunctionPtr function)
72         : m_call(call)
73         , m_function(function)
74     {
75     }
76
77     MacroAssembler::Call m_call;
78     FunctionPtr m_function;
79 };
80
81 struct InRecord {
82     InRecord(
83         MacroAssembler::PatchableJump jump, MacroAssembler::Label done,
84         SlowPathGenerator* slowPathGenerator, StructureStubInfo* stubInfo)
85         : m_jump(jump)
86         , m_done(done)
87         , m_slowPathGenerator(slowPathGenerator)
88         , m_stubInfo(stubInfo)
89     {
90     }
91     
92     MacroAssembler::PatchableJump m_jump;
93     MacroAssembler::Label m_done;
94     SlowPathGenerator* m_slowPathGenerator;
95     StructureStubInfo* m_stubInfo;
96 };
97
98 // === JITCompiler ===
99 //
100 // DFG::JITCompiler is responsible for generating JIT code from the dataflow graph.
101 // It does so by delegating to the speculative & non-speculative JITs, which
102 // generate to a MacroAssembler (which the JITCompiler owns through an inheritance
103 // relationship). The JITCompiler holds references to information required during
104 // compilation, and also records information used in linking (e.g. a list of all
105 // call to be linked).
106 class JITCompiler : public CCallHelpers {
107 public:
108     JITCompiler(Graph& dfg);
109     ~JITCompiler();
110     
111     void compile();
112     void compileFunction();
113     
114     // Accessors for properties.
115     Graph& graph() { return m_graph; }
116     
117     // Methods to set labels for the disassembler.
118     void setStartOfCode()
119     {
120         if (LIKELY(!m_disassembler))
121             return;
122         m_disassembler->setStartOfCode(labelIgnoringWatchpoints());
123     }
124     
125     void setForBlockIndex(BlockIndex blockIndex)
126     {
127         if (LIKELY(!m_disassembler))
128             return;
129         m_disassembler->setForBlockIndex(blockIndex, labelIgnoringWatchpoints());
130     }
131     
132     void setForNode(Node* node)
133     {
134         if (LIKELY(!m_disassembler))
135             return;
136         m_disassembler->setForNode(node, labelIgnoringWatchpoints());
137     }
138     
139     void setEndOfMainPath()
140     {
141         if (LIKELY(!m_disassembler))
142             return;
143         m_disassembler->setEndOfMainPath(labelIgnoringWatchpoints());
144     }
145     
146     void setEndOfCode()
147     {
148         if (LIKELY(!m_disassembler))
149             return;
150         m_disassembler->setEndOfCode(labelIgnoringWatchpoints());
151     }
152     
153     CallSiteIndex addCallSite(CodeOrigin codeOrigin)
154     {
155         return m_jitCode->common.addCodeOrigin(codeOrigin);
156     }
157
158     void emitStoreCodeOrigin(CodeOrigin codeOrigin)
159     {
160         CallSiteIndex callSite = addCallSite(codeOrigin);
161         store32(TrustedImm32(callSite.bits()), tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
162     }
163
164     // Add a call out from JIT code, without an exception check.
165     Call appendCall(const FunctionPtr& function)
166     {
167         Call functionCall = call();
168         m_calls.append(CallLinkRecord(functionCall, function));
169         return functionCall;
170     }
171     
172     void exceptionCheck()
173     {
174         m_exceptionChecks.append(emitExceptionCheck());
175     }
176
177     void exceptionCheckWithCallFrameRollback()
178     {
179         m_exceptionChecksWithCallFrameRollback.append(emitExceptionCheck());
180     }
181
182     // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
183     void fastExceptionCheck()
184     {
185         callExceptionFuzz();
186         m_exceptionChecks.append(branchTestPtr(Zero, GPRInfo::returnValueGPR));
187     }
188     
189     OSRExitCompilationInfo& appendExitInfo(MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList())
190     {
191         OSRExitCompilationInfo info;
192         info.m_failureJumps = jumpsToFail;
193         m_exitCompilationInfo.append(info);
194         return m_exitCompilationInfo.last();
195     }
196
197 #if USE(JSVALUE32_64)
198     void* addressOfDoubleConstant(Node*);
199 #endif
200
201     void addGetById(const JITGetByIdGenerator& gen, SlowPathGenerator* slowPath)
202     {
203         m_getByIds.append(InlineCacheWrapper<JITGetByIdGenerator>(gen, slowPath));
204     }
205     
206     void addPutById(const JITPutByIdGenerator& gen, SlowPathGenerator* slowPath)
207     {
208         m_putByIds.append(InlineCacheWrapper<JITPutByIdGenerator>(gen, slowPath));
209     }
210
211     void addIn(const InRecord& record)
212     {
213         m_ins.append(record);
214     }
215     
216     unsigned currentJSCallIndex() const
217     {
218         return m_jsCalls.size();
219     }
220
221     void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
222     {
223         m_jsCalls.append(JSCallRecord(fastCall, slowCall, targetToCheck, info));
224     }
225     
226     void addWeakReference(JSCell* target)
227     {
228         m_graph.m_plan.weakReferences.addLazily(target);
229     }
230     
231     void addWeakReferences(const StructureSet& structureSet)
232     {
233         for (unsigned i = structureSet.size(); i--;)
234             addWeakReference(structureSet[i]);
235     }
236     
237     template<typename T>
238     Jump branchWeakPtr(RelationalCondition cond, T left, JSCell* weakPtr)
239     {
240         Jump result = branchPtr(cond, left, TrustedImmPtr(weakPtr));
241         addWeakReference(weakPtr);
242         return result;
243     }
244
245     template<typename T>
246     Jump branchWeakStructure(RelationalCondition cond, T left, Structure* weakStructure)
247     {
248 #if USE(JSVALUE64)
249         Jump result = branch32(cond, left, TrustedImm32(weakStructure->id()));
250         addWeakReference(weakStructure);
251         return result;
252 #else
253         return branchWeakPtr(cond, left, weakStructure);
254 #endif
255     }
256
257     void noticeOSREntry(BasicBlock&, JITCompiler::Label blockHead, LinkBuffer&);
258     
259     RefPtr<JITCode> jitCode() { return m_jitCode; }
260     
261     Vector<Label>& blockHeads() { return m_blockHeads; }
262
263 private:
264     friend class OSRExitJumpPlaceholder;
265     
266     // Internal implementation to compile.
267     void compileEntry();
268     void compileSetupRegistersForEntry();
269     void compileBody();
270     void link(LinkBuffer&);
271     
272     void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
273     void compileExceptionHandlers();
274     void linkOSRExits();
275     void disassemble(LinkBuffer&);
276     
277     // The dataflow graph currently being generated.
278     Graph& m_graph;
279
280     std::unique_ptr<Disassembler> m_disassembler;
281     
282     RefPtr<JITCode> m_jitCode;
283     
284     // Vector of calls out from JIT code, including exception handler information.
285     // Count of the number of CallRecords with exception handlers.
286     Vector<CallLinkRecord> m_calls;
287     JumpList m_exceptionChecks;
288     JumpList m_exceptionChecksWithCallFrameRollback;
289     
290     Vector<Label> m_blockHeads;
291
292     struct JSCallRecord {
293         JSCallRecord(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
294             : m_fastCall(fastCall)
295             , m_slowCall(slowCall)
296             , m_targetToCheck(targetToCheck)
297             , m_info(info)
298         {
299         }
300         
301         Call m_fastCall;
302         Call m_slowCall;
303         DataLabelPtr m_targetToCheck;
304         CallLinkInfo* m_info;
305     };
306     
307     Vector<InlineCacheWrapper<JITGetByIdGenerator>, 4> m_getByIds;
308     Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds;
309     Vector<InRecord, 4> m_ins;
310     Vector<JSCallRecord, 4> m_jsCalls;
311     SegmentedVector<OSRExitCompilationInfo, 4> m_exitCompilationInfo;
312     Vector<Vector<Label>> m_exitSiteLabels;
313     
314     Call m_callArityFixup;
315     Label m_arityCheck;
316     std::unique_ptr<SpeculativeJIT> m_speculative;
317 };
318
319 } } // namespace JSC::DFG
320
321 #endif
322 #endif
323