571fe3121376942c5aaf257b7eb8fc20ab0e1a6b
[WebKit-https.git] / Source / JavaScriptCore / collector / handles / Global.h
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 Global_h
27 #define Global_h
28
29 #include "Assertions.h"
30 #include "Handle.h"
31 #include "HandleHeap.h"
32 #include "JSGlobalData.h"
33
34 namespace JSC {
35
36 /*
37     A Global is a persistent handle whose lifetime is not limited to any given
38     scope. Use Globals for data members and global variables.
39 */
40
41 template <typename T> class Global : public Handle<T> {
42 public:
43     typedef typename Handle<T>::ExternalType ExternalType;
44     Global(JSGlobalData& globalData, ExternalType ptr = ExternalType())
45         : Handle<T>(globalData.allocateGlobalHandle())
46     {
47         internalSet(ptr);
48     }
49
50     Global(JSGlobalData& globalData, Handle<T> handle)
51         : Handle<T>(globalData.allocateGlobalHandle())
52     {
53         internalSet(handle.get());
54     }
55     
56     enum EmptyValueTag { EmptyValue };
57     Global(EmptyValueTag)
58         : Handle<T>(0, HandleBase::DontNullCheckSlot)
59     {
60     }
61
62     ~Global()
63     {
64         HandleSlot slot = this->slot();
65         if (slot)
66             HandleHeap::heapFor(slot)->deallocate(slot);
67     }
68
69     void set(JSGlobalData& globalData, ExternalType value)
70     {
71         if (!value) {
72             clear();
73             return;
74         }
75         if (!this->slot())
76             this->setSlot(globalData.allocateGlobalHandle());
77         internalSet(value);
78     }
79
80     template <typename U> Global& operator=(const Global<U>& handle)
81     {
82         if (handle.slot()) {
83             if (!this->slot())
84                 this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
85             internalSet(handle.get());
86         } else
87             clear();
88         
89         return *this;
90     }
91     
92     Global& operator=(const Global& handle)
93     {
94         if (handle.slot()) {
95             if (!this->slot())
96                 this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
97             internalSet(handle.get());
98         } else
99             clear();
100         
101         return *this;
102     }
103
104     void clear()
105     {
106         if (this->slot())
107             internalSet(ExternalType());
108     }
109
110     enum HashTableDeletedValueType { HashTableDeletedValue };
111     const static intptr_t HashTableDeletedValueTag = 0x1;
112     Global(HashTableDeletedValueType)
113         : Handle<T>(reinterpret_cast<HandleSlot>(HashTableDeletedValueTag))
114     {
115     }
116     bool isHashTableDeletedValue() const { return slot() == reinterpret_cast<HandleSlot>(HashTableDeletedValueTag); }
117
118     template <typename U> Global(const Global<U>& other)
119         : Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
120     {
121         if (other.slot())
122             internalSet(other.get());
123     }
124     
125     Global(const Global& other)
126         : Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
127     {
128         if (other.slot())
129             internalSet(other.get());
130     }
131
132 protected:
133     void internalSet(ExternalType value)
134     {
135         JSValue newValue(HandleTypes<T>::toJSValue(value));
136         HandleSlot slot = this->slot();
137         ASSERT(slot);
138         HandleHeap::heapFor(slot)->writeBarrier(slot, newValue);
139         *slot = newValue;
140     }
141
142     using Handle<T>::slot;
143     
144 };
145
146 }
147
148 namespace WTF {
149
150 template<typename P> struct HashTraits<JSC::Global<P> > : GenericHashTraits<JSC::Global<P> > {
151     static const bool emptyValueIsZero = true;
152     static JSC::Global<P> emptyValue() { return JSC::Global<P>(JSC::Global<P>::EmptyValue); }
153     static void constructDeletedValue(JSC::Global<P>& slot) { new (&slot) JSC::Global<P>(JSC::Global<P>::HashTableDeletedValue); }
154     static bool isDeletedValue(const JSC::Global<P>& value) { return value.isHashTableDeletedValue(); }
155 };
156
157 }
158
159 #endif // Global_h