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

Last change on this file since 43424 was 43347, checked in by Darin Adler, 16 years ago

2009-05-07 Darin Adler <Darin Adler>

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