Home | History | Annotate | Download | only in heap
      1 /*
      2  * Copyright (C) 2009 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 Weak_h
     27 #define Weak_h
     28 
     29 #include "Assertions.h"
     30 #include "Handle.h"
     31 #include "HandleHeap.h"
     32 #include "JSGlobalData.h"
     33 
     34 namespace JSC {
     35 
     36 // A weakly referenced handle that becomes 0 when the value it points to is garbage collected.
     37 template <typename T> class Weak : public Handle<T> {
     38     using Handle<T>::slot;
     39     using Handle<T>::setSlot;
     40 
     41 public:
     42     typedef typename Handle<T>::ExternalType ExternalType;
     43 
     44     Weak()
     45         : Handle<T>()
     46     {
     47     }
     48 
     49     Weak(JSGlobalData& globalData, ExternalType value = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0)
     50         : Handle<T>(globalData.allocateGlobalHandle())
     51     {
     52         HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
     53         set(value);
     54     }
     55 
     56     Weak(const Weak& other)
     57         : Handle<T>()
     58     {
     59         if (!other.slot())
     60             return;
     61         setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
     62     }
     63 
     64     template <typename U> Weak(const Weak<U>& other)
     65         : Handle<T>()
     66     {
     67         if (!other.slot())
     68             return;
     69         setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
     70     }
     71 
     72     enum HashTableDeletedValueTag { HashTableDeletedValue };
     73     bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
     74     Weak(HashTableDeletedValueTag)
     75         : Handle<T>(hashTableDeletedValue())
     76     {
     77     }
     78 
     79     ~Weak()
     80     {
     81         clear();
     82     }
     83 
     84     void swap(Weak& other)
     85     {
     86         Handle<T>::swap(other);
     87     }
     88 
     89     ExternalType get() const { return  HandleTypes<T>::getFromSlot(slot()); }
     90 
     91     void clear()
     92     {
     93         if (!slot())
     94             return;
     95         HandleHeap::heapFor(slot())->deallocate(slot());
     96         setSlot(0);
     97     }
     98 
     99     void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0)
    100     {
    101         if (!slot()) {
    102             setSlot(globalData.allocateGlobalHandle());
    103             HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
    104         }
    105         ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner));
    106         set(value);
    107     }
    108 
    109     template <typename U> Weak& operator=(const Weak<U>& other)
    110     {
    111         clear();
    112         if (other.slot())
    113             setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
    114         return *this;
    115     }
    116 
    117     Weak& operator=(const Weak& other)
    118     {
    119         clear();
    120         if (other.slot())
    121             setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
    122         return *this;
    123     }
    124 
    125 private:
    126     static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
    127 
    128     void set(ExternalType externalType)
    129     {
    130         ASSERT(slot());
    131         JSValue value = HandleTypes<T>::toJSValue(externalType);
    132         ASSERT(!value || !value.isCell() || Heap::isMarked(value.asCell()));
    133         HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
    134         *slot() = value;
    135     }
    136 };
    137 
    138 template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
    139 {
    140     a.swap(b);
    141 }
    142 
    143 } // namespace JSC
    144 
    145 namespace WTF {
    146 
    147 template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTraits {
    148     static const bool canCompareWithMemcmp = false;
    149 };
    150 
    151 template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { };
    152 
    153 }
    154 
    155 #endif // Weak_h
    156