• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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