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 void emitStoreCodeOrigin(CodeOrigin codeOrigin
)
155 unsigned index
= m_jitCode
->common
.addCodeOrigin(codeOrigin
);
156 unsigned locationBits
= CallFrame::Location::encodeAsCodeOriginIndex(index
);
157 store32(TrustedImm32(locationBits
), tagFor(static_cast<VirtualRegister
>(JSStack::ArgumentCount
)));
160 // Add a call out from JIT code, without an exception check.
161 Call
appendCall(const FunctionPtr
& function
)
163 Call functionCall
= call();
164 m_calls
.append(CallLinkRecord(functionCall
, function
));
168 void exceptionCheck(Jump jumpToHandler
)
170 m_exceptionChecks
.append(jumpToHandler
);
173 void exceptionCheck()
175 m_exceptionChecks
.append(emitExceptionCheck());
178 void exceptionCheckWithCallFrameRollback()
180 m_exceptionChecksWithCallFrameRollback
.append(emitExceptionCheck());
183 // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
184 void fastExceptionCheck()
187 m_exceptionChecks
.append(branchTestPtr(Zero
, GPRInfo::returnValueGPR
));
190 OSRExitCompilationInfo
& appendExitInfo(MacroAssembler::JumpList jumpsToFail
= MacroAssembler::JumpList())
192 OSRExitCompilationInfo info
;
193 info
.m_failureJumps
= jumpsToFail
;
194 m_exitCompilationInfo
.append(info
);
195 return m_exitCompilationInfo
.last();
198 #if USE(JSVALUE32_64)
199 void* addressOfDoubleConstant(Node
*);
202 void addGetById(const JITGetByIdGenerator
& gen
, SlowPathGenerator
* slowPath
)
204 m_getByIds
.append(InlineCacheWrapper
<JITGetByIdGenerator
>(gen
, slowPath
));
207 void addPutById(const JITPutByIdGenerator
& gen
, SlowPathGenerator
* slowPath
)
209 m_putByIds
.append(InlineCacheWrapper
<JITPutByIdGenerator
>(gen
, slowPath
));
212 void addIn(const InRecord
& record
)
214 m_ins
.append(record
);
217 unsigned currentJSCallIndex() const
219 return m_jsCalls
.size();
222 void addJSCall(Call fastCall
, Call slowCall
, DataLabelPtr targetToCheck
, CallLinkInfo
* info
)
224 m_jsCalls
.append(JSCallRecord(fastCall
, slowCall
, targetToCheck
, info
));
227 void addWeakReference(JSCell
* target
)
229 m_graph
.m_plan
.weakReferences
.addLazily(target
);
232 void addWeakReferences(const StructureSet
& structureSet
)
234 for (unsigned i
= structureSet
.size(); i
--;)
235 addWeakReference(structureSet
[i
]);
239 Jump
branchWeakPtr(RelationalCondition cond
, T left
, JSCell
* weakPtr
)
241 Jump result
= branchPtr(cond
, left
, TrustedImmPtr(weakPtr
));
242 addWeakReference(weakPtr
);
247 Jump
branchWeakStructure(RelationalCondition cond
, T left
, Structure
* weakStructure
)
250 Jump result
= branch32(cond
, left
, TrustedImm32(weakStructure
->id()));
251 addWeakReference(weakStructure
);
254 return branchWeakPtr(cond
, left
, weakStructure
);
259 Jump
branchStructurePtr(RelationalCondition cond
, T left
, Structure
* structure
)
262 return branch32(cond
, left
, TrustedImm32(structure
->id()));
264 return branchPtr(cond
, left
, TrustedImmPtr(structure
));
268 void noticeOSREntry(BasicBlock
&, JITCompiler::Label blockHead
, LinkBuffer
&);
270 RefPtr
<JITCode
> jitCode() { return m_jitCode
; }
272 Vector
<Label
>& blockHeads() { return m_blockHeads
; }
275 friend class OSRExitJumpPlaceholder
;
277 // Internal implementation to compile.
280 void link(LinkBuffer
&);
282 void exitSpeculativeWithOSR(const OSRExit
&, SpeculationRecovery
*);
283 void compileExceptionHandlers();
285 void disassemble(LinkBuffer
&);
287 // The dataflow graph currently being generated.
290 std::unique_ptr
<Disassembler
> m_disassembler
;
292 RefPtr
<JITCode
> m_jitCode
;
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
;
300 Vector
<Label
> m_blockHeads
;
302 struct JSCallRecord
{
303 JSCallRecord(Call fastCall
, Call slowCall
, DataLabelPtr targetToCheck
, CallLinkInfo
* info
)
304 : m_fastCall(fastCall
)
305 , m_slowCall(slowCall
)
306 , m_targetToCheck(targetToCheck
)
313 DataLabelPtr m_targetToCheck
;
314 CallLinkInfo
* m_info
;
317 Vector
<InlineCacheWrapper
<JITGetByIdGenerator
>, 4> m_getByIds
;
318 Vector
<InlineCacheWrapper
<JITPutByIdGenerator
>, 4> m_putByIds
;
319 Vector
<InRecord
, 4> m_ins
;
320 Vector
<JSCallRecord
, 4> m_jsCalls
;
321 SegmentedVector
<OSRExitCompilationInfo
, 4> m_exitCompilationInfo
;
322 Vector
<Vector
<Label
>> m_exitSiteLabels
;
324 Call m_callArityFixup
;
326 std::unique_ptr
<SpeculativeJIT
> m_speculative
;
329 } } // namespace JSC::DFG