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). */
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
>;
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;
47 inline bool HasWrapper(nsXPCWrappedJS
* wrapper
) {
48 for (auto iter
= mTable
.iter(); !iter
.done(); iter
.next()) {
49 if (iter
.get().value() == wrapper
) {
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
);
64 if (!mTable
.add(p
, obj
, 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;
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
>;
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!");
121 if (!mMap
.add(ptr
, obj
, 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;
140 /*************************/
143 using Key
= const nsIID
*;
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
) {
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
>;
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
);
190 /*************************/
192 class ClassInfo2NativeSetMap
{
193 using Map
= mozilla::HashMap
<nsIClassInfo
*, RefPtr
<XPCNativeSet
>,
194 mozilla::DefaultHasher
<nsIClassInfo
*>,
195 mozilla::MallocAllocPolicy
>;
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
);
211 if (!mMap
.add(ptr
, info
, set
)) {
217 void Remove(nsIClassInfo
* info
) {
218 MOZ_ASSERT(info
, "bad param");
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
);
234 /*************************/
236 class ClassInfo2WrappedNativeProtoMap
{
237 using Map
= mozilla::HashMap
<nsIClassInfo
*, XPCWrappedNativeProto
*,
238 mozilla::DefaultHasher
<nsIClassInfo
*>,
239 mozilla::MallocAllocPolicy
>;
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
);
255 if (!mMap
.add(ptr
, info
, 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;
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
);
285 using Set
= mozilla::HashSet
<XPCNativeSet
*, NativeSetHasher
,
286 mozilla::MallocAllocPolicy
>;
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
);
303 if (!mSet
.add(ptr
, set
)) {
309 bool AddNew(const XPCNativeSetKey
* key
, XPCNativeSet
* set
) {
310 XPCNativeSet
* set2
= Add(key
, set
);
315 XPCNativeSetKey
key2(set
);
316 MOZ_ASSERT(key
->Hash() == key2
.Hash());
317 MOZ_ASSERT(set2
== set
, "Should not have found an existing entry");
322 void Remove(XPCNativeSet
* set
) {
323 MOZ_ASSERT(set
, "bad param");
325 XPCNativeSetKey
key(set
);
329 uint32_t Count() { return mSet
.count(); }
331 Set::Iterator
Iter() { return mSet
.iter(); }
333 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
339 /***************************************************************************/
341 class JSObject2JSObjectMap
{
342 using Map
= JS::GCHashMap
<JS::Heap
<JSObject
*>, JS::Heap
<JSObject
*>,
343 js::StableCellHasher
<JS::Heap
<JSObject
*>>,
344 js::SystemAllocPolicy
>;
347 JSObject2JSObjectMap() = default;
349 inline JSObject
* Find(JSObject
* key
) {
350 MOZ_ASSERT(key
, "bad param");
351 if (Map::Ptr p
= mTable
.lookup(key
)) {
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
);
362 JSObject
* oldValue
= p
->value();
366 if (!mTable
.add(p
, key
, value
)) {
369 MOZ_ASSERT(xpc::ObjectScope(key
)->mWaiverWrapperMap
== this);
373 inline void Remove(JSObject
* key
) {
374 MOZ_ASSERT(key
, "bad param");
378 inline uint32_t Count() { return mTable
.count(); }
380 void UpdateWeakPointers(JSTracer
* trc
) { mTable
.traceWeak(trc
); }
383 Map mTable
{XPC_WRAPPER_MAP_LENGTH
};
386 #endif /* xpcmaps_h___ */