ScopeChain.h 5.51 KB
Newer Older
darin's avatar
darin committed
1
/*
2
 *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
darin's avatar
darin committed
3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
mjs's avatar
mjs committed
16
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 *  Boston, MA 02110-1301, USA.
darin's avatar
darin committed
18 19 20
 *
 */

21 22
#ifndef ScopeChain_h
#define ScopeChain_h
darin's avatar
darin committed
23

24
#include "JSCell.h"
25
#include "Structure.h"
26
#include <wtf/FastAllocBase.h>
eseidel's avatar
eseidel committed
27

28
namespace JSC {
darin's avatar
darin committed
29

30
    class JSGlobalData;
31
    class JSGlobalObject;
darin's avatar
darin committed
32
    class JSObject;
33
    class ScopeChainIterator;
34
    class SlotVisitor;
darin's avatar
darin committed
35
    
36
    class ScopeChainNode : public JSCell {
37
    private:
38
        ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
39
            : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
darin@apple.com's avatar
darin@apple.com committed
40
            , globalData(globalData)
41
            , next(*globalData, this, next, WriteBarrier<ScopeChainNode>::MayBeNull)
42 43 44
            , object(*globalData, this, object)
            , globalObject(*globalData, this, globalObject)
            , globalThis(*globalData, this, globalThis)
45
        {
46 47 48 49 50 51
        }

    protected:
        void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
        {
            Base::finishCreation(*globalData);
52
            ASSERT_UNUSED(globalObject, globalObject);
53
        }
darin's avatar
darin committed
54

55
    public:
56 57
        typedef JSCell Base;

58 59
        static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
        {
60 61 62
            ScopeChainNode* node = new (allocateCell<ScopeChainNode>(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis);
            node->finishCreation(globalData, globalObject);
            return node;
63 64 65
        }
        static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
        {
66 67 68
            ScopeChainNode* node = new (allocateCell<ScopeChainNode>(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis);
            node->finishCreation(globalData, globalObject);
            return node;
69 70
        }
        
darin@apple.com's avatar
darin@apple.com committed
71
        JSGlobalData* globalData;
72 73 74 75
        WriteBarrier<ScopeChainNode> next;
        WriteBarrier<JSObject> object;
        WriteBarrier<JSGlobalObject> globalObject;
        WriteBarrier<JSObject> globalThis;
76 77 78 79

        ScopeChainNode* push(JSObject*);
        ScopeChainNode* pop();

80 81 82 83
        ScopeChainIterator begin();
        ScopeChainIterator end();

        int localDepth();
weinig@apple.com's avatar
weinig@apple.com committed
84

85
#ifndef NDEBUG        
86
        void print();
87
#endif
88
        
89
        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
90
        virtual void visitChildren(SlotVisitor&);
91 92
        static JS_EXPORTDATA const ClassInfo s_info;

93
    private:
94
        static const unsigned StructureFlags = OverridesVisitChildren;
darin's avatar
darin committed
95
    };
darin's avatar
darin committed
96

97 98 99
    inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
    {
        ASSERT(o);
100
        return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get());
101 102 103 104 105
    }

    inline ScopeChainNode* ScopeChainNode::pop()
    {
        ASSERT(next);
106
        return next.get();
107 108
    }

mjs's avatar
mjs committed
109 110
    class ScopeChainIterator {
    public:
111
        ScopeChainIterator(ScopeChainNode* node)
112 113 114
            : m_node(node)
        {
        }
mjs's avatar
mjs committed
115

116 117
        WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
        WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
mjs's avatar
mjs committed
118
    
119
        ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
mjs's avatar
mjs committed
120 121 122 123 124 125 126

        // postfix ++ intentionally omitted

        bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
        bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }

    private:
127
        ScopeChainNode* m_node;
mjs's avatar
mjs committed
128 129
    };

130
    inline ScopeChainIterator ScopeChainNode::begin()
131 132 133 134
    {
        return ScopeChainIterator(this); 
    }

135
    inline ScopeChainIterator ScopeChainNode::end()
136 137 138 139
    { 
        return ScopeChainIterator(0); 
    }

140
    ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
141
    {
142 143
        ASSERT(scopeChain()->globalData);
        return *scopeChain()->globalData;
eseidel's avatar
eseidel committed
144 145
    }

146 147 148 149 150 151
    ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
    {
        return scopeChain()->globalObject.get();
    }
    
    ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
152
    {
153
        return scopeChain()->globalThis.get();
154
    }
155 156 157 158 159 160 161 162 163 164 165
    
    ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
    {
        return static_cast<ScopeChainNode*>(jsValue().asCell());
    }
    
    ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
    {
        *this = JSValue(scopeChain);
        return *this;
    }
166

167
} // namespace JSC
darin's avatar
darin committed
168

169
#endif // ScopeChain_h