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 #ifndef HandleHeap_h
     27 #define HandleHeap_h
     28 
     29 #include "BlockStack.h"
     30 #include "Handle.h"
     31 #include "SentinelLinkedList.h"
     32 #include "SinglyLinkedList.h"
     33 
     34 namespace JSC {
     35 
     36 class HandleHeap;
     37 class HeapRootMarker;
     38 class JSGlobalData;
     39 class JSValue;
     40 class MarkStack;
     41 class TypeCounter;
     42 
     43 class WeakHandleOwner {
     44 public:
     45     virtual ~WeakHandleOwner();
     46     virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&);
     47     virtual void finalize(Handle<Unknown>, void* context);
     48 };
     49 
     50 class HandleHeap {
     51 public:
     52     static HandleHeap* heapFor(HandleSlot);
     53 
     54     HandleHeap(JSGlobalData*);
     55 
     56     JSGlobalData* globalData();
     57 
     58     HandleSlot allocate();
     59     void deallocate(HandleSlot);
     60 
     61     void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
     62     HandleSlot copyWeak(HandleSlot);
     63 
     64     void markStrongHandles(HeapRootMarker&);
     65     void markWeakHandles(HeapRootMarker&);
     66     void finalizeWeakHandles();
     67 
     68     void writeBarrier(HandleSlot, const JSValue&);
     69 
     70 #if !ASSERT_DISABLED
     71     bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
     72 #endif
     73 
     74     unsigned protectedGlobalObjectCount();
     75     void protectedObjectTypeCounts(TypeCounter&);
     76 
     77 private:
     78     class Node {
     79     public:
     80         Node(WTF::SentinelTag);
     81         Node(HandleHeap*);
     82 
     83         HandleSlot slot();
     84         HandleHeap* handleHeap();
     85 
     86         void makeWeak(WeakHandleOwner*, void* context);
     87         bool isWeak();
     88 
     89         WeakHandleOwner* weakOwner();
     90         void* weakOwnerContext();
     91 
     92         void setPrev(Node*);
     93         Node* prev();
     94 
     95         void setNext(Node*);
     96         Node* next();
     97 
     98     private:
     99         WeakHandleOwner* emptyWeakOwner();
    100 
    101         JSValue m_value;
    102         HandleHeap* m_handleHeap;
    103         WeakHandleOwner* m_weakOwner;
    104         void* m_weakOwnerContext;
    105         Node* m_prev;
    106         Node* m_next;
    107     };
    108 
    109     static HandleSlot toHandle(Node*);
    110     static Node* toNode(HandleSlot);
    111 
    112     void grow();
    113 
    114 #if !ASSERT_DISABLED
    115     bool isValidWeakNode(Node*);
    116 #endif
    117 
    118     JSGlobalData* m_globalData;
    119     BlockStack<Node> m_blockStack;
    120 
    121     SentinelLinkedList<Node> m_strongList;
    122     SentinelLinkedList<Node> m_weakList;
    123     SentinelLinkedList<Node> m_immediateList;
    124     SinglyLinkedList<Node> m_freeList;
    125     Node* m_nextToFinalize;
    126 };
    127 
    128 inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
    129 {
    130     return toNode(handle)->handleHeap();
    131 }
    132 
    133 inline JSGlobalData* HandleHeap::globalData()
    134 {
    135     return m_globalData;
    136 }
    137 
    138 inline HandleSlot HandleHeap::toHandle(Node* node)
    139 {
    140     return reinterpret_cast<HandleSlot>(node);
    141 }
    142 
    143 inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle)
    144 {
    145     return reinterpret_cast<Node*>(handle);
    146 }
    147 
    148 inline HandleSlot HandleHeap::allocate()
    149 {
    150     if (m_freeList.isEmpty())
    151         grow();
    152 
    153     Node* node = m_freeList.pop();
    154     new (node) Node(this);
    155     m_immediateList.push(node);
    156     return toHandle(node);
    157 }
    158 
    159 inline void HandleHeap::deallocate(HandleSlot handle)
    160 {
    161     Node* node = toNode(handle);
    162     if (node == m_nextToFinalize) {
    163         m_nextToFinalize = node->next();
    164         ASSERT(m_nextToFinalize->next());
    165     }
    166 
    167     SentinelLinkedList<Node>::remove(node);
    168     m_freeList.push(node);
    169 }
    170 
    171 inline HandleSlot HandleHeap::copyWeak(HandleSlot other)
    172 {
    173     Node* node = toNode(allocate());
    174     node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());
    175     writeBarrier(node->slot(), *other);
    176     *node->slot() = *other;
    177     return toHandle(node);
    178 }
    179 
    180 inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
    181 {
    182     Node* node = toNode(handle);
    183     node->makeWeak(weakOwner, context);
    184 
    185     SentinelLinkedList<Node>::remove(node);
    186     if (!*handle || !handle->isCell()) {
    187         m_immediateList.push(node);
    188         return;
    189     }
    190 
    191     m_weakList.push(node);
    192 }
    193 
    194 #if !ASSERT_DISABLED
    195 inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
    196 {
    197     return toNode(handle)->weakOwner() == weakOwner;
    198 }
    199 #endif
    200 
    201 inline HandleHeap::Node::Node(HandleHeap* handleHeap)
    202     : m_handleHeap(handleHeap)
    203     , m_weakOwner(0)
    204     , m_weakOwnerContext(0)
    205 {
    206 }
    207 
    208 inline HandleHeap::Node::Node(WTF::SentinelTag)
    209     : m_handleHeap(0)
    210     , m_weakOwner(0)
    211     , m_weakOwnerContext(0)
    212 {
    213 }
    214 
    215 inline HandleSlot HandleHeap::Node::slot()
    216 {
    217     return &m_value;
    218 }
    219 
    220 inline HandleHeap* HandleHeap::Node::handleHeap()
    221 {
    222     return m_handleHeap;
    223 }
    224 
    225 inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
    226 {
    227     m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
    228     m_weakOwnerContext = context;
    229 }
    230 
    231 inline bool HandleHeap::Node::isWeak()
    232 {
    233     return m_weakOwner; // True for emptyWeakOwner().
    234 }
    235 
    236 inline WeakHandleOwner* HandleHeap::Node::weakOwner()
    237 {
    238     return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
    239 }
    240 
    241 inline void* HandleHeap::Node::weakOwnerContext()
    242 {
    243     ASSERT(weakOwner());
    244     return m_weakOwnerContext;
    245 }
    246 
    247 inline void HandleHeap::Node::setPrev(Node* prev)
    248 {
    249     m_prev = prev;
    250 }
    251 
    252 inline HandleHeap::Node* HandleHeap::Node::prev()
    253 {
    254     return m_prev;
    255 }
    256 
    257 inline void HandleHeap::Node::setNext(Node* next)
    258 {
    259     m_next = next;
    260 }
    261 
    262 inline HandleHeap::Node* HandleHeap::Node::next()
    263 {
    264     return m_next;
    265 }
    266 
    267 // Sentinel to indicate that a node is weak, but its owner has no meaningful
    268 // callbacks. This allows us to optimize by skipping such nodes.
    269 inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
    270 {
    271     return reinterpret_cast<WeakHandleOwner*>(-1);
    272 }
    273 
    274 }
    275 
    276 #endif
    277