fix logic
[personal-kdelibs.git] / kjs / ExecState.h
blob9008a6ccf5c3f4567bca46520c651fc486efdfab
1 /*
2 * This file is part of the KDE libraries
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 * Copyright (C) 2008 Maksim Orlovich (maksim@kde.org)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #ifndef ExecState_H
26 #define ExecState_H
28 #include "completion.h"
29 #include "value.h"
30 #include "types.h"
31 #include "CommonIdentifiers.h"
32 #include "scope_chain.h"
33 #include "LocalStorage.h"
34 #include "wtf/Vector.h"
35 #include "PropertyNameArray.h"
37 namespace KJS {
38 class ActivationImp;
39 class Interpreter;
40 class FunctionImp;
41 class FunctionBodyNode;
42 class ProgramNode;
43 class JSGlobalObject;
45 enum CodeType { GlobalCode, EvalCode, FunctionCode };
47 /**
48 * Represents the current state of script execution. This object allows you
49 * obtain a handle the interpreter that is currently executing the script,
50 * and also the current execution context.
52 class KJS_EXPORT ExecState : Noncopyable {
53 friend class Interpreter;
54 friend class FunctionImp;
55 friend class GlobalFuncImp;
56 public:
57 /**
58 * Returns the interpreter associated with this execution state
60 * @return The interpreter executing the script
62 Interpreter* dynamicInterpreter() const { return m_interpreter; }
64 /**
65 * Returns the interpreter associated with the current scope's
66 * global object
68 * @return The interpreter currently in scope
70 Interpreter* lexicalInterpreter() const;
73 /**
74 These methods are used to keep track of PropertyNameArrays for ... in loops are going through
76 void pushPropertyNameArray() {
77 pushExceptionHandler(RemovePNA);
79 PropertyNameArrayInfo inf;
80 inf.array = new PropertyNameArray;
81 inf.pos = 0;
82 m_activePropertyNameArrays.append(inf);
85 void popPropertyNameArray() {
86 ASSERT(m_exceptionHandlers.last().type == RemovePNA);
87 popExceptionHandler();
89 delete m_activePropertyNameArrays.last().array;
90 m_activePropertyNameArrays.removeLast();
93 PropertyNameArray& activePropertyNameArray() {
94 return *m_activePropertyNameArrays.last().array;
97 int& activePropertyNameIter() {
98 return m_activePropertyNameArrays.last().pos;
103 * This describes how an exception should be handled
105 enum HandlerType {
106 JumpToCatch, ///< jump to the specified address
107 PopScope, ///< remove a scope chain entry, and run the next handler
108 RemoveDeferred, ///< remove any deferred exception object, and run the next entry
109 RemovePNA, ///< remove + delete top PropertyNameArray
110 Silent ///< just update the exception object. For debugger-type use only
113 void pushExceptionHandler(HandlerType type, Addr addr = 0);
115 void popExceptionHandler();
117 // Cleanup depth entries from the stack, w/o running jumps
118 void quietUnwind(int depth);
120 void setMachineRegisters(const unsigned char* pcBase, const unsigned char** pcLoc, LocalStorageEntry** machineLocalStoreLoc) {
121 m_pcBase = pcBase;
122 m_pc = pcLoc;
123 m_machineLocalStore = machineLocalStoreLoc;
127 The below methods deal with deferring of completions inside finally clauses.
128 Essentially, we clear any set exceptions and memorize any non-normal completion
129 (including the target addresses for the continue/break statements) on
130 the m_deferredCompletions stack. If the 'finally' finishes normally,
131 we will resume the previous completion. If not, finally's abnormal
132 termination is handled as usually; a RemoveDeferred cleanup stack
133 entry is added to unwind m_deferredCompletions if that happens.
136 void deferCompletion() {
137 pushExceptionHandler(RemoveDeferred);
138 m_deferredCompletions.append(abruptCompletion());
139 clearException();
143 This resumes dispatch of a completion that was deferred due to a try ... finally,
144 handling it as appropriate for whether it's inside an another try-finally.
145 This will handle all the cases itself except for one: return,
146 for which it will return the value to return (otherwise returning 0)
148 JSValue* reactivateCompletion(bool insideTryFinally);
151 * Set the exception associated with this execution state,
152 * updating the program counter appropriately, and executing any relevant EH cleanups.
153 * @param e The JSValue of the exception being set
155 void setException(JSValue* e);
158 * Records an abrupt completion of code, and jumps to the closest catch or finally.
159 * This always happens for exceptions, but can also happen for continue/break/return when
160 * they're inside try ... finally, since that case gets routed through the EH machinery.
162 void setAbruptCompletion(Completion comp);
165 * Clears the exception or other abnormal completion set on this execution state.
167 void clearException() { m_completion = Completion(); }
170 * Returns the exception associated with this execution state.
171 * @return The current execution state exception
173 JSValue* exception() const { return m_completion.complType() == Throw ? m_completion.value() : 0; }
176 * Use this to check if an exception was thrown in the current
177 * execution state.
179 * @return Whether an exception was thrown
181 bool hadException() const { return m_completion.complType() == Throw; }
183 Completion abruptCompletion() const { return m_completion; }
186 * Returns the scope chain for this execution context. This is used for
187 * variable lookup, with the list being searched from start to end until a
188 * variable is found.
190 * @return The execution context's scope chain
192 const ScopeChain& scopeChain() const { return scope; }
195 * Returns the variable object for the execution context. This contains a
196 * property for each variable declared in the execution context.
198 * @return The execution context's variable object
200 JSObject* variableObject() const { return m_variable; }
201 void setVariableObject(JSObject* v) { m_variable = v; }
204 * Returns the "this" value for the execution context. This is the value
205 * returned when a script references the special variable "this". It should
206 * always be an Object, unless application-specific code has passed in a
207 * different type.
209 * The object that is used as the "this" value depends on the type of
210 * execution context - for global contexts, the global object is used. For
211 * function objewcts, the value is given by the caller (e.g. in the case of
212 * obj.func(), obj would be the "this" value). For code executed by the
213 * built-in "eval" function, the this value is the same as the calling
214 * context.
216 * @return The execution context's "this" value
218 JSObject* thisValue() const { return m_thisVal; }
221 * Returns the context from which the current context was invoked. For
222 * global code this will be a null context (i.e. one for which
223 * isNull() returns true). You should check isNull() on the returned
224 * value before calling any of it's methods.
226 * @return The calling execution context
228 ExecState* callingExecState() { return m_callingExec; }
231 * Returns the execState of a previous nested evaluation session, if any.
233 ExecState* savedExecState() { return m_savedExec; }
235 JSObject* activationObject() {
236 assert(m_codeType == FunctionCode);
237 return m_variable;
240 CodeType codeType() { return m_codeType; }
241 FunctionBodyNode* currentBody() { return m_currentBody; }
242 FunctionImp* function() const { return m_function; }
244 void pushVariableObjectScope(JSVariableObject* s) { scope.pushVariableObject(s); }
245 void pushScope(JSObject* s) { scope.push(s); }
246 void popScope() { scope.pop(); }
248 void mark();
250 void initLocalStorage(LocalStorageEntry* store, size_t size) {
251 m_localStore = store;
252 m_localStoreSize = size;
255 void updateLocalStorage(LocalStorageEntry* newStore) {
256 m_localStore = newStore;
257 *m_machineLocalStore = newStore;
260 LocalStorageEntry* localStorage() { return m_localStore; }
262 // This is a workaround to avoid accessing the global variables for these identifiers in
263 // important property lookup functions, to avoid taking PIC branches in Mach-O binaries
264 const CommonIdentifiers& propertyNames() const { return *m_propertyNames; }
266 // Compatibility stuff:
267 ExecState* context() { return this; }
268 ExecState* callingContext() { return callingExecState(); }
269 protected:
270 ExecState(Interpreter* intp, ExecState* save);
271 ~ExecState();
272 void markSelf();
274 Interpreter* m_interpreter;
275 Completion m_completion;
276 CommonIdentifiers* m_propertyNames;
277 ExecState* m_callingExec;
278 ExecState* m_savedExec; // in case of recursion of evaluation. Needed to mark things properly;
279 // note that this is disjoint from the above, since that's only used for
280 // eval/function, while this is for global.
282 FunctionBodyNode* m_currentBody;
283 FunctionImp* m_function;
285 ScopeChain scope;
286 JSObject* m_variable;
287 JSObject* m_thisVal;
289 LocalStorageEntry* m_localStore;
290 size_t m_localStoreSize;
292 struct ExceptionHandler {
293 ExceptionHandler() {}
294 ExceptionHandler(HandlerType type, Addr dest):
295 type(type), dest(dest) {}
297 HandlerType type;
298 Addr dest;
301 const unsigned char* m_pcBase; // The address of pc = 0
302 const unsigned char** m_pc; // Where the current fetch address is stored
303 LocalStorageEntry** m_machineLocalStore; // Machine's copy of m_localStore
304 WTF::Vector<ExceptionHandler, 4> m_exceptionHandlers;
305 WTF::Vector<Completion, 4> m_deferredCompletions;
307 struct PropertyNameArrayInfo {
308 PropertyNameArray* array;
309 int pos;
311 WTF::Vector<PropertyNameArrayInfo, 2> m_activePropertyNameArrays;
313 CodeType m_codeType;
316 typedef ExecState Context; // Compatibility only
318 class GlobalExecState : public ExecState {
319 public:
320 GlobalExecState(Interpreter* intp, JSGlobalObject* global);
323 class InterpreterExecState : public ExecState {
324 public:
325 InterpreterExecState(Interpreter* intp, JSGlobalObject* global, JSObject* thisObject, ProgramNode*);
328 class EvalExecState : public ExecState {
329 public:
330 EvalExecState(Interpreter* intp, JSGlobalObject* global, ProgramNode* body, ExecState* callingExecState);
333 // Note: this does not push the activation on the scope chain,
334 // as the activation is not initialized at this point.
335 class FunctionExecState : public ExecState {
336 public:
337 FunctionExecState(Interpreter* intp, JSObject* thisObject,
338 FunctionBodyNode*, ExecState* callingExecState, FunctionImp*);
341 } // namespace KJS
343 #endif // ExecState_H