1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef GCIncomingRefCounted_h 27#define GCIncomingRefCounted_h 28 29#include <wtf/DeferrableRefCounted.h> 30#include <wtf/Vector.h> 31 32namespace JSC { 33 34class JSCell; 35 36// A C-heap-allocated object that may have additional reference counts 37// due to incoming references from the heap, which are tracked in 38// reverse: the object knows its incoming references. Such objects also 39// have the invariant that they don't have references back into the GC 40// heap. 41 42template<typename T> 43class GCIncomingRefCounted : public DeferrableRefCounted<T> { 44public: 45 GCIncomingRefCounted() 46 : m_encodedPointer(0) 47 { 48 } 49 50 ~GCIncomingRefCounted() 51 { 52 if (hasVectorOfCells()) 53 delete vectorOfCells(); 54 } 55 56 size_t numberOfIncomingReferences() const 57 { 58 if (!hasAnyIncoming()) 59 return 0; 60 if (hasSingleton()) 61 return 1; 62 return vectorOfCells()->size(); 63 } 64 65 JSCell* incomingReferenceAt(size_t index) const 66 { 67 ASSERT(hasAnyIncoming()); 68 if (hasSingleton()) { 69 ASSERT(!index); 70 return singleton(); 71 } 72 return vectorOfCells()->at(index); 73 } 74 75 // It's generally not a good idea to call this directly, since if this 76 // returns true, you're supposed to add this object to the GC's list. 77 // Call GCIncomingRefCountedSet::addReference() instead. 78 bool addIncomingReference(JSCell*); 79 80 // A filter function returns true if we wish to keep the incoming 81 // reference, and false if we don't. This may delete the object, 82 // and if it does so, this returns true. In general, you don't want 83 // to use this with a filter function that can return false unless 84 // you're also walking the GC's list. 85 template<typename FilterFunctionType> 86 bool filterIncomingReferences(FilterFunctionType&); 87 88private: 89 static uintptr_t singletonFlag() { return 1; } 90 91 bool hasVectorOfCells() const { return !(m_encodedPointer & singletonFlag()); } 92 bool hasAnyIncoming() const { return !!m_encodedPointer; } 93 bool hasSingleton() const { return hasAnyIncoming() && !hasVectorOfCells(); } 94 95 JSCell* singleton() const 96 { 97 ASSERT(hasSingleton()); 98 return bitwise_cast<JSCell*>(m_encodedPointer & ~singletonFlag()); 99 } 100 101 Vector<JSCell*>* vectorOfCells() const 102 { 103 ASSERT(hasVectorOfCells()); 104 return bitwise_cast<Vector<JSCell*>*>(m_encodedPointer); 105 } 106 107 // Singleton flag is set: this is a JSCell*. 108 // Singleton flag not set: this is a pointer to a vector of cells. 109 uintptr_t m_encodedPointer; 110}; 111 112} // namespace JSC 113 114#endif // GCIncomingRefCounted_h 115 116