]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/CallLinkInfo.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / CallLinkInfo.h
1 /*
2 * Copyright (C) 2012, 2014, 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 #ifndef CallLinkInfo_h
27 #define CallLinkInfo_h
28
29 #include "CodeLocation.h"
30 #include "CodeSpecializationKind.h"
31 #include "JITWriteBarrier.h"
32 #include "JSFunction.h"
33 #include "Opcode.h"
34 #include "PolymorphicCallStubRoutine.h"
35 #include "WriteBarrier.h"
36 #include <wtf/SentinelLinkedList.h>
37
38 namespace JSC {
39
40 #if ENABLE(JIT)
41
42 class RepatchBuffer;
43
44 class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
45 public:
46 enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs };
47 static CallType callTypeFor(OpcodeID opcodeID)
48 {
49 if (opcodeID == op_call || opcodeID == op_call_eval)
50 return Call;
51 if (opcodeID == op_construct)
52 return Construct;
53 if (opcodeID == op_construct_varargs)
54 return ConstructVarargs;
55 ASSERT(opcodeID == op_call_varargs);
56 return CallVarargs;
57 }
58
59 CallLinkInfo()
60 : m_isFTL(false)
61 , m_hasSeenShouldRepatch(false)
62 , m_hasSeenClosure(false)
63 , m_clearedByGC(false)
64 , m_callType(None)
65 , m_maxNumArguments(0)
66 , m_slowPathCount(0)
67 {
68 }
69
70 ~CallLinkInfo()
71 {
72 clearStub();
73
74 if (isOnList())
75 remove();
76 }
77
78 static CodeSpecializationKind specializationKindFor(CallType callType)
79 {
80 return specializationFromIsConstruct(callType == Construct || callType == ConstructVarargs);
81 }
82 CodeSpecializationKind specializationKind() const
83 {
84 return specializationKindFor(static_cast<CallType>(m_callType));
85 }
86
87 bool isLinked() { return m_stub || m_callee; }
88 void unlink(RepatchBuffer&);
89
90 void setUpCall(CallType callType, CodeOrigin codeOrigin, unsigned calleeGPR)
91 {
92 m_callType = callType;
93 m_codeOrigin = codeOrigin;
94 m_calleeGPR = calleeGPR;
95 }
96
97 void setCallLocations(CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
98 CodeLocationNearCall hotPathOther)
99 {
100 m_callReturnLocation = callReturnLocation;
101 m_hotPathBegin = hotPathBegin;
102 m_hotPathOther = hotPathOther;
103 }
104
105 void setUpCallFromFTL(CallType callType, CodeOrigin codeOrigin,
106 CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
107 CodeLocationNearCall hotPathOther, unsigned calleeGPR)
108 {
109 m_isFTL = true;
110 m_callType = callType;
111 m_codeOrigin = codeOrigin;
112 m_callReturnLocation = callReturnLocation;
113 m_hotPathBegin = hotPathBegin;
114 m_hotPathOther = hotPathOther;
115 m_calleeGPR = calleeGPR;
116 }
117
118 CodeLocationNearCall callReturnLocation()
119 {
120 return m_callReturnLocation;
121 }
122
123 CodeLocationDataLabelPtr hotPathBegin()
124 {
125 return m_hotPathBegin;
126 }
127
128 CodeLocationNearCall hotPathOther()
129 {
130 return m_hotPathOther;
131 }
132
133 void setCallee(VM& vm, CodeLocationDataLabelPtr location, JSCell* owner, JSFunction* callee)
134 {
135 m_callee.set(vm, location, owner, callee);
136 }
137
138 void clearCallee()
139 {
140 m_callee.clear();
141 }
142
143 JSFunction* callee()
144 {
145 return m_callee.get();
146 }
147
148 void setLastSeenCallee(VM& vm, const JSCell* owner, JSFunction* callee)
149 {
150 m_lastSeenCallee.set(vm, owner, callee);
151 }
152
153 void clearLastSeenCallee()
154 {
155 m_lastSeenCallee.clear();
156 }
157
158 JSFunction* lastSeenCallee()
159 {
160 return m_lastSeenCallee.get();
161 }
162
163 bool haveLastSeenCallee()
164 {
165 return !!m_lastSeenCallee;
166 }
167
168 void setStub(PassRefPtr<PolymorphicCallStubRoutine> newStub)
169 {
170 clearStub();
171 m_stub = newStub;
172 }
173
174 void clearStub();
175
176 PolymorphicCallStubRoutine* stub()
177 {
178 return m_stub.get();
179 }
180
181 bool seenOnce()
182 {
183 return m_hasSeenShouldRepatch;
184 }
185
186 void clearSeen()
187 {
188 m_hasSeenShouldRepatch = false;
189 }
190
191 void setSeen()
192 {
193 m_hasSeenShouldRepatch = true;
194 }
195
196 bool hasSeenClosure()
197 {
198 return m_hasSeenClosure;
199 }
200
201 void setHasSeenClosure()
202 {
203 m_hasSeenClosure = true;
204 }
205
206 bool clearedByGC()
207 {
208 return m_clearedByGC;
209 }
210
211 void setCallType(CallType callType)
212 {
213 m_callType = callType;
214 }
215
216 CallType callType()
217 {
218 return static_cast<CallType>(m_callType);
219 }
220
221 uint8_t* addressOfMaxNumArguments()
222 {
223 return &m_maxNumArguments;
224 }
225
226 uint8_t maxNumArguments()
227 {
228 return m_maxNumArguments;
229 }
230
231 static ptrdiff_t offsetOfSlowPathCount()
232 {
233 return OBJECT_OFFSETOF(CallLinkInfo, m_slowPathCount);
234 }
235
236 void setCalleeGPR(unsigned calleeGPR)
237 {
238 m_calleeGPR = calleeGPR;
239 }
240
241 unsigned calleeGPR()
242 {
243 return m_calleeGPR;
244 }
245
246 uint32_t slowPathCount()
247 {
248 return m_slowPathCount;
249 }
250
251 void setCodeOrigin(CodeOrigin codeOrigin)
252 {
253 m_codeOrigin = codeOrigin;
254 }
255
256 CodeOrigin codeOrigin()
257 {
258 return m_codeOrigin;
259 }
260
261 void visitWeak(RepatchBuffer&);
262
263 static CallLinkInfo& dummy();
264
265 private:
266 CodeLocationNearCall m_callReturnLocation;
267 CodeLocationDataLabelPtr m_hotPathBegin;
268 CodeLocationNearCall m_hotPathOther;
269 JITWriteBarrier<JSFunction> m_callee;
270 WriteBarrier<JSFunction> m_lastSeenCallee;
271 RefPtr<PolymorphicCallStubRoutine> m_stub;
272 bool m_isFTL : 1;
273 bool m_hasSeenShouldRepatch : 1;
274 bool m_hasSeenClosure : 1;
275 bool m_clearedByGC : 1;
276 unsigned m_callType : 4; // CallType
277 unsigned m_calleeGPR : 8;
278 uint8_t m_maxNumArguments; // Only used for varargs calls.
279 uint32_t m_slowPathCount;
280 CodeOrigin m_codeOrigin;
281 };
282
283 inline CodeOrigin getCallLinkInfoCodeOrigin(CallLinkInfo& callLinkInfo)
284 {
285 return callLinkInfo.codeOrigin();
286 }
287
288 typedef HashMap<CodeOrigin, CallLinkInfo*, CodeOriginApproximateHash> CallLinkInfoMap;
289
290 #else // ENABLE(JIT)
291
292 typedef HashMap<int, void*> CallLinkInfoMap;
293
294 #endif // ENABLE(JIT)
295
296 } // namespace JSC
297
298 #endif // CallLinkInfo_h