]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/WeakBlock.h
9e546ea32ecb3f2e1be1d54255cb55b741d5528e
[apple/javascriptcore.git] / heap / WeakBlock.h
1 /*
2 * Copyright (C) 2012 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 #ifndef WeakBlock_h
27 #define WeakBlock_h
28
29 #include "HeapBlock.h"
30 #include "WeakHandleOwner.h"
31 #include "WeakImpl.h"
32 #include <wtf/DoublyLinkedList.h>
33 #include <wtf/PageAllocation.h>
34 #include <wtf/StdLibExtras.h>
35
36 namespace JSC {
37
38 class HeapRootVisitor;
39 class JSValue;
40 class WeakHandleOwner;
41
42 class WeakBlock : public DoublyLinkedListNode<WeakBlock> {
43 public:
44 friend class WTF::DoublyLinkedListNode<WeakBlock>;
45 static const size_t blockSize = 4 * KB;
46
47 struct FreeCell {
48 FreeCell* next;
49 };
50
51 struct SweepResult {
52 SweepResult();
53 bool isNull() const;
54
55 bool blockIsFree;
56 FreeCell* freeList;
57 };
58
59 static WeakBlock* create();
60 static void destroy(WeakBlock*);
61
62 static WeakImpl* asWeakImpl(FreeCell*);
63
64 void sweep();
65 const SweepResult& sweepResult();
66 SweepResult takeSweepResult();
67
68 void visitLiveWeakImpls(HeapRootVisitor&);
69 void visitDeadWeakImpls(HeapRootVisitor&);
70
71 void finalizeAll();
72
73 private:
74 static FreeCell* asFreeCell(WeakImpl*);
75
76 WeakBlock(PageAllocation&);
77 WeakImpl* firstWeakImpl();
78 void finalize(WeakImpl*);
79 WeakImpl* weakImpls();
80 size_t weakImplCount();
81 void addToFreeList(FreeCell**, WeakImpl*);
82
83 PageAllocation m_allocation;
84 WeakBlock* m_prev;
85 WeakBlock* m_next;
86 SweepResult m_sweepResult;
87 };
88
89 inline WeakBlock::SweepResult::SweepResult()
90 : blockIsFree(true)
91 , freeList(0)
92 {
93 ASSERT(isNull());
94 }
95
96 inline bool WeakBlock::SweepResult::isNull() const
97 {
98 return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null.
99 }
100
101 inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell)
102 {
103 return reinterpret_cast<WeakImpl*>(freeCell);
104 }
105
106 inline WeakBlock::SweepResult WeakBlock::takeSweepResult()
107 {
108 SweepResult tmp;
109 std::swap(tmp, m_sweepResult);
110 ASSERT(m_sweepResult.isNull());
111 return tmp;
112 }
113
114 inline const WeakBlock::SweepResult& WeakBlock::sweepResult()
115 {
116 return m_sweepResult;
117 }
118
119 inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl)
120 {
121 return reinterpret_cast<FreeCell*>(weakImpl);
122 }
123
124 inline void WeakBlock::finalize(WeakImpl* weakImpl)
125 {
126 ASSERT(weakImpl->state() == WeakImpl::Dead);
127 weakImpl->setState(WeakImpl::Finalized);
128 WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
129 if (!weakHandleOwner)
130 return;
131 weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context());
132 }
133
134 inline WeakImpl* WeakBlock::weakImpls()
135 {
136 return reinterpret_cast<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
137 }
138
139 inline size_t WeakBlock::weakImplCount()
140 {
141 return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
142 }
143
144 inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl)
145 {
146 ASSERT(weakImpl->state() == WeakImpl::Deallocated);
147 FreeCell* freeCell = asFreeCell(weakImpl);
148 ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize));
149 ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize);
150 freeCell->next = *freeList;
151 *freeList = freeCell;
152 }
153
154 } // namespace JSC
155
156 #endif // WeakBlock_h