Typed arrays should be rewritten
[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 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 "StackIteratorPrivate.h"
32
33 namespace JSC  {
34
35     class Arguments;
36     class JSActivation;
37     class Interpreter;
38     class JSScope;
39
40     // Represents the current state of script execution.
41     // Passed as the first argument to most functions.
42     class ExecState : private Register {
43     public:
44         JSValue calleeAsValue() const { return this[JSStack::Callee].jsValue(); }
45         JSObject* callee() const { return this[JSStack::Callee].function(); }
46         CodeBlock* codeBlock() const { return this[JSStack::CodeBlock].Register::codeBlock(); }
47         JSScope* scope() const
48         {
49             ASSERT(this[JSStack::ScopeChain].Register::scope());
50             return this[JSStack::ScopeChain].Register::scope();
51         }
52
53         // Global object in which execution began.
54         JSGlobalObject* dynamicGlobalObject();
55
56         // Global object in which the currently executing code was defined.
57         // Differs from dynamicGlobalObject() during function calls across web browser frames.
58         JSGlobalObject* lexicalGlobalObject() const;
59
60         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
61         // the actual DOM window, which can't be "this" for security reasons.
62         JSObject* globalThisValue() const;
63
64         VM& vm() const;
65
66         // Convenience functions for access to global data.
67         // It takes a few memory references to get from a call frame to the global data
68         // pointer, so these are inefficient, and should be used sparingly in new code.
69         // But they're used in many places in legacy code, so they're not going away any time soon.
70
71         void clearException() { vm().exception = JSValue(); }
72         void clearSupplementaryExceptionInfo()
73         {
74             vm().clearExceptionStack();
75         }
76
77         JSValue exception() const { return vm().exception; }
78         bool hadException() const { return vm().exception; }
79
80         const CommonIdentifiers& propertyNames() const { return *vm().propertyNames; }
81         const MarkedArgumentBuffer& emptyList() const { return *vm().emptyList; }
82         Interpreter* interpreter() { return vm().interpreter; }
83         Heap* heap() { return &vm().heap; }
84 #ifndef NDEBUG
85         void dumpCaller();
86 #endif
87         static const HashTable* arrayConstructorTable(CallFrame* callFrame) { return callFrame->vm().arrayConstructorTable; }
88         static const HashTable* arrayPrototypeTable(CallFrame* callFrame) { return callFrame->vm().arrayPrototypeTable; }
89         static const HashTable* booleanPrototypeTable(CallFrame* callFrame) { return callFrame->vm().booleanPrototypeTable; }
90         static const HashTable* dataViewTable(CallFrame* callFrame) { return callFrame->vm().dataViewTable; }
91         static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->vm().dateTable; }
92         static const HashTable* dateConstructorTable(CallFrame* callFrame) { return callFrame->vm().dateConstructorTable; }
93         static const HashTable* errorPrototypeTable(CallFrame* callFrame) { return callFrame->vm().errorPrototypeTable; }
94         static const HashTable* globalObjectTable(CallFrame* callFrame) { return callFrame->vm().globalObjectTable; }
95         static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->vm().jsonTable; }
96         static const HashTable* numberConstructorTable(CallFrame* callFrame) { return callFrame->vm().numberConstructorTable; }
97         static const HashTable* numberPrototypeTable(CallFrame* callFrame) { return callFrame->vm().numberPrototypeTable; }
98         static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->vm().objectConstructorTable; }
99         static const HashTable* privateNamePrototypeTable(CallFrame* callFrame) { return callFrame->vm().privateNamePrototypeTable; }
100         static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->vm().regExpTable; }
101         static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->vm().regExpConstructorTable; }
102         static const HashTable* regExpPrototypeTable(CallFrame* callFrame) { return callFrame->vm().regExpPrototypeTable; }
103         static const HashTable* stringConstructorTable(CallFrame* callFrame) { return callFrame->vm().stringConstructorTable; }
104
105         static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
106         Register* registers() { return this; }
107
108         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
109
110         CallFrame* callerFrame() const { return this[JSStack::CallerFrame].callFrame(); }
111 #if ENABLE(JIT) || ENABLE(LLINT)
112         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[JSStack::ReturnPC].vPC()); }
113         bool hasReturnPC() const { return !!this[JSStack::ReturnPC].vPC(); }
114         void clearReturnPC() { registers()[JSStack::ReturnPC] = static_cast<Instruction*>(0); }
115 #endif
116         AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); }
117
118         class Location {
119         public:
120             static inline uint32_t decode(uint32_t bits);
121
122             static inline bool isBytecodeLocation(uint32_t bits);
123 #if USE(JSVALUE64)
124             static inline uint32_t encodeAsBytecodeOffset(uint32_t bits);
125 #else
126             static inline uint32_t encodeAsBytecodeInstruction(Instruction*);
127 #endif
128
129             static inline bool isCodeOriginIndex(uint32_t bits);
130             static inline uint32_t encodeAsCodeOriginIndex(uint32_t bits);
131
132             static inline bool isInlinedCode(uint32_t bits);
133             static inline uint32_t encodeAsInlinedCode(uint32_t bits);
134
135         private:
136             enum TypeTag {
137                 BytecodeLocationTag = 0,
138                 CodeOriginIndexTag = 1,
139                 IsInlinedCodeTag = 2,
140             };
141
142             static inline uint32_t encode(TypeTag, uint32_t bits);
143
144             static const uint32_t s_mask = 0x3;
145 #if USE(JSVALUE64)
146             static const uint32_t s_shift = 30;
147             static const uint32_t s_shiftedMask = s_mask << s_shift;
148 #else
149             static const uint32_t s_shift = 2;
150 #endif
151         };
152
153         bool isInlinedFrame() const;
154         void setIsInlinedFrame();
155
156         bool hasLocationAsBytecodeOffset() const;
157         bool hasLocationAsCodeOriginIndex() const;
158
159         unsigned locationAsRawBits() const;
160         unsigned locationAsBytecodeOffset() const;
161         unsigned locationAsCodeOriginIndex() const;
162
163         void setLocationAsRawBits(unsigned);
164         void setLocationAsBytecodeOffset(unsigned);
165
166 #if ENABLE(DFG_JIT)
167         unsigned bytecodeOffsetFromCodeOriginIndex();
168 #endif
169
170         Register* frameExtent()
171         {
172             if (!codeBlock())
173                 return registers();
174             return frameExtentInternal();
175         }
176     
177         Register* frameExtentInternal();
178     
179 #if ENABLE(DFG_JIT)
180         InlineCallFrame* inlineCallFrame() const { return this[JSStack::ReturnPC].asInlineCallFrame(); }
181 #else
182         // This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by
183         // isInlinedFrame(). But to make it easier to write code without having a bunch of
184         // #if's, we make a dummy implementation available anyway.
185         InlineCallFrame* inlineCallFrame() const
186         {
187             RELEASE_ASSERT_NOT_REACHED();
188             return 0;
189         }
190 #endif
191 #if USE(JSVALUE32_64)
192         Instruction* currentVPC() const
193         {
194             return bitwise_cast<Instruction*>(this[JSStack::ArgumentCount].tag());
195         }
196         void setCurrentVPC(Instruction* vpc)
197         {
198             this[JSStack::ArgumentCount].tag() = bitwise_cast<int32_t>(vpc);
199         }
200 #else
201         Instruction* currentVPC() const;
202         void setCurrentVPC(Instruction* vpc);
203 #endif
204
205         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[JSStack::CallerFrame] = callerFrame; }
206         void setScope(JSScope* scope) { static_cast<Register*>(this)[JSStack::ScopeChain] = scope; }
207
208         ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope,
209             CallFrame* callerFrame, int argc, JSObject* callee)
210         {
211             ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
212             ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->stack()->end() >= this);
213
214             setCodeBlock(codeBlock);
215             setScope(scope);
216             setCallerFrame(callerFrame);
217             setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
218             setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object)
219             setCallee(callee);
220         }
221
222         // Read a register from the codeframe (or constant from the CodeBlock).
223         Register& r(int);
224         // Read a register for a non-constant 
225         Register& uncheckedR(int);
226
227         // Access to arguments as passed. (After capture, arguments may move to a different location.)
228         size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
229         size_t argumentCountIncludingThis() const { return this[JSStack::ArgumentCount].payload(); }
230         static int argumentOffset(int argument) { return s_firstArgumentOffset - argument; }
231         static int argumentOffsetIncludingThis(int argument) { return s_thisArgumentOffset - argument; }
232
233         // In the following (argument() and setArgument()), the 'argument'
234         // parameter is the index of the arguments of the target function of
235         // this frame. The index starts at 0 for the first arg, 1 for the
236         // second, etc.
237         //
238         // The arguments (in this case) do not include the 'this' value.
239         // arguments(0) will not fetch the 'this' value. To get/set 'this',
240         // use thisValue() and setThisValue() below.
241
242         JSValue argument(size_t argument)
243         {
244             if (argument >= argumentCount())
245                  return jsUndefined();
246             return this[argumentOffset(argument)].jsValue();
247         }
248         void setArgument(size_t argument, JSValue value)
249         {
250             this[argumentOffset(argument)] = value;
251         }
252
253         static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); }
254         JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); }
255         void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; }
256
257         JSValue argumentAfterCapture(size_t argument);
258
259         static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + JSStack::CallFrameHeaderSize; }
260
261         // FIXME: Remove these.
262         int hostThisRegister() { return thisArgumentOffset(); }
263         JSValue hostThisValue() { return thisValue(); }
264
265         static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
266
267         bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
268         CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
269         CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
270
271         void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; }
272         void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(callee); }
273         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; }
274         void setReturnPC(void* value) { static_cast<Register*>(this)[JSStack::ReturnPC] = (Instruction*)value; }
275         
276 #if ENABLE(DFG_JIT)
277         void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast<Register*>(this)[JSStack::ReturnPC] = inlineCallFrame; }
278 #endif
279         CallFrame* callerFrameNoFlags() { return callerFrame()->removeHostCallFrameFlag(); }
280
281         JS_EXPORT_PRIVATE StackIterator begin(StackIterator::FrameFilter = 0);
282         JS_EXPORT_PRIVATE StackIterator find(JSFunction* calleeFunctionObj, StackIterator::FrameFilter = 0);
283         JS_EXPORT_PRIVATE StackIterator::Frame* end();
284
285     private:
286         static const intptr_t HostCallFrameFlag = 1;
287         static const int s_thisArgumentOffset = -1 - JSStack::CallFrameHeaderSize;
288         static const int s_firstArgumentOffset = s_thisArgumentOffset - 1;
289
290 #ifndef NDEBUG
291         JSStack* stack();
292 #endif
293         ExecState();
294         ~ExecState();
295
296         // The following are for internal use in debugging and verification
297         // code only and not meant as an API for general usage:
298
299         size_t argIndexForRegister(Register* reg)
300         {
301             // The register at 'offset' number of slots from the frame pointer
302             // i.e.
303             //       reg = frame[offset];
304             //   ==> reg = frame + offset;
305             //   ==> offset = reg - frame;
306             int offset = reg - this->registers();
307
308             // The offset is defined (based on argumentOffset()) to be:
309             //       offset = s_firstArgumentOffset - argIndex;
310             // Hence:
311             //       argIndex = s_firstArgumentOffset - offset;
312             size_t argIndex = s_firstArgumentOffset - offset;
313             return argIndex;
314         }
315
316         JSValue getArgumentUnsafe(size_t argIndex)
317         {
318             // User beware! This method does not verify that there is a valid
319             // argument at the specified argIndex. This is used for debugging
320             // and verification code only. The caller is expected to know what
321             // he/she is doing when calling this method.
322             return this[argumentOffset(argIndex)].jsValue();
323         }
324
325         friend class JSStack;
326         friend class VMInspector;
327     };
328
329 } // namespace JSC
330
331 #endif // CallFrame_h