1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/xpconnect/src/XPCMaps.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,714 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* Private maps (hashtables). */ 1.11 + 1.12 +#ifndef xpcmaps_h___ 1.13 +#define xpcmaps_h___ 1.14 + 1.15 +#include "mozilla/MemoryReporting.h" 1.16 + 1.17 + 1.18 +// Maps... 1.19 + 1.20 +// Note that most of the declarations for hash table entries begin with 1.21 +// a pointer to something or another. This makes them look enough like 1.22 +// the PLDHashEntryStub struct that the default OPs (PL_DHashGetStubOps()) 1.23 +// just do the right thing for most of our needs. 1.24 + 1.25 +// no virtuals in the maps - all the common stuff inlined 1.26 +// templates could be used to good effect here. 1.27 + 1.28 +/*************************/ 1.29 + 1.30 +class JSObject2WrappedJSMap 1.31 +{ 1.32 + typedef js::HashMap<JSObject*, nsXPCWrappedJS*, js::PointerHasher<JSObject*, 3>, 1.33 + js::SystemAllocPolicy> Map; 1.34 + 1.35 +public: 1.36 + static JSObject2WrappedJSMap* newMap(int size) { 1.37 + JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap(); 1.38 + if (map && map->mTable.init(size)) 1.39 + return map; 1.40 + delete map; 1.41 + return nullptr; 1.42 + } 1.43 + 1.44 + inline nsXPCWrappedJS* Find(JSObject* Obj) { 1.45 + NS_PRECONDITION(Obj,"bad param"); 1.46 + Map::Ptr p = mTable.lookup(Obj); 1.47 + return p ? p->value() : nullptr; 1.48 + } 1.49 + 1.50 + inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) { 1.51 + NS_PRECONDITION(wrapper,"bad param"); 1.52 + JSObject* obj = wrapper->GetJSObjectPreserveColor(); 1.53 + Map::AddPtr p = mTable.lookupForAdd(obj); 1.54 + if (p) 1.55 + return p->value(); 1.56 + if (!mTable.add(p, obj, wrapper)) 1.57 + return nullptr; 1.58 + JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this); 1.59 + return wrapper; 1.60 + } 1.61 + 1.62 + inline void Remove(nsXPCWrappedJS* wrapper) { 1.63 + NS_PRECONDITION(wrapper,"bad param"); 1.64 + mTable.remove(wrapper->GetJSObjectPreserveColor()); 1.65 + } 1.66 + 1.67 + inline uint32_t Count() {return mTable.count();} 1.68 + 1.69 + inline void Dump(int16_t depth) { 1.70 + for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) 1.71 + r.front().value()->DebugDump(depth); 1.72 + } 1.73 + 1.74 + void FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying); 1.75 + 1.76 + void ShutdownMarker(); 1.77 + 1.78 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { 1.79 + size_t n = mallocSizeOf(this); 1.80 + n += mTable.sizeOfExcludingThis(mallocSizeOf); 1.81 + return n; 1.82 + } 1.83 + 1.84 +private: 1.85 + JSObject2WrappedJSMap() {} 1.86 + 1.87 + /* 1.88 + * This function is called during minor GCs for each key in the HashMap that 1.89 + * has been moved. 1.90 + */ 1.91 + static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { 1.92 + JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(data); 1.93 + JSObject *prior = key; 1.94 + JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key"); 1.95 + self->mTable.rekeyIfMoved(prior, key); 1.96 + } 1.97 + 1.98 + Map mTable; 1.99 +}; 1.100 + 1.101 +/*************************/ 1.102 + 1.103 +class Native2WrappedNativeMap 1.104 +{ 1.105 +public: 1.106 + struct Entry : public PLDHashEntryHdr 1.107 + { 1.108 + nsISupports* key; 1.109 + XPCWrappedNative* value; 1.110 + }; 1.111 + 1.112 + static Native2WrappedNativeMap* newMap(int size); 1.113 + 1.114 + inline XPCWrappedNative* Find(nsISupports* Obj) 1.115 + { 1.116 + NS_PRECONDITION(Obj,"bad param"); 1.117 + Entry* entry = (Entry*) 1.118 + PL_DHashTableOperate(mTable, Obj, PL_DHASH_LOOKUP); 1.119 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.120 + return nullptr; 1.121 + return entry->value; 1.122 + } 1.123 + 1.124 + inline XPCWrappedNative* Add(XPCWrappedNative* wrapper) 1.125 + { 1.126 + NS_PRECONDITION(wrapper,"bad param"); 1.127 + nsISupports* obj = wrapper->GetIdentityObject(); 1.128 + MOZ_ASSERT(!Find(obj), "wrapper already in new scope!"); 1.129 + Entry* entry = (Entry*) 1.130 + PL_DHashTableOperate(mTable, obj, PL_DHASH_ADD); 1.131 + if (!entry) 1.132 + return nullptr; 1.133 + if (entry->key) 1.134 + return entry->value; 1.135 + entry->key = obj; 1.136 + entry->value = wrapper; 1.137 + return wrapper; 1.138 + } 1.139 + 1.140 + inline void Remove(XPCWrappedNative* wrapper) 1.141 + { 1.142 + NS_PRECONDITION(wrapper,"bad param"); 1.143 +#ifdef DEBUG 1.144 + XPCWrappedNative* wrapperInMap = Find(wrapper->GetIdentityObject()); 1.145 + MOZ_ASSERT(!wrapperInMap || wrapperInMap == wrapper, 1.146 + "About to remove a different wrapper with the same " 1.147 + "nsISupports identity! This will most likely cause serious " 1.148 + "problems!"); 1.149 +#endif 1.150 + PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE); 1.151 + } 1.152 + 1.153 + inline uint32_t Count() {return mTable->entryCount;} 1.154 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.155 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.156 + 1.157 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.158 + 1.159 + ~Native2WrappedNativeMap(); 1.160 +private: 1.161 + Native2WrappedNativeMap(); // no implementation 1.162 + Native2WrappedNativeMap(int size); 1.163 + 1.164 + static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); 1.165 + 1.166 +private: 1.167 + PLDHashTable *mTable; 1.168 +}; 1.169 + 1.170 +/*************************/ 1.171 + 1.172 +class IID2WrappedJSClassMap 1.173 +{ 1.174 +public: 1.175 + struct Entry : public PLDHashEntryHdr 1.176 + { 1.177 + const nsIID* key; 1.178 + nsXPCWrappedJSClass* value; 1.179 + 1.180 + static const struct PLDHashTableOps sOps; 1.181 + }; 1.182 + 1.183 + static IID2WrappedJSClassMap* newMap(int size); 1.184 + 1.185 + inline nsXPCWrappedJSClass* Find(REFNSIID iid) 1.186 + { 1.187 + Entry* entry = (Entry*) 1.188 + PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); 1.189 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.190 + return nullptr; 1.191 + return entry->value; 1.192 + } 1.193 + 1.194 + inline nsXPCWrappedJSClass* Add(nsXPCWrappedJSClass* clazz) 1.195 + { 1.196 + NS_PRECONDITION(clazz,"bad param"); 1.197 + const nsIID* iid = &clazz->GetIID(); 1.198 + Entry* entry = (Entry*) 1.199 + PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); 1.200 + if (!entry) 1.201 + return nullptr; 1.202 + if (entry->key) 1.203 + return entry->value; 1.204 + entry->key = iid; 1.205 + entry->value = clazz; 1.206 + return clazz; 1.207 + } 1.208 + 1.209 + inline void Remove(nsXPCWrappedJSClass* clazz) 1.210 + { 1.211 + NS_PRECONDITION(clazz,"bad param"); 1.212 + PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE); 1.213 + } 1.214 + 1.215 + inline uint32_t Count() {return mTable->entryCount;} 1.216 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.217 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.218 + 1.219 + ~IID2WrappedJSClassMap(); 1.220 +private: 1.221 + IID2WrappedJSClassMap(); // no implementation 1.222 + IID2WrappedJSClassMap(int size); 1.223 +private: 1.224 + PLDHashTable *mTable; 1.225 +}; 1.226 + 1.227 +/*************************/ 1.228 + 1.229 +class IID2NativeInterfaceMap 1.230 +{ 1.231 +public: 1.232 + struct Entry : public PLDHashEntryHdr 1.233 + { 1.234 + const nsIID* key; 1.235 + XPCNativeInterface* value; 1.236 + 1.237 + static const struct PLDHashTableOps sOps; 1.238 + }; 1.239 + 1.240 + static IID2NativeInterfaceMap* newMap(int size); 1.241 + 1.242 + inline XPCNativeInterface* Find(REFNSIID iid) 1.243 + { 1.244 + Entry* entry = (Entry*) 1.245 + PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); 1.246 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.247 + return nullptr; 1.248 + return entry->value; 1.249 + } 1.250 + 1.251 + inline XPCNativeInterface* Add(XPCNativeInterface* iface) 1.252 + { 1.253 + NS_PRECONDITION(iface,"bad param"); 1.254 + const nsIID* iid = iface->GetIID(); 1.255 + Entry* entry = (Entry*) 1.256 + PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); 1.257 + if (!entry) 1.258 + return nullptr; 1.259 + if (entry->key) 1.260 + return entry->value; 1.261 + entry->key = iid; 1.262 + entry->value = iface; 1.263 + return iface; 1.264 + } 1.265 + 1.266 + inline void Remove(XPCNativeInterface* iface) 1.267 + { 1.268 + NS_PRECONDITION(iface,"bad param"); 1.269 + PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE); 1.270 + } 1.271 + 1.272 + inline uint32_t Count() {return mTable->entryCount;} 1.273 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.274 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.275 + 1.276 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.277 + 1.278 + ~IID2NativeInterfaceMap(); 1.279 +private: 1.280 + IID2NativeInterfaceMap(); // no implementation 1.281 + IID2NativeInterfaceMap(int size); 1.282 + 1.283 + static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); 1.284 + 1.285 +private: 1.286 + PLDHashTable *mTable; 1.287 +}; 1.288 + 1.289 +/*************************/ 1.290 + 1.291 +class ClassInfo2NativeSetMap 1.292 +{ 1.293 +public: 1.294 + struct Entry : public PLDHashEntryHdr 1.295 + { 1.296 + nsIClassInfo* key; 1.297 + XPCNativeSet* value; 1.298 + }; 1.299 + 1.300 + static ClassInfo2NativeSetMap* newMap(int size); 1.301 + 1.302 + inline XPCNativeSet* Find(nsIClassInfo* info) 1.303 + { 1.304 + Entry* entry = (Entry*) 1.305 + PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); 1.306 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.307 + return nullptr; 1.308 + return entry->value; 1.309 + } 1.310 + 1.311 + inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) 1.312 + { 1.313 + NS_PRECONDITION(info,"bad param"); 1.314 + Entry* entry = (Entry*) 1.315 + PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); 1.316 + if (!entry) 1.317 + return nullptr; 1.318 + if (entry->key) 1.319 + return entry->value; 1.320 + entry->key = info; 1.321 + entry->value = set; 1.322 + return set; 1.323 + } 1.324 + 1.325 + inline void Remove(nsIClassInfo* info) 1.326 + { 1.327 + NS_PRECONDITION(info,"bad param"); 1.328 + PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); 1.329 + } 1.330 + 1.331 + inline uint32_t Count() {return mTable->entryCount;} 1.332 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.333 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.334 + 1.335 + // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets. 1.336 + // So we don't want to count those XPCNativeSets, because they are better 1.337 + // counted elsewhere (i.e. in XPCJSRuntime::mNativeSetMap, which holds 1.338 + // pointers to *all* XPCNativeSets). Hence the "Shallow". 1.339 + size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.340 + 1.341 + ~ClassInfo2NativeSetMap(); 1.342 +private: 1.343 + ClassInfo2NativeSetMap(); // no implementation 1.344 + ClassInfo2NativeSetMap(int size); 1.345 +private: 1.346 + PLDHashTable *mTable; 1.347 +}; 1.348 + 1.349 +/*************************/ 1.350 + 1.351 +class ClassInfo2WrappedNativeProtoMap 1.352 +{ 1.353 +public: 1.354 + struct Entry : public PLDHashEntryHdr 1.355 + { 1.356 + nsIClassInfo* key; 1.357 + XPCWrappedNativeProto* value; 1.358 + }; 1.359 + 1.360 + static ClassInfo2WrappedNativeProtoMap* newMap(int size); 1.361 + 1.362 + inline XPCWrappedNativeProto* Find(nsIClassInfo* info) 1.363 + { 1.364 + Entry* entry = (Entry*) 1.365 + PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); 1.366 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.367 + return nullptr; 1.368 + return entry->value; 1.369 + } 1.370 + 1.371 + inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) 1.372 + { 1.373 + NS_PRECONDITION(info,"bad param"); 1.374 + Entry* entry = (Entry*) 1.375 + PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); 1.376 + if (!entry) 1.377 + return nullptr; 1.378 + if (entry->key) 1.379 + return entry->value; 1.380 + entry->key = info; 1.381 + entry->value = proto; 1.382 + return proto; 1.383 + } 1.384 + 1.385 + inline void Remove(nsIClassInfo* info) 1.386 + { 1.387 + NS_PRECONDITION(info,"bad param"); 1.388 + PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); 1.389 + } 1.390 + 1.391 + inline uint32_t Count() {return mTable->entryCount;} 1.392 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.393 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.394 + 1.395 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.396 + 1.397 + ~ClassInfo2WrappedNativeProtoMap(); 1.398 +private: 1.399 + ClassInfo2WrappedNativeProtoMap(); // no implementation 1.400 + ClassInfo2WrappedNativeProtoMap(int size); 1.401 + 1.402 + static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); 1.403 + 1.404 +private: 1.405 + PLDHashTable *mTable; 1.406 +}; 1.407 + 1.408 +/*************************/ 1.409 + 1.410 +class NativeSetMap 1.411 +{ 1.412 +public: 1.413 + struct Entry : public PLDHashEntryHdr 1.414 + { 1.415 + XPCNativeSet* key_value; 1.416 + 1.417 + static bool 1.418 + Match(PLDHashTable *table, 1.419 + const PLDHashEntryHdr *entry, 1.420 + const void *key); 1.421 + 1.422 + static const struct PLDHashTableOps sOps; 1.423 + }; 1.424 + 1.425 + static NativeSetMap* newMap(int size); 1.426 + 1.427 + inline XPCNativeSet* Find(XPCNativeSetKey* key) 1.428 + { 1.429 + Entry* entry = (Entry*) 1.430 + PL_DHashTableOperate(mTable, key, PL_DHASH_LOOKUP); 1.431 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.432 + return nullptr; 1.433 + return entry->key_value; 1.434 + } 1.435 + 1.436 + inline XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set) 1.437 + { 1.438 + NS_PRECONDITION(key,"bad param"); 1.439 + NS_PRECONDITION(set,"bad param"); 1.440 + Entry* entry = (Entry*) 1.441 + PL_DHashTableOperate(mTable, key, PL_DHASH_ADD); 1.442 + if (!entry) 1.443 + return nullptr; 1.444 + if (entry->key_value) 1.445 + return entry->key_value; 1.446 + entry->key_value = set; 1.447 + return set; 1.448 + } 1.449 + 1.450 + inline XPCNativeSet* Add(XPCNativeSet* set) 1.451 + { 1.452 + XPCNativeSetKey key(set, nullptr, 0); 1.453 + return Add(&key, set); 1.454 + } 1.455 + 1.456 + inline void Remove(XPCNativeSet* set) 1.457 + { 1.458 + NS_PRECONDITION(set,"bad param"); 1.459 + 1.460 + XPCNativeSetKey key(set, nullptr, 0); 1.461 + PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE); 1.462 + } 1.463 + 1.464 + inline uint32_t Count() {return mTable->entryCount;} 1.465 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.466 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.467 + 1.468 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.469 + 1.470 + ~NativeSetMap(); 1.471 +private: 1.472 + NativeSetMap(); // no implementation 1.473 + NativeSetMap(int size); 1.474 + 1.475 + static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); 1.476 + 1.477 +private: 1.478 + PLDHashTable *mTable; 1.479 +}; 1.480 + 1.481 +/***************************************************************************/ 1.482 + 1.483 +class IID2ThisTranslatorMap 1.484 +{ 1.485 +public: 1.486 + struct Entry : public PLDHashEntryHdr 1.487 + { 1.488 + nsIID key; 1.489 + nsCOMPtr<nsIXPCFunctionThisTranslator> value; 1.490 + 1.491 + static bool 1.492 + Match(PLDHashTable *table, 1.493 + const PLDHashEntryHdr *entry, 1.494 + const void *key); 1.495 + 1.496 + static void 1.497 + Clear(PLDHashTable *table, PLDHashEntryHdr *entry); 1.498 + 1.499 + static const struct PLDHashTableOps sOps; 1.500 + }; 1.501 + 1.502 + static IID2ThisTranslatorMap* newMap(int size); 1.503 + 1.504 + inline nsIXPCFunctionThisTranslator* Find(REFNSIID iid) 1.505 + { 1.506 + Entry* entry = (Entry*) 1.507 + PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); 1.508 + if (PL_DHASH_ENTRY_IS_FREE(entry)) 1.509 + return nullptr; 1.510 + return entry->value; 1.511 + } 1.512 + 1.513 + inline nsIXPCFunctionThisTranslator* Add(REFNSIID iid, 1.514 + nsIXPCFunctionThisTranslator* obj) 1.515 + { 1.516 + 1.517 + Entry* entry = (Entry*) 1.518 + PL_DHashTableOperate(mTable, &iid, PL_DHASH_ADD); 1.519 + if (!entry) 1.520 + return nullptr; 1.521 + entry->value = obj; 1.522 + entry->key = iid; 1.523 + return obj; 1.524 + } 1.525 + 1.526 + inline void Remove(REFNSIID iid) 1.527 + { 1.528 + PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE); 1.529 + } 1.530 + 1.531 + inline uint32_t Count() {return mTable->entryCount;} 1.532 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.533 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.534 + 1.535 + ~IID2ThisTranslatorMap(); 1.536 +private: 1.537 + IID2ThisTranslatorMap(); // no implementation 1.538 + IID2ThisTranslatorMap(int size); 1.539 +private: 1.540 + PLDHashTable *mTable; 1.541 +}; 1.542 + 1.543 +/***************************************************************************/ 1.544 + 1.545 +class XPCNativeScriptableSharedMap 1.546 +{ 1.547 +public: 1.548 + struct Entry : public PLDHashEntryHdr 1.549 + { 1.550 + XPCNativeScriptableShared* key; 1.551 + 1.552 + static PLDHashNumber 1.553 + Hash(PLDHashTable *table, const void *key); 1.554 + 1.555 + static bool 1.556 + Match(PLDHashTable *table, 1.557 + const PLDHashEntryHdr *entry, 1.558 + const void *key); 1.559 + 1.560 + static const struct PLDHashTableOps sOps; 1.561 + }; 1.562 + 1.563 + static XPCNativeScriptableSharedMap* newMap(int size); 1.564 + 1.565 + bool GetNewOrUsed(uint32_t flags, char* name, uint32_t interfacesBitmap, 1.566 + XPCNativeScriptableInfo* si); 1.567 + 1.568 + inline uint32_t Count() {return mTable->entryCount;} 1.569 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.570 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.571 + 1.572 + ~XPCNativeScriptableSharedMap(); 1.573 +private: 1.574 + XPCNativeScriptableSharedMap(); // no implementation 1.575 + XPCNativeScriptableSharedMap(int size); 1.576 +private: 1.577 + PLDHashTable *mTable; 1.578 +}; 1.579 + 1.580 +/***************************************************************************/ 1.581 + 1.582 +class XPCWrappedNativeProtoMap 1.583 +{ 1.584 +public: 1.585 + static XPCWrappedNativeProtoMap* newMap(int size); 1.586 + 1.587 + inline XPCWrappedNativeProto* Add(XPCWrappedNativeProto* proto) 1.588 + { 1.589 + NS_PRECONDITION(proto,"bad param"); 1.590 + PLDHashEntryStub* entry = (PLDHashEntryStub*) 1.591 + PL_DHashTableOperate(mTable, proto, PL_DHASH_ADD); 1.592 + if (!entry) 1.593 + return nullptr; 1.594 + if (entry->key) 1.595 + return (XPCWrappedNativeProto*) entry->key; 1.596 + entry->key = proto; 1.597 + return proto; 1.598 + } 1.599 + 1.600 + inline void Remove(XPCWrappedNativeProto* proto) 1.601 + { 1.602 + NS_PRECONDITION(proto,"bad param"); 1.603 + PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE); 1.604 + } 1.605 + 1.606 + inline uint32_t Count() {return mTable->entryCount;} 1.607 + inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) 1.608 + {return PL_DHashTableEnumerate(mTable, f, arg);} 1.609 + 1.610 + ~XPCWrappedNativeProtoMap(); 1.611 +private: 1.612 + XPCWrappedNativeProtoMap(); // no implementation 1.613 + XPCWrappedNativeProtoMap(int size); 1.614 +private: 1.615 + PLDHashTable *mTable; 1.616 +}; 1.617 + 1.618 +/***************************************************************************/ 1.619 + 1.620 +class JSObject2JSObjectMap 1.621 +{ 1.622 + typedef js::HashMap<JSObject *, JS::Heap<JSObject *>, js::PointerHasher<JSObject *, 3>, 1.623 + js::SystemAllocPolicy> Map; 1.624 + 1.625 +public: 1.626 + static JSObject2JSObjectMap* newMap(int size) { 1.627 + JSObject2JSObjectMap* map = new JSObject2JSObjectMap(); 1.628 + if (map && map->mTable.init(size)) 1.629 + return map; 1.630 + delete map; 1.631 + return nullptr; 1.632 + } 1.633 + 1.634 + inline JSObject* Find(JSObject* key) { 1.635 + NS_PRECONDITION(key, "bad param"); 1.636 + if (Map::Ptr p = mTable.lookup(key)) 1.637 + return p->value(); 1.638 + return nullptr; 1.639 + } 1.640 + 1.641 + /* Note: If the entry already exists, return the old value. */ 1.642 + inline JSObject* Add(JSContext *cx, JSObject *key, JSObject *value) { 1.643 + NS_PRECONDITION(key,"bad param"); 1.644 + Map::AddPtr p = mTable.lookupForAdd(key); 1.645 + if (p) 1.646 + return p->value(); 1.647 + if (!mTable.add(p, key, value)) 1.648 + return nullptr; 1.649 + MOZ_ASSERT(xpc::GetCompartmentPrivate(key)->scope->mWaiverWrapperMap == this); 1.650 + JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this); 1.651 + return value; 1.652 + } 1.653 + 1.654 + inline void Remove(JSObject* key) { 1.655 + NS_PRECONDITION(key,"bad param"); 1.656 + mTable.remove(key); 1.657 + } 1.658 + 1.659 + inline uint32_t Count() { return mTable.count(); } 1.660 + 1.661 + void Sweep() { 1.662 + for (Map::Enum e(mTable); !e.empty(); e.popFront()) { 1.663 + JSObject *updated = e.front().key(); 1.664 + if (JS_IsAboutToBeFinalizedUnbarriered(&updated) || JS_IsAboutToBeFinalized(&e.front().value())) 1.665 + e.removeFront(); 1.666 + else if (updated != e.front().key()) 1.667 + e.rekeyFront(updated); 1.668 + } 1.669 + } 1.670 + 1.671 + void Reparent(JSContext *aCx, JSObject *aNewInnerArg) { 1.672 + JS::RootedObject aNewInner(aCx, aNewInnerArg); 1.673 + for (Map::Enum e(mTable); !e.empty(); e.popFront()) { 1.674 + /* 1.675 + * We reparent wrappers that have as their parent an inner window 1.676 + * whose outer has the new inner window as its current inner. 1.677 + */ 1.678 + JS::RootedObject wrapper(aCx, e.front().value()); 1.679 + JS::RootedObject parent(aCx, JS_GetParent(wrapper)); 1.680 + JS::RootedObject outer(aCx, JS_ObjectToOuterObject(aCx, parent)); 1.681 + if (outer) { 1.682 + JSObject *inner = JS_ObjectToInnerObject(aCx, outer); 1.683 + if (inner == aNewInner && inner != parent) 1.684 + JS_SetParent(aCx, wrapper, aNewInner); 1.685 + } else { 1.686 + JS_ClearPendingException(aCx); 1.687 + } 1.688 + } 1.689 + } 1.690 + 1.691 +private: 1.692 + JSObject2JSObjectMap() {} 1.693 + 1.694 + /* 1.695 + * This function is called during minor GCs for each key in the HashMap that 1.696 + * has been moved. 1.697 + */ 1.698 + static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { 1.699 + /* 1.700 + * To stop the barriers on the values of mTable firing while we are 1.701 + * marking the store buffer, we cast the table to one that is 1.702 + * binary-equivatlent but without the barriers, and update that. 1.703 + */ 1.704 + typedef js::HashMap<JSObject *, JSObject *, js::PointerHasher<JSObject *, 3>, 1.705 + js::SystemAllocPolicy> UnbarrieredMap; 1.706 + JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(data); 1.707 + UnbarrieredMap &table = reinterpret_cast<UnbarrieredMap &>(self->mTable); 1.708 + 1.709 + JSObject *prior = key; 1.710 + JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key"); 1.711 + table.rekeyIfMoved(prior, key); 1.712 + } 1.713 + 1.714 + Map mTable; 1.715 +}; 1.716 + 1.717 +#endif /* xpcmaps_h___ */