2 * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
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.
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.
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.
24 #include <wtf/FastAllocBase.h>
32 class ScopeChainIterator;
34 class ScopeChainNode {
35 WTF_MAKE_FAST_ALLOCATED;
37 ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
40 , globalData(globalData)
41 , globalObject(globalObject)
42 , globalThis(globalThis)
49 // Due to the number of subtle and timing dependent bugs that have occurred due
50 // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the
51 // contents in debug builds.
64 JSGlobalData* globalData;
65 JSGlobalObject* globalObject;
69 void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
70 void ref() { ASSERT(refCount); ++refCount; }
73 // Before calling "push" on a bare ScopeChainNode, a client should
74 // logically "copy" the node. Later, the client can "deref" the head
75 // of its chain of ScopeChainNodes to reclaim all the nodes it added
76 // after the logical copy, leaving nodes added before the logical copy
77 // (nodes shared with other clients) untouched.
78 ScopeChainNode* copy()
84 ScopeChainNode* push(JSObject*);
85 ScopeChainNode* pop();
87 ScopeChainIterator begin() const;
88 ScopeChainIterator end() const;
95 inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
98 return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
101 inline ScopeChainNode* ScopeChainNode::pop()
104 ScopeChainNode* result = next;
114 inline void ScopeChainNode::release()
116 // This function is only called by deref(),
117 // Deref ensures these conditions are true.
118 ASSERT(refCount == 0);
119 ScopeChainNode* n = this;
121 ScopeChainNode* next = n->next;
124 } while (n && --n->refCount == 0);
127 class ScopeChainIterator {
129 ScopeChainIterator(const ScopeChainNode* node)
134 JSObject* const & operator*() const { return m_node->object; }
135 JSObject* const * operator->() const { return &(operator*()); }
137 ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
139 // postfix ++ intentionally omitted
141 bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
142 bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
145 const ScopeChainNode* m_node;
148 inline ScopeChainIterator ScopeChainNode::begin() const
150 return ScopeChainIterator(this);
153 inline ScopeChainIterator ScopeChainNode::end() const
155 return ScopeChainIterator(0);
158 class NoScopeChain {};
163 ScopeChain(NoScopeChain)
168 ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
169 : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
173 ScopeChain(const ScopeChain& c)
174 : m_node(c.m_node->copy())
178 ScopeChain& operator=(const ScopeChain& c);
180 explicit ScopeChain(ScopeChainNode* node)
181 : m_node(node->copy())
194 void swap(ScopeChain&);
196 ScopeChainNode* node() const { return m_node; }
198 JSObject* top() const { return m_node->object; }
200 ScopeChainIterator begin() const { return m_node->begin(); }
201 ScopeChainIterator end() const { return m_node->end(); }
203 void push(JSObject* o) { m_node = m_node->push(o); }
205 void pop() { m_node = m_node->pop(); }
206 void clear() { m_node->deref(); m_node = 0; }
208 JSGlobalObject* globalObject() const { return m_node->globalObject; }
210 void markAggregate(MarkStack&) const;
212 // Caution: this should only be used if the codeblock this is being used
213 // with needs a full scope chain, otherwise this returns the depth of
214 // the preceeding call frame
216 // Returns the depth of the current call frame's scope chain
217 int localDepth() const;
220 void print() const { m_node->print(); }
224 ScopeChainNode* m_node;
227 inline void ScopeChain::swap(ScopeChain& o)
229 ScopeChainNode* tmp = m_node;
234 inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
243 #endif // ScopeChain_h