]>
Commit | Line | Data |
---|---|---|
1 | // -*- mode: c++; c-basic-offset: 4 -*- | |
2 | /* | |
3 | * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) | |
4 | * Copyright (C) 2001 Peter Kelly (pmk@post.com) | |
5 | * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Library General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Library General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Library General Public License | |
18 | * along with this library; see the file COPYING.LIB. If not, write to | |
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
20 | * Boston, MA 02110-1301, USA. | |
21 | * | |
22 | */ | |
23 | ||
24 | #ifndef ExecState_h | |
25 | #define ExecState_h | |
26 | ||
27 | #include "LabelStack.h" | |
28 | #include "LocalStorage.h" | |
29 | #include "completion.h" | |
30 | #include "list.h" | |
31 | #include "scope_chain.h" | |
32 | ||
33 | namespace KJS { | |
34 | ||
35 | class ActivationImp; | |
36 | class CommonIdentifiers; | |
37 | class EvalNode; | |
38 | class FunctionBodyNode; | |
39 | class FunctionImp; | |
40 | class GlobalFuncImp; | |
41 | class Interpreter; | |
42 | class JSGlobalObject; | |
43 | class JSVariableObject; | |
44 | class ProgramNode; | |
45 | class ScopeNode; | |
46 | ||
47 | enum CodeType { GlobalCode, EvalCode, FunctionCode }; | |
48 | ||
49 | typedef Vector<ExecState*, 16> ExecStateStack; | |
50 | ||
51 | // Represents the current state of script execution. | |
52 | // Passed as the first argument to most functions. | |
53 | class ExecState : Noncopyable { | |
54 | public: | |
55 | // Global object that was in scope when the current script started executing. | |
56 | JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; } | |
57 | ||
58 | // Global object that was in scope when the current body of code was defined. | |
59 | JSGlobalObject* lexicalGlobalObject() const; | |
60 | ||
61 | void setException(JSValue* e) { m_exception = e; } | |
62 | void clearException() { m_exception = 0; } | |
63 | JSValue* exception() const { return m_exception; } | |
64 | JSValue** exceptionSlot() { return &m_exception; } | |
65 | bool hadException() const { return !!m_exception; } | |
66 | ||
67 | const ScopeChain& scopeChain() const { return m_scopeChain; } | |
68 | void pushScope(JSObject* s) { m_scopeChain.push(s); } | |
69 | void popScope() { m_scopeChain.pop(); } | |
70 | void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); } | |
71 | ||
72 | JSVariableObject* variableObject() const { return m_variableObject; } | |
73 | void setVariableObject(JSVariableObject* v) { m_variableObject = v; } | |
74 | ||
75 | JSObject* thisValue() const { return m_thisValue; } | |
76 | ||
77 | ExecState* callingExecState() { return m_callingExec; } | |
78 | ||
79 | ActivationImp* activationObject() { return m_activation; } | |
80 | void setActivationObject(ActivationImp* a) { m_activation = a; } | |
81 | CodeType codeType() { return m_codeType; } | |
82 | ScopeNode* scopeNode() { return m_scopeNode; } | |
83 | FunctionImp* function() const { return m_function; } | |
84 | const List* arguments() const { return m_arguments; } | |
85 | ||
86 | LabelStack& seenLabels() { return m_labelStack; } | |
87 | ||
88 | void pushIteration() { m_iterationDepth++; } | |
89 | void popIteration() { m_iterationDepth--; } | |
90 | bool inIteration() const { return (m_iterationDepth > 0); } | |
91 | ||
92 | void pushSwitch() { m_switchDepth++; } | |
93 | void popSwitch() { m_switchDepth--; } | |
94 | bool inSwitch() const { return (m_switchDepth > 0); } | |
95 | ||
96 | // These pointers are used to avoid accessing global variables for these, | |
97 | // to avoid taking PIC branches in Mach-O binaries. | |
98 | const CommonIdentifiers& propertyNames() const { return *m_propertyNames; } | |
99 | const List& emptyList() const { return *m_emptyList; } | |
100 | ||
101 | LocalStorage& localStorage() { return *m_localStorage; } | |
102 | void setLocalStorage(LocalStorage* s) { m_localStorage = s; } | |
103 | ||
104 | // These are only valid right after calling execute(). | |
105 | ComplType completionType() const { return m_completionType; } | |
106 | const Identifier& breakOrContinueTarget() const | |
107 | { | |
108 | ASSERT(m_completionType == Break || m_completionType == Continue); | |
109 | return *m_breakOrContinueTarget; | |
110 | } | |
111 | ||
112 | // Only for use in the implementation of execute(). | |
113 | void setCompletionType(ComplType type) | |
114 | { | |
115 | ASSERT(type != Break); | |
116 | ASSERT(type != Continue); | |
117 | m_completionType = type; | |
118 | } | |
119 | JSValue* setNormalCompletion() | |
120 | { | |
121 | ASSERT(!hadException()); | |
122 | m_completionType = Normal; | |
123 | return 0; | |
124 | } | |
125 | JSValue* setNormalCompletion(JSValue* value) | |
126 | { | |
127 | ASSERT(!hadException()); | |
128 | m_completionType = Normal; | |
129 | return value; | |
130 | } | |
131 | JSValue* setBreakCompletion(const Identifier* target) | |
132 | { | |
133 | ASSERT(!hadException()); | |
134 | m_completionType = Break; | |
135 | m_breakOrContinueTarget = target; | |
136 | return 0; | |
137 | } | |
138 | JSValue* setContinueCompletion(const Identifier* target) | |
139 | { | |
140 | ASSERT(!hadException()); | |
141 | m_completionType = Continue; | |
142 | m_breakOrContinueTarget = target; | |
143 | return 0; | |
144 | } | |
145 | JSValue* setReturnValueCompletion(JSValue* returnValue) | |
146 | { | |
147 | ASSERT(!hadException()); | |
148 | ASSERT(returnValue); | |
149 | m_completionType = ReturnValue; | |
150 | return returnValue; | |
151 | } | |
152 | JSValue* setThrowCompletion(JSValue* exception) | |
153 | { | |
154 | ASSERT(!hadException()); | |
155 | ASSERT(exception); | |
156 | m_completionType = Throw; | |
157 | return exception; | |
158 | } | |
159 | JSValue* setInterruptedCompletion() | |
160 | { | |
161 | ASSERT(!hadException()); | |
162 | m_completionType = Interrupted; | |
163 | return 0; | |
164 | } | |
165 | JSValue* setInterruptedCompletion(JSValue* returnValue) | |
166 | { | |
167 | ASSERT(!hadException()); | |
168 | ASSERT(returnValue); | |
169 | m_completionType = Interrupted; | |
170 | return returnValue; | |
171 | } | |
172 | ||
173 | static void markActiveExecStates(); | |
174 | static ExecStateStack& activeExecStates(); | |
175 | ||
176 | protected: | |
177 | ExecState(JSGlobalObject*); | |
178 | ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*); | |
179 | ExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState); | |
180 | ExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*, | |
181 | ExecState* callingExecState, FunctionImp*, const List& args); | |
182 | ~ExecState(); | |
183 | ||
184 | // ExecStates are always stack-allocated, and the garbage collector | |
185 | // marks the stack, so we don't need to protect the objects below from GC. | |
186 | ||
187 | JSGlobalObject* m_globalObject; | |
188 | JSValue* m_exception; | |
189 | CommonIdentifiers* m_propertyNames; | |
190 | const List* m_emptyList; | |
191 | ||
192 | ExecState* m_callingExec; | |
193 | ||
194 | ScopeNode* m_scopeNode; | |
195 | ||
196 | FunctionImp* m_function; | |
197 | const List* m_arguments; | |
198 | ActivationImp* m_activation; | |
199 | LocalStorage* m_localStorage; | |
200 | ||
201 | ScopeChain m_scopeChain; | |
202 | JSVariableObject* m_variableObject; | |
203 | JSObject* m_thisValue; | |
204 | ||
205 | LabelStack m_labelStack; | |
206 | int m_iterationDepth; | |
207 | int m_switchDepth; | |
208 | CodeType m_codeType; | |
209 | ||
210 | ComplType m_completionType; | |
211 | const Identifier* m_breakOrContinueTarget; | |
212 | }; | |
213 | ||
214 | class GlobalExecState : public ExecState { | |
215 | public: | |
216 | GlobalExecState(JSGlobalObject*); | |
217 | ~GlobalExecState(); | |
218 | }; | |
219 | ||
220 | class InterpreterExecState : public ExecState { | |
221 | public: | |
222 | InterpreterExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*); | |
223 | ~InterpreterExecState(); | |
224 | }; | |
225 | ||
226 | class EvalExecState : public ExecState { | |
227 | public: | |
228 | EvalExecState(JSGlobalObject*, EvalNode*, ExecState* callingExecState); | |
229 | ~EvalExecState(); | |
230 | }; | |
231 | ||
232 | class FunctionExecState : public ExecState { | |
233 | public: | |
234 | FunctionExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*, | |
235 | ExecState* callingExecState, FunctionImp*, const List& args); | |
236 | ~FunctionExecState(); | |
237 | }; | |
238 | ||
239 | } // namespace KJS | |
240 | ||
241 | #endif // ExecState_h |