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