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 size_t MarkStack::s_pageSize = 0;
40
reset()41 void MarkStack::reset()
42 {
43 ASSERT(s_pageSize);
44 m_values.shrinkAllocation(s_pageSize);
45 m_markSets.shrinkAllocation(s_pageSize);
46 m_opaqueRoots.clear();
47 }
48
append(ConservativeRoots & conservativeRoots)49 void MarkStack::append(ConservativeRoots& conservativeRoots)
50 {
51 JSCell** roots = conservativeRoots.roots();
52 size_t size = conservativeRoots.size();
53 for (size_t i = 0; i < size; ++i)
54 internalAppend(roots[i]);
55 }
56
markChildren(JSCell * cell)57 inline void MarkStack::markChildren(JSCell* cell)
58 {
59 ASSERT(Heap::isMarked(cell));
60 if (cell->structure()->typeInfo().type() < CompoundType) {
61 cell->JSCell::markChildren(*this);
62 return;
63 }
64
65 if (!cell->structure()->typeInfo().overridesMarkChildren()) {
66 ASSERT(cell->isObject());
67 #ifdef NDEBUG
68 asObject(cell)->markChildrenDirect(*this);
69 #else
70 ASSERT(!m_isCheckingForDefaultMarkViolation);
71 m_isCheckingForDefaultMarkViolation = true;
72 cell->markChildren(*this);
73 ASSERT(m_isCheckingForDefaultMarkViolation);
74 m_isCheckingForDefaultMarkViolation = false;
75 #endif
76 return;
77 }
78 if (cell->vptr() == m_jsArrayVPtr) {
79 asArray(cell)->markChildrenDirect(*this);
80 return;
81 }
82 cell->markChildren(*this);
83 }
84
drain()85 void MarkStack::drain()
86 {
87 #if !ASSERT_DISABLED
88 ASSERT(!m_isDraining);
89 m_isDraining = true;
90 #endif
91 while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
92 while (!m_markSets.isEmpty() && m_values.size() < 50) {
93 ASSERT(!m_markSets.isEmpty());
94 MarkSet& current = m_markSets.last();
95 ASSERT(current.m_values);
96 JSValue* end = current.m_end;
97 ASSERT(current.m_values);
98 ASSERT(current.m_values != end);
99 findNextUnmarkedNullValue:
100 ASSERT(current.m_values != end);
101 JSValue value = *current.m_values;
102 current.m_values++;
103
104 JSCell* cell;
105 if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
106 if (current.m_values == end) {
107 m_markSets.removeLast();
108 continue;
109 }
110 goto findNextUnmarkedNullValue;
111 }
112
113 if (cell->structure()->typeInfo().type() < CompoundType) {
114 cell->JSCell::markChildren(*this);
115 if (current.m_values == end) {
116 m_markSets.removeLast();
117 continue;
118 }
119 goto findNextUnmarkedNullValue;
120 }
121
122 if (current.m_values == end)
123 m_markSets.removeLast();
124
125 markChildren(cell);
126 }
127 while (!m_values.isEmpty())
128 markChildren(m_values.removeLast());
129 }
130 #if !ASSERT_DISABLED
131 m_isDraining = false;
132 #endif
133 }
134
135 } // namespace JSC
136