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-2015 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 "JSStack.h"
28#include "MacroAssemblerCodeRef.h"
29#include "Register.h"
30#include "StackVisitor.h"
31#include "VM.h"
32#include "VMEntryRecord.h"
33
34namespace JSC {
35
36 class Arguments;
37 class Interpreter;
38 class JSScope;
39
40 struct CallSiteIndex {
41 CallSiteIndex()
42 : m_bits(UINT_MAX)
43 {
44 }
45
46 explicit CallSiteIndex(uint32_t bits)
47 : m_bits(bits)
48 { }
49#if USE(JSVALUE32_64)
50 explicit CallSiteIndex(Instruction* instruction)
51 : m_bits(bitwise_cast<uint32_t>(instruction))
52 { }
53#endif
54
55 explicit operator bool() const { return m_bits != UINT_MAX; }
56
57 inline uint32_t bits() const { return m_bits; }
58
59 private:
60 uint32_t m_bits;
61 };
62
63 // Represents the current state of script execution.
64 // Passed as the first argument to most functions.
65 class ExecState : private Register {
66 public:
67 JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); }
68 JSObject* callee() const { return this[JSStack::Callee].object(); }
69 SUPPRESS_ASAN JSValue unsafeCallee() const { return this[JSStack::Callee].asanUnsafeJSValue(); }
70 CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); }
71 SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const { return this[JSStack::CodeBlock].Register::asanUnsafeCodeBlock(); }
72 JSScope* scope(int scopeRegisterOffset) const
73 {
74 ASSERT(this[scopeRegisterOffset].Register::scope());
75 return this[scopeRegisterOffset].Register::scope();
76 }
77
78 // Global object in which execution began.
79 JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject();
80
81 // Global object in which the currently executing code was defined.
82 // Differs from vmEntryGlobalObject() during function calls across web browser frames.
83 JSGlobalObject* lexicalGlobalObject() const;
84
85 // Differs from lexicalGlobalObject because this will have DOM window shell rather than
86 // the actual DOM window, which can't be "this" for security reasons.
87 JSObject* globalThisValue() const;
88
89 VM& vm() const;
90
91 // Convenience functions for access to global data.
92 // It takes a few memory references to get from a call frame to the global data
93 // pointer, so these are inefficient, and should be used sparingly in new code.
94 // But they're used in many places in legacy code, so they're not going away any time soon.
95
96 void clearException() { vm().clearException(); }
97
98 Exception* exception() const { return vm().exception(); }
99 bool hadException() const { return !!vm().exception(); }
100
101 Exception* lastException() const { return vm().lastException(); }
102 void clearLastException() { vm().clearLastException(); }
103
104 AtomicStringTable* atomicStringTable() const { return vm().atomicStringTable(); }
105 const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; }
106 const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; }
107 Interpreter* interpreter() { return vm().interpreter; }
108 Heap* heap() { return &vm().heap; }
109
110
111 static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
112 Register* registers() { return this; }
113 const Register* registers() const { return this; }
114
115 CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
116
117 CallFrame* callerFrame() const { return static_cast<CallFrame*>(callerFrameOrVMEntryFrame()); }
118 void* callerFrameOrVMEntryFrame() const { return callerFrameAndPC().callerFrame; }
119 SUPPRESS_ASAN void* unsafeCallerFrameOrVMEntryFrame() const { return unsafeCallerFrameAndPC().callerFrame; }
120
121 CallFrame* unsafeCallerFrame(VMEntryFrame*&);
122 JS_EXPORT_PRIVATE CallFrame* callerFrame(VMEntryFrame*&);
123
124 static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }
125
126 ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); }
127 bool hasReturnPC() const { return !!callerFrameAndPC().pc; }
128 void clearReturnPC() { callerFrameAndPC().pc = 0; }
129 static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, pc); }
130 AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); }
131
132 bool callSiteBitsAreBytecodeOffset() const;
133 bool callSiteBitsAreCodeOriginIndex() const;
134
135 unsigned callSiteAsRawBits() const;
136 unsigned unsafeCallSiteAsRawBits() const;
137 CallSiteIndex callSiteIndex() const;
138 CallSiteIndex unsafeCallSiteIndex() const;
139 private:
140 unsigned callSiteBitsAsBytecodeOffset() const;
141 public:
142
143 // This will try to get you the bytecode offset, but you should be aware that
144 // this bytecode offset may be bogus in the presence of inlining. This will
145 // also return 0 if the call frame has no notion of bytecode offsets (for
146 // example if it's native code).
147 // https://bugs.webkit.org/show_bug.cgi?id=121754
148 unsigned bytecodeOffset();
149
150 // This will get you a CodeOrigin. It will always succeed. May return
151 // CodeOrigin(0) if we're in native code.
152 CodeOrigin codeOrigin();
153
154 Register* topOfFrame()
155 {
156 if (!codeBlock())
157 return registers();
158 return topOfFrameInternal();
159 }
160
161 Instruction* currentVPC() const; // This only makes sense in the LLInt and baseline.
162 void setCurrentVPC(Instruction* vpc);
163
164 void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; }
165 void setScope(int scopeRegisterOffset, JSScope* scope) { static_cast<Register*>(this)[scopeRegisterOffset] = scope; }
166
167 ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC,
168 CallFrame* callerFrame, int argc, JSObject* callee)
169 {
170 ASSERT(callerFrame == noCaller() || callerFrame->stack()->containsAddress(this));
171
172 setCodeBlock(codeBlock);
173 setCallerFrame(callerFrame);
174 setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
175 setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object)
176 setCallee(callee);
177 }
178
179 // Read a register from the codeframe (or constant from the CodeBlock).
180 Register& r(int);
181 Register& r(VirtualRegister);
182 // Read a register for a non-constant
183 Register& uncheckedR(int);
184 Register& uncheckedR(VirtualRegister);
185
186 // Access to arguments as passed. (After capture, arguments may move to a different location.)
187 size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
188 size_t argumentCountIncludingThis() const { return this[JSStack::ArgumentCount].payload(); }
189 static int argumentOffset(int argument) { return (JSStack::FirstArgument + argument); }
190 static int argumentOffsetIncludingThis(int argument) { return (JSStack::ThisArgument + argument); }
191
192 // In the following (argument() and setArgument()), the 'argument'
193 // parameter is the index of the arguments of the target function of
194 // this frame. The index starts at 0 for the first arg, 1 for the
195 // second, etc.
196 //
197 // The arguments (in this case) do not include the 'this' value.
198 // arguments(0) will not fetch the 'this' value. To get/set 'this',
199 // use thisValue() and setThisValue() below.
200
201 JSValue argument(size_t argument)
202 {
203 if (argument >= argumentCount())
204 return jsUndefined();
205 return getArgumentUnsafe(argument);
206 }
207 JSValue uncheckedArgument(size_t argument)
208 {
209 ASSERT(argument < argumentCount());
210 return getArgumentUnsafe(argument);
211 }
212 void setArgument(size_t argument, JSValue value)
213 {
214 this[argumentOffset(argument)] = value;
215 }
216
217 JSValue getArgumentUnsafe(size_t argIndex)
218 {
219 // User beware! This method does not verify that there is a valid
220 // argument at the specified argIndex. This is used for debugging
221 // and verification code only. The caller is expected to know what
222 // he/she is doing when calling this method.
223 return this[argumentOffset(argIndex)].jsValue();
224 }
225
226 static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
227 JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
228 void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }
229
230 // Under the constructor implemented in C++, thisValue holds the newTarget instead of the automatically constructed value.
231 // The result of this function is only effective under the "construct" context.
232 JSValue newTarget() { return thisValue(); }
233
234 JSValue argumentAfterCapture(size_t argument);
235
236 static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::ThisArgument - 1; }
237
238 static CallFrame* noCaller() { return 0; }
239
240 void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; }
241 void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = callee; }
242 void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; }
243 void setReturnPC(void* value) { callerFrameAndPC().pc = reinterpret_cast<Instruction*>(value); }
244
245 String friendlyFunctionName();
246
247 // CallFrame::iterate() expects a Functor that implements the following method:
248 // StackVisitor::Status operator()(StackVisitor&);
249
250 template <typename Functor> void iterate(Functor& functor)
251 {
252 StackVisitor::visit<Functor>(this, functor);
253 }
254
255 void dump(PrintStream&);
256 JS_EXPORT_PRIVATE const char* describeFrame();
257
258 private:
259
260#ifndef NDEBUG
261 JSStack* stack();
262#endif
263 ExecState();
264 ~ExecState();
265
266 Register* topOfFrameInternal();
267
268 // The following are for internal use in debugging and verification
269 // code only and not meant as an API for general usage:
270
271 size_t argIndexForRegister(Register* reg)
272 {
273 // The register at 'offset' number of slots from the frame pointer
274 // i.e.
275 // reg = frame[offset];
276 // ==> reg = frame + offset;
277 // ==> offset = reg - frame;
278 int offset = reg - this->registers();
279
280 // The offset is defined (based on argumentOffset()) to be:
281 // offset = JSStack::FirstArgument - argIndex;
282 // Hence:
283 // argIndex = JSStack::FirstArgument - offset;
284 size_t argIndex = offset - JSStack::FirstArgument;
285 return argIndex;
286 }
287
288 CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
289 const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
290 SUPPRESS_ASAN const CallerFrameAndPC& unsafeCallerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
291
292 friend class JSStack;
293 };
294
295} // namespace JSC
296
297#endif // CallFrame_h
298