Rename InlineCallFrame:: getCallerSkippingDeadFrames to something more descriptive
[WebKit-https.git] / Source / JavaScriptCore / bytecode / InlineCallFrame.h
1 /*
2  * Copyright (C) 2011-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 InlineCallFrame_h
27 #define InlineCallFrame_h
28
29 #include "CodeBlock.h"
30 #include "CodeBlockHash.h"
31 #include "CodeOrigin.h"
32 #include "ValueRecovery.h"
33 #include "WriteBarrier.h"
34 #include <wtf/BitVector.h>
35 #include <wtf/HashMap.h>
36 #include <wtf/PrintStream.h>
37 #include <wtf/StdLibExtras.h>
38 #include <wtf/Vector.h>
39
40 namespace JSC {
41
42 struct InlineCallFrame;
43 class ExecState;
44 class JSFunction;
45
46 struct InlineCallFrame {
47     enum Kind {
48         Call,
49         Construct,
50         TailCall,
51         CallVarargs,
52         ConstructVarargs,
53         TailCallVarargs,
54         
55         // For these, the stackOffset incorporates the argument count plus the true return PC
56         // slot.
57         GetterCall,
58         SetterCall
59     };
60
61     static CallMode callModeFor(Kind kind)
62     {
63         switch (kind) {
64         case Call:
65         case CallVarargs:
66         case GetterCall:
67         case SetterCall:
68             return CallMode::Regular;
69         case TailCall:
70         case TailCallVarargs:
71             return CallMode::Tail;
72         case Construct:
73         case ConstructVarargs:
74             return CallMode::Construct;
75         }
76         RELEASE_ASSERT_NOT_REACHED();
77     }
78
79     static Kind kindFor(CallMode callMode)
80     {
81         switch (callMode) {
82         case CallMode::Regular:
83             return Call;
84         case CallMode::Construct:
85             return Construct;
86         case CallMode::Tail:
87             return TailCall;
88         }
89         RELEASE_ASSERT_NOT_REACHED();
90     }
91     
92     static Kind varargsKindFor(CallMode callMode)
93     {
94         switch (callMode) {
95         case CallMode::Regular:
96             return CallVarargs;
97         case CallMode::Construct:
98             return ConstructVarargs;
99         case CallMode::Tail:
100             return TailCallVarargs;
101         }
102         RELEASE_ASSERT_NOT_REACHED();
103     }
104     
105     static CodeSpecializationKind specializationKindFor(Kind kind)
106     {
107         switch (kind) {
108         case Call:
109         case CallVarargs:
110         case TailCall:
111         case TailCallVarargs:
112         case GetterCall:
113         case SetterCall:
114             return CodeForCall;
115         case Construct:
116         case ConstructVarargs:
117             return CodeForConstruct;
118         }
119         RELEASE_ASSERT_NOT_REACHED();
120     }
121     
122     static bool isVarargs(Kind kind)
123     {
124         switch (kind) {
125         case CallVarargs:
126         case TailCallVarargs:
127         case ConstructVarargs:
128             return true;
129         default:
130             return false;
131         }
132     }
133
134     static bool isTail(Kind kind)
135     {
136         switch (kind) {
137         case TailCall:
138         case TailCallVarargs:
139             return true;
140         default:
141             return false;
142         }
143     }
144     bool isTail() const
145     {
146         return isTail(static_cast<Kind>(kind));
147     }
148
149     static CodeOrigin* computeCallerSkippingTailCalls(InlineCallFrame* inlineCallFrame, Kind* callerCallKind = nullptr)
150     {
151         CodeOrigin* codeOrigin;
152         bool tailCallee;
153         int callKind;
154         do {
155             tailCallee = inlineCallFrame->isTail();
156             callKind = inlineCallFrame->kind;
157             codeOrigin = &inlineCallFrame->directCaller;
158             inlineCallFrame = codeOrigin->inlineCallFrame;
159         } while (inlineCallFrame && tailCallee);
160
161         if (tailCallee)
162             return nullptr;
163
164         if (callerCallKind)
165             *callerCallKind = static_cast<Kind>(callKind);
166
167         return codeOrigin;
168     }
169
170     CodeOrigin* getCallerSkippingTailCalls(Kind* callerCallKind = nullptr)
171     {
172         return computeCallerSkippingTailCalls(this, callerCallKind);
173     }
174
175     InlineCallFrame* getCallerInlineFrameSkippingTailCalls()
176     {
177         CodeOrigin* caller = getCallerSkippingTailCalls();
178         return caller ? caller->inlineCallFrame : nullptr;
179     }
180     
181     Vector<ValueRecovery> arguments; // Includes 'this'.
182     WriteBarrier<CodeBlock> baselineCodeBlock;
183     ValueRecovery calleeRecovery;
184     CodeOrigin directCaller;
185
186     signed stackOffset : 28;
187     unsigned kind : 3; // real type is Kind
188     bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually.
189     VirtualRegister argumentCountRegister; // Only set when we inline a varargs call.
190     
191     // There is really no good notion of a "default" set of values for
192     // InlineCallFrame's fields. This constructor is here just to reduce confusion if
193     // we forgot to initialize explicitly.
194     InlineCallFrame()
195         : stackOffset(0)
196         , kind(Call)
197         , isClosureCall(false)
198     {
199     }
200     
201     bool isVarargs() const
202     {
203         return isVarargs(static_cast<Kind>(kind));
204     }
205
206     CodeSpecializationKind specializationKind() const { return specializationKindFor(static_cast<Kind>(kind)); }
207
208     JSFunction* calleeConstant() const;
209     
210     // Get the callee given a machine call frame to which this InlineCallFrame belongs.
211     JSFunction* calleeForCallFrame(ExecState*) const;
212     
213     CString inferredName() const;
214     CodeBlockHash hash() const;
215     CString hashAsStringIfPossible() const;
216     
217     void setStackOffset(signed offset)
218     {
219         stackOffset = offset;
220         RELEASE_ASSERT(static_cast<signed>(stackOffset) == offset);
221     }
222
223     ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); }
224     ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); }
225
226     bool isStrictMode() const { return baselineCodeBlock->isStrictMode(); }
227
228     void dumpBriefFunctionInformation(PrintStream&) const;
229     void dump(PrintStream&) const;
230     void dumpInContext(PrintStream&, DumpContext*) const;
231
232     MAKE_PRINT_METHOD(InlineCallFrame, dumpBriefFunctionInformation, briefFunctionInformation);
233
234 };
235
236 inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame)
237 {
238     RELEASE_ASSERT(inlineCallFrame);
239     return inlineCallFrame->baselineCodeBlock.get();
240 }
241
242 inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
243 {
244     if (codeOrigin.inlineCallFrame)
245         return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame);
246     return baselineCodeBlock;
247 }
248
249 } // namespace JSC
250
251 namespace WTF {
252
253 void printInternal(PrintStream&, JSC::InlineCallFrame::Kind);
254
255 } // namespace WTF
256
257 #endif // InlineCallFrame_h