2 * Copyright (C) 2011 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 <assembler/MacroAssembler.h>
32 #include <bytecode/CodeBlock.h>
33 #include <dfg/DFGGraph.h>
34 #include <dfg/DFGRegisterBank.h>
35 #include <jit/JITCode.h>
37 #include <dfg/DFGFPRInfo.h>
38 #include <dfg/DFGGPRInfo.h>
42 class AbstractSamplingCounter
;
48 class JITCodeGenerator
;
49 class NonSpeculativeJIT
;
51 class SpeculationRecovery
;
54 struct SpeculationCheck
;
58 // A record of a call out from JIT code to a helper function.
59 // Every CallRecord contains a reference to the call instruction & the function
60 // that it needs to be linked to. Calls that might throw an exception also record
61 // the Jump taken on exception (unset if not present), and ExceptionInfo (presently
62 // an unsigned, bytecode index) used to recover handler/source info.
64 // Constructor for a call with no exception handler.
65 CallRecord(MacroAssembler::Call call
, FunctionPtr function
)
67 , m_function(function
)
71 // Constructor for a call with an exception handler.
72 CallRecord(MacroAssembler::Call call
, FunctionPtr function
, MacroAssembler::Jump exceptionCheck
, ExceptionInfo exceptionInfo
)
74 , m_function(function
)
75 , m_exceptionCheck(exceptionCheck
)
76 , m_exceptionInfo(exceptionInfo
)
80 MacroAssembler::Call m_call
;
81 FunctionPtr m_function
;
82 MacroAssembler::Jump m_exceptionCheck
;
83 ExceptionInfo m_exceptionInfo
;
86 // === JITCompiler ===
88 // DFG::JITCompiler is responsible for generating JIT code from the dataflow graph.
89 // It does so by delegating to the speculative & non-speculative JITs, which
90 // generate to a MacroAssembler (which the JITCompiler owns through an inheritance
91 // relationship). The JITCompiler holds references to information required during
92 // compilation, and also records information used in linking (e.g. a list of all
93 // call to be linked).
94 class JITCompiler
: public MacroAssembler
{
96 JITCompiler(JSGlobalData
* globalData
, Graph
& dfg
, CodeBlock
* codeBlock
)
97 : m_globalData(globalData
)
99 , m_codeBlock(codeBlock
)
103 void compileFunction(JITCode
& entry
, MacroAssemblerCodePtr
& entryWithArityCheck
);
105 // Accessors for properties.
106 Graph
& graph() { return m_graph
; }
107 CodeBlock
* codeBlock() { return m_codeBlock
; }
108 JSGlobalData
* globalData() { return m_globalData
; }
111 void preserveReturnAddressAfterCall(GPRReg reg
)
116 void restoreReturnAddressBeforeReturn(GPRReg reg
)
121 void restoreReturnAddressBeforeReturn(Address address
)
126 void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry
, GPRReg to
)
128 loadPtr(Address(GPRInfo::callFrameRegister
, entry
* sizeof(Register
)), to
);
130 void emitPutToCallFrameHeader(GPRReg from
, RegisterFile::CallFrameHeaderEntry entry
)
132 storePtr(from
, Address(GPRInfo::callFrameRegister
, entry
* sizeof(Register
)));
135 void emitPutImmediateToCallFrameHeader(void* value
, RegisterFile::CallFrameHeaderEntry entry
)
137 storePtr(TrustedImmPtr(value
), Address(GPRInfo::callFrameRegister
, entry
* sizeof(Register
)));
141 static Address
addressForGlobalVar(GPRReg global
, int32_t varNumber
)
143 return Address(global
, varNumber
* sizeof(Register
));
146 static Address
addressFor(VirtualRegister virtualRegister
)
148 return Address(GPRInfo::callFrameRegister
, virtualRegister
* sizeof(Register
));
151 static Address
tagFor(VirtualRegister virtualRegister
)
153 return Address(GPRInfo::callFrameRegister
, virtualRegister
* sizeof(Register
) + OBJECT_OFFSETOF(EncodedValueDescriptor
, asBits
.tag
));
156 static Address
payloadFor(VirtualRegister virtualRegister
)
158 return Address(GPRInfo::callFrameRegister
, virtualRegister
* sizeof(Register
) + OBJECT_OFFSETOF(EncodedValueDescriptor
, asBits
.payload
));
161 // Add a call out from JIT code, without an exception check.
162 void appendCall(const FunctionPtr
& function
)
164 m_calls
.append(CallRecord(call(), function
));
165 // FIXME: should be able to JIT_ASSERT here that globalData->exception is null on return back to JIT code.
168 // Add a call out from JIT code, with an exception check.
169 void appendCallWithExceptionCheck(const FunctionPtr
& function
, unsigned exceptionInfo
)
171 Call functionCall
= call();
172 Jump exceptionCheck
= branchTestPtr(NonZero
, AbsoluteAddress(&globalData()->exception
));
173 m_calls
.append(CallRecord(functionCall
, function
, exceptionCheck
, exceptionInfo
));
176 // Helper methods to check nodes for constants.
177 bool isConstant(NodeIndex nodeIndex
)
179 return graph()[nodeIndex
].isConstant();
181 bool isInt32Constant(NodeIndex nodeIndex
)
183 return graph()[nodeIndex
].op
== Int32Constant
;
185 bool isDoubleConstant(NodeIndex nodeIndex
)
187 return graph()[nodeIndex
].op
== DoubleConstant
;
189 bool isJSConstant(NodeIndex nodeIndex
)
191 return graph()[nodeIndex
].op
== JSConstant
;
194 // Helper methods get constant values from nodes.
195 int32_t valueOfInt32Constant(NodeIndex nodeIndex
)
197 ASSERT(isInt32Constant(nodeIndex
));
198 return graph()[nodeIndex
].int32Constant();
200 double valueOfDoubleConstant(NodeIndex nodeIndex
)
202 ASSERT(isDoubleConstant(nodeIndex
));
203 return graph()[nodeIndex
].numericConstant();
205 JSValue
valueOfJSConstant(NodeIndex nodeIndex
)
207 ASSERT(isJSConstant(nodeIndex
));
208 unsigned constantIndex
= graph()[nodeIndex
].constantNumber();
209 return codeBlock()->constantRegister(FirstConstantRegisterIndex
+ constantIndex
).get();
212 // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
214 void jitAssertIsInt32(GPRReg
);
215 void jitAssertIsJSInt32(GPRReg
);
216 void jitAssertIsJSNumber(GPRReg
);
217 void jitAssertIsJSDouble(GPRReg
);
219 void jitAssertIsInt32(GPRReg
) {}
220 void jitAssertIsJSInt32(GPRReg
) {}
221 void jitAssertIsJSNumber(GPRReg
) {}
222 void jitAssertIsJSDouble(GPRReg
) {}
225 #if ENABLE(SAMPLING_COUNTERS)
226 // Debug profiling tool.
227 void emitCount(AbstractSamplingCounter
&, uint32_t increment
= 1);
230 #if ENABLE(SAMPLING_FLAGS)
231 void setSamplingFlag(int32_t flag
);
232 void clearSamplingFlag(int32_t flag
);
236 // These methods used in linking the speculative & non-speculative paths together.
237 void fillNumericToDouble(NodeIndex
, FPRReg
, GPRReg temporary
);
238 void fillInt32ToInteger(NodeIndex
, GPRReg
);
239 void fillToJS(NodeIndex
, GPRReg
);
240 void jumpFromSpeculativeToNonSpeculative(const SpeculationCheck
&, const EntryLocation
&, SpeculationRecovery
*);
241 void linkSpeculationChecks(SpeculativeJIT
&, NonSpeculativeJIT
&);
243 // The globalData, used to access constants such as the vPtrs.
244 JSGlobalData
* m_globalData
;
246 // The dataflow graph currently being generated.
249 // The codeBlock currently being generated, used to access information such as constant values, immediates.
250 CodeBlock
* m_codeBlock
;
252 // Vector of calls out from JIT code, including exception handler information.
253 Vector
<CallRecord
> m_calls
;
256 } } // namespace JSC::DFG