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