We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / bytecode / CallLinkInfo.h
1 /*
2  * Copyright (C) 2012-2018 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 #pragma once
27
28 #include "CallMode.h"
29 #include "CodeLocation.h"
30 #include "CodeSpecializationKind.h"
31 #include "PolymorphicCallStubRoutine.h"
32 #include "WriteBarrier.h"
33 #include <wtf/SentinelLinkedList.h>
34
35 namespace JSC {
36
37 #if ENABLE(JIT)
38
39 class FunctionCodeBlock;
40 class JSFunction;
41 enum OpcodeID : unsigned;
42 struct CallFrameShuffleData;
43
44 class CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> {
45 public:
46     enum CallType {
47         None,
48         Call,
49         CallVarargs,
50         Construct,
51         ConstructVarargs,
52         TailCall,
53         TailCallVarargs,
54         DirectCall,
55         DirectConstruct,
56         DirectTailCall
57     };
58     
59     static CallType callTypeFor(OpcodeID opcodeID);
60
61     static bool isVarargsCallType(CallType callType)
62     {
63         switch (callType) {
64         case CallVarargs:
65         case ConstructVarargs:
66         case TailCallVarargs:
67             return true;
68
69         default:
70             return false;
71         }
72     }
73
74     CallLinkInfo();
75         
76     ~CallLinkInfo();
77     
78     static CodeSpecializationKind specializationKindFor(CallType callType)
79     {
80         return specializationFromIsConstruct(callType == Construct || callType == ConstructVarargs || callType == DirectConstruct);
81     }
82     CodeSpecializationKind specializationKind() const
83     {
84         return specializationKindFor(static_cast<CallType>(m_callType));
85     }
86     
87     static CallMode callModeFor(CallType callType)
88     {
89         switch (callType) {
90         case Call:
91         case CallVarargs:
92         case DirectCall:
93             return CallMode::Regular;
94         case TailCall:
95         case TailCallVarargs:
96         case DirectTailCall:
97             return CallMode::Tail;
98         case Construct:
99         case ConstructVarargs:
100         case DirectConstruct:
101             return CallMode::Construct;
102         case None:
103             RELEASE_ASSERT_NOT_REACHED();
104         }
105
106         RELEASE_ASSERT_NOT_REACHED();
107     }
108     
109     static bool isDirect(CallType callType)
110     {
111         switch (callType) {
112         case DirectCall:
113         case DirectTailCall:
114         case DirectConstruct:
115             return true;
116         case Call:
117         case CallVarargs:
118         case TailCall:
119         case TailCallVarargs:
120         case Construct:
121         case ConstructVarargs:
122             return false;
123         case None:
124             RELEASE_ASSERT_NOT_REACHED();
125             return false;
126         }
127
128         RELEASE_ASSERT_NOT_REACHED();
129         return false;
130     }
131     
132     CallMode callMode() const
133     {
134         return callModeFor(static_cast<CallType>(m_callType));
135     }
136
137     bool isDirect()
138     {
139         return isDirect(static_cast<CallType>(m_callType));
140     }
141
142     bool isTailCall() const
143     {
144         return callMode() == CallMode::Tail;
145     }
146     
147     NearCallMode nearCallMode() const
148     {
149         return isTailCall() ? Tail : Regular;
150     }
151
152     bool isVarargs() const
153     {
154         return isVarargsCallType(static_cast<CallType>(m_callType));
155     }
156
157     bool isLinked() { return m_stub || m_calleeOrCodeBlock; }
158     void unlink(VM&);
159
160     void setUpCall(CallType callType, CodeOrigin codeOrigin, unsigned calleeGPR)
161     {
162         m_callType = callType;
163         m_codeOrigin = codeOrigin;
164         m_calleeGPR = calleeGPR;
165     }
166
167     void setCallLocations(
168         CodeLocationLabel<JSInternalPtrTag> callReturnLocationOrPatchableJump,
169         CodeLocationLabel<JSInternalPtrTag> hotPathBeginOrSlowPathStart,
170         CodeLocationNearCall<JSInternalPtrTag> hotPathOther)
171     {
172         m_callReturnLocationOrPatchableJump = callReturnLocationOrPatchableJump;
173         m_hotPathBeginOrSlowPathStart = hotPathBeginOrSlowPathStart;
174         m_hotPathOther = hotPathOther;
175     }
176
177     bool allowStubs() const { return m_allowStubs; }
178
179     void disallowStubs()
180     {
181         m_allowStubs = false;
182     }
183
184     CodeLocationNearCall<JSInternalPtrTag> callReturnLocation();
185     CodeLocationJump<JSInternalPtrTag> patchableJump();
186     CodeLocationDataLabelPtr<JSInternalPtrTag> hotPathBegin();
187     CodeLocationLabel<JSInternalPtrTag> slowPathStart();
188
189     CodeLocationNearCall<JSInternalPtrTag> hotPathOther()
190     {
191         return m_hotPathOther;
192     }
193
194     void setCallee(VM&, JSCell*, JSObject* callee);
195     void clearCallee();
196     JSObject* callee();
197
198     void setCodeBlock(VM&, JSCell*, FunctionCodeBlock*);
199     void clearCodeBlock();
200     FunctionCodeBlock* codeBlock();
201
202     void setLastSeenCallee(VM&, const JSCell* owner, JSObject* callee);
203     void clearLastSeenCallee();
204     JSObject* lastSeenCallee();
205     bool haveLastSeenCallee();
206     
207     void setExecutableDuringCompilation(ExecutableBase*);
208     ExecutableBase* executable();
209     
210     void setStub(Ref<PolymorphicCallStubRoutine>&& newStub)
211     {
212         clearStub();
213         m_stub = WTFMove(newStub);
214     }
215
216     void clearStub();
217
218     PolymorphicCallStubRoutine* stub()
219     {
220         return m_stub.get();
221     }
222
223     void setSlowStub(Ref<JITStubRoutine>&& newSlowStub)
224     {
225         m_slowStub = WTFMove(newSlowStub);
226     }
227
228     void clearSlowStub()
229     {
230         m_slowStub = nullptr;
231     }
232
233     JITStubRoutine* slowStub()
234     {
235         return m_slowStub.get();
236     }
237
238     bool seenOnce()
239     {
240         return m_hasSeenShouldRepatch;
241     }
242
243     void clearSeen()
244     {
245         m_hasSeenShouldRepatch = false;
246     }
247
248     void setSeen()
249     {
250         m_hasSeenShouldRepatch = true;
251     }
252
253     bool hasSeenClosure()
254     {
255         return m_hasSeenClosure;
256     }
257
258     void setHasSeenClosure()
259     {
260         m_hasSeenClosure = true;
261     }
262
263     bool clearedByGC()
264     {
265         return m_clearedByGC;
266     }
267     
268     bool clearedByVirtual()
269     {
270         return m_clearedByVirtual;
271     }
272
273     void setClearedByVirtual()
274     {
275         m_clearedByVirtual = true;
276     }
277     
278     void setCallType(CallType callType)
279     {
280         m_callType = callType;
281     }
282
283     CallType callType()
284     {
285         return static_cast<CallType>(m_callType);
286     }
287
288     uint32_t* addressOfMaxNumArguments()
289     {
290         return &m_maxNumArguments;
291     }
292
293     uint32_t maxNumArguments()
294     {
295         return m_maxNumArguments;
296     }
297     
298     void setMaxNumArguments(unsigned);
299
300     static ptrdiff_t offsetOfSlowPathCount()
301     {
302         return OBJECT_OFFSETOF(CallLinkInfo, m_slowPathCount);
303     }
304
305     void setCalleeGPR(unsigned calleeGPR)
306     {
307         m_calleeGPR = calleeGPR;
308     }
309
310     unsigned calleeGPR()
311     {
312         return m_calleeGPR;
313     }
314
315     uint32_t slowPathCount()
316     {
317         return m_slowPathCount;
318     }
319
320     void setCodeOrigin(CodeOrigin codeOrigin)
321     {
322         m_codeOrigin = codeOrigin;
323     }
324
325     CodeOrigin codeOrigin()
326     {
327         return m_codeOrigin;
328     }
329
330     void visitWeak(VM&);
331
332     void setFrameShuffleData(const CallFrameShuffleData&);
333
334     const CallFrameShuffleData* frameShuffleData()
335     {
336         return m_frameShuffleData.get();
337     }
338
339 private:
340     CodeLocationLabel<JSInternalPtrTag> m_callReturnLocationOrPatchableJump;
341     CodeLocationLabel<JSInternalPtrTag> m_hotPathBeginOrSlowPathStart;
342     CodeLocationNearCall<JSInternalPtrTag> m_hotPathOther;
343     WriteBarrier<JSCell> m_calleeOrCodeBlock;
344     WriteBarrier<JSCell> m_lastSeenCalleeOrExecutable;
345     RefPtr<PolymorphicCallStubRoutine> m_stub;
346     RefPtr<JITStubRoutine> m_slowStub;
347     std::unique_ptr<CallFrameShuffleData> m_frameShuffleData;
348     bool m_hasSeenShouldRepatch : 1;
349     bool m_hasSeenClosure : 1;
350     bool m_clearedByGC : 1;
351     bool m_clearedByVirtual : 1;
352     bool m_allowStubs : 1;
353     bool m_isLinked : 1;
354     unsigned m_callType : 4; // CallType
355     unsigned m_calleeGPR : 8;
356     uint32_t m_maxNumArguments; // For varargs: the profiled maximum number of arguments. For direct: the number of stack slots allocated for arguments.
357     uint32_t m_slowPathCount;
358     CodeOrigin m_codeOrigin;
359 };
360
361 inline CodeOrigin getCallLinkInfoCodeOrigin(CallLinkInfo& callLinkInfo)
362 {
363     return callLinkInfo.codeOrigin();
364 }
365
366 #endif // ENABLE(JIT)
367
368 } // namespace JSC