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.
28 #include "completion.h"
31 #include "CommonIdentifiers.h"
32 #include "scope_chain.h"
33 #include "LocalStorage.h"
34 #include "wtf/Vector.h"
35 #include "PropertyNameArray.h"
41 class FunctionBodyNode
;
45 enum CodeType
{ GlobalCode
, EvalCode
, FunctionCode
};
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
;
58 * Returns the interpreter associated with this execution state
60 * @return The interpreter executing the script
62 Interpreter
* dynamicInterpreter() const { return m_interpreter
; }
65 * Returns the interpreter associated with the current scope's
68 * @return The interpreter currently in scope
70 Interpreter
* lexicalInterpreter() const;
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
;
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
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
) {
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());
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
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
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
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
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
);
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(); }
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(); }
270 ExecState(Interpreter
* intp
, ExecState
* save
);
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
;
286 JSObject
* m_variable
;
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
) {}
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
;
311 WTF::Vector
<PropertyNameArrayInfo
, 2> m_activePropertyNameArrays
;
316 typedef ExecState Context
; // Compatibility only
318 class GlobalExecState
: public ExecState
{
320 GlobalExecState(Interpreter
* intp
, JSGlobalObject
* global
);
323 class InterpreterExecState
: public ExecState
{
325 InterpreterExecState(Interpreter
* intp
, JSGlobalObject
* global
, JSObject
* thisObject
, ProgramNode
*);
328 class EvalExecState
: public ExecState
{
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
{
337 FunctionExecState(Interpreter
* intp
, JSObject
* thisObject
,
338 FunctionBodyNode
*, ExecState
* callingExecState
, FunctionImp
*);
343 #endif // ExecState_H