]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGJITCompiler.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGJITCompiler.h
CommitLineData
14957cd0
A
1/*
2 * Copyright (C) 2011 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 <assembler/MacroAssembler.h>
32#include <bytecode/CodeBlock.h>
33#include <dfg/DFGGraph.h>
34#include <dfg/DFGRegisterBank.h>
35#include <jit/JITCode.h>
36
37#include <dfg/DFGFPRInfo.h>
38#include <dfg/DFGGPRInfo.h>
39
40namespace JSC {
41
42class AbstractSamplingCounter;
43class CodeBlock;
44class JSGlobalData;
45
46namespace DFG {
47
48class JITCodeGenerator;
49class NonSpeculativeJIT;
50class SpeculativeJIT;
51class SpeculationRecovery;
52
53struct EntryLocation;
54struct SpeculationCheck;
55
56// === CallRecord ===
57//
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.
63struct CallRecord {
64 // Constructor for a call with no exception handler.
65 CallRecord(MacroAssembler::Call call, FunctionPtr function)
66 : m_call(call)
67 , m_function(function)
68 {
69 }
70
71 // Constructor for a call with an exception handler.
72 CallRecord(MacroAssembler::Call call, FunctionPtr function, MacroAssembler::Jump exceptionCheck, ExceptionInfo exceptionInfo)
73 : m_call(call)
74 , m_function(function)
75 , m_exceptionCheck(exceptionCheck)
76 , m_exceptionInfo(exceptionInfo)
77 {
78 }
79
80 MacroAssembler::Call m_call;
81 FunctionPtr m_function;
82 MacroAssembler::Jump m_exceptionCheck;
83 ExceptionInfo m_exceptionInfo;
84};
85
86// === JITCompiler ===
87//
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).
94class JITCompiler : public MacroAssembler {
95public:
96 JITCompiler(JSGlobalData* globalData, Graph& dfg, CodeBlock* codeBlock)
97 : m_globalData(globalData)
98 , m_graph(dfg)
99 , m_codeBlock(codeBlock)
100 {
101 }
102
103 void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck);
104
105 // Accessors for properties.
106 Graph& graph() { return m_graph; }
107 CodeBlock* codeBlock() { return m_codeBlock; }
108 JSGlobalData* globalData() { return m_globalData; }
109
110#if CPU(X86_64)
111 void preserveReturnAddressAfterCall(GPRReg reg)
112 {
113 pop(reg);
114 }
115
116 void restoreReturnAddressBeforeReturn(GPRReg reg)
117 {
118 push(reg);
119 }
120
121 void restoreReturnAddressBeforeReturn(Address address)
122 {
123 push(address);
124 }
125
126 void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to)
127 {
128 loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
129 }
130 void emitPutToCallFrameHeader(GPRReg from, RegisterFile::CallFrameHeaderEntry entry)
131 {
132 storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
133 }
134
135 void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
136 {
137 storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
138 }
139#endif
140
141 static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
142 {
143 return Address(global, varNumber * sizeof(Register));
144 }
145
146 static Address addressFor(VirtualRegister virtualRegister)
147 {
148 return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
149 }
150
151 static Address tagFor(VirtualRegister virtualRegister)
152 {
153 return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
154 }
155
156 static Address payloadFor(VirtualRegister virtualRegister)
157 {
158 return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
159 }
160
161 // Add a call out from JIT code, without an exception check.
162 void appendCall(const FunctionPtr& function)
163 {
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.
166 }
167
168 // Add a call out from JIT code, with an exception check.
169 void appendCallWithExceptionCheck(const FunctionPtr& function, unsigned exceptionInfo)
170 {
171 Call functionCall = call();
172 Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
173 m_calls.append(CallRecord(functionCall, function, exceptionCheck, exceptionInfo));
174 }
175
176 // Helper methods to check nodes for constants.
177 bool isConstant(NodeIndex nodeIndex)
178 {
179 return graph()[nodeIndex].isConstant();
180 }
181 bool isInt32Constant(NodeIndex nodeIndex)
182 {
183 return graph()[nodeIndex].op == Int32Constant;
184 }
185 bool isDoubleConstant(NodeIndex nodeIndex)
186 {
187 return graph()[nodeIndex].op == DoubleConstant;
188 }
189 bool isJSConstant(NodeIndex nodeIndex)
190 {
191 return graph()[nodeIndex].op == JSConstant;
192 }
193
194 // Helper methods get constant values from nodes.
195 int32_t valueOfInt32Constant(NodeIndex nodeIndex)
196 {
197 ASSERT(isInt32Constant(nodeIndex));
198 return graph()[nodeIndex].int32Constant();
199 }
200 double valueOfDoubleConstant(NodeIndex nodeIndex)
201 {
202 ASSERT(isDoubleConstant(nodeIndex));
203 return graph()[nodeIndex].numericConstant();
204 }
205 JSValue valueOfJSConstant(NodeIndex nodeIndex)
206 {
207 ASSERT(isJSConstant(nodeIndex));
208 unsigned constantIndex = graph()[nodeIndex].constantNumber();
209 return codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex).get();
210 }
211
212 // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
213#if DFG_JIT_ASSERT
214 void jitAssertIsInt32(GPRReg);
215 void jitAssertIsJSInt32(GPRReg);
216 void jitAssertIsJSNumber(GPRReg);
217 void jitAssertIsJSDouble(GPRReg);
218#else
219 void jitAssertIsInt32(GPRReg) {}
220 void jitAssertIsJSInt32(GPRReg) {}
221 void jitAssertIsJSNumber(GPRReg) {}
222 void jitAssertIsJSDouble(GPRReg) {}
223#endif
224
225#if ENABLE(SAMPLING_COUNTERS)
226 // Debug profiling tool.
227 void emitCount(AbstractSamplingCounter&, uint32_t increment = 1);
228#endif
229
230#if ENABLE(SAMPLING_FLAGS)
231 void setSamplingFlag(int32_t flag);
232 void clearSamplingFlag(int32_t flag);
233#endif
234
235private:
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&);
242
243 // The globalData, used to access constants such as the vPtrs.
244 JSGlobalData* m_globalData;
245
246 // The dataflow graph currently being generated.
247 Graph& m_graph;
248
249 // The codeBlock currently being generated, used to access information such as constant values, immediates.
250 CodeBlock* m_codeBlock;
251
252 // Vector of calls out from JIT code, including exception handler information.
253 Vector<CallRecord> m_calls;
254};
255
256} } // namespace JSC::DFG
257
258#endif
259#endif
260