no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / js / xpconnect / src / XPCMaps.h
blobf1d32ab61c2f30c21da71364b6674bc42f15fddc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 /* Private maps (hashtables). */
9 #ifndef xpcmaps_h___
10 #define xpcmaps_h___
12 #include "mozilla/AllocPolicy.h"
13 #include "mozilla/MemoryReporting.h"
14 #include "mozilla/HashTable.h"
16 #include "js/GCHashTable.h"
18 /***************************************************************************/
19 // default initial sizes for maps (hashtables)
21 #define XPC_JS_MAP_LENGTH 32
23 #define XPC_NATIVE_MAP_LENGTH 8
24 #define XPC_NATIVE_PROTO_MAP_LENGTH 8
25 #define XPC_DYING_NATIVE_PROTO_MAP_LENGTH 8
26 #define XPC_NATIVE_INTERFACE_MAP_LENGTH 32
27 #define XPC_NATIVE_SET_MAP_LENGTH 32
28 #define XPC_WRAPPER_MAP_LENGTH 8
30 /*************************/
32 class JSObject2WrappedJSMap {
33 using Map = js::HashMap<JS::Heap<JSObject*>, nsXPCWrappedJS*,
34 js::StableCellHasher<JS::Heap<JSObject*>>,
35 InfallibleAllocPolicy>;
37 public:
38 JSObject2WrappedJSMap() = default;
40 inline nsXPCWrappedJS* Find(JSObject* Obj) {
41 MOZ_ASSERT(Obj, "bad param");
42 Map::Ptr p = mTable.lookup(Obj);
43 return p ? p->value() : nullptr;
46 #ifdef DEBUG
47 inline bool HasWrapper(nsXPCWrappedJS* wrapper) {
48 for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
49 if (iter.get().value() == wrapper) {
50 return true;
53 return false;
55 #endif
57 inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) {
58 MOZ_ASSERT(wrapper, "bad param");
59 JSObject* obj = wrapper->GetJSObjectPreserveColor();
60 Map::AddPtr p = mTable.lookupForAdd(obj);
61 if (p) {
62 return p->value();
64 if (!mTable.add(p, obj, wrapper)) {
65 return nullptr;
67 return wrapper;
70 inline void Remove(nsXPCWrappedJS* wrapper) {
71 MOZ_ASSERT(wrapper, "bad param");
72 mTable.remove(wrapper->GetJSObjectPreserveColor());
75 inline uint32_t Count() { return mTable.count(); }
77 inline void Dump(int16_t depth) {
78 for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
79 iter.get().value()->DebugDump(depth);
83 void UpdateWeakPointersAfterGC(JSTracer* trc);
85 void ShutdownMarker();
87 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
89 // Report the sum of SizeOfIncludingThis() for all wrapped JS in the map.
90 // Each wrapped JS is only in one map.
91 size_t SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const;
93 private:
94 Map mTable{XPC_JS_MAP_LENGTH};
97 /*************************/
99 class Native2WrappedNativeMap {
100 using Map = mozilla::HashMap<nsISupports*, XPCWrappedNative*,
101 mozilla::DefaultHasher<nsISupports*>,
102 mozilla::MallocAllocPolicy>;
104 public:
105 Native2WrappedNativeMap();
107 XPCWrappedNative* Find(nsISupports* obj) const {
108 MOZ_ASSERT(obj, "bad param");
109 Map::Ptr ptr = mMap.lookup(obj);
110 return ptr ? ptr->value() : nullptr;
113 XPCWrappedNative* Add(XPCWrappedNative* wrapper) {
114 MOZ_ASSERT(wrapper, "bad param");
115 nsISupports* obj = wrapper->GetIdentityObject();
116 Map::AddPtr ptr = mMap.lookupForAdd(obj);
117 MOZ_ASSERT(!ptr, "wrapper already in new scope!");
118 if (ptr) {
119 return ptr->value();
121 if (!mMap.add(ptr, obj, wrapper)) {
122 return nullptr;
124 return wrapper;
127 void Clear() { mMap.clear(); }
129 uint32_t Count() { return mMap.count(); }
131 Map::Iterator Iter() { return mMap.iter(); }
132 Map::ModIterator ModIter() { return mMap.modIter(); }
134 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
136 private:
137 Map mMap;
140 /*************************/
142 struct IIDHasher {
143 using Key = const nsIID*;
144 using Lookup = Key;
146 // Note this is returning the hash of the bit pattern of the first part of the
147 // nsID, not the hash of the pointer to the nsID.
148 static mozilla::HashNumber hash(Lookup lookup) {
149 uintptr_t v;
150 memcpy(&v, lookup, sizeof(v));
151 return mozilla::HashGeneric(v);
154 static bool match(Key key, Lookup lookup) { return key->Equals(*lookup); }
157 class IID2NativeInterfaceMap {
158 using Map = mozilla::HashMap<const nsIID*, XPCNativeInterface*, IIDHasher,
159 mozilla::MallocAllocPolicy>;
161 public:
162 IID2NativeInterfaceMap();
164 XPCNativeInterface* Find(REFNSIID iid) const {
165 Map::Ptr ptr = mMap.lookup(&iid);
166 return ptr ? ptr->value() : nullptr;
169 bool AddNew(XPCNativeInterface* iface) {
170 MOZ_ASSERT(iface, "bad param");
171 const nsIID* iid = iface->GetIID();
172 return mMap.putNew(iid, iface);
175 void Remove(XPCNativeInterface* iface) {
176 MOZ_ASSERT(iface, "bad param");
177 mMap.remove(iface->GetIID());
180 uint32_t Count() { return mMap.count(); }
182 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
184 void Trace(JSTracer* trc);
186 private:
187 Map mMap;
190 /*************************/
192 class ClassInfo2NativeSetMap {
193 using Map = mozilla::HashMap<nsIClassInfo*, RefPtr<XPCNativeSet>,
194 mozilla::DefaultHasher<nsIClassInfo*>,
195 mozilla::MallocAllocPolicy>;
197 public:
198 ClassInfo2NativeSetMap();
200 XPCNativeSet* Find(nsIClassInfo* info) const {
201 auto ptr = mMap.lookup(info);
202 return ptr ? ptr->value().get() : nullptr;
205 XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) {
206 MOZ_ASSERT(info, "bad param");
207 auto ptr = mMap.lookupForAdd(info);
208 if (ptr) {
209 return ptr->value();
211 if (!mMap.add(ptr, info, set)) {
212 return nullptr;
214 return set;
217 void Remove(nsIClassInfo* info) {
218 MOZ_ASSERT(info, "bad param");
219 mMap.remove(info);
222 uint32_t Count() { return mMap.count(); }
224 // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets.
225 // So we don't want to count those XPCNativeSets, because they are better
226 // counted elsewhere (i.e. in XPCJSContext::mNativeSetMap, which holds
227 // pointers to *all* XPCNativeSets). Hence the "Shallow".
228 size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
230 private:
231 Map mMap;
234 /*************************/
236 class ClassInfo2WrappedNativeProtoMap {
237 using Map = mozilla::HashMap<nsIClassInfo*, XPCWrappedNativeProto*,
238 mozilla::DefaultHasher<nsIClassInfo*>,
239 mozilla::MallocAllocPolicy>;
241 public:
242 ClassInfo2WrappedNativeProtoMap();
244 XPCWrappedNativeProto* Find(nsIClassInfo* info) const {
245 auto ptr = mMap.lookup(info);
246 return ptr ? ptr->value() : nullptr;
249 XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) {
250 MOZ_ASSERT(info, "bad param");
251 auto ptr = mMap.lookupForAdd(info);
252 if (ptr) {
253 return ptr->value();
255 if (!mMap.add(ptr, info, proto)) {
256 return nullptr;
258 return proto;
261 void Clear() { mMap.clear(); }
263 uint32_t Count() { return mMap.count(); }
265 Map::Iterator Iter() { return mMap.iter(); }
266 Map::ModIterator ModIter() { return mMap.modIter(); }
268 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
270 private:
271 Map mMap;
274 /*************************/
276 struct NativeSetHasher {
277 using Key = XPCNativeSet*;
278 using Lookup = const XPCNativeSetKey*;
280 static mozilla::HashNumber hash(Lookup lookup) { return lookup->Hash(); }
281 static bool match(Key key, Lookup lookup);
284 class NativeSetMap {
285 using Set = mozilla::HashSet<XPCNativeSet*, NativeSetHasher,
286 mozilla::MallocAllocPolicy>;
288 public:
289 NativeSetMap();
291 XPCNativeSet* Find(const XPCNativeSetKey* key) const {
292 auto ptr = mSet.lookup(key);
293 return ptr ? *ptr : nullptr;
296 XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set) {
297 MOZ_ASSERT(key, "bad param");
298 MOZ_ASSERT(set, "bad param");
299 auto ptr = mSet.lookupForAdd(key);
300 if (ptr) {
301 return *ptr;
303 if (!mSet.add(ptr, set)) {
304 return nullptr;
306 return set;
309 bool AddNew(const XPCNativeSetKey* key, XPCNativeSet* set) {
310 XPCNativeSet* set2 = Add(key, set);
311 if (!set2) {
312 return false;
314 #ifdef DEBUG
315 XPCNativeSetKey key2(set);
316 MOZ_ASSERT(key->Hash() == key2.Hash());
317 MOZ_ASSERT(set2 == set, "Should not have found an existing entry");
318 #endif
319 return true;
322 void Remove(XPCNativeSet* set) {
323 MOZ_ASSERT(set, "bad param");
325 XPCNativeSetKey key(set);
326 mSet.remove(&key);
329 uint32_t Count() { return mSet.count(); }
331 Set::Iterator Iter() { return mSet.iter(); }
333 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
335 private:
336 Set mSet;
339 /***************************************************************************/
341 class JSObject2JSObjectMap {
342 using Map = JS::GCHashMap<JS::Heap<JSObject*>, JS::Heap<JSObject*>,
343 js::StableCellHasher<JS::Heap<JSObject*>>,
344 js::SystemAllocPolicy>;
346 public:
347 JSObject2JSObjectMap() = default;
349 inline JSObject* Find(JSObject* key) {
350 MOZ_ASSERT(key, "bad param");
351 if (Map::Ptr p = mTable.lookup(key)) {
352 return p->value();
354 return nullptr;
357 /* Note: If the entry already exists, return the old value. */
358 inline JSObject* Add(JSContext* cx, JSObject* key, JSObject* value) {
359 MOZ_ASSERT(key, "bad param");
360 Map::AddPtr p = mTable.lookupForAdd(key);
361 if (p) {
362 JSObject* oldValue = p->value();
363 p->value() = value;
364 return oldValue;
366 if (!mTable.add(p, key, value)) {
367 return nullptr;
369 MOZ_ASSERT(xpc::ObjectScope(key)->mWaiverWrapperMap == this);
370 return value;
373 inline void Remove(JSObject* key) {
374 MOZ_ASSERT(key, "bad param");
375 mTable.remove(key);
378 inline uint32_t Count() { return mTable.count(); }
380 void UpdateWeakPointers(JSTracer* trc) { mTable.traceWeak(trc); }
382 private:
383 Map mTable{XPC_WRAPPER_MAP_LENGTH};
386 #endif /* xpcmaps_h___ */