Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* vim: set ts=8 sts=4 et sw=4 tw=99: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | /* Private maps (hashtables). */ |
michael@0 | 8 | |
michael@0 | 9 | #ifndef xpcmaps_h___ |
michael@0 | 10 | #define xpcmaps_h___ |
michael@0 | 11 | |
michael@0 | 12 | #include "mozilla/MemoryReporting.h" |
michael@0 | 13 | |
michael@0 | 14 | |
michael@0 | 15 | // Maps... |
michael@0 | 16 | |
michael@0 | 17 | // Note that most of the declarations for hash table entries begin with |
michael@0 | 18 | // a pointer to something or another. This makes them look enough like |
michael@0 | 19 | // the PLDHashEntryStub struct that the default OPs (PL_DHashGetStubOps()) |
michael@0 | 20 | // just do the right thing for most of our needs. |
michael@0 | 21 | |
michael@0 | 22 | // no virtuals in the maps - all the common stuff inlined |
michael@0 | 23 | // templates could be used to good effect here. |
michael@0 | 24 | |
michael@0 | 25 | /*************************/ |
michael@0 | 26 | |
michael@0 | 27 | class JSObject2WrappedJSMap |
michael@0 | 28 | { |
michael@0 | 29 | typedef js::HashMap<JSObject*, nsXPCWrappedJS*, js::PointerHasher<JSObject*, 3>, |
michael@0 | 30 | js::SystemAllocPolicy> Map; |
michael@0 | 31 | |
michael@0 | 32 | public: |
michael@0 | 33 | static JSObject2WrappedJSMap* newMap(int size) { |
michael@0 | 34 | JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap(); |
michael@0 | 35 | if (map && map->mTable.init(size)) |
michael@0 | 36 | return map; |
michael@0 | 37 | delete map; |
michael@0 | 38 | return nullptr; |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | inline nsXPCWrappedJS* Find(JSObject* Obj) { |
michael@0 | 42 | NS_PRECONDITION(Obj,"bad param"); |
michael@0 | 43 | Map::Ptr p = mTable.lookup(Obj); |
michael@0 | 44 | return p ? p->value() : nullptr; |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) { |
michael@0 | 48 | NS_PRECONDITION(wrapper,"bad param"); |
michael@0 | 49 | JSObject* obj = wrapper->GetJSObjectPreserveColor(); |
michael@0 | 50 | Map::AddPtr p = mTable.lookupForAdd(obj); |
michael@0 | 51 | if (p) |
michael@0 | 52 | return p->value(); |
michael@0 | 53 | if (!mTable.add(p, obj, wrapper)) |
michael@0 | 54 | return nullptr; |
michael@0 | 55 | JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this); |
michael@0 | 56 | return wrapper; |
michael@0 | 57 | } |
michael@0 | 58 | |
michael@0 | 59 | inline void Remove(nsXPCWrappedJS* wrapper) { |
michael@0 | 60 | NS_PRECONDITION(wrapper,"bad param"); |
michael@0 | 61 | mTable.remove(wrapper->GetJSObjectPreserveColor()); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | inline uint32_t Count() {return mTable.count();} |
michael@0 | 65 | |
michael@0 | 66 | inline void Dump(int16_t depth) { |
michael@0 | 67 | for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) |
michael@0 | 68 | r.front().value()->DebugDump(depth); |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | void FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying); |
michael@0 | 72 | |
michael@0 | 73 | void ShutdownMarker(); |
michael@0 | 74 | |
michael@0 | 75 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { |
michael@0 | 76 | size_t n = mallocSizeOf(this); |
michael@0 | 77 | n += mTable.sizeOfExcludingThis(mallocSizeOf); |
michael@0 | 78 | return n; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | private: |
michael@0 | 82 | JSObject2WrappedJSMap() {} |
michael@0 | 83 | |
michael@0 | 84 | /* |
michael@0 | 85 | * This function is called during minor GCs for each key in the HashMap that |
michael@0 | 86 | * has been moved. |
michael@0 | 87 | */ |
michael@0 | 88 | static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { |
michael@0 | 89 | JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(data); |
michael@0 | 90 | JSObject *prior = key; |
michael@0 | 91 | JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key"); |
michael@0 | 92 | self->mTable.rekeyIfMoved(prior, key); |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | Map mTable; |
michael@0 | 96 | }; |
michael@0 | 97 | |
michael@0 | 98 | /*************************/ |
michael@0 | 99 | |
michael@0 | 100 | class Native2WrappedNativeMap |
michael@0 | 101 | { |
michael@0 | 102 | public: |
michael@0 | 103 | struct Entry : public PLDHashEntryHdr |
michael@0 | 104 | { |
michael@0 | 105 | nsISupports* key; |
michael@0 | 106 | XPCWrappedNative* value; |
michael@0 | 107 | }; |
michael@0 | 108 | |
michael@0 | 109 | static Native2WrappedNativeMap* newMap(int size); |
michael@0 | 110 | |
michael@0 | 111 | inline XPCWrappedNative* Find(nsISupports* Obj) |
michael@0 | 112 | { |
michael@0 | 113 | NS_PRECONDITION(Obj,"bad param"); |
michael@0 | 114 | Entry* entry = (Entry*) |
michael@0 | 115 | PL_DHashTableOperate(mTable, Obj, PL_DHASH_LOOKUP); |
michael@0 | 116 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 117 | return nullptr; |
michael@0 | 118 | return entry->value; |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | inline XPCWrappedNative* Add(XPCWrappedNative* wrapper) |
michael@0 | 122 | { |
michael@0 | 123 | NS_PRECONDITION(wrapper,"bad param"); |
michael@0 | 124 | nsISupports* obj = wrapper->GetIdentityObject(); |
michael@0 | 125 | MOZ_ASSERT(!Find(obj), "wrapper already in new scope!"); |
michael@0 | 126 | Entry* entry = (Entry*) |
michael@0 | 127 | PL_DHashTableOperate(mTable, obj, PL_DHASH_ADD); |
michael@0 | 128 | if (!entry) |
michael@0 | 129 | return nullptr; |
michael@0 | 130 | if (entry->key) |
michael@0 | 131 | return entry->value; |
michael@0 | 132 | entry->key = obj; |
michael@0 | 133 | entry->value = wrapper; |
michael@0 | 134 | return wrapper; |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | inline void Remove(XPCWrappedNative* wrapper) |
michael@0 | 138 | { |
michael@0 | 139 | NS_PRECONDITION(wrapper,"bad param"); |
michael@0 | 140 | #ifdef DEBUG |
michael@0 | 141 | XPCWrappedNative* wrapperInMap = Find(wrapper->GetIdentityObject()); |
michael@0 | 142 | MOZ_ASSERT(!wrapperInMap || wrapperInMap == wrapper, |
michael@0 | 143 | "About to remove a different wrapper with the same " |
michael@0 | 144 | "nsISupports identity! This will most likely cause serious " |
michael@0 | 145 | "problems!"); |
michael@0 | 146 | #endif |
michael@0 | 147 | PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE); |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 151 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 152 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 153 | |
michael@0 | 154 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
michael@0 | 155 | |
michael@0 | 156 | ~Native2WrappedNativeMap(); |
michael@0 | 157 | private: |
michael@0 | 158 | Native2WrappedNativeMap(); // no implementation |
michael@0 | 159 | Native2WrappedNativeMap(int size); |
michael@0 | 160 | |
michael@0 | 161 | static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
michael@0 | 162 | |
michael@0 | 163 | private: |
michael@0 | 164 | PLDHashTable *mTable; |
michael@0 | 165 | }; |
michael@0 | 166 | |
michael@0 | 167 | /*************************/ |
michael@0 | 168 | |
michael@0 | 169 | class IID2WrappedJSClassMap |
michael@0 | 170 | { |
michael@0 | 171 | public: |
michael@0 | 172 | struct Entry : public PLDHashEntryHdr |
michael@0 | 173 | { |
michael@0 | 174 | const nsIID* key; |
michael@0 | 175 | nsXPCWrappedJSClass* value; |
michael@0 | 176 | |
michael@0 | 177 | static const struct PLDHashTableOps sOps; |
michael@0 | 178 | }; |
michael@0 | 179 | |
michael@0 | 180 | static IID2WrappedJSClassMap* newMap(int size); |
michael@0 | 181 | |
michael@0 | 182 | inline nsXPCWrappedJSClass* Find(REFNSIID iid) |
michael@0 | 183 | { |
michael@0 | 184 | Entry* entry = (Entry*) |
michael@0 | 185 | PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
michael@0 | 186 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 187 | return nullptr; |
michael@0 | 188 | return entry->value; |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | inline nsXPCWrappedJSClass* Add(nsXPCWrappedJSClass* clazz) |
michael@0 | 192 | { |
michael@0 | 193 | NS_PRECONDITION(clazz,"bad param"); |
michael@0 | 194 | const nsIID* iid = &clazz->GetIID(); |
michael@0 | 195 | Entry* entry = (Entry*) |
michael@0 | 196 | PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); |
michael@0 | 197 | if (!entry) |
michael@0 | 198 | return nullptr; |
michael@0 | 199 | if (entry->key) |
michael@0 | 200 | return entry->value; |
michael@0 | 201 | entry->key = iid; |
michael@0 | 202 | entry->value = clazz; |
michael@0 | 203 | return clazz; |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | inline void Remove(nsXPCWrappedJSClass* clazz) |
michael@0 | 207 | { |
michael@0 | 208 | NS_PRECONDITION(clazz,"bad param"); |
michael@0 | 209 | PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE); |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 213 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 214 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 215 | |
michael@0 | 216 | ~IID2WrappedJSClassMap(); |
michael@0 | 217 | private: |
michael@0 | 218 | IID2WrappedJSClassMap(); // no implementation |
michael@0 | 219 | IID2WrappedJSClassMap(int size); |
michael@0 | 220 | private: |
michael@0 | 221 | PLDHashTable *mTable; |
michael@0 | 222 | }; |
michael@0 | 223 | |
michael@0 | 224 | /*************************/ |
michael@0 | 225 | |
michael@0 | 226 | class IID2NativeInterfaceMap |
michael@0 | 227 | { |
michael@0 | 228 | public: |
michael@0 | 229 | struct Entry : public PLDHashEntryHdr |
michael@0 | 230 | { |
michael@0 | 231 | const nsIID* key; |
michael@0 | 232 | XPCNativeInterface* value; |
michael@0 | 233 | |
michael@0 | 234 | static const struct PLDHashTableOps sOps; |
michael@0 | 235 | }; |
michael@0 | 236 | |
michael@0 | 237 | static IID2NativeInterfaceMap* newMap(int size); |
michael@0 | 238 | |
michael@0 | 239 | inline XPCNativeInterface* Find(REFNSIID iid) |
michael@0 | 240 | { |
michael@0 | 241 | Entry* entry = (Entry*) |
michael@0 | 242 | PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
michael@0 | 243 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 244 | return nullptr; |
michael@0 | 245 | return entry->value; |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | inline XPCNativeInterface* Add(XPCNativeInterface* iface) |
michael@0 | 249 | { |
michael@0 | 250 | NS_PRECONDITION(iface,"bad param"); |
michael@0 | 251 | const nsIID* iid = iface->GetIID(); |
michael@0 | 252 | Entry* entry = (Entry*) |
michael@0 | 253 | PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); |
michael@0 | 254 | if (!entry) |
michael@0 | 255 | return nullptr; |
michael@0 | 256 | if (entry->key) |
michael@0 | 257 | return entry->value; |
michael@0 | 258 | entry->key = iid; |
michael@0 | 259 | entry->value = iface; |
michael@0 | 260 | return iface; |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | inline void Remove(XPCNativeInterface* iface) |
michael@0 | 264 | { |
michael@0 | 265 | NS_PRECONDITION(iface,"bad param"); |
michael@0 | 266 | PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE); |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 270 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 271 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 272 | |
michael@0 | 273 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
michael@0 | 274 | |
michael@0 | 275 | ~IID2NativeInterfaceMap(); |
michael@0 | 276 | private: |
michael@0 | 277 | IID2NativeInterfaceMap(); // no implementation |
michael@0 | 278 | IID2NativeInterfaceMap(int size); |
michael@0 | 279 | |
michael@0 | 280 | static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
michael@0 | 281 | |
michael@0 | 282 | private: |
michael@0 | 283 | PLDHashTable *mTable; |
michael@0 | 284 | }; |
michael@0 | 285 | |
michael@0 | 286 | /*************************/ |
michael@0 | 287 | |
michael@0 | 288 | class ClassInfo2NativeSetMap |
michael@0 | 289 | { |
michael@0 | 290 | public: |
michael@0 | 291 | struct Entry : public PLDHashEntryHdr |
michael@0 | 292 | { |
michael@0 | 293 | nsIClassInfo* key; |
michael@0 | 294 | XPCNativeSet* value; |
michael@0 | 295 | }; |
michael@0 | 296 | |
michael@0 | 297 | static ClassInfo2NativeSetMap* newMap(int size); |
michael@0 | 298 | |
michael@0 | 299 | inline XPCNativeSet* Find(nsIClassInfo* info) |
michael@0 | 300 | { |
michael@0 | 301 | Entry* entry = (Entry*) |
michael@0 | 302 | PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); |
michael@0 | 303 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 304 | return nullptr; |
michael@0 | 305 | return entry->value; |
michael@0 | 306 | } |
michael@0 | 307 | |
michael@0 | 308 | inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) |
michael@0 | 309 | { |
michael@0 | 310 | NS_PRECONDITION(info,"bad param"); |
michael@0 | 311 | Entry* entry = (Entry*) |
michael@0 | 312 | PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); |
michael@0 | 313 | if (!entry) |
michael@0 | 314 | return nullptr; |
michael@0 | 315 | if (entry->key) |
michael@0 | 316 | return entry->value; |
michael@0 | 317 | entry->key = info; |
michael@0 | 318 | entry->value = set; |
michael@0 | 319 | return set; |
michael@0 | 320 | } |
michael@0 | 321 | |
michael@0 | 322 | inline void Remove(nsIClassInfo* info) |
michael@0 | 323 | { |
michael@0 | 324 | NS_PRECONDITION(info,"bad param"); |
michael@0 | 325 | PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); |
michael@0 | 326 | } |
michael@0 | 327 | |
michael@0 | 328 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 329 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 330 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 331 | |
michael@0 | 332 | // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets. |
michael@0 | 333 | // So we don't want to count those XPCNativeSets, because they are better |
michael@0 | 334 | // counted elsewhere (i.e. in XPCJSRuntime::mNativeSetMap, which holds |
michael@0 | 335 | // pointers to *all* XPCNativeSets). Hence the "Shallow". |
michael@0 | 336 | size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
michael@0 | 337 | |
michael@0 | 338 | ~ClassInfo2NativeSetMap(); |
michael@0 | 339 | private: |
michael@0 | 340 | ClassInfo2NativeSetMap(); // no implementation |
michael@0 | 341 | ClassInfo2NativeSetMap(int size); |
michael@0 | 342 | private: |
michael@0 | 343 | PLDHashTable *mTable; |
michael@0 | 344 | }; |
michael@0 | 345 | |
michael@0 | 346 | /*************************/ |
michael@0 | 347 | |
michael@0 | 348 | class ClassInfo2WrappedNativeProtoMap |
michael@0 | 349 | { |
michael@0 | 350 | public: |
michael@0 | 351 | struct Entry : public PLDHashEntryHdr |
michael@0 | 352 | { |
michael@0 | 353 | nsIClassInfo* key; |
michael@0 | 354 | XPCWrappedNativeProto* value; |
michael@0 | 355 | }; |
michael@0 | 356 | |
michael@0 | 357 | static ClassInfo2WrappedNativeProtoMap* newMap(int size); |
michael@0 | 358 | |
michael@0 | 359 | inline XPCWrappedNativeProto* Find(nsIClassInfo* info) |
michael@0 | 360 | { |
michael@0 | 361 | Entry* entry = (Entry*) |
michael@0 | 362 | PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); |
michael@0 | 363 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 364 | return nullptr; |
michael@0 | 365 | return entry->value; |
michael@0 | 366 | } |
michael@0 | 367 | |
michael@0 | 368 | inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) |
michael@0 | 369 | { |
michael@0 | 370 | NS_PRECONDITION(info,"bad param"); |
michael@0 | 371 | Entry* entry = (Entry*) |
michael@0 | 372 | PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); |
michael@0 | 373 | if (!entry) |
michael@0 | 374 | return nullptr; |
michael@0 | 375 | if (entry->key) |
michael@0 | 376 | return entry->value; |
michael@0 | 377 | entry->key = info; |
michael@0 | 378 | entry->value = proto; |
michael@0 | 379 | return proto; |
michael@0 | 380 | } |
michael@0 | 381 | |
michael@0 | 382 | inline void Remove(nsIClassInfo* info) |
michael@0 | 383 | { |
michael@0 | 384 | NS_PRECONDITION(info,"bad param"); |
michael@0 | 385 | PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 389 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 390 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 391 | |
michael@0 | 392 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
michael@0 | 393 | |
michael@0 | 394 | ~ClassInfo2WrappedNativeProtoMap(); |
michael@0 | 395 | private: |
michael@0 | 396 | ClassInfo2WrappedNativeProtoMap(); // no implementation |
michael@0 | 397 | ClassInfo2WrappedNativeProtoMap(int size); |
michael@0 | 398 | |
michael@0 | 399 | static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
michael@0 | 400 | |
michael@0 | 401 | private: |
michael@0 | 402 | PLDHashTable *mTable; |
michael@0 | 403 | }; |
michael@0 | 404 | |
michael@0 | 405 | /*************************/ |
michael@0 | 406 | |
michael@0 | 407 | class NativeSetMap |
michael@0 | 408 | { |
michael@0 | 409 | public: |
michael@0 | 410 | struct Entry : public PLDHashEntryHdr |
michael@0 | 411 | { |
michael@0 | 412 | XPCNativeSet* key_value; |
michael@0 | 413 | |
michael@0 | 414 | static bool |
michael@0 | 415 | Match(PLDHashTable *table, |
michael@0 | 416 | const PLDHashEntryHdr *entry, |
michael@0 | 417 | const void *key); |
michael@0 | 418 | |
michael@0 | 419 | static const struct PLDHashTableOps sOps; |
michael@0 | 420 | }; |
michael@0 | 421 | |
michael@0 | 422 | static NativeSetMap* newMap(int size); |
michael@0 | 423 | |
michael@0 | 424 | inline XPCNativeSet* Find(XPCNativeSetKey* key) |
michael@0 | 425 | { |
michael@0 | 426 | Entry* entry = (Entry*) |
michael@0 | 427 | PL_DHashTableOperate(mTable, key, PL_DHASH_LOOKUP); |
michael@0 | 428 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 429 | return nullptr; |
michael@0 | 430 | return entry->key_value; |
michael@0 | 431 | } |
michael@0 | 432 | |
michael@0 | 433 | inline XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set) |
michael@0 | 434 | { |
michael@0 | 435 | NS_PRECONDITION(key,"bad param"); |
michael@0 | 436 | NS_PRECONDITION(set,"bad param"); |
michael@0 | 437 | Entry* entry = (Entry*) |
michael@0 | 438 | PL_DHashTableOperate(mTable, key, PL_DHASH_ADD); |
michael@0 | 439 | if (!entry) |
michael@0 | 440 | return nullptr; |
michael@0 | 441 | if (entry->key_value) |
michael@0 | 442 | return entry->key_value; |
michael@0 | 443 | entry->key_value = set; |
michael@0 | 444 | return set; |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | inline XPCNativeSet* Add(XPCNativeSet* set) |
michael@0 | 448 | { |
michael@0 | 449 | XPCNativeSetKey key(set, nullptr, 0); |
michael@0 | 450 | return Add(&key, set); |
michael@0 | 451 | } |
michael@0 | 452 | |
michael@0 | 453 | inline void Remove(XPCNativeSet* set) |
michael@0 | 454 | { |
michael@0 | 455 | NS_PRECONDITION(set,"bad param"); |
michael@0 | 456 | |
michael@0 | 457 | XPCNativeSetKey key(set, nullptr, 0); |
michael@0 | 458 | PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE); |
michael@0 | 459 | } |
michael@0 | 460 | |
michael@0 | 461 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 462 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 463 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 464 | |
michael@0 | 465 | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
michael@0 | 466 | |
michael@0 | 467 | ~NativeSetMap(); |
michael@0 | 468 | private: |
michael@0 | 469 | NativeSetMap(); // no implementation |
michael@0 | 470 | NativeSetMap(int size); |
michael@0 | 471 | |
michael@0 | 472 | static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
michael@0 | 473 | |
michael@0 | 474 | private: |
michael@0 | 475 | PLDHashTable *mTable; |
michael@0 | 476 | }; |
michael@0 | 477 | |
michael@0 | 478 | /***************************************************************************/ |
michael@0 | 479 | |
michael@0 | 480 | class IID2ThisTranslatorMap |
michael@0 | 481 | { |
michael@0 | 482 | public: |
michael@0 | 483 | struct Entry : public PLDHashEntryHdr |
michael@0 | 484 | { |
michael@0 | 485 | nsIID key; |
michael@0 | 486 | nsCOMPtr<nsIXPCFunctionThisTranslator> value; |
michael@0 | 487 | |
michael@0 | 488 | static bool |
michael@0 | 489 | Match(PLDHashTable *table, |
michael@0 | 490 | const PLDHashEntryHdr *entry, |
michael@0 | 491 | const void *key); |
michael@0 | 492 | |
michael@0 | 493 | static void |
michael@0 | 494 | Clear(PLDHashTable *table, PLDHashEntryHdr *entry); |
michael@0 | 495 | |
michael@0 | 496 | static const struct PLDHashTableOps sOps; |
michael@0 | 497 | }; |
michael@0 | 498 | |
michael@0 | 499 | static IID2ThisTranslatorMap* newMap(int size); |
michael@0 | 500 | |
michael@0 | 501 | inline nsIXPCFunctionThisTranslator* Find(REFNSIID iid) |
michael@0 | 502 | { |
michael@0 | 503 | Entry* entry = (Entry*) |
michael@0 | 504 | PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
michael@0 | 505 | if (PL_DHASH_ENTRY_IS_FREE(entry)) |
michael@0 | 506 | return nullptr; |
michael@0 | 507 | return entry->value; |
michael@0 | 508 | } |
michael@0 | 509 | |
michael@0 | 510 | inline nsIXPCFunctionThisTranslator* Add(REFNSIID iid, |
michael@0 | 511 | nsIXPCFunctionThisTranslator* obj) |
michael@0 | 512 | { |
michael@0 | 513 | |
michael@0 | 514 | Entry* entry = (Entry*) |
michael@0 | 515 | PL_DHashTableOperate(mTable, &iid, PL_DHASH_ADD); |
michael@0 | 516 | if (!entry) |
michael@0 | 517 | return nullptr; |
michael@0 | 518 | entry->value = obj; |
michael@0 | 519 | entry->key = iid; |
michael@0 | 520 | return obj; |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | inline void Remove(REFNSIID iid) |
michael@0 | 524 | { |
michael@0 | 525 | PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE); |
michael@0 | 526 | } |
michael@0 | 527 | |
michael@0 | 528 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 529 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 530 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 531 | |
michael@0 | 532 | ~IID2ThisTranslatorMap(); |
michael@0 | 533 | private: |
michael@0 | 534 | IID2ThisTranslatorMap(); // no implementation |
michael@0 | 535 | IID2ThisTranslatorMap(int size); |
michael@0 | 536 | private: |
michael@0 | 537 | PLDHashTable *mTable; |
michael@0 | 538 | }; |
michael@0 | 539 | |
michael@0 | 540 | /***************************************************************************/ |
michael@0 | 541 | |
michael@0 | 542 | class XPCNativeScriptableSharedMap |
michael@0 | 543 | { |
michael@0 | 544 | public: |
michael@0 | 545 | struct Entry : public PLDHashEntryHdr |
michael@0 | 546 | { |
michael@0 | 547 | XPCNativeScriptableShared* key; |
michael@0 | 548 | |
michael@0 | 549 | static PLDHashNumber |
michael@0 | 550 | Hash(PLDHashTable *table, const void *key); |
michael@0 | 551 | |
michael@0 | 552 | static bool |
michael@0 | 553 | Match(PLDHashTable *table, |
michael@0 | 554 | const PLDHashEntryHdr *entry, |
michael@0 | 555 | const void *key); |
michael@0 | 556 | |
michael@0 | 557 | static const struct PLDHashTableOps sOps; |
michael@0 | 558 | }; |
michael@0 | 559 | |
michael@0 | 560 | static XPCNativeScriptableSharedMap* newMap(int size); |
michael@0 | 561 | |
michael@0 | 562 | bool GetNewOrUsed(uint32_t flags, char* name, uint32_t interfacesBitmap, |
michael@0 | 563 | XPCNativeScriptableInfo* si); |
michael@0 | 564 | |
michael@0 | 565 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 566 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 567 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 568 | |
michael@0 | 569 | ~XPCNativeScriptableSharedMap(); |
michael@0 | 570 | private: |
michael@0 | 571 | XPCNativeScriptableSharedMap(); // no implementation |
michael@0 | 572 | XPCNativeScriptableSharedMap(int size); |
michael@0 | 573 | private: |
michael@0 | 574 | PLDHashTable *mTable; |
michael@0 | 575 | }; |
michael@0 | 576 | |
michael@0 | 577 | /***************************************************************************/ |
michael@0 | 578 | |
michael@0 | 579 | class XPCWrappedNativeProtoMap |
michael@0 | 580 | { |
michael@0 | 581 | public: |
michael@0 | 582 | static XPCWrappedNativeProtoMap* newMap(int size); |
michael@0 | 583 | |
michael@0 | 584 | inline XPCWrappedNativeProto* Add(XPCWrappedNativeProto* proto) |
michael@0 | 585 | { |
michael@0 | 586 | NS_PRECONDITION(proto,"bad param"); |
michael@0 | 587 | PLDHashEntryStub* entry = (PLDHashEntryStub*) |
michael@0 | 588 | PL_DHashTableOperate(mTable, proto, PL_DHASH_ADD); |
michael@0 | 589 | if (!entry) |
michael@0 | 590 | return nullptr; |
michael@0 | 591 | if (entry->key) |
michael@0 | 592 | return (XPCWrappedNativeProto*) entry->key; |
michael@0 | 593 | entry->key = proto; |
michael@0 | 594 | return proto; |
michael@0 | 595 | } |
michael@0 | 596 | |
michael@0 | 597 | inline void Remove(XPCWrappedNativeProto* proto) |
michael@0 | 598 | { |
michael@0 | 599 | NS_PRECONDITION(proto,"bad param"); |
michael@0 | 600 | PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE); |
michael@0 | 601 | } |
michael@0 | 602 | |
michael@0 | 603 | inline uint32_t Count() {return mTable->entryCount;} |
michael@0 | 604 | inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
michael@0 | 605 | {return PL_DHashTableEnumerate(mTable, f, arg);} |
michael@0 | 606 | |
michael@0 | 607 | ~XPCWrappedNativeProtoMap(); |
michael@0 | 608 | private: |
michael@0 | 609 | XPCWrappedNativeProtoMap(); // no implementation |
michael@0 | 610 | XPCWrappedNativeProtoMap(int size); |
michael@0 | 611 | private: |
michael@0 | 612 | PLDHashTable *mTable; |
michael@0 | 613 | }; |
michael@0 | 614 | |
michael@0 | 615 | /***************************************************************************/ |
michael@0 | 616 | |
michael@0 | 617 | class JSObject2JSObjectMap |
michael@0 | 618 | { |
michael@0 | 619 | typedef js::HashMap<JSObject *, JS::Heap<JSObject *>, js::PointerHasher<JSObject *, 3>, |
michael@0 | 620 | js::SystemAllocPolicy> Map; |
michael@0 | 621 | |
michael@0 | 622 | public: |
michael@0 | 623 | static JSObject2JSObjectMap* newMap(int size) { |
michael@0 | 624 | JSObject2JSObjectMap* map = new JSObject2JSObjectMap(); |
michael@0 | 625 | if (map && map->mTable.init(size)) |
michael@0 | 626 | return map; |
michael@0 | 627 | delete map; |
michael@0 | 628 | return nullptr; |
michael@0 | 629 | } |
michael@0 | 630 | |
michael@0 | 631 | inline JSObject* Find(JSObject* key) { |
michael@0 | 632 | NS_PRECONDITION(key, "bad param"); |
michael@0 | 633 | if (Map::Ptr p = mTable.lookup(key)) |
michael@0 | 634 | return p->value(); |
michael@0 | 635 | return nullptr; |
michael@0 | 636 | } |
michael@0 | 637 | |
michael@0 | 638 | /* Note: If the entry already exists, return the old value. */ |
michael@0 | 639 | inline JSObject* Add(JSContext *cx, JSObject *key, JSObject *value) { |
michael@0 | 640 | NS_PRECONDITION(key,"bad param"); |
michael@0 | 641 | Map::AddPtr p = mTable.lookupForAdd(key); |
michael@0 | 642 | if (p) |
michael@0 | 643 | return p->value(); |
michael@0 | 644 | if (!mTable.add(p, key, value)) |
michael@0 | 645 | return nullptr; |
michael@0 | 646 | MOZ_ASSERT(xpc::GetCompartmentPrivate(key)->scope->mWaiverWrapperMap == this); |
michael@0 | 647 | JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this); |
michael@0 | 648 | return value; |
michael@0 | 649 | } |
michael@0 | 650 | |
michael@0 | 651 | inline void Remove(JSObject* key) { |
michael@0 | 652 | NS_PRECONDITION(key,"bad param"); |
michael@0 | 653 | mTable.remove(key); |
michael@0 | 654 | } |
michael@0 | 655 | |
michael@0 | 656 | inline uint32_t Count() { return mTable.count(); } |
michael@0 | 657 | |
michael@0 | 658 | void Sweep() { |
michael@0 | 659 | for (Map::Enum e(mTable); !e.empty(); e.popFront()) { |
michael@0 | 660 | JSObject *updated = e.front().key(); |
michael@0 | 661 | if (JS_IsAboutToBeFinalizedUnbarriered(&updated) || JS_IsAboutToBeFinalized(&e.front().value())) |
michael@0 | 662 | e.removeFront(); |
michael@0 | 663 | else if (updated != e.front().key()) |
michael@0 | 664 | e.rekeyFront(updated); |
michael@0 | 665 | } |
michael@0 | 666 | } |
michael@0 | 667 | |
michael@0 | 668 | void Reparent(JSContext *aCx, JSObject *aNewInnerArg) { |
michael@0 | 669 | JS::RootedObject aNewInner(aCx, aNewInnerArg); |
michael@0 | 670 | for (Map::Enum e(mTable); !e.empty(); e.popFront()) { |
michael@0 | 671 | /* |
michael@0 | 672 | * We reparent wrappers that have as their parent an inner window |
michael@0 | 673 | * whose outer has the new inner window as its current inner. |
michael@0 | 674 | */ |
michael@0 | 675 | JS::RootedObject wrapper(aCx, e.front().value()); |
michael@0 | 676 | JS::RootedObject parent(aCx, JS_GetParent(wrapper)); |
michael@0 | 677 | JS::RootedObject outer(aCx, JS_ObjectToOuterObject(aCx, parent)); |
michael@0 | 678 | if (outer) { |
michael@0 | 679 | JSObject *inner = JS_ObjectToInnerObject(aCx, outer); |
michael@0 | 680 | if (inner == aNewInner && inner != parent) |
michael@0 | 681 | JS_SetParent(aCx, wrapper, aNewInner); |
michael@0 | 682 | } else { |
michael@0 | 683 | JS_ClearPendingException(aCx); |
michael@0 | 684 | } |
michael@0 | 685 | } |
michael@0 | 686 | } |
michael@0 | 687 | |
michael@0 | 688 | private: |
michael@0 | 689 | JSObject2JSObjectMap() {} |
michael@0 | 690 | |
michael@0 | 691 | /* |
michael@0 | 692 | * This function is called during minor GCs for each key in the HashMap that |
michael@0 | 693 | * has been moved. |
michael@0 | 694 | */ |
michael@0 | 695 | static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { |
michael@0 | 696 | /* |
michael@0 | 697 | * To stop the barriers on the values of mTable firing while we are |
michael@0 | 698 | * marking the store buffer, we cast the table to one that is |
michael@0 | 699 | * binary-equivatlent but without the barriers, and update that. |
michael@0 | 700 | */ |
michael@0 | 701 | typedef js::HashMap<JSObject *, JSObject *, js::PointerHasher<JSObject *, 3>, |
michael@0 | 702 | js::SystemAllocPolicy> UnbarrieredMap; |
michael@0 | 703 | JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(data); |
michael@0 | 704 | UnbarrieredMap &table = reinterpret_cast<UnbarrieredMap &>(self->mTable); |
michael@0 | 705 | |
michael@0 | 706 | JSObject *prior = key; |
michael@0 | 707 | JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key"); |
michael@0 | 708 | table.rekeyIfMoved(prior, key); |
michael@0 | 709 | } |
michael@0 | 710 | |
michael@0 | 711 | Map mTable; |
michael@0 | 712 | }; |
michael@0 | 713 | |
michael@0 | 714 | #endif /* xpcmaps_h___ */ |