2011-04-07 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / collector / handles / HandleHeap.cpp
1 /*
2  * Copyright (C) 2011 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 #include "config.h"
27 #include "HandleHeap.h"
28
29 #include "JSObject.h"
30
31 namespace JSC {
32
33 WeakHandleOwner::~WeakHandleOwner()
34 {
35 }
36
37 bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, MarkStack&)
38 {
39     return false;
40 }
41
42 void WeakHandleOwner::finalize(Handle<Unknown>, void*)
43 {
44 }
45
46 HandleHeap::HandleHeap(JSGlobalData* globalData)
47     : m_globalData(globalData)
48     , m_nextToFinalize(0)
49 {
50     grow();
51 }
52
53 void HandleHeap::grow()
54 {
55     Node* block = m_blockStack.grow();
56     for (int i = m_blockStack.blockLength - 1; i >= 0; --i) {
57         Node* node = &block[i];
58         new (node) Node(this);
59         m_freeList.push(node);
60     }
61 }
62
63 void HandleHeap::markStrongHandles(HeapRootMarker& heapRootMarker)
64 {
65     Node* end = m_strongList.end();
66     for (Node* node = m_strongList.begin(); node != end; node = node->next())
67         heapRootMarker.mark(node->slot());
68 }
69
70 void HandleHeap::markWeakHandles(HeapRootMarker& heapRootMarker)
71 {
72     MarkStack& markStack = heapRootMarker.markStack();
73
74     int oldCount;
75     do {
76         oldCount = markStack.opaqueRootCount();
77
78         Node* end = m_weakList.end();
79         for (Node* node = m_weakList.begin(); node != end; node = node->next()) {
80             ASSERT(isValidWeakNode(node));
81             JSCell* cell = node->slot()->asCell();
82             if (Heap::isMarked(cell))
83                 continue;
84
85             WeakHandleOwner* weakOwner = node->weakOwner();
86             if (!weakOwner)
87                 continue;
88
89             if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), markStack))
90                 continue;
91
92             heapRootMarker.mark(node->slot());
93         }
94     } while (oldCount != markStack.opaqueRootCount()); // If the set of opaque roots has grown, more handles may have become reachable.
95 }
96
97 void HandleHeap::finalizeWeakHandles()
98 {
99     Node* end = m_weakList.end();
100     for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {
101         m_nextToFinalize = node->next();
102
103         ASSERT(isValidWeakNode(node));
104         JSCell* cell = node->slot()->asCell();
105         if (Heap::isMarked(cell))
106             continue;
107
108         if (WeakHandleOwner* weakOwner = node->weakOwner()) {
109             weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext());
110             if (m_nextToFinalize != node->next()) // Owner deallocated node.
111                 continue;
112         }
113
114         *node->slot() = JSValue();
115         SentinelLinkedList<Node>::remove(node);
116         m_immediateList.push(node);
117     }
118     
119     m_nextToFinalize = 0;
120 }
121
122 void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value)
123 {
124     ASSERT(!m_nextToFinalize); // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
125
126     if (!value == !*slot && slot->isCell() == value.isCell())
127         return;
128
129     Node* node = toNode(slot);
130     SentinelLinkedList<Node>::remove(node);
131     if (!value || !value.isCell()) {
132         m_immediateList.push(node);
133         return;
134     }
135
136     if (node->isWeak()) {
137         m_weakList.push(node);
138         return;
139     }
140
141     m_strongList.push(node);
142 }
143
144 unsigned HandleHeap::protectedGlobalObjectCount()
145 {
146     unsigned count = 0;
147     Node* end = m_strongList.end();
148     for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
149         JSValue value = *node->slot();
150         if (value.isObject() && asObject(value.asCell())->isGlobalObject())
151             count++;
152     }
153     return count;
154 }
155
156 #if !ASSERT_DISABLED
157 bool HandleHeap::isValidWeakNode(Node* node)
158 {
159     if (!node->isWeak())
160         return false;
161
162     JSValue value = *node->slot();
163     if (!value || !value.isCell())
164         return false;
165
166     JSCell* cell = value.asCell();
167     if (!cell || !cell->structure())
168         return false;
169
170 #if ENABLE(JSC_ZOMBIES)
171     if (cell->isZombie())
172         return false;
173 #endif
174
175     return true;
176 }
177 #endif
178
179 } // namespace JSC