Changeset 113141 in webkit for trunk/Source/JavaScriptCore/heap
- Timestamp:
- Apr 3, 2012, 10:28:13 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore/heap
- Files:
-
- 7 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/heap/Handle.h
r95901 r113141 60 60 operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } 61 61 62 HandleSlot slot() const { return m_slot; } 63 62 64 protected: 63 65 HandleBase(HandleSlot slot) … … 68 70 void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); } 69 71 70 HandleSlot slot() const { return m_slot; }71 72 void setSlot(HandleSlot slot) 72 73 { … … 134 135 private: 135 136 friend class HandleHeap; 137 friend class WeakBlock; 136 138 137 139 static Handle<T> wrapSlot(HandleSlot slot) -
trunk/Source/JavaScriptCore/heap/HandleHeap.cpp
r103243 r113141 32 32 namespace JSC { 33 33 34 WeakHandleOwner::~WeakHandleOwner()35 {36 }37 38 bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&)39 {40 return false;41 }42 43 void WeakHandleOwner::finalize(Handle<Unknown>, void*)44 {45 }46 47 34 HandleHeap::HandleHeap(JSGlobalData* globalData) 48 35 : m_globalData(globalData) … … 74 61 } 75 62 76 void HandleHeap::visitWeakHandles(HeapRootVisitor& heapRootVisitor)77 {78 SlotVisitor& visitor = heapRootVisitor.visitor();79 80 Node* end = m_weakList.end();81 for (Node* node = m_weakList.begin(); node != end; node = node->next()) {82 #if ENABLE(GC_VALIDATION)83 if (!isValidWeakNode(node))84 CRASH();85 #endif86 JSCell* cell = node->slot()->asCell();87 if (Heap::isMarked(cell))88 continue;89 90 WeakHandleOwner* weakOwner = node->weakOwner();91 if (!weakOwner)92 continue;93 94 if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor))95 continue;96 97 heapRootVisitor.visit(node->slot());98 }99 }100 101 void HandleHeap::finalizeWeakHandles()102 {103 Node* end = m_weakList.end();104 for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {105 m_nextToFinalize = node->next();106 #if ENABLE(GC_VALIDATION)107 if (!isValidWeakNode(node))108 CRASH();109 #endif110 111 JSCell* cell = node->slot()->asCell();112 if (Heap::isMarked(cell))113 continue;114 115 if (WeakHandleOwner* weakOwner = node->weakOwner()) {116 weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext());117 if (m_nextToFinalize != node->next()) // Owner deallocated node.118 continue;119 }120 #if ENABLE(GC_VALIDATION)121 if (!isLiveNode(node))122 CRASH();123 #endif124 *node->slot() = JSValue();125 SentinelLinkedList<Node>::remove(node);126 m_immediateList.push(node);127 }128 129 m_nextToFinalize = 0;130 }131 132 63 void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) 133 64 { … … 148 79 if (!value || !value.isCell()) { 149 80 m_immediateList.push(node); 150 return;151 }152 153 if (node->isWeak()) {154 m_weakList.push(node);155 #if ENABLE(GC_VALIDATION)156 if (!isLiveNode(node))157 CRASH();158 #endif159 81 return; 160 82 } … … 189 111 return true; 190 112 } 191 192 bool HandleHeap::isValidWeakNode(Node* node)193 {194 if (!isLiveNode(node))195 return false;196 if (!node->isWeak())197 return false;198 199 JSValue value = *node->slot();200 if (!value || !value.isCell())201 return false;202 203 JSCell* cell = value.asCell();204 if (!cell || !cell->structure())205 return false;206 207 return true;208 }209 113 #endif 210 114 -
trunk/Source/JavaScriptCore/heap/HandleHeap.h
r110033 r113141 41 41 class SlotVisitor; 42 42 43 class JS_EXPORT_PRIVATE WeakHandleOwner {44 public:45 virtual ~WeakHandleOwner();46 virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);47 virtual void finalize(Handle<Unknown>, void* context);48 };49 50 43 class HandleHeap { 51 44 public: … … 59 52 void deallocate(HandleSlot); 60 53 61 void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);62 HandleSlot copyWeak(HandleSlot);63 64 54 void visitStrongHandles(HeapRootVisitor&); 65 void visitWeakHandles(HeapRootVisitor&);66 void finalizeWeakHandles();67 55 68 56 JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&); 69 70 #if !ASSERT_DISABLED71 bool hasWeakOwner(HandleSlot, WeakHandleOwner*);72 bool hasFinalizer(HandleSlot);73 #endif74 57 75 58 unsigned protectedGlobalObjectCount(); … … 86 69 HandleHeap* handleHeap(); 87 70 88 void makeWeak(WeakHandleOwner*, void* context);89 bool isWeak();90 91 WeakHandleOwner* weakOwner();92 void* weakOwnerContext();93 94 71 void setPrev(Node*); 95 72 Node* prev(); … … 99 76 100 77 private: 101 WeakHandleOwner* emptyWeakOwner();102 103 78 JSValue m_value; 104 79 HandleHeap* m_handleHeap; 105 WeakHandleOwner* m_weakOwner;106 void* m_weakOwnerContext;107 80 Node* m_prev; 108 81 Node* m_next; … … 115 88 116 89 #if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED 117 bool isValidWeakNode(Node*);118 90 bool isLiveNode(Node*); 119 91 #endif … … 123 95 124 96 SentinelLinkedList<Node> m_strongList; 125 SentinelLinkedList<Node> m_weakList;126 97 SentinelLinkedList<Node> m_immediateList; 127 98 SinglyLinkedList<Node> m_freeList; … … 176 147 } 177 148 178 inline HandleSlot HandleHeap::copyWeak(HandleSlot other)179 {180 Node* node = toNode(allocate());181 node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());182 writeBarrier(node->slot(), *other);183 *node->slot() = *other;184 return toHandle(node);185 }186 187 inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)188 {189 // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.190 // File a bug with stack trace if you hit this.191 if (m_nextToFinalize)192 CRASH();193 Node* node = toNode(handle);194 node->makeWeak(weakOwner, context);195 196 SentinelLinkedList<Node>::remove(node);197 if (!*handle || !handle->isCell()) {198 m_immediateList.push(node);199 return;200 }201 202 m_weakList.push(node);203 }204 205 #if !ASSERT_DISABLED206 inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)207 {208 return toNode(handle)->weakOwner() == weakOwner;209 }210 211 inline bool HandleHeap::hasFinalizer(HandleSlot handle)212 {213 return toNode(handle)->weakOwner();214 }215 #endif216 217 149 inline HandleHeap::Node::Node(HandleHeap* handleHeap) 218 150 : m_handleHeap(handleHeap) 219 , m_weakOwner(0)220 , m_weakOwnerContext(0)221 151 , m_prev(0) 222 152 , m_next(0) … … 226 156 inline HandleHeap::Node::Node(WTF::SentinelTag) 227 157 : m_handleHeap(0) 228 , m_weakOwner(0)229 , m_weakOwnerContext(0)230 158 , m_prev(0) 231 159 , m_next(0) … … 243 171 } 244 172 245 inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)246 {247 m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();248 m_weakOwnerContext = context;249 }250 251 inline bool HandleHeap::Node::isWeak()252 {253 return m_weakOwner; // True for emptyWeakOwner().254 }255 256 inline WeakHandleOwner* HandleHeap::Node::weakOwner()257 {258 return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().259 }260 261 inline void* HandleHeap::Node::weakOwnerContext()262 {263 ASSERT(weakOwner());264 return m_weakOwnerContext;265 }266 267 173 inline void HandleHeap::Node::setPrev(Node* prev) 268 174 { … … 283 189 { 284 190 return m_next; 285 }286 287 // Sentinel to indicate that a node is weak, but its owner has no meaningful288 // callbacks. This allows us to optimize by skipping such nodes.289 inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()290 {291 return reinterpret_cast<WeakHandleOwner*>(-1);292 191 } 293 192 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r112624 r113141 314 314 , m_minBytesPerCycle(heapSizeForHint(heapSize)) 315 315 , m_lastFullGCSize(0) 316 , m_waterMark(0)317 316 , m_highWaterMark(m_minBytesPerCycle) 318 317 , m_operationInProgress(NoOperation) … … 320 319 , m_storageSpace(this) 321 320 , m_blockFreeingThreadShouldQuit(false) 322 , m_extraCost(0)323 321 , m_markListSet(0) 324 322 , m_activityCallback(DefaultGCActivityCallback::create(this)) … … 326 324 , m_sharedData(globalData) 327 325 , m_slotVisitor(m_sharedData) 326 , m_weakHeap(this) 328 327 , m_handleHeap(globalData) 329 328 , m_isSafeToCollect(false) … … 377 376 clearMarks(); 378 377 379 m_ handleHeap.finalizeWeakHandles();378 m_weakHeap.finalizeAll(); 380 379 m_globalData->smallStrings.finalizeSmallStrings(); 381 380 shrink(); … … 467 466 // collecting more frequently as long as it stays alive. 468 467 469 if (m_extraCost > maxExtraCost && m_extraCost > highWaterMark() / 2) 470 collectAllGarbage(); 471 m_extraCost += cost; 468 addToWaterMark(cost); 472 469 } 473 470 … … 688 685 } 689 686 690 // Weak handles must be marked last, because their owners use the set of691 // opaque roots to determine reachability.692 { 693 GCPHASE(Visiting WeakHandles);687 // Weak references must be marked last because their liveness depends on 688 // the liveness of the rest of the object graph. 689 { 690 GCPHASE(VisitingLiveWeakHandles); 694 691 while (true) { 695 m_ handleHeap.visitWeakHandles(heapRootVisitor);692 m_weakHeap.visitLiveWeakImpls(heapRootVisitor); 696 693 harvestWeakReferences(); 697 694 if (visitor.isEmpty()) … … 706 703 } 707 704 } 705 706 { 707 GCPHASE(VisitingDeadWeakHandles); 708 m_weakHeap.visitDeadWeakImpls(heapRootVisitor); 709 } 710 708 711 GCCOUNTER(VisitedValueCount, visitor.visitCount()); 709 712 … … 816 819 { 817 820 GCPHASE(FinalizeWeakHandles); 818 m_ handleHeap.finalizeWeakHandles();821 m_weakHeap.sweep(); 819 822 m_globalData->smallStrings.finalizeSmallStrings(); 820 823 } … … 847 850 if (fullGC) { 848 851 m_lastFullGCSize = newSize; 849 setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));852 m_highWaterMark = max(proportionalBytes, m_minBytesPerCycle); 850 853 } 851 854 double lastGCEndTime = WTF::currentTime(); … … 863 866 void Heap::resetAllocators() 864 867 { 865 m_extraCost = 0;866 868 m_objectSpace.resetAllocators(); 869 m_weakHeap.resetAllocator(); 867 870 } 868 871 … … 925 928 void Heap::addFinalizer(JSCell* cell, Finalizer finalizer) 926 929 { 927 Weak<JSCell> weak(*globalData(), cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); 928 weak.leakHandle(); // Balanced by FinalizerOwner::finalize(). 930 weakHeap()->allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize(). 929 931 } 930 932 931 933 void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context) 932 934 { 933 Weak<JSCell> weak(Weak<JSCell>::Adopt, handle);935 HandleSlot slot = handle.slot(); 934 936 Finalizer finalizer = reinterpret_cast<Finalizer>(context); 935 finalizer(weak.get()); 937 finalizer(slot->asCell()); 938 WeakHeap::deallocate(WeakImpl::asWeakImpl(slot)); 936 939 } 937 940 -
trunk/Source/JavaScriptCore/heap/Heap.h
r112624 r113141 31 31 #include "MarkedSpace.h" 32 32 #include "SlotVisitor.h" 33 #include "WeakHandleOwner.h" 34 #include "WeakHeap.h" 33 35 #include "WriteBarrierSupport.h" 34 36 #include <wtf/DoublyLinkedList.h> … … 137 139 template<typename Functor> typename Functor::ReturnType forEachProtectedCell(); 138 140 141 WeakHeap* weakHeap() { return &m_weakHeap; } 139 142 HandleHeap* handleHeap() { return &m_handleHeap; } 140 143 HandleStack* handleStack() { return &m_handleStack; } 141 144 142 145 void getConservativeRegisterRoots(HashSet<JSCell*>& roots); 146 147 void addToWaterMark(size_t); 143 148 144 149 double lastGCLength() { return m_lastGCLength; } … … 161 166 size_t waterMark(); 162 167 size_t highWaterMark(); 163 void setHighWaterMark(size_t);164 168 bool shouldCollect(); 165 169 … … 205 209 const size_t m_minBytesPerCycle; 206 210 size_t m_lastFullGCSize; 207 size_t m_waterMark;208 211 size_t m_highWaterMark; 209 212 … … 224 227 #endif 225 228 226 size_t m_extraCost;227 228 229 ProtectCountSet m_protectedValues; 229 230 Vector<Vector<ValueStringPair>* > m_tempSortingVectors; … … 237 238 SlotVisitor m_slotVisitor; 238 239 240 WeakHeap m_weakHeap; 239 241 HandleHeap m_handleHeap; 240 242 HandleStack m_handleStack; … … 301 303 } 302 304 303 inline void Heap::setHighWaterMark(size_t newHighWaterMark) 304 { 305 m_highWaterMark = newHighWaterMark; 305 inline void Heap::addToWaterMark(size_t size) 306 { 307 m_objectSpace.addToWaterMark(size); 308 if (waterMark() > highWaterMark()) 309 collect(DoNotSweep); 306 310 } 307 311 -
trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp
r107445 r113141 33 33 MarkedSpace::MarkedSpace(Heap* heap) 34 34 : m_waterMark(0) 35 , m_nurseryWaterMark(0)36 35 , m_heap(heap) 37 36 { … … 50 49 { 51 50 m_waterMark = 0; 52 m_nurseryWaterMark = 0;53 51 54 52 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { -
trunk/Source/JavaScriptCore/heap/MarkedSpace.h
r110033 r113141 67 67 68 68 size_t waterMark(); 69 size_t nurseryWaterMark();69 void addToWaterMark(size_t); 70 70 71 71 typedef HashSet<MarkedBlock*>::iterator BlockIterator; … … 78 78 void shrink(); 79 79 void freeBlocks(MarkedBlock* head); 80 80 81 void didAddBlock(MarkedBlock*); 81 82 void didConsumeFreeList(MarkedBlock*); … … 103 104 104 105 size_t m_waterMark; 105 size_t m_nurseryWaterMark;106 106 Heap* m_heap; 107 107 MarkedBlockSet m_blocks; … … 113 113 } 114 114 115 inline size_t MarkedSpace::nurseryWaterMark()116 { 117 return m_nurseryWaterMark;115 inline void MarkedSpace::addToWaterMark(size_t size) 116 { 117 m_waterMark += size; 118 118 } 119 119 … … 200 200 inline void MarkedSpace::didConsumeFreeList(MarkedBlock* block) 201 201 { 202 m_nurseryWaterMark += block->capacity() - block->size();203 202 m_waterMark += block->capacity(); 204 203 } -
trunk/Source/JavaScriptCore/heap/PassWeak.h
r110033 r113141 27 27 #define PassWeak_h 28 28 29 #include "JSCell.h" 29 30 #include <wtf/Assertions.h> 30 #include "Handle.h"31 31 #include <wtf/NullPtr.h> 32 32 #include <wtf/TypeTraits.h> … … 36 36 template<typename T> class Weak; 37 37 template<typename T> class PassWeak; 38 template<typename T> PassWeak<T> adoptWeak(HandleSlot); 39 40 template<typename T> class PassWeak : public Handle<T> { 41 using Handle<T>::slot; 42 using Handle<T>::setSlot; 43 38 template<typename T> PassWeak<T> adoptWeak(WeakImpl*); 39 40 template<typename Base, typename T> class WeakImplAccessor { 44 41 public: 45 typedef typename Handle<T>::ExternalType ExternalType; 46 47 PassWeak() : Handle<T>() { } 48 PassWeak(std::nullptr_t) : Handle<T>() { } 49 50 PassWeak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) 51 : Handle<T>(globalData.heap.handleHeap()->allocate()) 52 { 53 HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); 54 JSValue value = HandleTypes<T>::toJSValue(externalType); 55 HandleHeap::heapFor(slot())->writeBarrier(slot(), value); 56 *slot() = value; 57 } 42 typedef T* GetType; 43 44 T* operator->() const; 45 T& operator*() const; 46 GetType get() const; 47 48 #if !ASSERT_DISABLED 49 bool was(GetType) const; 50 #endif 51 }; 52 53 template<typename Base> class WeakImplAccessor<Base, Unknown> { 54 public: 55 typedef JSValue GetType; 56 57 const JSValue* operator->() const; 58 const JSValue& operator*() const; 59 GetType get() const; 60 }; 61 62 template<typename T> class PassWeak : public WeakImplAccessor<PassWeak<T>, T> { 63 public: 64 friend class WeakImplAccessor<PassWeak<T>, T>; 65 typedef typename WeakImplAccessor<PassWeak<T>, T>::GetType GetType; 66 67 PassWeak(); 68 PassWeak(std::nullptr_t); 69 PassWeak(JSGlobalData&, GetType = GetType(), WeakHandleOwner* = 0, void* context = 0); 58 70 59 71 // It somewhat breaks the type system to allow transfer of ownership out of 60 72 // a const PassWeak. However, it makes it much easier to work with PassWeak 61 73 // temporaries, and we don't have a need to use real const PassWeaks anyway. 62 PassWeak(const PassWeak& o) : Handle<T>(o.leakHandle()) { } 63 template<typename U> PassWeak(const PassWeak<U>& o) : Handle<T>(o.leakHandle()) { } 64 65 ~PassWeak() 66 { 67 if (!slot()) 68 return; 69 HandleHeap::heapFor(slot())->deallocate(slot()); 70 setSlot(0); 71 } 72 73 ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); } 74 75 HandleSlot leakHandle() const WARN_UNUSED_RETURN; 74 PassWeak(const PassWeak&); 75 template<typename U> PassWeak(const PassWeak<U>&); 76 77 ~PassWeak(); 78 79 bool operator!() const; 80 81 // This conversion operator allows implicit conversion to bool but not to other integer types. 82 typedef JSValue (PassWeak::*UnspecifiedBoolType); 83 operator UnspecifiedBoolType*() const; 84 85 WeakImpl* leakImpl() const WARN_UNUSED_RETURN; 76 86 77 87 private: 78 friend PassWeak adoptWeak<T>(HandleSlot); 79 80 explicit PassWeak(HandleSlot slot) : Handle<T>(slot) { } 88 friend PassWeak adoptWeak<T>(WeakImpl*); 89 explicit PassWeak(WeakImpl*); 90 91 WeakImpl* m_impl; 81 92 }; 82 93 83 template<typename T> inline HandleSlot PassWeak<T>::leakHandle() const 84 { 85 HandleSlot slot = this->slot(); 86 const_cast<PassWeak<T>*>(this)->setSlot(0); 87 return slot; 88 } 89 90 template<typename T> PassWeak<T> adoptWeak(HandleSlot slot) 91 { 92 return PassWeak<T>(slot); 94 template<typename Base, typename T> inline T* WeakImplAccessor<Base, T>::operator->() const 95 { 96 ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); 97 return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); 98 } 99 100 template<typename Base, typename T> inline T& WeakImplAccessor<Base, T>::operator*() const 101 { 102 ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); 103 return *jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); 104 } 105 106 template<typename Base, typename T> inline typename WeakImplAccessor<Base, T>::GetType WeakImplAccessor<Base, T>::get() const 107 { 108 if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live) 109 return GetType(); 110 return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); 111 } 112 113 #if !ASSERT_DISABLED 114 template<typename Base, typename T> inline bool WeakImplAccessor<Base, T>::was(typename WeakImplAccessor<Base, T>::GetType other) const 115 { 116 return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()) == other; 117 } 118 #endif 119 120 template<typename Base> inline const JSValue* WeakImplAccessor<Base, Unknown>::operator->() const 121 { 122 ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); 123 return &static_cast<const Base*>(this)->m_impl->jsValue(); 124 } 125 126 template<typename Base> inline const JSValue& WeakImplAccessor<Base, Unknown>::operator*() const 127 { 128 ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); 129 return static_cast<const Base*>(this)->m_impl->jsValue(); 130 } 131 132 template<typename Base> inline typename WeakImplAccessor<Base, Unknown>::GetType WeakImplAccessor<Base, Unknown>::get() const 133 { 134 if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live) 135 return GetType(); 136 return static_cast<const Base*>(this)->m_impl->jsValue(); 137 } 138 139 template<typename T> inline PassWeak<T>::PassWeak() 140 : m_impl(0) 141 { 142 } 143 144 template<typename T> inline PassWeak<T>::PassWeak(std::nullptr_t) 145 : m_impl(0) 146 { 147 } 148 149 template<typename T> inline PassWeak<T>::PassWeak(JSGlobalData& globalData, typename PassWeak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context) 150 : m_impl(globalData.heap.weakHeap()->allocate(getType, weakOwner, context)) 151 { 152 } 153 154 template<typename T> inline PassWeak<T>::PassWeak(const PassWeak& o) 155 : m_impl(o.leakImpl()) 156 { 157 } 158 159 template<typename T> template<typename U> inline PassWeak<T>::PassWeak(const PassWeak<U>& o) 160 : m_impl(o.leakImpl()) 161 { 162 } 163 164 template<typename T> inline PassWeak<T>::~PassWeak() 165 { 166 if (!m_impl) 167 return; 168 WeakHeap::deallocate(m_impl); 169 } 170 171 template<typename T> inline bool PassWeak<T>::operator!() const 172 { 173 return !m_impl || m_impl->state() != WeakImpl::Live || !m_impl->jsValue(); 174 } 175 176 template<typename T> inline PassWeak<T>::operator UnspecifiedBoolType*() const 177 { 178 return reinterpret_cast<UnspecifiedBoolType*>(!!*this); 179 } 180 181 template<typename T> inline PassWeak<T>::PassWeak(WeakImpl* impl) 182 : m_impl(impl) 183 { 184 } 185 186 template<typename T> inline WeakImpl* PassWeak<T>::leakImpl() const 187 { 188 WeakImpl* tmp = 0; 189 std::swap(tmp, const_cast<WeakImpl*&>(m_impl)); 190 return tmp; 191 } 192 193 template<typename T> PassWeak<T> inline adoptWeak(WeakImpl* impl) 194 { 195 return PassWeak<T>(impl); 93 196 } 94 197 -
trunk/Source/JavaScriptCore/heap/Strong.h
r110033 r113141 82 82 } 83 83 84 bool operator!() const { return !slot() || !*slot(); } 85 86 // This conversion operator allows implicit conversion to bool but not to other integer types. 87 typedef JSValue (HandleBase::*UnspecifiedBoolType); 88 operator UnspecifiedBoolType*() const { return !!*this ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } 89 84 90 void swap(Strong& other) 85 91 { 86 92 Handle<T>::swap(other); 87 93 } 94 95 ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); } 88 96 89 97 void set(JSGlobalData&, ExternalType); -
trunk/Source/JavaScriptCore/heap/Weak.h
r110033 r113141 28 28 29 29 #include <wtf/Assertions.h> 30 #include "Handle.h"31 #include "HandleHeap.h"32 30 #include "JSGlobalData.h" 33 31 #include "PassWeak.h" … … 35 33 namespace JSC { 36 34 37 // A weakly referenced handle that becomes 0 when the value it points to is garbage collected. 38 template <typename T> class Weak : public Handle<T> { 35 template<typename T> class Weak : public WeakImplAccessor<Weak<T>, T> { 39 36 WTF_MAKE_NONCOPYABLE(Weak); 37 public: 38 friend class WeakImplAccessor<Weak<T>, T>; 39 typedef typename WeakImplAccessor<Weak<T>, T>::GetType GetType; 40 40 41 using Handle<T>::slot; 42 using Handle<T>::setSlot; 43 44 public: 45 typedef typename Handle<T>::ExternalType ExternalType; 46 47 Weak() 48 : Handle<T>() 49 { 50 } 51 52 Weak(std::nullptr_t) 53 : Handle<T>() 54 { 55 } 56 57 Weak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) 58 : Handle<T>(globalData.heap.handleHeap()->allocate()) 59 { 60 HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); 61 JSValue value = HandleTypes<T>::toJSValue(externalType); 62 HandleHeap::heapFor(slot())->writeBarrier(slot(), value); 63 *slot() = value; 64 } 65 66 enum AdoptTag { Adopt }; 67 template<typename U> Weak(AdoptTag, Handle<U> handle) 68 : Handle<T>(handle.slot()) 69 { 70 validateCell(get()); 71 } 41 Weak(); 42 Weak(std::nullptr_t); 43 Weak(JSGlobalData&, GetType = GetType(), WeakHandleOwner* = 0, void* context = 0); 72 44 73 45 enum HashTableDeletedValueTag { HashTableDeletedValue }; 74 bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); } 75 Weak(HashTableDeletedValueTag) 76 : Handle<T>(hashTableDeletedValue()) 77 { 78 } 46 bool isHashTableDeletedValue() const; 47 Weak(HashTableDeletedValueTag); 79 48 80 template<typename U> Weak(const PassWeak<U>& other) 81 : Handle<T>(other.leakHandle()) 82 { 83 } 49 template<typename U> Weak(const PassWeak<U>&); 84 50 85 ~Weak() 86 { 87 clear(); 88 } 51 ~Weak(); 89 52 90 void swap(Weak& other)91 {92 Handle<T>::swap(other);93 }53 void swap(Weak&); 54 Weak& operator=(const PassWeak<T>&); 55 56 bool operator!() const; 94 57 95 Weak& operator=(const PassWeak<T>&); 58 // This conversion operator allows implicit conversion to bool but not to other integer types. 59 typedef JSValue (HandleBase::*UnspecifiedBoolType); 60 operator UnspecifiedBoolType*() const; 96 61 97 ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); } 62 PassWeak<T> release(); 63 void clear(); 98 64 99 PassWeak<T> release() { PassWeak<T> tmp = adoptWeak<T>(slot()); setSlot(0); return tmp; } 65 private: 66 static WeakImpl* hashTableDeletedValue(); 100 67 101 void clear() 102 { 103 if (!slot()) 104 return; 105 HandleHeap::heapFor(slot())->deallocate(slot()); 106 setSlot(0); 107 } 108 109 HandleSlot leakHandle() 110 { 111 ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot())); 112 HandleSlot result = slot(); 113 setSlot(0); 114 return result; 115 } 68 WeakImpl* m_impl; 69 }; 116 70 117 private: 118 static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); } 119 }; 71 template<typename T> inline Weak<T>::Weak() 72 : m_impl(0) 73 { 74 } 75 76 template<typename T> inline Weak<T>::Weak(std::nullptr_t) 77 : m_impl(0) 78 { 79 } 80 81 template<typename T> inline Weak<T>::Weak(JSGlobalData& globalData, typename Weak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context) 82 : m_impl(globalData.heap.weakHeap()->allocate(getType, weakOwner, context)) 83 { 84 } 85 86 template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const 87 { 88 return m_impl == hashTableDeletedValue(); 89 } 90 91 template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag) 92 : m_impl(hashTableDeletedValue()) 93 { 94 } 95 96 template<typename T> template<typename U> inline Weak<T>::Weak(const PassWeak<U>& other) 97 : m_impl(other.leakImpl()) 98 { 99 } 100 101 template<typename T> inline Weak<T>::~Weak() 102 { 103 clear(); 104 } 120 105 121 106 template<class T> inline void swap(Weak<T>& a, Weak<T>& b) … … 124 109 } 125 110 111 template<typename T> inline void Weak<T>::swap(Weak& other) 112 { 113 std::swap(m_impl, other.m_impl); 114 } 115 126 116 template<typename T> inline Weak<T>& Weak<T>::operator=(const PassWeak<T>& o) 127 117 { 128 118 clear(); 129 setSlot(o.leakHandle());119 m_impl = o.leakImpl(); 130 120 return *this; 121 } 122 123 template<typename T> inline bool Weak<T>::operator!() const 124 { 125 return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live; 126 } 127 128 template<typename T> inline Weak<T>::operator UnspecifiedBoolType*() const 129 { 130 return reinterpret_cast<UnspecifiedBoolType*>(!!*this); 131 } 132 133 template<typename T> inline PassWeak<T> Weak<T>::release() 134 { 135 PassWeak<T> tmp = adoptWeak<T>(m_impl); 136 m_impl = 0; 137 return tmp; 138 } 139 140 template<typename T> inline void Weak<T>::clear() 141 { 142 if (!m_impl) 143 return; 144 WeakHeap::deallocate(m_impl); 145 m_impl = 0; 146 } 147 148 template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue() 149 { 150 return reinterpret_cast<WeakImpl*>(-1); 131 151 } 132 152 … … 152 172 static PassOutType passOut(EmptyValueType) { return PassOutType(); } 153 173 154 typedef typename StorageType:: ExternalType PeekType;174 typedef typename StorageType::GetType PeekType; 155 175 static PeekType peek(const StorageType& value) { return value.get(); } 156 176 static PeekType peek(EmptyValueType) { return PeekType(); }
Note:
See TracChangeset
for help on using the changeset viewer.