Changeset 79904 in webkit for trunk/Source/JavaScriptCore/runtime/ScopeChain.h
- Timestamp:
- Feb 28, 2011, 1:05:22 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/ScopeChain.h
r77151 r79904 22 22 #define ScopeChain_h 23 23 24 #include " WriteBarrier.h"24 #include "JSCell.h" 25 25 #include <wtf/FastAllocBase.h> 26 26 … … 33 33 class ScopeChainIterator; 34 34 35 class ScopeChainNode { 36 WTF_MAKE_FAST_ALLOCATED; 35 class ScopeChainNode : public JSCell { 37 36 public: 38 37 ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) 39 : next(next) 40 , object(object) 38 : JSCell(globalData->scopeChainNodeStructure.get()) 41 39 , globalData(globalData) 42 , globalObject(globalObject) 43 , globalThis(globalThis) 44 , refCount(1) 40 , next(*globalData, this, next) 41 , object(*globalData, this, object) 42 , globalObject(*globalData, this, globalObject) 43 , globalThis(*globalData, this, globalThis) 45 44 { 46 45 ASSERT(globalData); 47 46 ASSERT(globalObject); 48 47 } 49 #ifndef NDEBUG50 // Due to the number of subtle and timing dependent bugs that have occurred due51 // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the52 // contents in debug builds.53 ~ScopeChainNode()54 {55 next = 0;56 globalData = 0;57 globalObject = 0;58 globalThis = 0;59 }60 #endif61 48 62 ScopeChainNode* next;63 DeprecatedPtr<JSObject> object;64 49 JSGlobalData* globalData; 65 JSGlobalObject* globalObject; 66 JSObject* globalThis; 67 int refCount; 68 69 void deref() { ASSERT(refCount); if (--refCount == 0) { release();} } 70 void ref() { ASSERT(refCount); ++refCount; } 71 void release(); 72 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() 79 { 80 ref(); 81 return this; 82 } 50 WriteBarrier<ScopeChainNode> next; 51 WriteBarrier<JSObject> object; 52 WriteBarrier<JSGlobalObject> globalObject; 53 WriteBarrier<JSObject> globalThis; 83 54 84 55 ScopeChainNode* push(JSObject*); 85 56 ScopeChainNode* pop(); 86 57 87 ScopeChainIterator begin() const; 88 ScopeChainIterator end() const; 58 ScopeChainIterator begin(); 59 ScopeChainIterator end(); 60 61 int localDepth(); 89 62 90 63 #ifndef NDEBUG 91 void print() const;64 void print(); 92 65 #endif 66 67 static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } 68 virtual void markChildren(MarkStack&); 69 private: 70 static const unsigned StructureFlags = OverridesMarkChildren; 93 71 }; 94 72 … … 96 74 { 97 75 ASSERT(o); 98 return new ScopeChainNode(this, o, globalData, globalObject, globalThis);76 return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get()); 99 77 } 100 78 … … 102 80 { 103 81 ASSERT(next); 104 ScopeChainNode* result = next; 105 106 if (--refCount != 0) 107 ++result->refCount; 108 else 109 delete this; 110 111 return result; 112 } 113 114 inline void ScopeChainNode::release() 115 { 116 // This function is only called by deref(), 117 // Deref ensures these conditions are true. 118 ASSERT(refCount == 0); 119 ScopeChainNode* n = this; 120 do { 121 ScopeChainNode* next = n->next; 122 delete n; 123 n = next; 124 } while (n && --n->refCount == 0); 82 return next.get(); 125 83 } 126 84 127 85 class ScopeChainIterator { 128 86 public: 129 ScopeChainIterator( constScopeChainNode* node)87 ScopeChainIterator(ScopeChainNode* node) 130 88 : m_node(node) 131 89 { 132 90 } 133 91 134 DeprecatedPtr<JSObject> const & operator*() const { return m_node->object; }135 DeprecatedPtr<JSObject> const * operator->() const { return &(operator*()); }92 WriteBarrier<JSObject> const & operator*() const { return m_node->object; } 93 WriteBarrier<JSObject> const * operator->() const { return &(operator*()); } 136 94 137 ScopeChainIterator& operator++() { m_node = m_node->next ; return *this; }95 ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; } 138 96 139 97 // postfix ++ intentionally omitted … … 143 101 144 102 private: 145 const ScopeChainNode*m_node;103 DeprecatedPtr<ScopeChainNode> m_node; 146 104 }; 147 105 148 inline ScopeChainIterator ScopeChainNode::begin() const106 inline ScopeChainIterator ScopeChainNode::begin() 149 107 { 150 108 return ScopeChainIterator(this); 151 109 } 152 110 153 inline ScopeChainIterator ScopeChainNode::end() const111 inline ScopeChainIterator ScopeChainNode::end() 154 112 { 155 113 return ScopeChainIterator(0); 156 114 } 157 115 158 class NoScopeChain {}; 159 160 class ScopeChain { 161 friend class JIT; 162 public: 163 ScopeChain(NoScopeChain) 164 : m_node(0) 165 { 166 } 167 168 ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) 169 : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis)) 170 { 171 } 172 173 ScopeChain(const ScopeChain& c) 174 : m_node(c.m_node->copy()) 175 { 176 } 177 178 ScopeChain& operator=(const ScopeChain& c); 179 180 explicit ScopeChain(ScopeChainNode* node) 181 : m_node(node->copy()) 182 { 183 } 184 185 ~ScopeChain() 186 { 187 if (m_node) 188 m_node->deref(); 189 #ifndef NDEBUG 190 m_node = 0; 191 #endif 192 } 193 194 void swap(ScopeChain&); 195 196 ScopeChainNode* node() const { return m_node; } 197 198 JSObject* top() const { return m_node->object.get(); } 199 200 ScopeChainIterator begin() const { return m_node->begin(); } 201 ScopeChainIterator end() const { return m_node->end(); } 202 203 void push(JSObject* o) { m_node = m_node->push(o); } 204 205 void pop() { m_node = m_node->pop(); } 206 void clear() { m_node->deref(); m_node = 0; } 207 208 JSGlobalObject* globalObject() const { return m_node->globalObject; } 209 210 void markAggregate(MarkStack&) const; 211 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 215 // 216 // Returns the depth of the current call frame's scope chain 217 int localDepth() const; 218 219 #ifndef NDEBUG 220 void print() const { m_node->print(); } 221 #endif 222 223 private: 224 ScopeChainNode* m_node; 225 }; 226 227 inline void ScopeChain::swap(ScopeChain& o) 116 ALWAYS_INLINE JSGlobalData& ExecState::globalData() const 228 117 { 229 ScopeChainNode* tmp = m_node; 230 m_node = o.m_node; 231 o.m_node = tmp; 118 ASSERT(scopeChain()->globalData); 119 return *scopeChain()->globalData; 232 120 } 233 121 234 inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)122 ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const 235 123 { 236 ScopeChain tmp(c); 237 swap(tmp); 238 return *this; 124 return scopeChain()->globalObject.get(); 125 } 126 127 ALWAYS_INLINE JSObject* ExecState::globalThisValue() const 128 { 129 return scopeChain()->globalThis.get(); 239 130 } 240 131
Note:
See TracChangeset
for help on using the changeset viewer.