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