|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "js/WeakMapPtr.h" |
|
8 |
|
9 #include "jsweakmap.h" |
|
10 |
|
11 // |
|
12 // Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap |
|
13 // for a few public data types. |
|
14 // |
|
15 |
|
16 using namespace js; |
|
17 |
|
18 namespace { |
|
19 |
|
20 template<typename T> |
|
21 struct DataType |
|
22 { |
|
23 }; |
|
24 |
|
25 template<> |
|
26 struct DataType<JSObject*> |
|
27 { |
|
28 typedef EncapsulatedPtrObject Encapsulated; |
|
29 static JSObject *NullValue() { return nullptr; } |
|
30 }; |
|
31 |
|
32 template<> |
|
33 struct DataType<JS::Value> |
|
34 { |
|
35 typedef EncapsulatedValue Encapsulated; |
|
36 static JS::Value NullValue() { return JS::UndefinedValue(); } |
|
37 }; |
|
38 |
|
39 template <typename K, typename V> |
|
40 struct Utils |
|
41 { |
|
42 typedef typename DataType<K>::Encapsulated KeyType; |
|
43 typedef typename DataType<V>::Encapsulated ValueType; |
|
44 typedef WeakMap<KeyType, ValueType> Type; |
|
45 typedef Type* PtrType; |
|
46 static PtrType cast(void *ptr) { return static_cast<PtrType>(ptr); } |
|
47 }; |
|
48 |
|
49 } /* namespace */ |
|
50 |
|
51 template <typename K, typename V> |
|
52 void |
|
53 JS::WeakMapPtr<K, V>::destroy() |
|
54 { |
|
55 MOZ_ASSERT(initialized()); |
|
56 auto map = Utils<K, V>::cast(ptr); |
|
57 // If this destruction happens mid-GC, we might be in the compartment's list |
|
58 // of known live weakmaps. If we are, remove ourselves before deleting. |
|
59 if (map->isInList()) |
|
60 WeakMapBase::removeWeakMapFromList(map); |
|
61 map->check(); |
|
62 js_delete(map); |
|
63 ptr = nullptr; |
|
64 } |
|
65 |
|
66 template <typename K, typename V> |
|
67 bool |
|
68 JS::WeakMapPtr<K, V>::init(JSContext *cx) |
|
69 { |
|
70 MOZ_ASSERT(!initialized()); |
|
71 typename Utils<K, V>::PtrType map = cx->runtime()->new_<typename Utils<K,V>::Type>(cx); |
|
72 if (!map || !map->init()) |
|
73 return false; |
|
74 ptr = map; |
|
75 return true; |
|
76 } |
|
77 |
|
78 template <typename K, typename V> |
|
79 void |
|
80 JS::WeakMapPtr<K, V>::trace(JSTracer *trc) |
|
81 { |
|
82 MOZ_ASSERT(initialized()); |
|
83 return Utils<K, V>::cast(ptr)->trace(trc); |
|
84 } |
|
85 |
|
86 template <typename K, typename V> |
|
87 V |
|
88 JS::WeakMapPtr<K, V>::lookup(const K &key) |
|
89 { |
|
90 MOZ_ASSERT(initialized()); |
|
91 typename Utils<K, V>::Type::Ptr result = Utils<K, V>::cast(ptr)->lookup(key); |
|
92 if (!result) |
|
93 return DataType<V>::NullValue(); |
|
94 return result->value(); |
|
95 } |
|
96 |
|
97 template <typename K, typename V> |
|
98 /* static */ void |
|
99 JS::WeakMapPtr<K, V>::keyMarkCallback(JSTracer *trc, K key, void *data) |
|
100 { |
|
101 auto map = static_cast< JS::WeakMapPtr<K, V>* >(data); |
|
102 K prior = key; |
|
103 JS_CallObjectTracer(trc, &key, "WeakMapPtr key"); |
|
104 return Utils<K, V>::cast(map->ptr)->rekeyIfMoved(prior, key); |
|
105 } |
|
106 |
|
107 template <typename K, typename V> |
|
108 bool |
|
109 JS::WeakMapPtr<K, V>::put(JSContext *cx, const K &key, const V &value) |
|
110 { |
|
111 MOZ_ASSERT(initialized()); |
|
112 if (!Utils<K, V>::cast(ptr)->put(key, value)) |
|
113 return false; |
|
114 JS_StoreObjectPostBarrierCallback(cx, keyMarkCallback, key, this); |
|
115 // Values do not need to be barriered because only put() is supported, |
|
116 // which is always an initializing write. |
|
117 return true; |
|
118 } |
|
119 |
|
120 // |
|
121 // Supported specializations of JS::WeakMap: |
|
122 // |
|
123 |
|
124 template class JS::WeakMapPtr<JSObject*, JSObject*>; |
|
125 |
|
126 #ifdef DEBUG |
|
127 // Nobody's using this at the moment, but we want to make sure it compiles. |
|
128 template class JS::WeakMapPtr<JSObject*, JS::Value>; |
|
129 #endif |