Bumping manifests a=b2g-bump
[gecko.git] / js / xpconnect / src / XPCMaps.h
blob8fb36f49128774ad06bec6e6a2596c15b5bc41af
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/. */
7 /* Private maps (hashtables). */
9 #ifndef xpcmaps_h___
10 #define xpcmaps_h___
12 #include "mozilla/MemoryReporting.h"
15 // Maps...
17 // Note that most of the declarations for hash table entries begin with
18 // a pointer to something or another. This makes them look enough like
19 // the PLDHashEntryStub struct that the default OPs (PL_DHashGetStubOps())
20 // just do the right thing for most of our needs.
22 // no virtuals in the maps - all the common stuff inlined
23 // templates could be used to good effect here.
25 /*************************/
27 class JSObject2WrappedJSMap
29 typedef js::HashMap<JSObject*, nsXPCWrappedJS*, js::PointerHasher<JSObject*, 3>,
30 js::SystemAllocPolicy> Map;
32 public:
33 static JSObject2WrappedJSMap* newMap(int length) {
34 JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap();
35 if (map && map->mTable.init(length))
36 return map;
37 delete map;
38 return nullptr;
41 inline nsXPCWrappedJS* Find(JSObject* Obj) {
42 NS_PRECONDITION(Obj,"bad param");
43 Map::Ptr p = mTable.lookup(Obj);
44 return p ? p->value() : nullptr;
47 inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) {
48 NS_PRECONDITION(wrapper,"bad param");
49 JSObject* obj = wrapper->GetJSObjectPreserveColor();
50 Map::AddPtr p = mTable.lookupForAdd(obj);
51 if (p)
52 return p->value();
53 if (!mTable.add(p, obj, wrapper))
54 return nullptr;
55 JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this);
56 return wrapper;
59 inline void Remove(nsXPCWrappedJS* wrapper) {
60 NS_PRECONDITION(wrapper,"bad param");
61 mTable.remove(wrapper->GetJSObjectPreserveColor());
64 inline uint32_t Count() {return mTable.count();}
66 inline void Dump(int16_t depth) {
67 for (Map::Range r = mTable.all(); !r.empty(); r.popFront())
68 r.front().value()->DebugDump(depth);
71 void FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying);
73 void ShutdownMarker();
75 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
77 // Report the sum of SizeOfIncludingThis() for all wrapped JS in the map.
78 // Each wrapped JS is only in one map.
79 size_t SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const;
81 private:
82 JSObject2WrappedJSMap() {}
85 * This function is called during minor GCs for each key in the HashMap that
86 * has been moved.
88 static void KeyMarkCallback(JSTracer* trc, JSObject* key, void* data) {
89 JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(data);
90 JSObject* prior = key;
91 JS_CallUnbarrieredObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key");
92 self->mTable.rekeyIfMoved(prior, key);
95 Map mTable;
98 /*************************/
100 class Native2WrappedNativeMap
102 public:
103 struct Entry : public PLDHashEntryHdr
105 nsISupports* key;
106 XPCWrappedNative* value;
109 static Native2WrappedNativeMap* newMap(int length);
111 inline XPCWrappedNative* Find(nsISupports* Obj)
113 NS_PRECONDITION(Obj,"bad param");
114 Entry* entry = (Entry*)
115 PL_DHashTableOperate(mTable, Obj, PL_DHASH_LOOKUP);
116 if (PL_DHASH_ENTRY_IS_FREE(entry))
117 return nullptr;
118 return entry->value;
121 inline XPCWrappedNative* Add(XPCWrappedNative* wrapper)
123 NS_PRECONDITION(wrapper,"bad param");
124 nsISupports* obj = wrapper->GetIdentityObject();
125 MOZ_ASSERT(!Find(obj), "wrapper already in new scope!");
126 Entry* entry = (Entry*)
127 PL_DHashTableOperate(mTable, obj, PL_DHASH_ADD);
128 if (!entry)
129 return nullptr;
130 if (entry->key)
131 return entry->value;
132 entry->key = obj;
133 entry->value = wrapper;
134 return wrapper;
137 inline void Remove(XPCWrappedNative* wrapper)
139 NS_PRECONDITION(wrapper,"bad param");
140 #ifdef DEBUG
141 XPCWrappedNative* wrapperInMap = Find(wrapper->GetIdentityObject());
142 MOZ_ASSERT(!wrapperInMap || wrapperInMap == wrapper,
143 "About to remove a different wrapper with the same "
144 "nsISupports identity! This will most likely cause serious "
145 "problems!");
146 #endif
147 PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE);
150 inline uint32_t Count() { return mTable->EntryCount(); }
151 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
152 {return PL_DHashTableEnumerate(mTable, f, arg);}
154 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
156 ~Native2WrappedNativeMap();
157 private:
158 Native2WrappedNativeMap(); // no implementation
159 explicit Native2WrappedNativeMap(int size);
161 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
163 private:
164 PLDHashTable* mTable;
167 /*************************/
169 class IID2WrappedJSClassMap
171 public:
172 struct Entry : public PLDHashEntryHdr
174 const nsIID* key;
175 nsXPCWrappedJSClass* value;
177 static const struct PLDHashTableOps sOps;
180 static IID2WrappedJSClassMap* newMap(int length);
182 inline nsXPCWrappedJSClass* Find(REFNSIID iid)
184 Entry* entry = (Entry*)
185 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP);
186 if (PL_DHASH_ENTRY_IS_FREE(entry))
187 return nullptr;
188 return entry->value;
191 inline nsXPCWrappedJSClass* Add(nsXPCWrappedJSClass* clazz)
193 NS_PRECONDITION(clazz,"bad param");
194 const nsIID* iid = &clazz->GetIID();
195 Entry* entry = (Entry*)
196 PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD);
197 if (!entry)
198 return nullptr;
199 if (entry->key)
200 return entry->value;
201 entry->key = iid;
202 entry->value = clazz;
203 return clazz;
206 inline void Remove(nsXPCWrappedJSClass* clazz)
208 NS_PRECONDITION(clazz,"bad param");
209 PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE);
212 inline uint32_t Count() { return mTable->EntryCount(); }
213 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
214 {return PL_DHashTableEnumerate(mTable, f, arg);}
216 ~IID2WrappedJSClassMap();
217 private:
218 IID2WrappedJSClassMap(); // no implementation
219 explicit IID2WrappedJSClassMap(int size);
220 private:
221 PLDHashTable* mTable;
224 /*************************/
226 class IID2NativeInterfaceMap
228 public:
229 struct Entry : public PLDHashEntryHdr
231 const nsIID* key;
232 XPCNativeInterface* value;
234 static const struct PLDHashTableOps sOps;
237 static IID2NativeInterfaceMap* newMap(int length);
239 inline XPCNativeInterface* Find(REFNSIID iid)
241 Entry* entry = (Entry*)
242 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP);
243 if (PL_DHASH_ENTRY_IS_FREE(entry))
244 return nullptr;
245 return entry->value;
248 inline XPCNativeInterface* Add(XPCNativeInterface* iface)
250 NS_PRECONDITION(iface,"bad param");
251 const nsIID* iid = iface->GetIID();
252 Entry* entry = (Entry*)
253 PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD);
254 if (!entry)
255 return nullptr;
256 if (entry->key)
257 return entry->value;
258 entry->key = iid;
259 entry->value = iface;
260 return iface;
263 inline void Remove(XPCNativeInterface* iface)
265 NS_PRECONDITION(iface,"bad param");
266 PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE);
269 inline uint32_t Count() { return mTable->EntryCount(); }
270 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
271 {return PL_DHashTableEnumerate(mTable, f, arg);}
273 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
275 ~IID2NativeInterfaceMap();
276 private:
277 IID2NativeInterfaceMap(); // no implementation
278 explicit IID2NativeInterfaceMap(int size);
280 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
282 private:
283 PLDHashTable* mTable;
286 /*************************/
288 class ClassInfo2NativeSetMap
290 public:
291 struct Entry : public PLDHashEntryHdr
293 nsIClassInfo* key;
294 XPCNativeSet* value;
297 static ClassInfo2NativeSetMap* newMap(int length);
299 inline XPCNativeSet* Find(nsIClassInfo* info)
301 Entry* entry = (Entry*)
302 PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP);
303 if (PL_DHASH_ENTRY_IS_FREE(entry))
304 return nullptr;
305 return entry->value;
308 inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set)
310 NS_PRECONDITION(info,"bad param");
311 Entry* entry = (Entry*)
312 PL_DHashTableOperate(mTable, info, PL_DHASH_ADD);
313 if (!entry)
314 return nullptr;
315 if (entry->key)
316 return entry->value;
317 entry->key = info;
318 entry->value = set;
319 return set;
322 inline void Remove(nsIClassInfo* info)
324 NS_PRECONDITION(info,"bad param");
325 PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE);
328 inline uint32_t Count() { return mTable->EntryCount(); }
329 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
330 {return PL_DHashTableEnumerate(mTable, f, arg);}
332 // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets.
333 // So we don't want to count those XPCNativeSets, because they are better
334 // counted elsewhere (i.e. in XPCJSRuntime::mNativeSetMap, which holds
335 // pointers to *all* XPCNativeSets). Hence the "Shallow".
336 size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
338 ~ClassInfo2NativeSetMap();
339 private:
340 ClassInfo2NativeSetMap(); // no implementation
341 explicit ClassInfo2NativeSetMap(int size);
342 private:
343 PLDHashTable* mTable;
346 /*************************/
348 class ClassInfo2WrappedNativeProtoMap
350 public:
351 struct Entry : public PLDHashEntryHdr
353 nsIClassInfo* key;
354 XPCWrappedNativeProto* value;
357 static ClassInfo2WrappedNativeProtoMap* newMap(int length);
359 inline XPCWrappedNativeProto* Find(nsIClassInfo* info)
361 Entry* entry = (Entry*)
362 PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP);
363 if (PL_DHASH_ENTRY_IS_FREE(entry))
364 return nullptr;
365 return entry->value;
368 inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto)
370 NS_PRECONDITION(info,"bad param");
371 Entry* entry = (Entry*)
372 PL_DHashTableOperate(mTable, info, PL_DHASH_ADD);
373 if (!entry)
374 return nullptr;
375 if (entry->key)
376 return entry->value;
377 entry->key = info;
378 entry->value = proto;
379 return proto;
382 inline void Remove(nsIClassInfo* info)
384 NS_PRECONDITION(info,"bad param");
385 PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE);
388 inline uint32_t Count() { return mTable->EntryCount(); }
389 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
390 {return PL_DHashTableEnumerate(mTable, f, arg);}
392 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
394 ~ClassInfo2WrappedNativeProtoMap();
395 private:
396 ClassInfo2WrappedNativeProtoMap(); // no implementation
397 explicit ClassInfo2WrappedNativeProtoMap(int size);
399 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
401 private:
402 PLDHashTable* mTable;
405 /*************************/
407 class NativeSetMap
409 public:
410 struct Entry : public PLDHashEntryHdr
412 XPCNativeSet* key_value;
414 static bool
415 Match(PLDHashTable* table,
416 const PLDHashEntryHdr* entry,
417 const void* key);
419 static const struct PLDHashTableOps sOps;
422 static NativeSetMap* newMap(int length);
424 inline XPCNativeSet* Find(XPCNativeSetKey* key)
426 Entry* entry = (Entry*)
427 PL_DHashTableOperate(mTable, key, PL_DHASH_LOOKUP);
428 if (PL_DHASH_ENTRY_IS_FREE(entry))
429 return nullptr;
430 return entry->key_value;
433 inline XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set)
435 NS_PRECONDITION(key,"bad param");
436 NS_PRECONDITION(set,"bad param");
437 Entry* entry = (Entry*)
438 PL_DHashTableOperate(mTable, key, PL_DHASH_ADD);
439 if (!entry)
440 return nullptr;
441 if (entry->key_value)
442 return entry->key_value;
443 entry->key_value = set;
444 return set;
447 inline XPCNativeSet* Add(XPCNativeSet* set)
449 XPCNativeSetKey key(set, nullptr, 0);
450 return Add(&key, set);
453 inline void Remove(XPCNativeSet* set)
455 NS_PRECONDITION(set,"bad param");
457 XPCNativeSetKey key(set, nullptr, 0);
458 PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE);
461 inline uint32_t Count() { return mTable->EntryCount(); }
462 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
463 {return PL_DHashTableEnumerate(mTable, f, arg);}
465 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
467 ~NativeSetMap();
468 private:
469 NativeSetMap(); // no implementation
470 explicit NativeSetMap(int size);
472 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
474 private:
475 PLDHashTable* mTable;
478 /***************************************************************************/
480 class IID2ThisTranslatorMap
482 public:
483 struct Entry : public PLDHashEntryHdr
485 nsIID key;
486 nsCOMPtr<nsIXPCFunctionThisTranslator> value;
488 static bool
489 Match(PLDHashTable* table,
490 const PLDHashEntryHdr* entry,
491 const void* key);
493 static void
494 Clear(PLDHashTable* table, PLDHashEntryHdr* entry);
496 static const struct PLDHashTableOps sOps;
499 static IID2ThisTranslatorMap* newMap(int length);
501 inline nsIXPCFunctionThisTranslator* Find(REFNSIID iid)
503 Entry* entry = (Entry*)
504 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP);
505 if (PL_DHASH_ENTRY_IS_FREE(entry))
506 return nullptr;
507 return entry->value;
510 inline nsIXPCFunctionThisTranslator* Add(REFNSIID iid,
511 nsIXPCFunctionThisTranslator* obj)
514 Entry* entry = (Entry*)
515 PL_DHashTableOperate(mTable, &iid, PL_DHASH_ADD);
516 if (!entry)
517 return nullptr;
518 entry->value = obj;
519 entry->key = iid;
520 return obj;
523 inline void Remove(REFNSIID iid)
525 PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE);
528 inline uint32_t Count() { return mTable->EntryCount(); }
529 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
530 {return PL_DHashTableEnumerate(mTable, f, arg);}
532 ~IID2ThisTranslatorMap();
533 private:
534 IID2ThisTranslatorMap(); // no implementation
535 explicit IID2ThisTranslatorMap(int size);
536 private:
537 PLDHashTable* mTable;
540 /***************************************************************************/
542 class XPCNativeScriptableSharedMap
544 public:
545 struct Entry : public PLDHashEntryHdr
547 XPCNativeScriptableShared* key;
549 static PLDHashNumber
550 Hash(PLDHashTable* table, const void* key);
552 static bool
553 Match(PLDHashTable* table,
554 const PLDHashEntryHdr* entry,
555 const void* key);
557 static const struct PLDHashTableOps sOps;
560 static XPCNativeScriptableSharedMap* newMap(int length);
562 bool GetNewOrUsed(uint32_t flags, char* name, uint32_t interfacesBitmap,
563 XPCNativeScriptableInfo* si);
565 inline uint32_t Count() { return mTable->EntryCount(); }
566 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
567 {return PL_DHashTableEnumerate(mTable, f, arg);}
569 ~XPCNativeScriptableSharedMap();
570 private:
571 XPCNativeScriptableSharedMap(); // no implementation
572 explicit XPCNativeScriptableSharedMap(int size);
573 private:
574 PLDHashTable* mTable;
577 /***************************************************************************/
579 class XPCWrappedNativeProtoMap
581 public:
582 static XPCWrappedNativeProtoMap* newMap(int length);
584 inline XPCWrappedNativeProto* Add(XPCWrappedNativeProto* proto)
586 NS_PRECONDITION(proto,"bad param");
587 PLDHashEntryStub* entry = (PLDHashEntryStub*)
588 PL_DHashTableOperate(mTable, proto, PL_DHASH_ADD);
589 if (!entry)
590 return nullptr;
591 if (entry->key)
592 return (XPCWrappedNativeProto*) entry->key;
593 entry->key = proto;
594 return proto;
597 inline void Remove(XPCWrappedNativeProto* proto)
599 NS_PRECONDITION(proto,"bad param");
600 PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE);
603 inline uint32_t Count() { return mTable->EntryCount(); }
604 inline uint32_t Enumerate(PLDHashEnumerator f, void* arg)
605 {return PL_DHashTableEnumerate(mTable, f, arg);}
607 ~XPCWrappedNativeProtoMap();
608 private:
609 XPCWrappedNativeProtoMap(); // no implementation
610 explicit XPCWrappedNativeProtoMap(int size);
611 private:
612 PLDHashTable* mTable;
615 /***************************************************************************/
617 class JSObject2JSObjectMap
619 typedef js::HashMap<JSObject*, JS::Heap<JSObject*>, js::PointerHasher<JSObject*, 3>,
620 js::SystemAllocPolicy> Map;
622 public:
623 static JSObject2JSObjectMap* newMap(int length) {
624 JSObject2JSObjectMap* map = new JSObject2JSObjectMap();
625 if (map && map->mTable.init(length))
626 return map;
627 delete map;
628 return nullptr;
631 inline JSObject* Find(JSObject* key) {
632 NS_PRECONDITION(key, "bad param");
633 if (Map::Ptr p = mTable.lookup(key))
634 return p->value();
635 return nullptr;
638 /* Note: If the entry already exists, return the old value. */
639 inline JSObject* Add(JSContext* cx, JSObject* key, JSObject* value) {
640 NS_PRECONDITION(key,"bad param");
641 Map::AddPtr p = mTable.lookupForAdd(key);
642 if (p)
643 return p->value();
644 if (!mTable.add(p, key, value))
645 return nullptr;
646 MOZ_ASSERT(xpc::CompartmentPrivate::Get(key)->scope->mWaiverWrapperMap == this);
647 JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this);
648 return value;
651 inline void Remove(JSObject* key) {
652 NS_PRECONDITION(key,"bad param");
653 mTable.remove(key);
656 inline uint32_t Count() { return mTable.count(); }
658 void Sweep() {
659 for (Map::Enum e(mTable); !e.empty(); e.popFront()) {
660 JSObject* updated = e.front().key();
661 if (JS_IsAboutToBeFinalizedUnbarriered(&updated) || JS_IsAboutToBeFinalized(&e.front().value()))
662 e.removeFront();
663 else if (updated != e.front().key())
664 e.rekeyFront(updated);
668 void Reparent(JSContext* aCx, JSObject* aNewInnerArg) {
669 JS::RootedObject aNewInner(aCx, aNewInnerArg);
670 for (Map::Enum e(mTable); !e.empty(); e.popFront()) {
672 * We reparent wrappers that have as their parent an inner window
673 * whose outer has the new inner window as its current inner.
675 JS::RootedObject wrapper(aCx, e.front().value());
676 JS::RootedObject parent(aCx, JS_GetParent(wrapper));
677 JS::RootedObject outer(aCx, JS_ObjectToOuterObject(aCx, parent));
678 if (outer) {
679 JSObject* inner = JS_ObjectToInnerObject(aCx, outer);
680 if (inner == aNewInner && inner != parent)
681 JS_SetParent(aCx, wrapper, aNewInner);
682 } else {
683 JS_ClearPendingException(aCx);
688 private:
689 JSObject2JSObjectMap() {}
692 * This function is called during minor GCs for each key in the HashMap that
693 * has been moved.
695 static void KeyMarkCallback(JSTracer* trc, JSObject* key, void* data) {
697 * To stop the barriers on the values of mTable firing while we are
698 * marking the store buffer, we cast the table to one that is
699 * binary-equivatlent but without the barriers, and update that.
701 typedef js::HashMap<JSObject*, JSObject*, js::PointerHasher<JSObject*, 3>,
702 js::SystemAllocPolicy> UnbarrieredMap;
703 JSObject2JSObjectMap* self = static_cast<JSObject2JSObjectMap*>(data);
704 UnbarrieredMap& table = reinterpret_cast<UnbarrieredMap&>(self->mTable);
706 JSObject* prior = key;
707 JS_CallUnbarrieredObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key");
708 table.rekeyIfMoved(prior, key);
711 Map mTable;
714 #endif /* xpcmaps_h___ */