Changeset 2824 in webkit for trunk/JavaScriptCore/kjs/scope_chain.cpp
- Timestamp:
- Nov 22, 2002, 1:04:55 AM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/scope_chain.cpp
r2821 r2824 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * This file is part of the KDE libraries 4 * Copyright (C) 1999-2001 Harri Porten ([email protected]) 5 * Copyright (C) 2001 Peter Kelly ([email protected]) 3 * Copyright (C) 2002 Apple Computer, Inc. 6 4 * 7 5 * This library is free software; you can redistribute it and/or … … 24 22 #include "scope_chain.h" 25 23 24 #include "object.h" 25 26 26 namespace KJS { 27 27 28 struct ScopeChainNode { 29 ScopeChainNode(const Value &val, ScopeChainNode *p, ScopeChainNode *n) 30 : member(val.imp()), prev(p), next(n) { } 31 ScopeChainNode(ValueImp *val, ScopeChainNode *p, ScopeChainNode *n) 32 : member(val), prev(p), next(n) { } 33 ValueImp *member; 34 ScopeChainNode *prev, *next; 35 }; 36 37 struct ScopeChainHookNode : public ScopeChainNode { 38 ScopeChainHookNode(bool needsMarking) : ScopeChainNode(Value(), this, this), 39 listRefCount(1), nodesRefCount(needsMarking ? 0 : 1) { } 40 int listRefCount; 41 int nodesRefCount; 42 }; 43 44 // ------------------------------ ScopeChainIterator --------------------------------- 45 46 ValueImp* ScopeChainIterator::operator->() const 28 ScopeChainNode::ScopeChainNode(ScopeChainNode *n, ObjectImp *o) 29 : next(n), object(o), nodeAndObjectRefCount(1), nodeOnlyRefCount(0) 47 30 { 48 return node->member;31 o->ref(); 49 32 } 50 33 51 Value ScopeChainIterator::operator*() const34 inline void ScopeChain::ref() const 52 35 { 53 return Value(node->member); 36 for (ScopeChainNode *n = _node; n; n = n->next) { 37 if (n->nodeAndObjectRefCount++ != 0) 38 break; 39 n->object->ref(); 40 } 54 41 } 55 42 56 Value ScopeChainIterator::operator++() 43 ScopeChain::ScopeChain(const NoRefScopeChain &c) 44 : _node(c._node) 57 45 { 58 node = node->next; 59 return Value(node->member); 46 ref(); 60 47 } 61 48 62 Value ScopeChainIterator::operator++(int)49 ScopeChain &ScopeChain::operator=(const ScopeChain &c) 63 50 { 64 const ScopeChainNode *n = node; 65 ++*this; 66 return Value(n->member); 51 c.ref(); 52 deref(); 53 _node = c._node; 54 return *this; 67 55 } 68 56 69 // ------------------------------ ScopeChain ----------------------------------------- 70 71 ScopeChain::ScopeChain(bool needsMarking) : hook(new ScopeChainHookNode(needsMarking)), m_needsMarking(needsMarking) 57 void ScopeChain::push(ObjectImp *o) 72 58 { 59 _node = new ScopeChainNode(_node, o); 73 60 } 74 61 75 ScopeChain::ScopeChain(const ScopeChain& l) : hook(l.hook), m_needsMarking(false)62 void ScopeChain::pop() 76 63 { 77 ++hook->listRefCount; 78 if (hook->nodesRefCount++ == 0) 79 refAll(); 64 ScopeChainNode *oldNode = _node; 65 assert(oldNode); 66 ScopeChainNode *newNode = oldNode->next; 67 _node = newNode; 68 69 // Three cases: 70 // 1) This was not the last reference of the old node. 71 // In this case we move our ref from the old to the new node. 72 // 2) This was the last reference of the old node, but there are garbage collected references. 73 // In this case, the new node doesn't get any new ref, and the object is deref'd. 74 // 3) This was the last reference of the old node. 75 // In this case the object is deref'd and the entire node goes. 76 if (--oldNode->nodeAndObjectRefCount != 0) { 77 if (newNode) 78 ++newNode->nodeAndObjectRefCount; 79 } else { 80 oldNode->object->deref(); 81 if (oldNode->nodeOnlyRefCount == 0) 82 delete oldNode; 83 } 80 84 } 81 85 82 ScopeChain& ScopeChain::operator=(const ScopeChain& l)86 void ScopeChain::release() 83 87 { 84 ScopeChain(l).swap(*this); 85 return *this; 88 ScopeChainNode *n = _node; 89 do { 90 ScopeChainNode *next = n->next; 91 n->object->deref(); 92 if (n->nodeOnlyRefCount == 0) 93 delete n; 94 n = next; 95 } while (n && --n->nodeAndObjectRefCount == 0); 86 96 } 87 97 88 ScopeChain::~ScopeChain() 98 inline void NoRefScopeChain::ref() const 89 99 { 90 if (!m_needsMarking) 91 if (--hook->nodesRefCount == 0) 92 derefAll(); 93 94 if (--hook->listRefCount == 0) { 95 assert(hook->nodesRefCount == 0); 96 clearInternal(); 97 delete hook; 98 } 100 for (ScopeChainNode *n = _node; n; n = n->next) 101 if (n->nodeOnlyRefCount++ != 0) 102 break; 99 103 } 100 104 101 void ScopeChain::mark() const 105 NoRefScopeChain &NoRefScopeChain::operator=(const ScopeChain &c) 102 106 { 103 ScopeChainNode *n = hook->next; 104 while (n != hook) { 105 if (!n->member->marked()) 106 n->member->mark(); 107 n = n->next; 108 } 107 c.ref(); 108 deref(); 109 _node = c._node; 110 return *this; 109 111 } 110 112 111 void ScopeChain::append(const Value& val)113 void NoRefScopeChain::mark() 112 114 { 113 ScopeChainNode *n = new ScopeChainNode(val, hook->prev, hook);114 if (hook->nodesRefCount)115 n->member->ref();116 hook->prev->next = n;117 hook->prev = n;115 for (ScopeChainNode *n = _node; n; n = n->next) { 116 ObjectImp *o = n->object; 117 if (!o->marked()) 118 o->mark(); 119 } 118 120 } 119 121 120 void ScopeChain::prepend(const Value& val)122 void NoRefScopeChain::release() 121 123 { 122 ScopeChainNode *n = new ScopeChainNode(val, hook, hook->next); 123 if (hook->nodesRefCount) 124 n->member->ref(); 125 hook->next->prev = n; 126 hook->next = n; 127 } 128 129 void ScopeChain::prepend(ValueImp *val) 130 { 131 ScopeChainNode *n = new ScopeChainNode(val, hook, hook->next); 132 if (hook->nodesRefCount) 133 n->member->ref(); 134 hook->next->prev = n; 135 hook->next = n; 136 } 137 138 void ScopeChain::prependList(const ScopeChain& lst) 139 { 140 ScopeChainNode *otherHook = lst.hook; 141 ScopeChainNode *n = otherHook->prev; 142 while (n != otherHook) { 143 prepend(n->member); 144 n = n->prev; 145 } 146 } 147 148 void ScopeChain::removeFirst() 149 { 150 erase(hook->next); 151 } 152 153 void ScopeChain::clearInternal() 154 { 155 ScopeChainNode *n = hook->next; 156 while (n != hook) { 157 n = n->next; 158 delete n->prev; 159 } 160 161 hook->next = hook; 162 hook->prev = hook; 163 } 164 165 ScopeChain ScopeChain::copy() const 166 { 167 ScopeChain newScopeChain; 168 newScopeChain.prependList(*this); 169 return newScopeChain; 170 } 171 172 ScopeChainIterator ScopeChain::begin() const 173 { 174 return ScopeChainIterator(hook->next); 175 } 176 177 ScopeChainIterator ScopeChain::end() const 178 { 179 return ScopeChainIterator(hook); 180 } 181 182 void ScopeChain::erase(ScopeChainNode *n) 183 { 184 if (n != hook) { 185 if (hook->nodesRefCount) 186 n->member->deref(); 187 n->next->prev = n->prev; 188 n->prev->next = n->next; 189 delete n; 190 } 191 } 192 193 void ScopeChain::refAll() const 194 { 195 for (ScopeChainNode *n = hook->next; n != hook; n = n->next) 196 n->member->ref(); 197 } 198 199 void ScopeChain::derefAll() const 200 { 201 for (ScopeChainNode *n = hook->next; n != hook; n = n->next) 202 n->member->deref(); 203 } 204 205 void ScopeChain::swap(ScopeChain &other) 206 { 207 if (!m_needsMarking) 208 if (other.hook->nodesRefCount++ == 0) 209 other.refAll(); 210 if (!other.m_needsMarking) 211 if (hook->nodesRefCount++ == 0) 212 refAll(); 213 214 if (!m_needsMarking) 215 if (--hook->nodesRefCount == 0) 216 derefAll(); 217 if (!other.m_needsMarking) 218 if (--other.hook->nodesRefCount == 0) 219 other.derefAll(); 220 221 ScopeChainHookNode *tmp = hook; 222 hook = other.hook; 223 other.hook = tmp; 224 } 225 226 bool ScopeChain::isEmpty() const 227 { 228 return hook->next == hook; 124 ScopeChainNode *n = _node; 125 do { 126 ScopeChainNode *next = n->next; 127 if (n->nodeAndObjectRefCount == 0) 128 delete n; 129 n = next; 130 } while (n && --n->nodeOnlyRefCount == 0); 229 131 } 230 132
Note:
See TracChangeset
for help on using the changeset viewer.