d651187f19e60147ed3a21ce5cc0de2e7bc083c1
[WebKit-https.git] / Source / JavaScriptCore / interpreter / CallFrame.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2007, 2008, 2011, 2013, 2014 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifndef CallFrame_h
24 #define CallFrame_h
25
26 #include "AbstractPC.h"
27 #include "VM.h"
28 #include "JSStack.h"
29 #include "MacroAssemblerCodeRef.h"
30 #include "Register.h"
31 #include "StackVisitor.h"
32 #include "VMEntryRecord.h"
33
34 namespace JSC  {
35
36     class Arguments;
37     class JSActivation;
38     class Interpreter;
39     class JSScope;
40
41     // Represents the current state of script execution.
42     // Passed as the first argument to most functions.
43     class ExecState : private Register {
44     public:
45         JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); }
46         JSObject* callee() const { return this[JSStack::Callee].function(); }
47         CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); }
48         JSScope* scope() const
49         {
50             ASSERT(this[JSStack::ScopeChain].Register::scope());
51             return this[JSStack::ScopeChain].Register::scope();
52         }
53
54         bool hasActivation() const { return !!uncheckedActivation(); }
55         JSActivation* activation() const;
56         JSValue uncheckedActivation() const;
57
58         // Global object in which execution began.
59         JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject();
60
61         // Global object in which the currently executing code was defined.
62         // Differs from vmEntryGlobalObject() during function calls across web browser frames.
63         JSGlobalObject* lexicalGlobalObject() const;
64
65         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
66         // the actual DOM window, which can't be "this" for security reasons.
67         JSObject* globalThisValue() const;
68
69         VM& vm() const;
70
71         // Convenience functions for access to global data.
72         // It takes a few memory references to get from a call frame to the global data
73         // pointer, so these are inefficient, and should be used sparingly in new code.
74         // But they're used in many places in legacy code, so they're not going away any time soon.
75
76         void clearException() { vm().clearException(); }
77         void clearSupplementaryExceptionInfo()
78         {
79             vm().clearExceptionStack();
80         }
81
82         JSValue exception() const { return vm().exception(); }
83         bool hadException() const { return !vm().exception().isEmpty(); }
84
85         AtomicStringTable* atomicStringTable() const { return vm().atomicStringTable(); }
86         const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; }
87         const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; }
88         Interpreter* interpreter() { return vm().interpreter; }
89         Heap* heap() { return &vm().heap; }
90
91
92         static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
93         Register* registers() { return this; }
94         const Register* registers() const { return this; }
95
96         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
97
98         CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrVMEntryFrame()); }
99
100         JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&);
101
102         static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }
103
104         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); }
105         bool hasReturnPC() const { return !!callerFrameAndPC().pc; }
106         void clearReturnPC() { callerFrameAndPC().pc = 0; }
107         static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, pc); }
108         AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); }
109
110         class Location {
111         public:
112             static inline uint32_t decode(uint32_t bits);
113
114             static inline bool isBytecodeLocation(uint32_t bits);
115 #if USE(JSVALUE64)
116             static inline uint32_t encodeAsBytecodeOffset(uint32_t bits);
117 #else
118             static inline uint32_t encodeAsBytecodeInstruction(Instruction*);
119 #endif
120
121             static inline bool isCodeOriginIndex(uint32_t bits);
122             static inline uint32_t encodeAsCodeOriginIndex(uint32_t bits);
123
124         private:
125             enum TypeTag {
126                 BytecodeLocationTag = 0,
127                 CodeOriginIndexTag = 1,
128             };
129
130             static inline uint32_t encode(TypeTag, uint32_t bits);
131
132             static const uint32_t s_mask = 0x1;
133 #if USE(JSVALUE64)
134             static const uint32_t s_shift = 31;
135             static const uint32_t s_shiftedMask = s_mask << s_shift;
136 #else
137             static const uint32_t s_shift = 1;
138 #endif
139         };
140
141         bool hasLocationAsBytecodeOffset() const;
142         bool hasLocationAsCodeOriginIndex() const;
143
144         unsigned locationAsRawBits() const;
145         unsigned locationAsBytecodeOffset() const;
146         unsigned locationAsCodeOriginIndex() const;
147
148         void setLocationAsRawBits(unsigned);
149         void setLocationAsBytecodeOffset(unsigned);
150
151 #if ENABLE(DFG_JIT)
152         unsigned bytecodeOffsetFromCodeOriginIndex();
153 #endif
154         
155         // This will try to get you the bytecode offset, but you should be aware that
156         // this bytecode offset may be bogus in the presence of inlining. This will
157         // also return 0 if the call frame has no notion of bytecode offsets (for
158         // example if it's native code).
159         // https://bugs.webkit.org/show_bug.cgi?id=121754
160         unsigned bytecodeOffset();
161         
162         // This will get you a CodeOrigin. It will always succeed. May return
163         // CodeOrigin(0) if we're in native code.
164         CodeOrigin codeOrigin();
165
166         Register* topOfFrame()
167         {
168             if (!codeBlock())
169                 return registers();
170             return topOfFrameInternal();
171         }
172     
173 #if USE(JSVALUE32_64)
174         Instruction* currentVPC() const
175         {
176             return bitwise_cast<Instruction*>(this[JSStack::ArgumentCount].tag());
177         }
178         void setCurrentVPC(Instruction* vpc)
179         {
180             this[JSStack::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
181         }
182 #else
183         Instruction* currentVPC() const;
184         void setCurrentVPC(Instruction* vpc);
185 #endif
186
187         void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; }
188         void setScope(JSScope* scope) { static_cast<Register*>(this)[JSStack::ScopeChain] = scope; }
189         void setActivation(JSActivation*);
190
191         ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope,
192             CallFrame* callerFrame, int argc, JSObject* callee)
193         {
194             ASSERT(callerFrame == noCaller() || callerFrame->stack()->containsAddress(this));
195
196             setCodeBlock(codeBlock);
197             setScope(scope);
198             setCallerFrame(callerFrame);
199             setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
200             setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object)
201             setCallee(callee);
202         }
203
204         // Read a register from the codeframe (or constant from the CodeBlock).
205         Register& r(int);
206         // Read a register for a non-constant
207         Register& uncheckedR(int);
208
209         // Access to arguments as passed. (After capture, arguments may move to a different location.)
210         size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
211         size_t argumentCountIncludingThis() const { return this[JSStack::ArgumentCount].payload(); }
212         static int argumentOffset(int argument) { return (JSStack::FirstArgument + argument); }
213         static int argumentOffsetIncludingThis(int argument) { return (JSStack::ThisArgument + argument); }
214
215         // In the following (argument() and setArgument()), the 'argument'
216         // parameter is the index of the arguments of the target function of
217         // this frame. The index starts at 0 for the first arg, 1 for the
218         // second, etc.
219         //
220         // The arguments (in this case) do not include the 'this' value.
221         // arguments(0) will not fetch the 'this' value. To get/set 'this',
222         // use thisValue() and setThisValue() below.
223
224         JSValue argument(size_t argument)
225         {
226             if (argument >= argumentCount())
227                  return jsUndefined();
228             return getArgumentUnsafe(argument);
229         }
230         JSValue uncheckedArgument(size_t argument)
231         {
232             ASSERT(argument < argumentCount());
233             return getArgumentUnsafe(argument);
234         }
235         void setArgument(size_t argument, JSValue value)
236         {
237             this[argumentOffset(argument)] = value;
238         }
239
240         static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
241         JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
242         void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }
243
244         JSValue argumentAfterCapture(size_t argument);
245
246         static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::ThisArgument - 1; }
247
248         static CallFrame* noCaller() { return 0; }
249
250         void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; }
251         void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(callee); }
252         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; }
253         void setReturnPC(void* value) { callerFrameAndPC().pc = reinterpret_cast<Instruction*>(value); }
254
255         // CallFrame::iterate() expects a Functor that implements the following method:
256         //     StackVisitor::Status operator()(StackVisitor&);
257
258         template <typename Functor> void iterate(Functor& functor)
259         {
260             StackVisitor::visit<Functor>(this, functor);
261         }
262
263         void dump(PrintStream&);
264         JS_EXPORT_PRIVATE const char* describeFrame();
265
266     private:
267
268 #ifndef NDEBUG
269         JSStack* stack();
270 #endif
271         ExecState();
272         ~ExecState();
273
274         Register* topOfFrameInternal();
275
276         // The following are for internal use in debugging and verification
277         // code only and not meant as an API for general usage:
278
279         size_t argIndexForRegister(Register* reg)
280         {
281             // The register at 'offset' number of slots from the frame pointer
282             // i.e.
283             //       reg = frame[offset];
284             //   ==> reg = frame + offset;
285             //   ==> offset = reg - frame;
286             int offset = reg - this->registers();
287
288             // The offset is defined (based on argumentOffset()) to be:
289             //       offset = JSStack::FirstArgument - argIndex;
290             // Hence:
291             //       argIndex = JSStack::FirstArgument - offset;
292             size_t argIndex = offset - JSStack::FirstArgument;
293             return argIndex;
294         }
295
296         JSValue getArgumentUnsafe(size_t argIndex)
297         {
298             // User beware! This method does not verify that there is a valid
299             // argument at the specified argIndex. This is used for debugging
300             // and verification code only. The caller is expected to know what
301             // he/she is doing when calling this method.
302             return this[argumentOffset(argIndex)].jsValue();
303         }
304
305         void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
306
307         CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
308         const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
309
310         friend class JSStack;
311         friend class VMInspector;
312     };
313
314 } // namespace JSC
315
316 #endif // CallFrame_h