Home | History | Annotate | Download | only in heap
      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 
     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 
     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 
     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 
     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