2 * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGJITCompiler_h
27 #define DFGJITCompiler_h
31 #include "CCallHelpers.h"
32 #include "CodeBlock.h"
33 #include "DFGDisassembler.h"
35 #include "DFGInlineCacheWrapper.h"
36 #include "DFGJITCode.h"
37 #include "DFGOSRExitCompilationInfo.h"
38 #include "DFGRegisterBank.h"
42 #include "JITInlineCacheGenerator.h"
43 #include "LinkBuffer.h"
44 #include "MacroAssembler.h"
45 #include "TempRegisterSet.h"
49 class AbstractSamplingCounter;
55 class JITCodeGenerator;
56 class NodeToRegisterMap;
57 class OSRExitJumpPlaceholder;
58 class SlowPathGenerator;
60 class SpeculationRecovery;
65 // === CallLinkRecord ===
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)
73 , m_function(function)
77 MacroAssembler::Call m_call;
78 FunctionPtr m_function;
83 MacroAssembler::PatchableJump jump, MacroAssembler::Label done,
84 SlowPathGenerator* slowPathGenerator, StructureStubInfo* stubInfo)
87 , m_slowPathGenerator(slowPathGenerator)
88 , m_stubInfo(stubInfo)
92 MacroAssembler::PatchableJump m_jump;
93 MacroAssembler::Label m_done;
94 SlowPathGenerator* m_slowPathGenerator;
95 StructureStubInfo* m_stubInfo;
98 // === JITCompiler ===
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 {
108 JITCompiler(Graph& dfg);
112 void compileFunction();
114 // Accessors for properties.
115 Graph& graph() { return m_graph; }
117 // Methods to set labels for the disassembler.
118 void setStartOfCode()
120 if (LIKELY(!m_disassembler))
122 m_disassembler->setStartOfCode(labelIgnoringWatchpoints());
125 void setForBlockIndex(BlockIndex blockIndex)
127 if (LIKELY(!m_disassembler))
129 m_disassembler->setForBlockIndex(blockIndex, labelIgnoringWatchpoints());
132 void setForNode(Node* node)
134 if (LIKELY(!m_disassembler))
136 m_disassembler->setForNode(node, labelIgnoringWatchpoints());
139 void setEndOfMainPath()
141 if (LIKELY(!m_disassembler))
143 m_disassembler->setEndOfMainPath(labelIgnoringWatchpoints());
148 if (LIKELY(!m_disassembler))
150 m_disassembler->setEndOfCode(labelIgnoringWatchpoints());
153 CallSiteIndex addCallSite(CodeOrigin codeOrigin)
155 return m_jitCode->common.addCodeOrigin(codeOrigin);
158 void emitStoreCodeOrigin(CodeOrigin codeOrigin)
160 CallSiteIndex callSite = addCallSite(codeOrigin);
161 store32(TrustedImm32(callSite.bits()), tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
164 // Add a call out from JIT code, without an exception check.
165 Call appendCall(const FunctionPtr& function)
167 Call functionCall = call();
168 m_calls.append(CallLinkRecord(functionCall, function));
172 void exceptionCheck()
174 m_exceptionChecks.append(emitExceptionCheck());
177 void exceptionCheckWithCallFrameRollback()
179 m_exceptionChecksWithCallFrameRollback.append(emitExceptionCheck());
182 // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
183 void fastExceptionCheck()
186 m_exceptionChecks.append(branchTestPtr(Zero, GPRInfo::returnValueGPR));
189 OSRExitCompilationInfo& appendExitInfo(MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList())
191 OSRExitCompilationInfo info;
192 info.m_failureJumps = jumpsToFail;
193 m_exitCompilationInfo.append(info);
194 return m_exitCompilationInfo.last();
197 #if USE(JSVALUE32_64)
198 void* addressOfDoubleConstant(Node*);
201 void addGetById(const JITGetByIdGenerator& gen, SlowPathGenerator* slowPath)
203 m_getByIds.append(InlineCacheWrapper<JITGetByIdGenerator>(gen, slowPath));
206 void addPutById(const JITPutByIdGenerator& gen, SlowPathGenerator* slowPath)
208 m_putByIds.append(InlineCacheWrapper<JITPutByIdGenerator>(gen, slowPath));
211 void addIn(const InRecord& record)
213 m_ins.append(record);
216 unsigned currentJSCallIndex() const
218 return m_jsCalls.size();
221 void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
223 m_jsCalls.append(JSCallRecord(fastCall, slowCall, targetToCheck, info));
226 void addWeakReference(JSCell* target)
228 m_graph.m_plan.weakReferences.addLazily(target);
231 void addWeakReferences(const StructureSet& structureSet)
233 for (unsigned i = structureSet.size(); i--;)
234 addWeakReference(structureSet[i]);
238 Jump branchWeakPtr(RelationalCondition cond, T left, JSCell* weakPtr)
240 Jump result = branchPtr(cond, left, TrustedImmPtr(weakPtr));
241 addWeakReference(weakPtr);
246 Jump branchWeakStructure(RelationalCondition cond, T left, Structure* weakStructure)
249 Jump result = branch32(cond, left, TrustedImm32(weakStructure->id()));
250 addWeakReference(weakStructure);
253 return branchWeakPtr(cond, left, weakStructure);
257 void noticeOSREntry(BasicBlock&, JITCompiler::Label blockHead, LinkBuffer&);
259 RefPtr<JITCode> jitCode() { return m_jitCode; }
261 Vector<Label>& blockHeads() { return m_blockHeads; }
264 friend class OSRExitJumpPlaceholder;
266 // Internal implementation to compile.
268 void compileSetupRegistersForEntry();
270 void link(LinkBuffer&);
272 void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
273 void compileExceptionHandlers();
275 void disassemble(LinkBuffer&);
277 // The dataflow graph currently being generated.
280 std::unique_ptr<Disassembler> m_disassembler;
282 RefPtr<JITCode> m_jitCode;
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;
290 Vector<Label> m_blockHeads;
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)
303 DataLabelPtr m_targetToCheck;
304 CallLinkInfo* m_info;
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;
314 Call m_callArityFixup;
316 std::unique_ptr<SpeculativeJIT> m_speculative;
319 } } // namespace JSC::DFG