Home | History | Annotate | Download | only in heap
      1 /*
      2  * Copyright (C) 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. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "HandleHeap.h"
     28 
     29 #include "JSObject.h"
     30 
     31 namespace JSC {
     32 
     33 WeakHandleOwner::~WeakHandleOwner()
     34 {
     35 }
     36 
     37 bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, MarkStack&)
     38 {
     39     return false;
     40 }
     41 
     42 void WeakHandleOwner::finalize(Handle<Unknown>, void*)
     43 {
     44 }
     45 
     46 HandleHeap::HandleHeap(JSGlobalData* globalData)
     47     : m_globalData(globalData)
     48     , m_nextToFinalize(0)
     49 {
     50     grow();
     51 }
     52 
     53 void HandleHeap::grow()
     54 {
     55     Node* block = m_blockStack.grow();
     56     for (int i = m_blockStack.blockLength - 1; i >= 0; --i) {
     57         Node* node = &block[i];
     58         new (node) Node(this);
     59         m_freeList.push(node);
     60     }
     61 }
     62 
     63 void HandleHeap::markStrongHandles(HeapRootMarker& heapRootMarker)
     64 {
     65     Node* end = m_strongList.end();
     66     for (Node* node = m_strongList.begin(); node != end; node = node->next())
     67         heapRootMarker.mark(node->slot());
     68 }
     69 
     70 void HandleHeap::markWeakHandles(HeapRootMarker& heapRootMarker)
     71 {
     72     MarkStack& markStack = heapRootMarker.markStack();
     73 
     74     Node* end = m_weakList.end();
     75     for (Node* node = m_weakList.begin(); node != end; node = node->next()) {
     76         ASSERT(isValidWeakNode(node));
     77         JSCell* cell = node->slot()->asCell();
     78         if (Heap::isMarked(cell))
     79             continue;
     80 
     81         WeakHandleOwner* weakOwner = node->weakOwner();
     82         if (!weakOwner)
     83             continue;
     84 
     85         if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), markStack))
     86             continue;
     87 
     88         heapRootMarker.mark(node->slot());
     89     }
     90 }
     91 
     92 void HandleHeap::finalizeWeakHandles()
     93 {
     94     Node* end = m_weakList.end();
     95     for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {
     96         m_nextToFinalize = node->next();
     97 
     98         ASSERT(isValidWeakNode(node));
     99         JSCell* cell = node->slot()->asCell();
    100         if (Heap::isMarked(cell))
    101             continue;
    102 
    103         if (WeakHandleOwner* weakOwner = node->weakOwner()) {
    104             weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext());
    105             if (m_nextToFinalize != node->next()) // Owner deallocated node.
    106                 continue;
    107         }
    108 
    109         *node->slot() = JSValue();
    110         SentinelLinkedList<Node>::remove(node);
    111         m_immediateList.push(node);
    112     }
    113 
    114     m_nextToFinalize = 0;
    115 }
    116 
    117 void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value)
    118 {
    119     ASSERT(!m_nextToFinalize); // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
    120 
    121     if (!value == !*slot && slot->isCell() == value.isCell())
    122         return;
    123 
    124     Node* node = toNode(slot);
    125     SentinelLinkedList<Node>::remove(node);
    126     if (!value || !value.isCell()) {
    127         m_immediateList.push(node);
    128         return;
    129     }
    130 
    131     if (node->isWeak()) {
    132         m_weakList.push(node);
    133         return;
    134     }
    135 
    136     m_strongList.push(node);
    137 }
    138 
    139 unsigned HandleHeap::protectedGlobalObjectCount()
    140 {
    141     unsigned count = 0;
    142     Node* end = m_strongList.end();
    143     for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
    144         JSValue value = *node->slot();
    145         if (value.isObject() && asObject(value.asCell())->isGlobalObject())
    146             count++;
    147     }
    148     return count;
    149 }
    150 
    151 #if !ASSERT_DISABLED
    152 bool HandleHeap::isValidWeakNode(Node* node)
    153 {
    154     if (!node->isWeak())
    155         return false;
    156 
    157     JSValue value = *node->slot();
    158     if (!value || !value.isCell())
    159         return false;
    160 
    161     JSCell* cell = value.asCell();
    162     if (!cell || !cell->structure())
    163         return false;
    164 
    165 #if ENABLE(JSC_ZOMBIES)
    166     if (cell->isZombie())
    167         return false;
    168 #endif
    169 
    170     return true;
    171 }
    172 #endif
    173 
    174 } // namespace JSC
    175