]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
1 | /* |
2 | * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) | |
3 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) | |
14957cd0 | 4 | * Copyright (C) 2003, 2007, 2008, 2011 Apple Inc. All rights reserved. |
9dae56ea A |
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 "JSGlobalData.h" | |
14957cd0 | 27 | #include "MacroAssemblerCodeRef.h" |
9dae56ea | 28 | #include "RegisterFile.h" |
9dae56ea A |
29 | |
30 | namespace JSC { | |
31 | ||
32 | class Arguments; | |
33 | class JSActivation; | |
34 | class Interpreter; | |
14957cd0 | 35 | class ScopeChainNode; |
9dae56ea A |
36 | |
37 | // Represents the current state of script execution. | |
38 | // Passed as the first argument to most functions. | |
39 | class ExecState : private Register { | |
40 | public: | |
14957cd0 | 41 | JSObject* callee() const { return this[RegisterFile::Callee].function(); } |
9dae56ea | 42 | CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } |
f9bf01c6 A |
43 | ScopeChainNode* scopeChain() const |
44 | { | |
45 | ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain()); | |
46 | return this[RegisterFile::ScopeChain].Register::scopeChain(); | |
47 | } | |
9dae56ea A |
48 | |
49 | // Global object in which execution began. | |
50 | JSGlobalObject* dynamicGlobalObject(); | |
51 | ||
52 | // Global object in which the currently executing code was defined. | |
53 | // Differs from dynamicGlobalObject() during function calls across web browser frames. | |
14957cd0 | 54 | inline JSGlobalObject* lexicalGlobalObject() const; |
9dae56ea A |
55 | |
56 | // Differs from lexicalGlobalObject because this will have DOM window shell rather than | |
57 | // the actual DOM window, which can't be "this" for security reasons. | |
14957cd0 | 58 | inline JSObject* globalThisValue() const; |
9dae56ea | 59 | |
14957cd0 | 60 | inline JSGlobalData& globalData() const; |
9dae56ea A |
61 | |
62 | // Convenience functions for access to global data. | |
63 | // It takes a few memory references to get from a call frame to the global data | |
64 | // pointer, so these are inefficient, and should be used sparingly in new code. | |
65 | // But they're used in many places in legacy code, so they're not going away any time soon. | |
66 | ||
ba379fdc A |
67 | void clearException() { globalData().exception = JSValue(); } |
68 | JSValue exception() const { return globalData().exception; } | |
9dae56ea A |
69 | bool hadException() const { return globalData().exception; } |
70 | ||
71 | const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; } | |
ba379fdc | 72 | const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; } |
9dae56ea A |
73 | Interpreter* interpreter() { return globalData().interpreter; } |
74 | Heap* heap() { return &globalData().heap; } | |
ba379fdc A |
75 | #ifndef NDEBUG |
76 | void dumpCaller(); | |
77 | #endif | |
14957cd0 A |
78 | static const HashTable* arrayConstructorTable(CallFrame* callFrame) { return callFrame->globalData().arrayConstructorTable; } |
79 | static const HashTable* arrayPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().arrayPrototypeTable; } | |
80 | static const HashTable* booleanPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().booleanPrototypeTable; } | |
9dae56ea | 81 | static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; } |
14957cd0 A |
82 | static const HashTable* dateConstructorTable(CallFrame* callFrame) { return callFrame->globalData().dateConstructorTable; } |
83 | static const HashTable* errorPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().errorPrototypeTable; } | |
84 | static const HashTable* globalObjectTable(CallFrame* callFrame) { return callFrame->globalData().globalObjectTable; } | |
ba379fdc | 85 | static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; } |
9dae56ea | 86 | static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; } |
14957cd0 A |
87 | static const HashTable* numberConstructorTable(CallFrame* callFrame) { return callFrame->globalData().numberConstructorTable; } |
88 | static const HashTable* numberPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().numberPrototypeTable; } | |
89 | static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->globalData().objectConstructorTable; } | |
90 | static const HashTable* objectPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().objectPrototypeTable; } | |
9dae56ea A |
91 | static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; } |
92 | static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; } | |
14957cd0 | 93 | static const HashTable* regExpPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().regExpPrototypeTable; } |
9dae56ea | 94 | static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; } |
14957cd0 | 95 | static const HashTable* stringConstructorTable(CallFrame* callFrame) { return callFrame->globalData().stringConstructorTable; } |
9dae56ea | 96 | |
9dae56ea A |
97 | static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); } |
98 | Register* registers() { return this; } | |
99 | ||
100 | CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; } | |
101 | ||
9dae56ea | 102 | CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); } |
4e4e5a6f A |
103 | #if ENABLE(JIT) |
104 | ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); } | |
105 | #endif | |
106 | #if ENABLE(INTERPRETER) | |
107 | Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); } | |
108 | #endif | |
9dae56ea | 109 | |
ba379fdc A |
110 | void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; } |
111 | void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; } | |
9dae56ea A |
112 | |
113 | ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, | |
14957cd0 | 114 | CallFrame* callerFrame, int argc, JSObject* callee) |
9dae56ea A |
115 | { |
116 | ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller. | |
14957cd0 | 117 | ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->registerFile()->end() >= this); |
9dae56ea A |
118 | |
119 | setCodeBlock(codeBlock); | |
120 | setScopeChain(scopeChain); | |
121 | setCallerFrame(callerFrame); | |
14957cd0 A |
122 | setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. |
123 | setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object) | |
124 | setCallee(callee); | |
9dae56ea A |
125 | } |
126 | ||
ba379fdc A |
127 | // Read a register from the codeframe (or constant from the CodeBlock). |
128 | inline Register& r(int); | |
14957cd0 A |
129 | // Read a register for a non-constant |
130 | inline Register& uncheckedR(int); | |
131 | ||
132 | // Access to arguments. | |
133 | int hostThisRegister() { return -RegisterFile::CallFrameHeaderSize - argumentCountIncludingThis(); } | |
134 | JSValue hostThisValue() { return this[hostThisRegister()].jsValue(); } | |
135 | size_t argumentCount() const { return argumentCountIncludingThis() - 1; } | |
136 | size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].i(); } | |
137 | JSValue argument(int argumentNumber) | |
138 | { | |
139 | int argumentIndex = -RegisterFile::CallFrameHeaderSize - this[RegisterFile::ArgumentCount].i() + argumentNumber + 1; | |
140 | if (argumentIndex >= -RegisterFile::CallFrameHeaderSize) | |
141 | return jsUndefined(); | |
142 | return this[argumentIndex].jsValue(); | |
143 | } | |
9dae56ea A |
144 | |
145 | static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); } | |
ba379fdc | 146 | |
9dae56ea A |
147 | bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; } |
148 | CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); } | |
149 | CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); } | |
150 | ||
14957cd0 A |
151 | void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); } |
152 | void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = Register::withCallee(callee); } | |
ba379fdc | 153 | void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; } |
14957cd0 | 154 | void setReturnPC(void* value) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = (Instruction*)value; } |
ba379fdc | 155 | |
14957cd0 | 156 | private: |
ba379fdc | 157 | static const intptr_t HostCallFrameFlag = 1; |
14957cd0 A |
158 | #ifndef NDEBUG |
159 | RegisterFile* registerFile(); | |
160 | #endif | |
9dae56ea A |
161 | ExecState(); |
162 | ~ExecState(); | |
163 | }; | |
164 | ||
165 | } // namespace JSC | |
166 | ||
167 | #endif // CallFrame_h |