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) 7 * 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. 12 * 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. 17 * 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. 22 * 23 */ 24 25 #ifndef ExecState_H 26 #define ExecState_H 27 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" 36 37 namespace KJS 38 { 39 class ActivationImp; 40 class Interpreter; 41 class FunctionImp; 42 class FunctionBodyNode; 43 class ProgramNode; 44 class JSGlobalObject; 45 46 enum CodeType { GlobalCode, EvalCode, FunctionCode }; 47 48 /** 49 * Represents the current state of script execution. This object allows you 50 * obtain a handle the interpreter that is currently executing the script, 51 * and also the current execution context. 52 */ 53 class KJS_EXPORT ExecState : Noncopyable 54 { 55 friend class Interpreter; 56 friend class FunctionImp; 57 friend class GlobalFuncImp; 58 public: 59 /** 60 * Returns the interpreter associated with this execution state 61 * 62 * @return The interpreter executing the script 63 */ dynamicInterpreter()64 Interpreter *dynamicInterpreter() const 65 { 66 return m_interpreter; 67 } 68 69 /** 70 * Returns the interpreter associated with the current scope's 71 * global object 72 * 73 * @return The interpreter currently in scope 74 */ 75 Interpreter *lexicalInterpreter() const; 76 77 /** 78 * This describes how an exception should be handled 79 */ 80 enum HandlerType { 81 JumpToCatch, ///< jump to the specified address 82 PopScope, ///< remove a scope chain entry, and run the next handler 83 RemoveDeferred, ///< remove any deferred exception object, and run the next entry 84 Silent ///< just update the exception object. For debugger-type use only 85 }; 86 87 void pushExceptionHandler(HandlerType type, Addr addr = 0); 88 89 void popExceptionHandler(); 90 91 // Cleanup depth entries from the stack, w/o running jumps 92 void quietUnwind(int depth); 93 setMachineRegisters(const unsigned char * pcBase,const unsigned char ** pcLoc,LocalStorageEntry ** machineLocalStoreLoc)94 void setMachineRegisters(const unsigned char *pcBase, const unsigned char **pcLoc, LocalStorageEntry **machineLocalStoreLoc) 95 { 96 m_pcBase = pcBase; 97 m_pc = pcLoc; 98 m_machineLocalStore = machineLocalStoreLoc; 99 } 100 101 /** 102 The below methods deal with deferring of completions inside finally clauses. 103 Essentially, we clear any set exceptions and memorize any non-normal completion 104 (including the target addresses for the continue/break statements) on 105 the m_deferredCompletions stack. If the 'finally' finishes normally, 106 we will resume the previous completion. If not, finally's abnormal 107 termination is handled as usually; a RemoveDeferred cleanup stack 108 entry is added to unwind m_deferredCompletions if that happens. 109 */ 110 deferCompletion()111 void deferCompletion() 112 { 113 pushExceptionHandler(RemoveDeferred); 114 m_deferredCompletions.append(abruptCompletion()); 115 clearException(); 116 } 117 118 /** 119 This resumes dispatch of a completion that was deferred due to a try ... finally, 120 handling it as appropriate for whether it's inside an another try-finally. 121 This will handle all the cases itself except for one: return, 122 for which it will return the value to return (otherwise returning 0) 123 */ 124 JSValue *reactivateCompletion(bool insideTryFinally); 125 126 /** 127 * Set the exception associated with this execution state, 128 * updating the program counter appropriately, and executing any relevant EH cleanups. 129 * @param e The JSValue of the exception being set 130 */ 131 void setException(JSValue *e); 132 133 /** 134 * Records an abrupt completion of code, and jumps to the closest catch or finally. 135 * This always happens for exceptions, but can also happen for continue/break/return when 136 * they're inside try ... finally, since that case gets routed through the EH machinery. 137 */ 138 void setAbruptCompletion(Completion comp); 139 140 /** 141 * Clears the exception or other abnormal completion set on this execution state. 142 */ clearException()143 void clearException() 144 { 145 m_completion = Completion(); 146 } 147 148 /** 149 * Returns the exception associated with this execution state. 150 * @return The current execution state exception 151 */ exception()152 JSValue *exception() const 153 { 154 return m_completion.complType() == Throw ? m_completion.value() : nullptr; 155 } 156 157 /** 158 * Use this to check if an exception was thrown in the current 159 * execution state. 160 * 161 * @return Whether an exception was thrown 162 */ hadException()163 bool hadException() const 164 { 165 return m_completion.complType() == Throw; 166 } 167 abruptCompletion()168 Completion abruptCompletion() const 169 { 170 return m_completion; 171 } 172 173 /** 174 * Returns the scope chain for this execution context. This is used for 175 * variable lookup, with the list being searched from start to end until a 176 * variable is found. 177 * 178 * @return The execution context's scope chain 179 */ scopeChain()180 const ScopeChain &scopeChain() const 181 { 182 return scope; 183 } 184 185 /** 186 * Returns the variable object for the execution context. This contains a 187 * property for each variable declared in the execution context. 188 * 189 * @return The execution context's variable object 190 */ variableObject()191 JSObject *variableObject() const 192 { 193 return m_variable; 194 } setVariableObject(JSObject * v)195 void setVariableObject(JSObject *v) 196 { 197 m_variable = v; 198 } 199 200 /** 201 * Returns the "this" value for the execution context. This is the value 202 * returned when a script references the special variable "this". It should 203 * always be an Object, unless application-specific code has passed in a 204 * different type. 205 * 206 * The object that is used as the "this" value depends on the type of 207 * execution context - for global contexts, the global object is used. For 208 * function objewcts, the value is given by the caller (e.g. in the case of 209 * obj.func(), obj would be the "this" value). For code executed by the 210 * built-in "eval" function, the this value is the same as the calling 211 * context. 212 * 213 * @return The execution context's "this" value 214 */ thisValue()215 JSObject *thisValue() const 216 { 217 return m_thisVal; 218 } 219 220 /** 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 its methods. 225 * 226 * @return The calling execution context 227 */ callingExecState()228 ExecState *callingExecState() 229 { 230 return m_callingExec; 231 } 232 233 /** 234 * Returns the execState of a previous nested evaluation session, if any. 235 */ savedExecState()236 ExecState *savedExecState() 237 { 238 return m_savedExec; 239 } 240 activationObject()241 JSObject *activationObject() 242 { 243 assert(m_codeType == FunctionCode); 244 return m_variable; 245 } 246 codeType()247 CodeType codeType() 248 { 249 return m_codeType; 250 } currentBody()251 FunctionBodyNode *currentBody() 252 { 253 return m_currentBody; 254 } function()255 FunctionImp *function() const 256 { 257 return m_function; 258 } 259 pushVariableObjectScope(JSVariableObject * s)260 void pushVariableObjectScope(JSVariableObject *s) 261 { 262 scope.pushVariableObject(s); 263 } pushScope(JSObject * s)264 void pushScope(JSObject *s) 265 { 266 scope.push(s); 267 } popScope()268 void popScope() 269 { 270 scope.pop(); 271 } 272 273 void mark(); 274 initLocalStorage(LocalStorageEntry * store,size_t size)275 void initLocalStorage(LocalStorageEntry *store, size_t size) 276 { 277 m_localStore = store; 278 m_localStoreSize = size; 279 } 280 updateLocalStorage(LocalStorageEntry * newStore)281 void updateLocalStorage(LocalStorageEntry *newStore) 282 { 283 m_localStore = newStore; 284 *m_machineLocalStore = newStore; 285 } 286 localStorage()287 LocalStorageEntry *localStorage() 288 { 289 return m_localStore; 290 } 291 292 // This is a workaround to avoid accessing the global variables for these identifiers in 293 // important property lookup functions, to avoid taking PIC branches in Mach-O binaries propertyNames()294 const CommonIdentifiers &propertyNames() const 295 { 296 return *m_propertyNames; 297 } 298 299 // Compatibility stuff: context()300 ExecState *context() 301 { 302 return this; 303 } callingContext()304 ExecState *callingContext() 305 { 306 return callingExecState(); 307 } 308 protected: 309 ExecState(Interpreter *intp, ExecState *save); 310 ~ExecState(); 311 void markSelf(); 312 313 Interpreter *m_interpreter; 314 Completion m_completion; 315 CommonIdentifiers *m_propertyNames; 316 ExecState *m_callingExec; 317 ExecState *m_savedExec; // in case of recursion of evaluation. Needed to mark things properly; 318 // note that this is disjoint from the above, since that's only used for 319 // eval/function, while this is for global. 320 321 FunctionBodyNode *m_currentBody; 322 FunctionImp *m_function; 323 324 ScopeChain scope; 325 JSObject *m_variable; 326 JSObject *m_thisVal; 327 328 LocalStorageEntry *m_localStore; 329 size_t m_localStoreSize; 330 331 struct ExceptionHandler { ExceptionHandlerExceptionHandler332 ExceptionHandler() {} ExceptionHandlerExceptionHandler333 ExceptionHandler(HandlerType type, Addr dest): 334 type(type), dest(dest) {} 335 336 HandlerType type; 337 Addr dest; 338 }; 339 340 const unsigned char *m_pcBase; // The address of pc = 0 341 const unsigned char **m_pc; // Where the current fetch address is stored 342 LocalStorageEntry **m_machineLocalStore; // Machine's copy of m_localStore 343 WTF::Vector<ExceptionHandler, 4> m_exceptionHandlers; 344 WTF::Vector<Completion, 4> m_deferredCompletions; 345 346 CodeType m_codeType; 347 }; 348 349 typedef ExecState Context; // Compatibility only 350 351 class GlobalExecState : public ExecState 352 { 353 public: 354 GlobalExecState(Interpreter *intp, JSGlobalObject *global); 355 }; 356 357 class InterpreterExecState : public ExecState 358 { 359 public: 360 InterpreterExecState(Interpreter *intp, JSGlobalObject *global, JSObject *thisObject, ProgramNode *); 361 }; 362 363 class EvalExecState : public ExecState 364 { 365 public: 366 EvalExecState(Interpreter *intp, JSGlobalObject *global, ProgramNode *body, ExecState *callingExecState); 367 }; 368 369 // Note: this does not push the activation on the scope chain, 370 // as the activation is not initialized at this point. 371 class FunctionExecState : public ExecState 372 { 373 public: 374 FunctionExecState(Interpreter *intp, JSObject *thisObject, 375 FunctionBodyNode *, ExecState *callingExecState, FunctionImp *); 376 }; 377 378 } // namespace KJS 379 380 #endif // ExecState_H 381