File indexing completed on 2024-05-12 15:43:20
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 0005 * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. 0006 * Copyright (C) 2008 Maksim Orlovich (maksim@kde.org) 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this library; see the file COPYING.LIB. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 * 0023 */ 0024 0025 #ifndef ExecState_H 0026 #define ExecState_H 0027 0028 #include "completion.h" 0029 #include "value.h" 0030 #include "types.h" 0031 #include "CommonIdentifiers.h" 0032 #include "scope_chain.h" 0033 #include "LocalStorage.h" 0034 #include "wtf/Vector.h" 0035 #include "PropertyNameArray.h" 0036 0037 namespace KJS 0038 { 0039 class ActivationImp; 0040 class Interpreter; 0041 class FunctionImp; 0042 class FunctionBodyNode; 0043 class ProgramNode; 0044 class JSGlobalObject; 0045 0046 enum CodeType { GlobalCode, EvalCode, FunctionCode }; 0047 0048 /** 0049 * Represents the current state of script execution. This object allows you 0050 * obtain a handle the interpreter that is currently executing the script, 0051 * and also the current execution context. 0052 */ 0053 class KJS_EXPORT ExecState : Noncopyable 0054 { 0055 friend class Interpreter; 0056 friend class FunctionImp; 0057 friend class GlobalFuncImp; 0058 public: 0059 /** 0060 * Returns the interpreter associated with this execution state 0061 * 0062 * @return The interpreter executing the script 0063 */ 0064 Interpreter *dynamicInterpreter() const 0065 { 0066 return m_interpreter; 0067 } 0068 0069 /** 0070 * Returns the interpreter associated with the current scope's 0071 * global object 0072 * 0073 * @return The interpreter currently in scope 0074 */ 0075 Interpreter *lexicalInterpreter() const; 0076 0077 /** 0078 * This describes how an exception should be handled 0079 */ 0080 enum HandlerType { 0081 JumpToCatch, ///< jump to the specified address 0082 PopScope, ///< remove a scope chain entry, and run the next handler 0083 RemoveDeferred, ///< remove any deferred exception object, and run the next entry 0084 Silent ///< just update the exception object. For debugger-type use only 0085 }; 0086 0087 void pushExceptionHandler(HandlerType type, Addr addr = 0); 0088 0089 void popExceptionHandler(); 0090 0091 // Cleanup depth entries from the stack, w/o running jumps 0092 void quietUnwind(int depth); 0093 0094 void setMachineRegisters(const unsigned char *pcBase, const unsigned char **pcLoc, LocalStorageEntry **machineLocalStoreLoc) 0095 { 0096 m_pcBase = pcBase; 0097 m_pc = pcLoc; 0098 m_machineLocalStore = machineLocalStoreLoc; 0099 } 0100 0101 /** 0102 The below methods deal with deferring of completions inside finally clauses. 0103 Essentially, we clear any set exceptions and memorize any non-normal completion 0104 (including the target addresses for the continue/break statements) on 0105 the m_deferredCompletions stack. If the 'finally' finishes normally, 0106 we will resume the previous completion. If not, finally's abnormal 0107 termination is handled as usually; a RemoveDeferred cleanup stack 0108 entry is added to unwind m_deferredCompletions if that happens. 0109 */ 0110 0111 void deferCompletion() 0112 { 0113 pushExceptionHandler(RemoveDeferred); 0114 m_deferredCompletions.append(abruptCompletion()); 0115 clearException(); 0116 } 0117 0118 /** 0119 This resumes dispatch of a completion that was deferred due to a try ... finally, 0120 handling it as appropriate for whether it's inside an another try-finally. 0121 This will handle all the cases itself except for one: return, 0122 for which it will return the value to return (otherwise returning 0) 0123 */ 0124 JSValue *reactivateCompletion(bool insideTryFinally); 0125 0126 /** 0127 * Set the exception associated with this execution state, 0128 * updating the program counter appropriately, and executing any relevant EH cleanups. 0129 * @param e The JSValue of the exception being set 0130 */ 0131 void setException(JSValue *e); 0132 0133 /** 0134 * Records an abrupt completion of code, and jumps to the closest catch or finally. 0135 * This always happens for exceptions, but can also happen for continue/break/return when 0136 * they're inside try ... finally, since that case gets routed through the EH machinery. 0137 */ 0138 void setAbruptCompletion(Completion comp); 0139 0140 /** 0141 * Clears the exception or other abnormal completion set on this execution state. 0142 */ 0143 void clearException() 0144 { 0145 m_completion = Completion(); 0146 } 0147 0148 /** 0149 * Returns the exception associated with this execution state. 0150 * @return The current execution state exception 0151 */ 0152 JSValue *exception() const 0153 { 0154 return m_completion.complType() == Throw ? m_completion.value() : nullptr; 0155 } 0156 0157 /** 0158 * Use this to check if an exception was thrown in the current 0159 * execution state. 0160 * 0161 * @return Whether an exception was thrown 0162 */ 0163 bool hadException() const 0164 { 0165 return m_completion.complType() == Throw; 0166 } 0167 0168 Completion abruptCompletion() const 0169 { 0170 return m_completion; 0171 } 0172 0173 /** 0174 * Returns the scope chain for this execution context. This is used for 0175 * variable lookup, with the list being searched from start to end until a 0176 * variable is found. 0177 * 0178 * @return The execution context's scope chain 0179 */ 0180 const ScopeChain &scopeChain() const 0181 { 0182 return scope; 0183 } 0184 0185 /** 0186 * Returns the variable object for the execution context. This contains a 0187 * property for each variable declared in the execution context. 0188 * 0189 * @return The execution context's variable object 0190 */ 0191 JSObject *variableObject() const 0192 { 0193 return m_variable; 0194 } 0195 void setVariableObject(JSObject *v) 0196 { 0197 m_variable = v; 0198 } 0199 0200 /** 0201 * Returns the "this" value for the execution context. This is the value 0202 * returned when a script references the special variable "this". It should 0203 * always be an Object, unless application-specific code has passed in a 0204 * different type. 0205 * 0206 * The object that is used as the "this" value depends on the type of 0207 * execution context - for global contexts, the global object is used. For 0208 * function objewcts, the value is given by the caller (e.g. in the case of 0209 * obj.func(), obj would be the "this" value). For code executed by the 0210 * built-in "eval" function, the this value is the same as the calling 0211 * context. 0212 * 0213 * @return The execution context's "this" value 0214 */ 0215 JSObject *thisValue() const 0216 { 0217 return m_thisVal; 0218 } 0219 0220 /** 0221 * Returns the context from which the current context was invoked. For 0222 * global code this will be a null context (i.e. one for which 0223 * isNull() returns true). You should check isNull() on the returned 0224 * value before calling any of its methods. 0225 * 0226 * @return The calling execution context 0227 */ 0228 ExecState *callingExecState() 0229 { 0230 return m_callingExec; 0231 } 0232 0233 /** 0234 * Returns the execState of a previous nested evaluation session, if any. 0235 */ 0236 ExecState *savedExecState() 0237 { 0238 return m_savedExec; 0239 } 0240 0241 JSObject *activationObject() 0242 { 0243 assert(m_codeType == FunctionCode); 0244 return m_variable; 0245 } 0246 0247 CodeType codeType() 0248 { 0249 return m_codeType; 0250 } 0251 FunctionBodyNode *currentBody() 0252 { 0253 return m_currentBody; 0254 } 0255 FunctionImp *function() const 0256 { 0257 return m_function; 0258 } 0259 0260 void pushVariableObjectScope(JSVariableObject *s) 0261 { 0262 scope.pushVariableObject(s); 0263 } 0264 void pushScope(JSObject *s) 0265 { 0266 scope.push(s); 0267 } 0268 void popScope() 0269 { 0270 scope.pop(); 0271 } 0272 0273 void mark(); 0274 0275 void initLocalStorage(LocalStorageEntry *store, size_t size) 0276 { 0277 m_localStore = store; 0278 m_localStoreSize = size; 0279 } 0280 0281 void updateLocalStorage(LocalStorageEntry *newStore) 0282 { 0283 m_localStore = newStore; 0284 *m_machineLocalStore = newStore; 0285 } 0286 0287 LocalStorageEntry *localStorage() 0288 { 0289 return m_localStore; 0290 } 0291 0292 // This is a workaround to avoid accessing the global variables for these identifiers in 0293 // important property lookup functions, to avoid taking PIC branches in Mach-O binaries 0294 const CommonIdentifiers &propertyNames() const 0295 { 0296 return *m_propertyNames; 0297 } 0298 0299 // Compatibility stuff: 0300 ExecState *context() 0301 { 0302 return this; 0303 } 0304 ExecState *callingContext() 0305 { 0306 return callingExecState(); 0307 } 0308 protected: 0309 ExecState(Interpreter *intp, ExecState *save); 0310 ~ExecState(); 0311 void markSelf(); 0312 0313 Interpreter *m_interpreter; 0314 Completion m_completion; 0315 CommonIdentifiers *m_propertyNames; 0316 ExecState *m_callingExec; 0317 ExecState *m_savedExec; // in case of recursion of evaluation. Needed to mark things properly; 0318 // note that this is disjoint from the above, since that's only used for 0319 // eval/function, while this is for global. 0320 0321 FunctionBodyNode *m_currentBody; 0322 FunctionImp *m_function; 0323 0324 ScopeChain scope; 0325 JSObject *m_variable; 0326 JSObject *m_thisVal; 0327 0328 LocalStorageEntry *m_localStore; 0329 size_t m_localStoreSize; 0330 0331 struct ExceptionHandler { 0332 ExceptionHandler() {} 0333 ExceptionHandler(HandlerType type, Addr dest): 0334 type(type), dest(dest) {} 0335 0336 HandlerType type; 0337 Addr dest; 0338 }; 0339 0340 const unsigned char *m_pcBase; // The address of pc = 0 0341 const unsigned char **m_pc; // Where the current fetch address is stored 0342 LocalStorageEntry **m_machineLocalStore; // Machine's copy of m_localStore 0343 WTF::Vector<ExceptionHandler, 4> m_exceptionHandlers; 0344 WTF::Vector<Completion, 4> m_deferredCompletions; 0345 0346 CodeType m_codeType; 0347 }; 0348 0349 typedef ExecState Context; // Compatibility only 0350 0351 class GlobalExecState : public ExecState 0352 { 0353 public: 0354 GlobalExecState(Interpreter *intp, JSGlobalObject *global); 0355 }; 0356 0357 class InterpreterExecState : public ExecState 0358 { 0359 public: 0360 InterpreterExecState(Interpreter *intp, JSGlobalObject *global, JSObject *thisObject, ProgramNode *); 0361 }; 0362 0363 class EvalExecState : public ExecState 0364 { 0365 public: 0366 EvalExecState(Interpreter *intp, JSGlobalObject *global, ProgramNode *body, ExecState *callingExecState); 0367 }; 0368 0369 // Note: this does not push the activation on the scope chain, 0370 // as the activation is not initialized at this point. 0371 class FunctionExecState : public ExecState 0372 { 0373 public: 0374 FunctionExecState(Interpreter *intp, JSObject *thisObject, 0375 FunctionBodyNode *, ExecState *callingExecState, FunctionImp *); 0376 }; 0377 0378 } // namespace KJS 0379 0380 #endif // ExecState_H