2011-05-24 Geoffrey Garen <ggaren@apple.com>
[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 inline void MarkStack::visitChildren(JSCell* cell)
55 {
56     ASSERT(Heap::isMarked(cell));
57     if (cell->structure()->typeInfo().type() < CompoundType) {
58         cell->JSCell::visitChildren(*this);
59         return;
60     }
61
62     if (!cell->structure()->typeInfo().overridesVisitChildren()) {
63         ASSERT(cell->isObject());
64 #ifdef NDEBUG
65         asObject(cell)->visitChildrenDirect(*this);
66 #else
67         ASSERT(!m_isCheckingForDefaultMarkViolation);
68         m_isCheckingForDefaultMarkViolation = true;
69         cell->visitChildren(*this);
70         ASSERT(m_isCheckingForDefaultMarkViolation);
71         m_isCheckingForDefaultMarkViolation = false;
72 #endif
73         return;
74     }
75     if (cell->vptr() == m_jsArrayVPtr) {
76         asArray(cell)->visitChildrenDirect(*this);
77         return;
78     }
79     cell->visitChildren(*this);
80 }
81
82 void MarkStack::drain()
83 {
84 #if !ASSERT_DISABLED
85     ASSERT(!m_isDraining);
86     m_isDraining = true;
87 #endif
88     while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
89         while (!m_markSets.isEmpty() && m_values.size() < 50) {
90             ASSERT(!m_markSets.isEmpty());
91             MarkSet& current = m_markSets.last();
92             ASSERT(current.m_values);
93             JSValue* end = current.m_end;
94             ASSERT(current.m_values);
95             ASSERT(current.m_values != end);
96         findNextUnmarkedNullValue:
97             ASSERT(current.m_values != end);
98             JSValue value = *current.m_values;
99             current.m_values++;
100
101             JSCell* cell;
102             if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
103                 if (current.m_values == end) {
104                     m_markSets.removeLast();
105                     continue;
106                 }
107                 goto findNextUnmarkedNullValue;
108             }
109
110             if (cell->structure()->typeInfo().type() < CompoundType) {
111                 cell->JSCell::visitChildren(*this);
112                 if (current.m_values == end) {
113                     m_markSets.removeLast();
114                     continue;
115                 }
116                 goto findNextUnmarkedNullValue;
117             }
118
119             if (current.m_values == end)
120                 m_markSets.removeLast();
121
122             visitChildren(cell);
123         }
124         while (!m_values.isEmpty())
125             visitChildren(m_values.removeLast());
126     }
127 #if !ASSERT_DISABLED
128     m_isDraining = false;
129 #endif
130 }
131
132 #if ENABLE(GC_VALIDATION)
133 void MarkStack::validateSet(JSValue* values, size_t count)
134 {
135     for (size_t i = 0; i < count; i++) {
136         if (values[i])
137             validateValue(values[i]);
138     }
139 }
140
141 void MarkStack::validateValue(JSValue value)
142 {
143     if (!value)
144         CRASH();
145     if (!value.isCell())
146         return;
147     JSCell* cell = value.asCell();
148     if (!cell)
149         CRASH();
150
151     if (!cell->structure())
152         CRASH();
153
154     // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
155     // I hate this sentence.
156     if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
157         CRASH();
158 }
159 #endif
160
161 } // namespace JSC