Home | History | Annotate | Download | only in interpreter
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      4  *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
      5  *
      6  *  This library is free software; you can redistribute it and/or
      7  *  modify it under the terms of the GNU Library General Public
      8  *  License as published by the Free Software Foundation; either
      9  *  version 2 of the License, or (at your option) any later version.
     10  *
     11  *  This library is distributed in the hope that it will be useful,
     12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  *  Library General Public License for more details.
     15  *
     16  *  You should have received a copy of the GNU Library General Public License
     17  *  along with this library; see the file COPYING.LIB.  If not, write to
     18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  *  Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #ifndef CallFrame_h
     24 #define CallFrame_h
     25 
     26 #include "JSGlobalData.h"
     27 #include "RegisterFile.h"
     28 #include "ScopeChain.h"
     29 
     30 namespace JSC  {
     31 
     32     class Arguments;
     33     class JSActivation;
     34     class Interpreter;
     35 
     36     // Represents the current state of script execution.
     37     // Passed as the first argument to most functions.
     38     class ExecState : private Register {
     39     public:
     40         JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
     41         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
     42         ScopeChainNode* scopeChain() const
     43         {
     44             ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain());
     45             return this[RegisterFile::ScopeChain].Register::scopeChain();
     46         }
     47         int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
     48 
     49         JSValue thisValue();
     50 
     51         // Global object in which execution began.
     52         JSGlobalObject* dynamicGlobalObject();
     53 
     54         // Global object in which the currently executing code was defined.
     55         // Differs from dynamicGlobalObject() during function calls across web browser frames.
     56         JSGlobalObject* lexicalGlobalObject() const
     57         {
     58             return scopeChain()->globalObject;
     59         }
     60 
     61         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
     62         // the actual DOM window, which can't be "this" for security reasons.
     63         JSObject* globalThisValue() const
     64         {
     65             return scopeChain()->globalThis;
     66         }
     67 
     68         // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
     69         // We should make this more uniform and either use a reference everywhere
     70         // or a pointer everywhere.
     71         JSGlobalData& globalData() const
     72         {
     73             ASSERT(scopeChain()->globalData);
     74             return *scopeChain()->globalData;
     75         }
     76 
     77         // Convenience functions for access to global data.
     78         // It takes a few memory references to get from a call frame to the global data
     79         // pointer, so these are inefficient, and should be used sparingly in new code.
     80         // But they're used in many places in legacy code, so they're not going away any time soon.
     81 
     82         void setException(JSValue exception) { globalData().exception = exception; }
     83         void clearException() { globalData().exception = JSValue(); }
     84         JSValue exception() const { return globalData().exception; }
     85         JSValue* exceptionSlot() { return &globalData().exception; }
     86         bool hadException() const { return globalData().exception; }
     87 
     88         const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
     89         const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; }
     90         Interpreter* interpreter() { return globalData().interpreter; }
     91         Heap* heap() { return &globalData().heap; }
     92 #ifndef NDEBUG
     93         void dumpCaller();
     94 #endif
     95         static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
     96         static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
     97         static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; }
     98         static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
     99         static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
    100         static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
    101         static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
    102         static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
    103 
    104         static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
    105         Register* registers() { return this; }
    106 
    107         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
    108 
    109         CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
    110         Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
    111         Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
    112 
    113         void setCalleeArguments(JSValue arguments) { static_cast<Register*>(this)[RegisterFile::OptionalCalleeArguments] = arguments; }
    114         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
    115         void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
    116 
    117         ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
    118             CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
    119         {
    120             ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
    121 
    122             setCodeBlock(codeBlock);
    123             setScopeChain(scopeChain);
    124             setCallerFrame(callerFrame);
    125             static_cast<Register*>(this)[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
    126             static_cast<Register*>(this)[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister);
    127             setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
    128             setCallee(function);
    129             setCalleeArguments(JSValue());
    130         }
    131 
    132         // Read a register from the codeframe (or constant from the CodeBlock).
    133         inline Register& r(int);
    134 
    135         static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
    136         int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
    137 
    138         bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
    139         CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
    140         CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
    141 
    142     private:
    143         void setArgumentCount(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
    144         void setCallee(JSFunction* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = callee; }
    145         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
    146 
    147         static const intptr_t HostCallFrameFlag = 1;
    148 
    149         ExecState();
    150         ~ExecState();
    151     };
    152 
    153 } // namespace JSC
    154 
    155 #endif // CallFrame_h
    156