]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/ScopeChain.h
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / runtime / ScopeChain.h
index 32b5e9235cd358cc8fe2657b02c6dbd6ac1b1711..c382008f11587428e96ac8790642756a6072bb74 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #ifndef ScopeChain_h
 #define ScopeChain_h
 
-#include <wtf/Assertions.h>
+#include "JSCell.h"
+#include "Structure.h"
+#include <wtf/FastAllocBase.h>
 
 namespace JSC {
 
     class JSGlobalData;
     class JSGlobalObject;
     class JSObject;
+    class LLIntOffsetsExtractor;
     class ScopeChainIterator;
+    class SlotVisitor;
     
-    class ScopeChainNode {
-    public:
-        ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
-            : next(next)
-            , object(object)
+    class ScopeChainNode : public JSCell {
+    private:
+        ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+            : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
-            , globalThis(globalThis)
-            , refCount(1)
+            , next(*globalData, this, next, WriteBarrier<ScopeChainNode>::MayBeNull)
+            , object(*globalData, this, object)
+            , globalObject(*globalData, this, globalObject)
+            , globalThis(*globalData, this, globalThis)
         {
-            ASSERT(globalData);
         }
 
-        ScopeChainNode* next;
-        JSObject* object;
-        JSGlobalData* globalData;
-        JSObject* globalThis;
-        int refCount;
-
-        void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
-        void ref() { ASSERT(refCount); ++refCount; }
-        void release();
-
-        // Before calling "push" on a bare ScopeChainNode, a client should
-        // logically "copy" the node. Later, the client can "deref" the head
-        // of its chain of ScopeChainNodes to reclaim all the nodes it added
-        // after the logical copy, leaving nodes added before the logical copy
-        // (nodes shared with other clients) untouched.
-        ScopeChainNode* copy()
+    protected:
+        void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
         {
-            ref();
-            return this;
+            Base::finishCreation(*globalData);
+            ASSERT_UNUSED(globalObject, globalObject);
         }
 
+    public:
+        typedef JSCell Base;
+
+        static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+        {
+            ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis);
+            node->finishCreation(globalData, globalObject);
+            return node;
+        }
+        static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+        {
+            ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis);
+            node->finishCreation(globalData, globalObject);
+            return node;
+        }
+        
+        JSGlobalData* globalData;
+        WriteBarrier<ScopeChainNode> next;
+        WriteBarrier<JSObject> object;
+        WriteBarrier<JSGlobalObject> globalObject;
+        WriteBarrier<JSObject> globalThis;
+
         ScopeChainNode* push(JSObject*);
         ScopeChainNode* pop();
 
-        ScopeChainIterator begin() const;
-        ScopeChainIterator end() const;
+        ScopeChainIterator begin();
+        ScopeChainIterator end();
 
-        JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
-        JSObject* globalThisObject() const { return globalThis; }
+        int localDepth();
 
 #ifndef NDEBUG        
-        void print() const;
+        void print();
 #endif
+        
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
+        static void visitChildren(JSCell*, SlotVisitor&);
+        static JS_EXPORTDATA const ClassInfo s_info;
+
+    private:
+        friend class LLIntOffsetsExtractor;
+        
+        static const unsigned StructureFlags = OverridesVisitChildren;
     };
 
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
-        return new ScopeChainNode(this, o, globalData, globalThis);
+        return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get());
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
     {
         ASSERT(next);
-        ScopeChainNode* result = next;
-
-        if (--refCount != 0)
-            ++result->refCount;
-        else
-            delete this;
-
-        return result;
-    }
-
-    inline void ScopeChainNode::release()
-    {
-        // This function is only called by deref(),
-        // Deref ensures these conditions are true.
-        ASSERT(refCount == 0);
-        ScopeChainNode* n = this;
-        do {
-            ScopeChainNode* next = n->next;
-            delete n;
-            n = next;
-        } while (n && --n->refCount == 0);
+        return next.get();
     }
 
     class ScopeChainIterator {
     public:
-        ScopeChainIterator(const ScopeChainNode* node)
+        ScopeChainIterator(ScopeChainNode* node)
             : m_node(node)
         {
         }
 
-        JSObject* const & operator*() const { return m_node->object; }
-        JSObject* const * operator->() const { return &(operator*()); }
+        WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
+        WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
     
-        ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
+        ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
 
         // postfix ++ intentionally omitted
 
@@ -127,96 +127,43 @@ namespace JSC {
         bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
 
     private:
-        const ScopeChainNode* m_node;
+        ScopeChainNode* m_node;
     };
 
-    inline ScopeChainIterator ScopeChainNode::begin() const
+    inline ScopeChainIterator ScopeChainNode::begin()
     {
         return ScopeChainIterator(this); 
     }
 
-    inline ScopeChainIterator ScopeChainNode::end() const
+    inline ScopeChainIterator ScopeChainNode::end()
     { 
         return ScopeChainIterator(0); 
     }
 
-    class NoScopeChain {};
-
-    class ScopeChain {
-        friend class JIT;
-    public:
-        ScopeChain(NoScopeChain)
-            : m_node(0)
-        {
-        }
-
-        ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis)
-            : m_node(new ScopeChainNode(0, o, globalData, globalThis))
-        {
-        }
-
-        ScopeChain(const ScopeChain& c)
-            : m_node(c.m_node->copy())
-        {
-        }
-
-        ScopeChain& operator=(const ScopeChain& c);
-
-        explicit ScopeChain(ScopeChainNode* node)
-            : m_node(node->copy())
-        {
-        }
-
-        ~ScopeChain()
-        {
-            if (m_node)
-                m_node->deref();
-        }
-
-        void swap(ScopeChain&);
-
-        ScopeChainNode* node() const { return m_node; }
-
-        JSObject* top() const { return m_node->object; }
-
-        ScopeChainIterator begin() const { return m_node->begin(); }
-        ScopeChainIterator end() const { return m_node->end(); }
-
-        void push(JSObject* o) { m_node = m_node->push(o); }
-
-        void pop() { m_node = m_node->pop(); }
-        void clear() { m_node->deref(); m_node = 0; }
-        
-        JSGlobalObject* globalObject() const { return m_node->globalObject(); }
-
-        void mark() const;
-
-        // Caution: this should only be used if the codeblock this is being used
-        // with needs a full scope chain, otherwise this returns the depth of
-        // the preceeding call frame
-        //
-        // Returns the depth of the current call frame's scope chain
-        int localDepth() const;
-
-#ifndef NDEBUG        
-        void print() const { m_node->print(); }
-#endif
-
-    private:
-        ScopeChainNode* m_node;
-    };
-
-    inline void ScopeChain::swap(ScopeChain& o)
+    ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
     {
-        ScopeChainNode* tmp = m_node;
-        m_node = o.m_node;
-        o.m_node = tmp;
+        ASSERT(scopeChain()->globalData);
+        return *scopeChain()->globalData;
     }
 
-    inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+    ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
+    {
+        return scopeChain()->globalObject.get();
+    }
+    
+    ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
+    {
+        return scopeChain()->globalThis.get();
+    }
+    
+    ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
+    {
+        return static_cast<ScopeChainNode*>(jsValue().asCell());
+    }
+    
+    ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
     {
-        ScopeChain tmp(c);
-        swap(tmp);
+        *this = JSValue(scopeChain);
         return *this;
     }