MarkStack.cpp 5.09 KB
Newer Older
1
/*
2
 * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "MarkStack.h"

29
#include "ConservativeRoots.h"
30 31 32
#include "Heap.h"
#include "JSArray.h"
#include "JSCell.h"
33 34
#include "JSObject.h"
#include "ScopeChain.h"
35 36
#include "Structure.h"

37
namespace JSC {
38

39
void MarkStack::reset()
40
{
41 42
    m_values.shrinkAllocation(pageSize());
    m_markSets.shrinkAllocation(pageSize());
43
    m_opaqueRoots.clear();
44 45
}

46 47 48 49 50 51 52 53
void MarkStack::append(ConservativeRoots& conservativeRoots)
{
    JSCell** roots = conservativeRoots.roots();
    size_t size = conservativeRoots.size();
    for (size_t i = 0; i < size; ++i)
        internalAppend(roots[i]);
}

54
inline void SlotVisitor::visitChildren(JSCell* cell)
55
{
56 57 58 59
#if ENABLE(SIMPLE_HEAP_PROFILING)
    m_visitedTypeCounts.count(cell);
#endif

60
    ASSERT(Heap::isMarked(cell));
61
    if (cell->structure()->typeInfo().type() < CompoundType) {
62
        cell->JSCell::visitChildren(*this);
63 64 65
        return;
    }

66
    if (!cell->structure()->typeInfo().overridesVisitChildren()) {
67
        ASSERT(cell->isObject());
68
#ifdef NDEBUG
69
        asObject(cell)->visitChildrenDirect(*this);
70 71 72
#else
        ASSERT(!m_isCheckingForDefaultMarkViolation);
        m_isCheckingForDefaultMarkViolation = true;
73
        cell->visitChildren(*this);
74 75 76 77 78 79
        ASSERT(m_isCheckingForDefaultMarkViolation);
        m_isCheckingForDefaultMarkViolation = false;
#endif
        return;
    }
    if (cell->vptr() == m_jsArrayVPtr) {
80
        asArray(cell)->visitChildrenDirect(*this);
81 82
        return;
    }
83
    cell->visitChildren(*this);
84 85
}

86
void SlotVisitor::drain()
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
{
#if !ASSERT_DISABLED
    ASSERT(!m_isDraining);
    m_isDraining = true;
#endif
    while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
        while (!m_markSets.isEmpty() && m_values.size() < 50) {
            ASSERT(!m_markSets.isEmpty());
            MarkSet& current = m_markSets.last();
            ASSERT(current.m_values);
            JSValue* end = current.m_end;
            ASSERT(current.m_values);
            ASSERT(current.m_values != end);
        findNextUnmarkedNullValue:
            ASSERT(current.m_values != end);
            JSValue value = *current.m_values;
            current.m_values++;

            JSCell* cell;
            if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
                if (current.m_values == end) {
                    m_markSets.removeLast();
                    continue;
                }
                goto findNextUnmarkedNullValue;
            }

            if (cell->structure()->typeInfo().type() < CompoundType) {
115 116 117
#if ENABLE(SIMPLE_HEAP_PROFILING)
                m_visitedTypeCounts.count(cell);
#endif
118
                cell->JSCell::visitChildren(*this);
119 120 121 122 123 124 125 126 127 128
                if (current.m_values == end) {
                    m_markSets.removeLast();
                    continue;
                }
                goto findNextUnmarkedNullValue;
            }

            if (current.m_values == end)
                m_markSets.removeLast();

129
            visitChildren(cell);
130 131
        }
        while (!m_values.isEmpty())
132
            visitChildren(m_values.removeLast());
133 134 135 136
    }
#if !ASSERT_DISABLED
    m_isDraining = false;
#endif
137
}
138

139
#if ENABLE(GC_VALIDATION)
140 141 142 143 144 145 146 147 148 149
void MarkStack::validateSet(JSValue* values, size_t count)
{
    for (size_t i = 0; i < count; i++) {
        if (values[i])
            validateValue(values[i]);
    }
}

void MarkStack::validateValue(JSValue value)
{
150 151
    if (!value)
        CRASH();
152 153 154
    if (!value.isCell())
        return;
    JSCell* cell = value.asCell();
155 156 157 158 159 160
    if (!cell)
        CRASH();

    if (!cell->structure())
        CRASH();

161 162
    // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
    // I hate this sentence.
163 164
    if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
        CRASH();
165
}
166
#endif
167

168
} // namespace JSC