| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #ifndef V8_UTIL_H_ |
| 29 #define V8_UTIL_H_ |
| 30 |
| 31 #include "v8.h" |
| 32 |
| 33 /** |
| 34 * Support for Persistent containers. |
| 35 * |
| 36 * C++11 embedders can use STL containers with UniquePersistent values, |
| 37 * but pre-C++11 does not support the required move semantic and hence |
| 38 * may want these container classes. |
| 39 */ |
| 40 namespace v8 { |
| 41 |
| 42 typedef uintptr_t PersistentContainerValue; |
| 43 static const uintptr_t kPersistentContainerNotFound = 0; |
| 44 |
| 45 /** |
| 46 * A map wrapper that allows using UniquePersistent as a mapped value. |
| 47 * C++11 embedders don't need this class, as they can use UniquePersistent |
| 48 * directly in std containers. |
| 49 * |
| 50 * The map relies on a backing map, whose type and accessors are described |
| 51 * by the Traits class. The backing map will handle values of type |
| 52 * PersistentContainerValue, with all conversion into and out of V8 |
| 53 * handles being transparently handled by this class. |
| 54 */ |
| 55 template<class K, class V, class Traits> |
| 56 class PersistentValueMap { |
| 57 public: |
| 58 V8_INLINE explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} |
| 59 |
| 60 V8_INLINE ~PersistentValueMap() { Clear(); } |
| 61 |
| 62 V8_INLINE Isolate* GetIsolate() { return isolate_; } |
| 63 |
| 64 /** |
| 65 * Return size of the map. |
| 66 */ |
| 67 V8_INLINE size_t Size() { return Traits::Size(&impl_); } |
| 68 |
| 69 /** |
| 70 * Get value stored in map. |
| 71 */ |
| 72 V8_INLINE Local<V> Get(const K& key) { |
| 73 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key))); |
| 74 } |
| 75 |
| 76 /** |
| 77 * Check whether a value is contained in the map. |
| 78 */ |
| 79 V8_INLINE bool Contains(const K& key) { |
| 80 return Traits::Get(&impl_, key) != 0; |
| 81 } |
| 82 |
| 83 /** |
| 84 * Get value stored in map and set it in returnValue. |
| 85 * Return true if a value was found. |
| 86 */ |
| 87 V8_INLINE bool SetReturnValue(const K& key, |
| 88 ReturnValue<Value>& returnValue); |
| 89 |
| 90 /** |
| 91 * Call Isolate::SetReference with the given parent and the map value. |
| 92 */ |
| 93 V8_INLINE void SetReference(const K& key, |
| 94 const v8::Persistent<v8::Object>& parent) { |
| 95 GetIsolate()->SetReference( |
| 96 reinterpret_cast<internal::Object**>(parent.val_), |
| 97 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); |
| 98 } |
| 99 |
| 100 /** |
| 101 * Put value into map. Depending on Traits::kIsWeak, the value will be held |
| 102 * by the map strongly or weakly. |
| 103 * Returns old value as UniquePersistent. |
| 104 */ |
| 105 UniquePersistent<V> Set(const K& key, Local<V> value) { |
| 106 UniquePersistent<V> persistent(isolate_, value); |
| 107 return SetUnique(key, &persistent); |
| 108 } |
| 109 |
| 110 /** |
| 111 * Put value into map, like Set(const K&, Local<V>). |
| 112 */ |
| 113 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) { |
| 114 return SetUnique(key, &value); |
| 115 } |
| 116 |
| 117 /** |
| 118 * Return value for key and remove it from the map. |
| 119 */ |
| 120 V8_INLINE UniquePersistent<V> Remove(const K& key) { |
| 121 return Release(Traits::Remove(&impl_, key)).Pass(); |
| 122 } |
| 123 |
| 124 /** |
| 125 * Traverses the map repeatedly, |
| 126 * in case side effects of disposal cause insertions. |
| 127 **/ |
| 128 void Clear(); |
| 129 |
| 130 private: |
| 131 PersistentValueMap(PersistentValueMap&); |
| 132 void operator=(PersistentValueMap&); |
| 133 |
| 134 /** |
| 135 * Put the value into the map, and set the 'weak' callback when demanded |
| 136 * by the Traits class. |
| 137 */ |
| 138 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
| 139 if (Traits::kIsWeak) { |
| 140 Local<V> value(Local<V>::New(isolate_, *persistent)); |
| 141 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( |
| 142 Traits::WeakCallbackParameter(&impl_, key, value), WeakCallback); |
| 143 } |
| 144 PersistentContainerValue old_value = |
| 145 Traits::Set(&impl_, key, ClearAndLeak(persistent)); |
| 146 return Release(old_value).Pass(); |
| 147 } |
| 148 |
| 149 static void WeakCallback( |
| 150 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data); |
| 151 V8_INLINE static V* FromVal(PersistentContainerValue v) { |
| 152 return reinterpret_cast<V*>(v); |
| 153 } |
| 154 V8_INLINE static PersistentContainerValue ClearAndLeak( |
| 155 UniquePersistent<V>* persistent) { |
| 156 V* v = persistent->val_; |
| 157 persistent->val_ = 0; |
| 158 return reinterpret_cast<PersistentContainerValue>(v); |
| 159 } |
| 160 |
| 161 /** |
| 162 * Return a container value as UniquePersistent and make sure the weak |
| 163 * callback is properly disposed of. All remove functionality should go |
| 164 * through this. |
| 165 */ |
| 166 V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) { |
| 167 UniquePersistent<V> p; |
| 168 p.val_ = FromVal(v); |
| 169 if (Traits::kIsWeak && !p.IsEmpty()) { |
| 170 Traits::DisposeCallbackData( |
| 171 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
| 172 } |
| 173 return p.Pass(); |
| 174 } |
| 175 |
| 176 Isolate* isolate_; |
| 177 typename Traits::Impl impl_; |
| 178 }; |
| 179 |
| 180 template <class K, class V, class Traits> |
| 181 bool PersistentValueMap<K, V, Traits>::SetReturnValue(const K& key, |
| 182 ReturnValue<Value>& returnValue) { |
| 183 PersistentContainerValue value = Traits::Get(&impl_, key); |
| 184 bool hasValue = value != 0; |
| 185 if (hasValue) { |
| 186 returnValue.SetInternal( |
| 187 *reinterpret_cast<internal::Object**>(FromVal(value))); |
| 188 } |
| 189 return hasValue; |
| 190 } |
| 191 |
| 192 template <class K, class V, class Traits> |
| 193 void PersistentValueMap<K, V, Traits>::Clear() { |
| 194 typedef typename Traits::Iterator It; |
| 195 HandleScope handle_scope(isolate_); |
| 196 // TODO(dcarney): figure out if this swap and loop is necessary. |
| 197 while (!Traits::Empty(&impl_)) { |
| 198 typename Traits::Impl impl; |
| 199 Traits::Swap(impl_, impl); |
| 200 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { |
| 201 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), &impl, |
| 202 Traits::Key(i)); |
| 203 } |
| 204 } |
| 205 } |
| 206 |
| 207 |
| 208 template <class K, class V, class Traits> |
| 209 void PersistentValueMap<K, V, Traits>::WeakCallback( |
| 210 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { |
| 211 typename Traits::Impl* impl = Traits::ImplFromWeakCallbackData(data); |
| 212 K key = Traits::KeyFromWeakCallbackData(data); |
| 213 PersistentContainerValue value = Traits::Remove(impl, key); |
| 214 Traits::Dispose(data.GetIsolate(), Release(value).Pass(), impl, key); |
| 215 } |
| 216 |
| 217 } // namespace v8 |
| 218 |
| 219 #endif // V8_UTIL_H_ |
| OLD | NEW |