Unreviewed, rolling out r209766.
[WebKit.git] / Source / JavaScriptCore / heap / WeakBlock.h
1 /*
2  * Copyright (C) 2012, 2016 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "CellContainer.h"
29 #include "WeakImpl.h"
30 #include <wtf/DoublyLinkedList.h>
31 #include <wtf/StdLibExtras.h>
32
33 namespace JSC {
34
35 class Heap;
36 class HeapRootVisitor;
37
38 class WeakBlock : public DoublyLinkedListNode<WeakBlock> {
39 public:
40     friend class WTF::DoublyLinkedListNode<WeakBlock>;
41     static const size_t blockSize = 256; // 1/16 of MarkedBlock size
42
43     struct FreeCell {
44         FreeCell* next;
45     };
46
47     struct SweepResult {
48         bool isNull() const;
49
50         bool blockIsFree { true };
51         bool blockIsLogicallyEmpty { true };
52         FreeCell* freeList { nullptr };
53     };
54
55     static WeakBlock* create(Heap&, CellContainer);
56     static void destroy(Heap&, WeakBlock*);
57
58     static WeakImpl* asWeakImpl(FreeCell*);
59
60     bool isEmpty();
61     bool isLogicallyEmptyButNotFree() const;
62
63     void sweep();
64     SweepResult takeSweepResult();
65
66     void visit(HeapRootVisitor&);
67     void reap();
68
69     void lastChanceToFinalize();
70     void disconnectContainer() { m_container = CellContainer(); }
71
72 private:
73     static FreeCell* asFreeCell(WeakImpl*);
74     
75     template<typename ContainerType>
76     void specializedVisit(ContainerType&, HeapRootVisitor&);
77
78     explicit WeakBlock(CellContainer);
79     void finalize(WeakImpl*);
80     WeakImpl* weakImpls();
81     size_t weakImplCount();
82     void addToFreeList(FreeCell**, WeakImpl*);
83
84     CellContainer m_container;
85     WeakBlock* m_prev;
86     WeakBlock* m_next;
87     SweepResult m_sweepResult;
88 };
89
90 inline bool WeakBlock::SweepResult::isNull() const
91 {
92     return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null.
93 }
94
95 inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell)
96 {
97     return reinterpret_cast_ptr<WeakImpl*>(freeCell);
98 }
99
100 inline WeakBlock::SweepResult WeakBlock::takeSweepResult()
101 {
102     SweepResult tmp;
103     std::swap(tmp, m_sweepResult);
104     ASSERT(m_sweepResult.isNull());
105     return tmp;
106 }
107
108 inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl)
109 {
110     return reinterpret_cast_ptr<FreeCell*>(weakImpl);
111 }
112
113 inline WeakImpl* WeakBlock::weakImpls()
114 {
115     return reinterpret_cast_ptr<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
116 }
117
118 inline size_t WeakBlock::weakImplCount()
119 {
120     return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
121 }
122
123 inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl)
124 {
125     ASSERT(weakImpl->state() == WeakImpl::Deallocated);
126     FreeCell* freeCell = asFreeCell(weakImpl);
127     ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize));
128     ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize);
129     freeCell->next = *freeList;
130     *freeList = freeCell;
131 }
132
133 inline bool WeakBlock::isEmpty()
134 {
135     return !m_sweepResult.isNull() && m_sweepResult.blockIsFree;
136 }
137
138 inline bool WeakBlock::isLogicallyEmptyButNotFree() const
139 {
140     return !m_sweepResult.isNull() && !m_sweepResult.blockIsFree && m_sweepResult.blockIsLogicallyEmpty;
141 }
142
143 } // namespace JSC