Add logic to collect dirty objects as roots
[WebKit-https.git] / Source / JavaScriptCore / heap / MarkStack.cpp
1 /*
2  * Copyright (C) 2009, 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. ``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 #include "config.h"
27 #include "MarkStack.h"
28
29 #include "ConservativeRoots.h"
30 #include "Heap.h"
31 #include "JSArray.h"
32 #include "JSCell.h"
33 #include "JSObject.h"
34 #include "ScopeChain.h"
35 #include "Structure.h"
36
37 namespace JSC {
38
39 void MarkStack::reset()
40 {
41     m_values.shrinkAllocation(pageSize());
42     m_markSets.shrinkAllocation(pageSize());
43     m_opaqueRoots.clear();
44 }
45
46 void MarkStack::append(ConservativeRoots& conservativeRoots)
47 {
48     JSCell** roots = conservativeRoots.roots();
49     size_t size = conservativeRoots.size();
50     for (size_t i = 0; i < size; ++i)
51         internalAppend(roots[i]);
52 }
53
54 void SlotVisitor::visitChildren(JSCell* cell)
55 {
56 #if ENABLE(SIMPLE_HEAP_PROFILING)
57     m_visitedTypeCounts.count(cell);
58 #endif
59
60     ASSERT(Heap::isMarked(cell));
61     if (cell->structure()->typeInfo().type() < CompoundType) {
62         JSCell::visitChildren(cell, *this);
63         return;
64     }
65
66     if (!cell->structure()->typeInfo().overridesVisitChildren()) {
67         ASSERT(cell->isObject());
68 #ifdef NDEBUG
69         asObject(cell)->visitChildrenDirect(*this);
70 #else
71         ASSERT(!m_isCheckingForDefaultMarkViolation);
72         m_isCheckingForDefaultMarkViolation = true;
73         cell->methodTable()->visitChildren(cell, *this);
74         ASSERT(m_isCheckingForDefaultMarkViolation);
75         m_isCheckingForDefaultMarkViolation = false;
76 #endif
77         return;
78     }
79     if (cell->vptr() == m_jsArrayVPtr) {
80         asArray(cell)->visitChildrenDirect(*this);
81         return;
82     }
83     cell->methodTable()->visitChildren(cell, *this);
84 }
85
86 void SlotVisitor::drain()
87 {
88 #if !ASSERT_DISABLED
89     ASSERT(!m_isDraining);
90     m_isDraining = true;
91 #endif
92     while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
93         while (!m_markSets.isEmpty() && m_values.size() < 50) {
94             ASSERT(!m_markSets.isEmpty());
95             MarkSet& current = m_markSets.last();
96             ASSERT(current.m_values);
97             JSValue* end = current.m_end;
98             ASSERT(current.m_values);
99             ASSERT(current.m_values != end);
100         findNextUnmarkedNullValue:
101             ASSERT(current.m_values != end);
102             JSValue value = *current.m_values;
103             current.m_values++;
104
105             JSCell* cell;
106             if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
107                 if (current.m_values == end) {
108                     m_markSets.removeLast();
109                     continue;
110                 }
111                 goto findNextUnmarkedNullValue;
112             }
113
114             if (cell->structure()->typeInfo().type() < CompoundType) {
115 #if ENABLE(SIMPLE_HEAP_PROFILING)
116                 m_visitedTypeCounts.count(cell);
117 #endif
118                 JSCell::visitChildren(cell, *this);
119                 if (current.m_values == end) {
120                     m_markSets.removeLast();
121                     continue;
122                 }
123                 goto findNextUnmarkedNullValue;
124             }
125
126             if (current.m_values == end)
127                 m_markSets.removeLast();
128
129             visitChildren(cell);
130         }
131         while (!m_values.isEmpty())
132             visitChildren(m_values.removeLast());
133     }
134 #if !ASSERT_DISABLED
135     m_isDraining = false;
136 #endif
137 }
138
139 void SlotVisitor::harvestWeakReferences()
140 {
141     while (m_firstWeakReferenceHarvester) {
142         WeakReferenceHarvester* current = m_firstWeakReferenceHarvester;
143         WeakReferenceHarvester* next = reinterpret_cast<WeakReferenceHarvester*>(current->m_nextAndFlag & ~1);
144         current->m_nextAndFlag = 0;
145         m_firstWeakReferenceHarvester = next;
146         current->visitWeakReferences(*this);
147     }
148 }
149
150 #if ENABLE(GC_VALIDATION)
151 void MarkStack::validateSet(JSValue* values, size_t count)
152 {
153     for (size_t i = 0; i < count; i++) {
154         if (values[i])
155             validateValue(values[i]);
156     }
157 }
158
159 void MarkStack::validateValue(JSValue value)
160 {
161     if (!value)
162         CRASH();
163     if (!value.isCell())
164         return;
165     JSCell* cell = value.asCell();
166     if (!cell)
167         CRASH();
168
169     if (!cell->structure())
170         CRASH();
171
172     // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
173     // I hate this sentence.
174     if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
175         CRASH();
176 }
177 #else
178 void MarkStack::validateValue(JSValue)
179 {
180
181 #endif
182
183 } // namespace JSC