source: webkit/trunk/JavaScriptCore/runtime/ScopeChain.h@ 47025

Last change on this file since 47025 was 47025, checked in by [email protected], 16 years ago

Add includes needed for non-allinonefile builds

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