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