Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: include/v8-util.h

Issue 212893007: Amend PersistentValueMap. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address feedback comments, round 2. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 24 matching lines...) Expand all
35 * Support for Persistent containers. 35 * Support for Persistent containers.
36 * 36 *
37 * C++11 embedders can use STL containers with UniquePersistent values, 37 * C++11 embedders can use STL containers with UniquePersistent values,
38 * but pre-C++11 does not support the required move semantic and hence 38 * but pre-C++11 does not support the required move semantic and hence
39 * may want these container classes. 39 * may want these container classes.
40 */ 40 */
41 namespace v8 { 41 namespace v8 {
42 42
43 typedef uintptr_t PersistentContainerValue; 43 typedef uintptr_t PersistentContainerValue;
44 static const uintptr_t kPersistentContainerNotFound = 0; 44 static const uintptr_t kPersistentContainerNotFound = 0;
45 enum PersistentContainerCallbackType {
46 kNotWeak,
47 kWeak
48 };
45 49
46 50
47 /** 51 /**
48 * A default trait implemenation for PersistentValueMap which uses std::map 52 * A default trait implemenation for PersistentValueMap which uses std::map
49 * as a backing map. 53 * as a backing map.
50 * 54 *
51 * Users will have to implement their own weak callbacks & dispose traits. 55 * Users will have to implement their own weak callbacks & dispose traits.
52 */ 56 */
53 template<typename K, typename V> 57 template<typename K, typename V>
54 class StdMapTraits { 58 class StdMapTraits {
(...skipping 30 matching lines...) Expand all
85 PersistentContainerValue value = it->second; 89 PersistentContainerValue value = it->second;
86 impl->erase(it); 90 impl->erase(it);
87 return value; 91 return value;
88 } 92 }
89 }; 93 };
90 94
91 95
92 /** 96 /**
93 * A default trait implementation for PersistentValueMap, which inherits 97 * A default trait implementation for PersistentValueMap, which inherits
94 * a std:map backing map from StdMapTraits and holds non-weak persistent 98 * a std:map backing map from StdMapTraits and holds non-weak persistent
95 * objects. 99 * objects and has no special Dispose handling.
96 * 100 *
97 * Users have to implement their own dispose trait. 101 * You should not derive from this class, since MapType depends on the
102 * surrounding class, and hence a subclass cannot simply inherit the methods.
98 */ 103 */
99 template<typename K, typename V> 104 template<typename K, typename V>
100 class StrongMapTraits : public StdMapTraits<K, V> { 105 class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
101 public: 106 public:
102 // Weak callback & friends: 107 // Weak callback & friends:
103 static const bool kIsWeak = false; 108 static const PersistentContainerCallbackType kCallbackType = kNotWeak;
104 typedef typename StdMapTraits<K, V>::Impl Impl; 109 typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
110 MapType;
105 typedef void WeakCallbackDataType; 111 typedef void WeakCallbackDataType;
112
106 static WeakCallbackDataType* WeakCallbackParameter( 113 static WeakCallbackDataType* WeakCallbackParameter(
107 Impl* impl, const K& key, Local<V> value); 114 MapType* map, const K& key, Local<V> value) {
108 static Impl* ImplFromWeakCallbackData( 115 return NULL;
109 const WeakCallbackData<V, WeakCallbackDataType>& data); 116 }
117 static MapType* MapFromWeakCallbackData(
118 const WeakCallbackData<V, WeakCallbackDataType>& data) {
119 return NULL;
120 }
110 static K KeyFromWeakCallbackData( 121 static K KeyFromWeakCallbackData(
111 const WeakCallbackData<V, WeakCallbackDataType>& data); 122 const WeakCallbackData<V, WeakCallbackDataType>& data) {
112 static void DisposeCallbackData(WeakCallbackDataType* data); 123 return K();
124 }
125 static void DisposeCallbackData(WeakCallbackDataType* data) { }
126 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { }
113 }; 127 };
114 128
115 129
116 /**
117 * A default trait implementation for PersistentValueMap, with a std::map
118 * backing map, non-weak persistents as values, and no special dispose
119 * handling. Can be used as-is.
120 */
121 template<typename K, typename V>
122 class DefaultPersistentValueMapTraits : public StrongMapTraits<K, V> {
123 public:
124 typedef typename StrongMapTraits<K, V>::Impl Impl;
125 static void Dispose(Isolate* isolate, UniquePersistent<V> value,
126 Impl* impl, K key) { }
127 };
128
129
130 /** 130 /**
131 * A map wrapper that allows using UniquePersistent as a mapped value. 131 * A map wrapper that allows using UniquePersistent as a mapped value.
132 * C++11 embedders don't need this class, as they can use UniquePersistent 132 * C++11 embedders don't need this class, as they can use UniquePersistent
133 * directly in std containers. 133 * directly in std containers.
134 * 134 *
135 * The map relies on a backing map, whose type and accessors are described 135 * The map relies on a backing map, whose type and accessors are described
136 * by the Traits class. The backing map will handle values of type 136 * by the Traits class. The backing map will handle values of type
137 * PersistentContainerValue, with all conversion into and out of V8 137 * PersistentContainerValue, with all conversion into and out of V8
138 * handles being transparently handled by this class. 138 * handles being transparently handled by this class.
139 */ 139 */
140 template<typename K, typename V, typename Traits> 140 template<typename K, typename V, typename Traits>
141 class PersistentValueMap { 141 class PersistentValueMap {
142 public: 142 public:
143 V8_INLINE explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} 143 V8_INLINE explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {}
144 144
145 V8_INLINE ~PersistentValueMap() { Clear(); } 145 V8_INLINE ~PersistentValueMap() { Clear(); }
146 146
147 V8_INLINE Isolate* GetIsolate() { return isolate_; } 147 V8_INLINE Isolate* GetIsolate() { return isolate_; }
148 148
149 /** 149 /**
150 * Return size of the map. 150 * Return size of the map.
151 */ 151 */
152 V8_INLINE size_t Size() { return Traits::Size(&impl_); } 152 V8_INLINE size_t Size() { return Traits::Size(&impl_); }
153 153
154 /** 154 /**
155 * Return whether the map holds weak persistents. 155 * Return whether the map holds weak persistents.
156 */ 156 */
157 V8_INLINE bool IsWeak() { return Traits::kIsWeak; } 157 V8_INLINE bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
158 158
159 /** 159 /**
160 * Get value stored in map. 160 * Get value stored in map.
161 */ 161 */
162 V8_INLINE Local<V> Get(const K& key) { 162 V8_INLINE Local<V> Get(const K& key) {
163 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key))); 163 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
164 } 164 }
165 165
166 /** 166 /**
167 * Check whether a value is contained in the map. 167 * Check whether a value is contained in the map.
168 */ 168 */
169 V8_INLINE bool Contains(const K& key) { 169 V8_INLINE bool Contains(const K& key) {
170 return Traits::Get(&impl_, key) != 0; 170 return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
171 } 171 }
172 172
173 /** 173 /**
174 * Get value stored in map and set it in returnValue. 174 * Get value stored in map and set it in returnValue.
175 * Return true if a value was found. 175 * Return true if a value was found.
176 */ 176 */
177 V8_INLINE bool SetReturnValue(const K& key, 177 V8_INLINE bool SetReturnValue(const K& key,
178 ReturnValue<Value>& returnValue) { 178 ReturnValue<Value> returnValue) {
179 PersistentContainerValue value = Traits::Get(&impl_, key); 179 return SetReturnValueFromVal(returnValue, Traits::Get(&impl_, key));
180 bool hasValue = value != 0;
181 if (hasValue) {
182 returnValue.SetInternal(
183 *reinterpret_cast<internal::Object**>(FromVal(value)));
184 }
185 return hasValue;
186 } 180 }
187 181
188 /** 182 /**
189 * Call Isolate::SetReference with the given parent and the map value. 183 * Call Isolate::SetReference with the given parent and the map value.
190 */ 184 */
191 V8_INLINE void SetReference(const K& key, 185 V8_INLINE void SetReference(const K& key,
192 const Persistent<Object>& parent) { 186 const Persistent<Object>& parent) {
193 GetIsolate()->SetReference( 187 GetIsolate()->SetReference(
194 reinterpret_cast<internal::Object**>(parent.val_), 188 reinterpret_cast<internal::Object**>(parent.val_),
195 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key)))); 189 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
(...skipping 28 matching lines...) Expand all
224 * in case side effects of disposal cause insertions. 218 * in case side effects of disposal cause insertions.
225 **/ 219 **/
226 void Clear() { 220 void Clear() {
227 typedef typename Traits::Iterator It; 221 typedef typename Traits::Iterator It;
228 HandleScope handle_scope(isolate_); 222 HandleScope handle_scope(isolate_);
229 // TODO(dcarney): figure out if this swap and loop is necessary. 223 // TODO(dcarney): figure out if this swap and loop is necessary.
230 while (!Traits::Empty(&impl_)) { 224 while (!Traits::Empty(&impl_)) {
231 typename Traits::Impl impl; 225 typename Traits::Impl impl;
232 Traits::Swap(impl_, impl); 226 Traits::Swap(impl_, impl);
233 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { 227 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
234 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), &impl, 228 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
235 Traits::Key(i)); 229 Traits::Key(i));
236 } 230 }
237 } 231 }
238 } 232 }
239 233
234 /**
235 * Helper class for GetReference/SetWithReference. Do not use outside
236 * that context.
237 */
238 class PersistentValueReference {
239 public:
240 PersistentValueReference() : value_(kPersistentContainerNotFound) { }
241 PersistentValueReference(const PersistentValueReference& other)
242 : value_(other.value_) { }
243
244 Local<V> NewLocal(Isolate* isolate) const {
245 return Local<V>::New(isolate, FromVal(value_));
246 }
247 bool IsEmpty() const {
248 return value_ == kPersistentContainerNotFound;
249 }
250 template<typename T>
251 bool SetReturnValue(ReturnValue<T> returnValue) {
252 return SetReturnValueFromVal(returnValue, value_);
253 }
254 void Reset() {
255 value_ = kPersistentContainerNotFound;
256 }
257 void operator=(const PersistentValueReference& other) {
258 value_ = other.value_;
259 }
260
261 private:
262 friend class PersistentValueMap;
263
264 explicit PersistentValueReference(PersistentContainerValue value)
265 : value_(value) { }
266
267 void operator=(PersistentContainerValue value) {
268 value_ = value;
269 }
270
271 PersistentContainerValue value_;
272 };
273
274 /**
275 * Get a reference to a map value. This enables fast, repeated access
276 * to a value stored in the map while the map remains unchanged.
277 *
278 * Careful: This is potentially unsafe, so please use with care.
279 * The value will become invalid if the value for this key changes
280 * in the underlying map, as a result of Set or Remove for the same
281 * key; as a result of the weak callback for the same key; or as a
282 * result of calling Clear() or destruction of the map.
283 */
284 V8_INLINE PersistentValueReference GetReference(const K& key) {
285 return PersistentValueReference(Traits::Get(&impl_, key));
286 }
287
288 /**
289 * Put a value into the map and update the reference.
290 * Restrictions of GetReference apply here as well.
291 */
292 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
293 PersistentValueReference* reference) {
294 *reference = Leak(&value);
295 return SetUnique(key, &value);
296 }
297
240 private: 298 private:
241 PersistentValueMap(PersistentValueMap&); 299 PersistentValueMap(PersistentValueMap&);
242 void operator=(PersistentValueMap&); 300 void operator=(PersistentValueMap&);
243 301
244 /** 302 /**
245 * Put the value into the map, and set the 'weak' callback when demanded 303 * Put the value into the map, and set the 'weak' callback when demanded
246 * by the Traits class. 304 * by the Traits class.
247 */ 305 */
248 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { 306 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
249 if (Traits::kIsWeak) { 307 if (Traits::kCallbackType != kNotWeak) {
250 Local<V> value(Local<V>::New(isolate_, *persistent)); 308 Local<V> value(Local<V>::New(isolate_, *persistent));
251 persistent->template SetWeak<typename Traits::WeakCallbackDataType>( 309 persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
252 Traits::WeakCallbackParameter(&impl_, key, value), WeakCallback); 310 Traits::WeakCallbackParameter(this, key, value), WeakCallback);
253 } 311 }
254 PersistentContainerValue old_value = 312 PersistentContainerValue old_value =
255 Traits::Set(&impl_, key, ClearAndLeak(persistent)); 313 Traits::Set(&impl_, key, ClearAndLeak(persistent));
256 return Release(old_value).Pass(); 314 return Release(old_value).Pass();
257 } 315 }
258 316
259 static void WeakCallback( 317 static void WeakCallback(
260 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { 318 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
261 if (Traits::kIsWeak) { 319 if (Traits::kCallbackType != kNotWeak) {
262 typename Traits::Impl* impl = Traits::ImplFromWeakCallbackData(data); 320 PersistentValueMap<K, V, Traits>* persistentValueMap =
321 Traits::MapFromWeakCallbackData(data);
263 K key = Traits::KeyFromWeakCallbackData(data); 322 K key = Traits::KeyFromWeakCallbackData(data);
264 PersistentContainerValue value = Traits::Remove(impl, key); 323 Traits::Dispose(data.GetIsolate(),
265 Traits::Dispose(data.GetIsolate(), Release(value).Pass(), impl, key); 324 persistentValueMap->Remove(key).Pass(), key);
266 } 325 }
267 } 326 }
268 327
269 V8_INLINE static V* FromVal(PersistentContainerValue v) { 328 V8_INLINE static V* FromVal(PersistentContainerValue v) {
270 return reinterpret_cast<V*>(v); 329 return reinterpret_cast<V*>(v);
271 } 330 }
272 331
332 V8_INLINE static bool SetReturnValueFromVal(
333 ReturnValue<Value>& returnValue, PersistentContainerValue value) {
334 bool hasValue = value != kPersistentContainerNotFound;
335 if (hasValue) {
336 returnValue.SetInternal(
337 *reinterpret_cast<internal::Object**>(FromVal(value)));
338 }
339 return hasValue;
340 }
341
273 V8_INLINE static PersistentContainerValue ClearAndLeak( 342 V8_INLINE static PersistentContainerValue ClearAndLeak(
274 UniquePersistent<V>* persistent) { 343 UniquePersistent<V>* persistent) {
275 V* v = persistent->val_; 344 V* v = persistent->val_;
276 persistent->val_ = 0; 345 persistent->val_ = 0;
277 return reinterpret_cast<PersistentContainerValue>(v); 346 return reinterpret_cast<PersistentContainerValue>(v);
278 } 347 }
279 348
349 V8_INLINE static PersistentContainerValue Leak(
350 UniquePersistent<V>* persistent) {
351 return reinterpret_cast<PersistentContainerValue>(persistent->val_);
352 }
353
280 /** 354 /**
281 * Return a container value as UniquePersistent and make sure the weak 355 * Return a container value as UniquePersistent and make sure the weak
282 * callback is properly disposed of. All remove functionality should go 356 * callback is properly disposed of. All remove functionality should go
283 * through this. 357 * through this.
284 */ 358 */
285 V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) { 359 V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) {
286 UniquePersistent<V> p; 360 UniquePersistent<V> p;
287 p.val_ = FromVal(v); 361 p.val_ = FromVal(v);
288 if (Traits::kIsWeak && !p.IsEmpty()) { 362 if (Traits::kCallbackType != kNotWeak && !p.IsEmpty()) {
289 Traits::DisposeCallbackData( 363 Traits::DisposeCallbackData(
290 p.template ClearWeak<typename Traits::WeakCallbackDataType>()); 364 p.template ClearWeak<typename Traits::WeakCallbackDataType>());
291 } 365 }
292 return p.Pass(); 366 return p.Pass();
293 } 367 }
294 368
295 Isolate* isolate_; 369 Isolate* isolate_;
296 typename Traits::Impl impl_; 370 typename Traits::Impl impl_;
297 }; 371 };
298 372
299 373
300 /** 374 /**
301 * A map that uses UniquePersistent as value and std::map as the backing 375 * A map that uses UniquePersistent as value and std::map as the backing
302 * implementation. Persistents are held non-weak. 376 * implementation. Persistents are held non-weak.
303 * 377 *
304 * C++11 embedders don't need this class, as they can use 378 * C++11 embedders don't need this class, as they can use
305 * UniquePersistent directly in std containers. 379 * UniquePersistent directly in std containers.
306 */ 380 */
307 template<typename K, typename V, 381 template<typename K, typename V,
308 typename Traits = DefaultPersistentValueMapTraits<K, V> > 382 typename Traits = DefaultPersistentValueMapTraits<K, V> >
309 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> { 383 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
310 public: 384 public:
311 explicit StdPersistentValueMap(Isolate* isolate) 385 explicit StdPersistentValueMap(Isolate* isolate)
312 : PersistentValueMap<K, V, Traits>(isolate) {} 386 : PersistentValueMap<K, V, Traits>(isolate) {}
313 }; 387 };
314 388
315
316 /**
317 * Empty default implementations for StrongTraits methods.
318 *
319 * These should not be necessary, since they're only used in code that
320 * is surrounded by if(Traits::kIsWeak), which for StrongMapTraits is
321 * compile-time false. Most compilers can live without them; however
322 * the compiler we use from 64-bit Win differs.
323 *
324 * TODO(vogelheim): Remove these once they're no longer necessary.
325 */
326 template<typename K, typename V>
327 typename StrongMapTraits<K, V>::WeakCallbackDataType*
328 StrongMapTraits<K, V>::WeakCallbackParameter(
329 Impl* impl, const K& key, Local<V> value) {
330 return NULL;
331 }
332
333
334 template<typename K, typename V>
335 typename StrongMapTraits<K, V>::Impl*
336 StrongMapTraits<K, V>::ImplFromWeakCallbackData(
337 const WeakCallbackData<V, WeakCallbackDataType>& data) {
338 return NULL;
339 }
340
341
342 template<typename K, typename V>
343 K StrongMapTraits<K, V>::KeyFromWeakCallbackData(
344 const WeakCallbackData<V, WeakCallbackDataType>& data) {
345 return K();
346 }
347
348
349 template<typename K, typename V>
350 void StrongMapTraits<K, V>::DisposeCallbackData(WeakCallbackDataType* data) {
351 }
352
353 } // namespace v8 389 } // namespace v8
354 390
355 #endif // V8_UTIL_H_ 391 #endif // V8_UTIL_H_
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698