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