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