JavaScriptCore/runtime/ScopeChain.h
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 "FastAllocBase.h"
       
    25 
       
    26 namespace JSC {
       
    27 
       
    28     class JSGlobalData;
       
    29     class JSGlobalObject;
       
    30     class JSObject;
       
    31     class MarkStack;
       
    32     class ScopeChainIterator;
       
    33     
       
    34     class ScopeChainNode : public FastAllocBase {
       
    35     public:
       
    36         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
       
    37             : next(next)
       
    38             , object(object)
       
    39             , globalData(globalData)
       
    40             , globalObject(globalObject)
       
    41             , globalThis(globalThis)
       
    42             , refCount(1)
       
    43         {
       
    44             ASSERT(globalData);
       
    45             ASSERT(globalObject);
       
    46         }
       
    47 #ifndef NDEBUG
       
    48         // Due to the number of subtle and timing dependent bugs that have occurred due
       
    49         // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the
       
    50         // contents in debug builds.
       
    51         ~ScopeChainNode()
       
    52         {
       
    53             next = 0;
       
    54             object = 0;
       
    55             globalData = 0;
       
    56             globalObject = 0;
       
    57             globalThis = 0;
       
    58         }
       
    59 #endif
       
    60 
       
    61         ScopeChainNode* next;
       
    62         JSObject* object;
       
    63         JSGlobalData* globalData;
       
    64         JSGlobalObject* globalObject;
       
    65         JSObject* globalThis;
       
    66         int refCount;
       
    67 
       
    68         void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
       
    69         void ref() { ASSERT(refCount); ++refCount; }
       
    70         void release();
       
    71 
       
    72         // Before calling "push" on a bare ScopeChainNode, a client should
       
    73         // logically "copy" the node. Later, the client can "deref" the head
       
    74         // of its chain of ScopeChainNodes to reclaim all the nodes it added
       
    75         // after the logical copy, leaving nodes added before the logical copy
       
    76         // (nodes shared with other clients) untouched.
       
    77         ScopeChainNode* copy()
       
    78         {
       
    79             ref();
       
    80             return this;
       
    81         }
       
    82 
       
    83         ScopeChainNode* push(JSObject*);
       
    84         ScopeChainNode* pop();
       
    85 
       
    86         ScopeChainIterator begin() const;
       
    87         ScopeChainIterator end() const;
       
    88 
       
    89 #ifndef NDEBUG        
       
    90         void print() const;
       
    91 #endif
       
    92     };
       
    93 
       
    94     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
       
    95     {
       
    96         ASSERT(o);
       
    97         return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
       
    98     }
       
    99 
       
   100     inline ScopeChainNode* ScopeChainNode::pop()
       
   101     {
       
   102         ASSERT(next);
       
   103         ScopeChainNode* result = next;
       
   104 
       
   105         if (--refCount != 0)
       
   106             ++result->refCount;
       
   107         else
       
   108             delete this;
       
   109 
       
   110         return result;
       
   111     }
       
   112 
       
   113     inline void ScopeChainNode::release()
       
   114     {
       
   115         // This function is only called by deref(),
       
   116         // Deref ensures these conditions are true.
       
   117         ASSERT(refCount == 0);
       
   118         ScopeChainNode* n = this;
       
   119         do {
       
   120             ScopeChainNode* next = n->next;
       
   121             delete n;
       
   122             n = next;
       
   123         } while (n && --n->refCount == 0);
       
   124     }
       
   125 
       
   126     class ScopeChainIterator {
       
   127     public:
       
   128         ScopeChainIterator(const ScopeChainNode* node)
       
   129             : m_node(node)
       
   130         {
       
   131         }
       
   132 
       
   133         JSObject* const & operator*() const { return m_node->object; }
       
   134         JSObject* const * operator->() const { return &(operator*()); }
       
   135     
       
   136         ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
       
   137 
       
   138         // postfix ++ intentionally omitted
       
   139 
       
   140         bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
       
   141         bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
       
   142 
       
   143     private:
       
   144         const ScopeChainNode* m_node;
       
   145     };
       
   146 
       
   147     inline ScopeChainIterator ScopeChainNode::begin() const
       
   148     {
       
   149         return ScopeChainIterator(this); 
       
   150     }
       
   151 
       
   152     inline ScopeChainIterator ScopeChainNode::end() const
       
   153     { 
       
   154         return ScopeChainIterator(0); 
       
   155     }
       
   156 
       
   157     class NoScopeChain {};
       
   158 
       
   159     class ScopeChain {
       
   160         friend class JIT;
       
   161     public:
       
   162         ScopeChain(NoScopeChain)
       
   163             : m_node(0)
       
   164         {
       
   165         }
       
   166 
       
   167         ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
       
   168             : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
       
   169         {
       
   170         }
       
   171 
       
   172         ScopeChain(const ScopeChain& c)
       
   173             : m_node(c.m_node->copy())
       
   174         {
       
   175         }
       
   176 
       
   177         ScopeChain& operator=(const ScopeChain& c);
       
   178 
       
   179         explicit ScopeChain(ScopeChainNode* node)
       
   180             : m_node(node->copy())
       
   181         {
       
   182         }
       
   183 
       
   184         ~ScopeChain()
       
   185         {
       
   186             if (m_node)
       
   187                 m_node->deref();
       
   188 #ifndef NDEBUG
       
   189             m_node = 0;
       
   190 #endif
       
   191         }
       
   192 
       
   193         void swap(ScopeChain&);
       
   194 
       
   195         ScopeChainNode* node() const { return m_node; }
       
   196 
       
   197         JSObject* top() const { return m_node->object; }
       
   198 
       
   199         ScopeChainIterator begin() const { return m_node->begin(); }
       
   200         ScopeChainIterator end() const { return m_node->end(); }
       
   201 
       
   202         void push(JSObject* o) { m_node = m_node->push(o); }
       
   203 
       
   204         void pop() { m_node = m_node->pop(); }
       
   205         void clear() { m_node->deref(); m_node = 0; }
       
   206         
       
   207         JSGlobalObject* globalObject() const { return m_node->globalObject; }
       
   208 
       
   209         void markAggregate(MarkStack&) const;
       
   210 
       
   211         // Caution: this should only be used if the codeblock this is being used
       
   212         // with needs a full scope chain, otherwise this returns the depth of
       
   213         // the preceeding call frame
       
   214         //
       
   215         // Returns the depth of the current call frame's scope chain
       
   216         int localDepth() const;
       
   217 
       
   218 #ifndef NDEBUG        
       
   219         void print() const { m_node->print(); }
       
   220 #endif
       
   221 
       
   222     private:
       
   223         ScopeChainNode* m_node;
       
   224     };
       
   225 
       
   226     inline void ScopeChain::swap(ScopeChain& o)
       
   227     {
       
   228         ScopeChainNode* tmp = m_node;
       
   229         m_node = o.m_node;
       
   230         o.m_node = tmp;
       
   231     }
       
   232 
       
   233     inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
       
   234     {
       
   235         ScopeChain tmp(c);
       
   236         swap(tmp);
       
   237         return *this;
       
   238     }
       
   239 
       
   240 } // namespace JSC
       
   241 
       
   242 #endif // ScopeChain_h