]>
Commit | Line | Data |
---|---|---|
6fe7ccc8 | 1 | /* |
ed1e77d3 | 2 | * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. |
6fe7ccc8 A |
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" | |
93a37866 | 30 | #include "CodeSpecializationKind.h" |
6fe7ccc8 A |
31 | #include "JITWriteBarrier.h" |
32 | #include "JSFunction.h" | |
33 | #include "Opcode.h" | |
ed1e77d3 | 34 | #include "PolymorphicCallStubRoutine.h" |
6fe7ccc8 | 35 | #include "WriteBarrier.h" |
6fe7ccc8 A |
36 | #include <wtf/SentinelLinkedList.h> |
37 | ||
38 | namespace JSC { | |
39 | ||
40 | #if ENABLE(JIT) | |
41 | ||
42 | class RepatchBuffer; | |
43 | ||
ed1e77d3 A |
44 | class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> { |
45 | public: | |
81345200 | 46 | enum CallType { None, Call, CallVarargs, Construct, ConstructVarargs }; |
6fe7ccc8 A |
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; | |
81345200 A |
53 | if (opcodeID == op_construct_varargs) |
54 | return ConstructVarargs; | |
6fe7ccc8 A |
55 | ASSERT(opcodeID == op_call_varargs); |
56 | return CallVarargs; | |
57 | } | |
ed1e77d3 | 58 | |
6fe7ccc8 | 59 | CallLinkInfo() |
ed1e77d3 A |
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) | |
6fe7ccc8 A |
67 | { |
68 | } | |
69 | ||
70 | ~CallLinkInfo() | |
71 | { | |
ed1e77d3 A |
72 | clearStub(); |
73 | ||
6fe7ccc8 A |
74 | if (isOnList()) |
75 | remove(); | |
76 | } | |
93a37866 | 77 | |
ed1e77d3 | 78 | static CodeSpecializationKind specializationKindFor(CallType callType) |
93a37866 | 79 | { |
81345200 | 80 | return specializationFromIsConstruct(callType == Construct || callType == ConstructVarargs); |
93a37866 | 81 | } |
ed1e77d3 A |
82 | CodeSpecializationKind specializationKind() const |
83 | { | |
84 | return specializationKindFor(static_cast<CallType>(m_callType)); | |
85 | } | |
6fe7ccc8 | 86 | |
ed1e77d3 | 87 | bool isLinked() { return m_stub || m_callee; } |
81345200 | 88 | void unlink(RepatchBuffer&); |
6fe7ccc8 | 89 | |
ed1e77d3 A |
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 | ||
6fe7ccc8 A |
181 | bool seenOnce() |
182 | { | |
ed1e77d3 A |
183 | return m_hasSeenShouldRepatch; |
184 | } | |
185 | ||
186 | void clearSeen() | |
187 | { | |
188 | m_hasSeenShouldRepatch = false; | |
6fe7ccc8 A |
189 | } |
190 | ||
191 | void setSeen() | |
192 | { | |
ed1e77d3 | 193 | m_hasSeenShouldRepatch = true; |
6fe7ccc8 | 194 | } |
ed1e77d3 A |
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 | ||
81345200 | 261 | void visitWeak(RepatchBuffer&); |
ed1e77d3 | 262 | |
81345200 | 263 | static CallLinkInfo& dummy(); |
ed1e77d3 A |
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; | |
6fe7ccc8 A |
281 | }; |
282 | ||
81345200 | 283 | inline CodeOrigin getCallLinkInfoCodeOrigin(CallLinkInfo& callLinkInfo) |
6fe7ccc8 | 284 | { |
ed1e77d3 | 285 | return callLinkInfo.codeOrigin(); |
6fe7ccc8 A |
286 | } |
287 | ||
81345200 A |
288 | typedef HashMap<CodeOrigin, CallLinkInfo*, CodeOriginApproximateHash> CallLinkInfoMap; |
289 | ||
290 | #else // ENABLE(JIT) | |
291 | ||
292 | typedef HashMap<int, void*> CallLinkInfoMap; | |
293 | ||
6fe7ccc8 A |
294 | #endif // ENABLE(JIT) |
295 | ||
296 | } // namespace JSC | |
297 | ||
298 | #endif // CallLinkInfo_h |