Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
      3  *
      4  *  This library is free software; you can redistribute it and/or
      5  *  modify it under the terms of the GNU Library General Public
      6  *  License as published by the Free Software Foundation; either
      7  *  version 2 of the License, or (at your option) any later version.
      8  *
      9  *  This library is distributed in the hope that it will be useful,
     10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  *  Library General Public License for more details.
     13  *
     14  *  You should have received a copy of the GNU Library General Public License
     15  *  along with this library; see the file COPYING.LIB.  If not, write to
     16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  *  Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef ScopeChain_h
     22 #define ScopeChain_h
     23 
     24 #include "JSCell.h"
     25 #include "Structure.h"
     26 #include <wtf/FastAllocBase.h>
     27 
     28 namespace JSC {
     29 
     30     class JSGlobalData;
     31     class JSGlobalObject;
     32     class JSObject;
     33     class MarkStack;
     34     class ScopeChainIterator;
     35 
     36     class ScopeChainNode : public JSCell {
     37     public:
     38         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
     39             : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
     40             , globalData(globalData)
     41             , next(*globalData, this, next)
     42             , object(*globalData, this, object)
     43             , globalObject(*globalData, this, globalObject)
     44             , globalThis(*globalData, this, globalThis)
     45         {
     46             ASSERT(globalData);
     47             ASSERT(globalObject);
     48         }
     49 
     50         JSGlobalData* globalData;
     51         WriteBarrier<ScopeChainNode> next;
     52         WriteBarrier<JSObject> object;
     53         WriteBarrier<JSGlobalObject> globalObject;
     54         WriteBarrier<JSObject> globalThis;
     55 
     56         ScopeChainNode* push(JSObject*);
     57         ScopeChainNode* pop();
     58 
     59         ScopeChainIterator begin();
     60         ScopeChainIterator end();
     61 
     62         int localDepth();
     63 
     64 #ifndef NDEBUG
     65         void print();
     66 #endif
     67 
     68         static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
     69         virtual void markChildren(MarkStack&);
     70     private:
     71         static const unsigned StructureFlags = OverridesMarkChildren;
     72         static const ClassInfo s_info;
     73     };
     74 
     75     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     76     {
     77         ASSERT(o);
     78         return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get());
     79     }
     80 
     81     inline ScopeChainNode* ScopeChainNode::pop()
     82     {
     83         ASSERT(next);
     84         return next.get();
     85     }
     86 
     87     class ScopeChainIterator {
     88     public:
     89         ScopeChainIterator(ScopeChainNode* node)
     90             : m_node(node)
     91         {
     92         }
     93 
     94         WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
     95         WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
     96 
     97         ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
     98 
     99         // postfix ++ intentionally omitted
    100 
    101         bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
    102         bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
    103 
    104     private:
    105         ScopeChainNode* m_node;
    106     };
    107 
    108     inline ScopeChainIterator ScopeChainNode::begin()
    109     {
    110         return ScopeChainIterator(this);
    111     }
    112 
    113     inline ScopeChainIterator ScopeChainNode::end()
    114     {
    115         return ScopeChainIterator(0);
    116     }
    117 
    118     ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
    119     {
    120         ASSERT(scopeChain()->globalData);
    121         return *scopeChain()->globalData;
    122     }
    123 
    124     ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
    125     {
    126         return scopeChain()->globalObject.get();
    127     }
    128 
    129     ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
    130     {
    131         return scopeChain()->globalThis.get();
    132     }
    133 
    134     ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
    135     {
    136         return static_cast<ScopeChainNode*>(jsValue().asCell());
    137     }
    138 
    139     ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
    140     {
    141         *this = JSValue(scopeChain);
    142         return *this;
    143     }
    144 
    145 } // namespace JSC
    146 
    147 #endif // ScopeChain_h
    148