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