]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/Weak.h
a235a570b820a371cf541ee213e01013a683efd5
[apple/javascriptcore.git] / heap / Weak.h
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 enum AdoptTag { Adopt };
57 template<typename U> Weak(AdoptTag, Handle<U> handle)
58 : Handle<T>(handle.slot())
59 {
60 validateCell(get());
61 }
62
63 Weak(const Weak& other)
64 : Handle<T>()
65 {
66 if (!other.slot())
67 return;
68 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
69 }
70
71 template <typename U> Weak(const Weak<U>& other)
72 : Handle<T>()
73 {
74 if (!other.slot())
75 return;
76 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
77 }
78
79 enum HashTableDeletedValueTag { HashTableDeletedValue };
80 bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
81 Weak(HashTableDeletedValueTag)
82 : Handle<T>(hashTableDeletedValue())
83 {
84 }
85
86 ~Weak()
87 {
88 clear();
89 }
90
91 void swap(Weak& other)
92 {
93 Handle<T>::swap(other);
94 }
95
96 ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); }
97
98 void clear()
99 {
100 if (!slot())
101 return;
102 HandleHeap::heapFor(slot())->deallocate(slot());
103 setSlot(0);
104 }
105
106 void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0)
107 {
108 if (!slot()) {
109 setSlot(globalData.allocateGlobalHandle());
110 HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
111 }
112 ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner));
113 set(value);
114 }
115
116 template <typename U> Weak& operator=(const Weak<U>& other)
117 {
118 clear();
119 if (other.slot())
120 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
121 return *this;
122 }
123
124 Weak& operator=(const Weak& other)
125 {
126 clear();
127 if (other.slot())
128 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
129 return *this;
130 }
131
132 HandleSlot leakHandle()
133 {
134 ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
135 HandleSlot result = slot();
136 setSlot(0);
137 return result;
138 }
139
140 private:
141 static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
142
143 void set(ExternalType externalType)
144 {
145 ASSERT(slot());
146 JSValue value = HandleTypes<T>::toJSValue(externalType);
147 ASSERT(!value || !value.isCell() || Heap::isMarked(value.asCell()));
148 HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
149 *slot() = value;
150 }
151 };
152
153 template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
154 {
155 a.swap(b);
156 }
157
158 } // namespace JSC
159
160 namespace WTF {
161
162 template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTraits {
163 static const bool canCompareWithMemcmp = false;
164 };
165
166 template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { };
167
168 }
169
170 #endif // Weak_h