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