js/xpconnect/src/XPCMaps.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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___ */

mercurial