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 GCIncomingRefCountedInlines_h 27#define GCIncomingRefCountedInlines_h 28 29#include "GCIncomingRefCounted.h" 30#include "Heap.h" 31 32namespace JSC { 33 34template<typename T> 35bool GCIncomingRefCounted<T>::addIncomingReference(JSCell* cell) 36{ 37 if (!hasAnyIncoming()) { 38 m_encodedPointer = bitwise_cast<uintptr_t>(cell) | singletonFlag(); 39 this->setIsDeferred(true); 40 ASSERT(hasSingleton()); 41 return true; 42 } 43 44 ASSERT(Heap::heap(incomingReferenceAt(0)) == Heap::heap(cell)); 45 46 if (hasSingleton()) { 47 Vector<JSCell*>* vector = new Vector<JSCell*>(); 48 vector->append(singleton()); 49 vector->append(cell); 50 m_encodedPointer = bitwise_cast<uintptr_t>(vector); 51 ASSERT(hasVectorOfCells()); 52 return false; 53 } 54 55 vectorOfCells()->append(cell); 56 return false; 57} 58 59template<typename T> 60template<typename FilterFunctionType> 61bool GCIncomingRefCounted<T>::filterIncomingReferences(FilterFunctionType& filterFunction) 62{ 63 const bool verbose = false; 64 65 if (verbose) 66 dataLog("Filtering incoming references.\n"); 67 68 if (!hasAnyIncoming()) { 69 ASSERT(!this->isDeferred()); 70 ASSERT(this->refCount()); 71 if (verbose) 72 dataLog(" Has no incoming.\n"); 73 return false; 74 } 75 76 ASSERT(this->isDeferred()); 77 78 if (hasSingleton()) { 79 if (filterFunction(singleton())) { 80 if (verbose) 81 dataLog(" Singleton passed.\n"); 82 return false; 83 } 84 85 if (verbose) 86 dataLog(" Removing singleton.\n"); 87 m_encodedPointer = 0; 88 ASSERT(!hasAnyIncoming()); 89 this->setIsDeferred(false); 90 return true; 91 } 92 93 if (verbose) 94 dataLog(" Has ", vectorOfCells()->size(), " entries.\n"); 95 for (size_t i = 0; i < vectorOfCells()->size(); ++i) { 96 if (filterFunction(vectorOfCells()->at(i))) 97 continue; 98 vectorOfCells()->at(i--) = vectorOfCells()->last(); 99 vectorOfCells()->removeLast(); 100 } 101 102 if (vectorOfCells()->size() >= 2) { 103 if (verbose) 104 dataLog(" Still has ", vectorOfCells()->size(), " entries.\n"); 105 return false; 106 } 107 108 if (vectorOfCells()->isEmpty()) { 109 if (verbose) 110 dataLog(" Removing.\n"); 111 delete vectorOfCells(); 112 m_encodedPointer = 0; 113 ASSERT(!hasAnyIncoming()); 114 this->setIsDeferred(false); 115 return true; 116 } 117 118 if (verbose) 119 dataLog(" Shrinking to singleton.\n"); 120 JSCell* singleton = vectorOfCells()->at(0); 121 delete vectorOfCells(); 122 m_encodedPointer = bitwise_cast<uintptr_t>(singleton) | singletonFlag(); 123 ASSERT(hasSingleton()); 124 return false; 125} 126 127} // namespace JSC 128 129#endif // GCIncomingRefCountedInlines_h 130 131