js/xpconnect/src/XPCMaps.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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 #include "mozilla/MathAlgorithms.h"
michael@0 10 #include "mozilla/MemoryReporting.h"
michael@0 11 #include "xpcprivate.h"
michael@0 12
michael@0 13 #include "js/HashTable.h"
michael@0 14
michael@0 15 using namespace mozilla;
michael@0 16
michael@0 17 /***************************************************************************/
michael@0 18 // static shared...
michael@0 19
michael@0 20 // Note this is returning the bit pattern of the first part of the nsID, not
michael@0 21 // the pointer to the nsID.
michael@0 22
michael@0 23 static PLDHashNumber
michael@0 24 HashIIDPtrKey(PLDHashTable *table, const void *key)
michael@0 25 {
michael@0 26 return *((js::HashNumber*)key);
michael@0 27 }
michael@0 28
michael@0 29 static bool
michael@0 30 MatchIIDPtrKey(PLDHashTable *table,
michael@0 31 const PLDHashEntryHdr *entry,
michael@0 32 const void *key)
michael@0 33 {
michael@0 34 return ((const nsID*)key)->
michael@0 35 Equals(*((const nsID*)((PLDHashEntryStub*)entry)->key));
michael@0 36 }
michael@0 37
michael@0 38 static PLDHashNumber
michael@0 39 HashNativeKey(PLDHashTable *table, const void *key)
michael@0 40 {
michael@0 41 XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
michael@0 42
michael@0 43 PLDHashNumber h = 0;
michael@0 44
michael@0 45 XPCNativeSet* Set;
michael@0 46 XPCNativeInterface* Addition;
michael@0 47 uint16_t Position;
michael@0 48
michael@0 49 if (Key->IsAKey()) {
michael@0 50 Set = Key->GetBaseSet();
michael@0 51 Addition = Key->GetAddition();
michael@0 52 Position = Key->GetPosition();
michael@0 53 } else {
michael@0 54 Set = (XPCNativeSet*) Key;
michael@0 55 Addition = nullptr;
michael@0 56 Position = 0;
michael@0 57 }
michael@0 58
michael@0 59 if (!Set) {
michael@0 60 MOZ_ASSERT(Addition, "bad key");
michael@0 61 // This would be an XOR like below.
michael@0 62 // But "0 ^ x == x". So it does not matter.
michael@0 63 h = (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2;
michael@0 64 } else {
michael@0 65 XPCNativeInterface** Current = Set->GetInterfaceArray();
michael@0 66 uint16_t count = Set->GetInterfaceCount();
michael@0 67 if (Addition) {
michael@0 68 count++;
michael@0 69 for (uint16_t i = 0; i < count; i++) {
michael@0 70 if (i == Position)
michael@0 71 h ^= (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2;
michael@0 72 else
michael@0 73 h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
michael@0 74 }
michael@0 75 } else {
michael@0 76 for (uint16_t i = 0; i < count; i++)
michael@0 77 h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
michael@0 78 }
michael@0 79 }
michael@0 80
michael@0 81 return h;
michael@0 82 }
michael@0 83
michael@0 84 /***************************************************************************/
michael@0 85 // implement JSObject2WrappedJSMap...
michael@0 86
michael@0 87 void
michael@0 88 JSObject2WrappedJSMap::FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying)
michael@0 89 {
michael@0 90 for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
michael@0 91 nsXPCWrappedJS* wrapper = r.front().value();
michael@0 92 MOZ_ASSERT(wrapper, "found a null JS wrapper!");
michael@0 93
michael@0 94 // walk the wrapper chain and find any whose JSObject is to be finalized
michael@0 95 while (wrapper) {
michael@0 96 if (wrapper->IsSubjectToFinalization() && wrapper->IsObjectAboutToBeFinalized())
michael@0 97 dying->AppendElement(wrapper);
michael@0 98 wrapper = wrapper->GetNextWrapper();
michael@0 99 }
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 void
michael@0 104 JSObject2WrappedJSMap::ShutdownMarker()
michael@0 105 {
michael@0 106 for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
michael@0 107 nsXPCWrappedJS* wrapper = r.front().value();
michael@0 108 MOZ_ASSERT(wrapper, "found a null JS wrapper!");
michael@0 109 MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!");
michael@0 110 wrapper->SystemIsBeingShutDown();
michael@0 111 }
michael@0 112 }
michael@0 113
michael@0 114 /***************************************************************************/
michael@0 115 // implement Native2WrappedNativeMap...
michael@0 116
michael@0 117 // static
michael@0 118 Native2WrappedNativeMap*
michael@0 119 Native2WrappedNativeMap::newMap(int size)
michael@0 120 {
michael@0 121 Native2WrappedNativeMap* map = new Native2WrappedNativeMap(size);
michael@0 122 if (map && map->mTable)
michael@0 123 return map;
michael@0 124 // Allocation of the map or the creation of its hash table has
michael@0 125 // failed. This will cause a nullptr deref later when we attempt
michael@0 126 // to use the map, so we abort immediately to provide a more
michael@0 127 // useful crash stack.
michael@0 128 NS_RUNTIMEABORT("Ran out of memory.");
michael@0 129 return nullptr;
michael@0 130 }
michael@0 131
michael@0 132 Native2WrappedNativeMap::Native2WrappedNativeMap(int size)
michael@0 133 {
michael@0 134 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
michael@0 135 sizeof(Entry), size);
michael@0 136 }
michael@0 137
michael@0 138 Native2WrappedNativeMap::~Native2WrappedNativeMap()
michael@0 139 {
michael@0 140 if (mTable)
michael@0 141 PL_DHashTableDestroy(mTable);
michael@0 142 }
michael@0 143
michael@0 144 size_t
michael@0 145 Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
michael@0 146 {
michael@0 147 size_t n = 0;
michael@0 148 n += mallocSizeOf(this);
michael@0 149 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
michael@0 150 return n;
michael@0 151 }
michael@0 152
michael@0 153 /* static */ size_t
michael@0 154 Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
michael@0 155 mozilla::MallocSizeOf mallocSizeOf, void *)
michael@0 156 {
michael@0 157 return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value);
michael@0 158 }
michael@0 159
michael@0 160 /***************************************************************************/
michael@0 161 // implement IID2WrappedJSClassMap...
michael@0 162
michael@0 163 const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
michael@0 164 {
michael@0 165 PL_DHashAllocTable,
michael@0 166 PL_DHashFreeTable,
michael@0 167 HashIIDPtrKey,
michael@0 168 MatchIIDPtrKey,
michael@0 169 PL_DHashMoveEntryStub,
michael@0 170 PL_DHashClearEntryStub,
michael@0 171 PL_DHashFinalizeStub
michael@0 172 };
michael@0 173
michael@0 174 // static
michael@0 175 IID2WrappedJSClassMap*
michael@0 176 IID2WrappedJSClassMap::newMap(int size)
michael@0 177 {
michael@0 178 IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(size);
michael@0 179 if (map && map->mTable)
michael@0 180 return map;
michael@0 181 delete map;
michael@0 182 return nullptr;
michael@0 183 }
michael@0 184
michael@0 185 IID2WrappedJSClassMap::IID2WrappedJSClassMap(int size)
michael@0 186 {
michael@0 187 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
michael@0 188 }
michael@0 189
michael@0 190 IID2WrappedJSClassMap::~IID2WrappedJSClassMap()
michael@0 191 {
michael@0 192 if (mTable)
michael@0 193 PL_DHashTableDestroy(mTable);
michael@0 194 }
michael@0 195
michael@0 196
michael@0 197 /***************************************************************************/
michael@0 198 // implement IID2NativeInterfaceMap...
michael@0 199
michael@0 200 const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps =
michael@0 201 {
michael@0 202 PL_DHashAllocTable,
michael@0 203 PL_DHashFreeTable,
michael@0 204 HashIIDPtrKey,
michael@0 205 MatchIIDPtrKey,
michael@0 206 PL_DHashMoveEntryStub,
michael@0 207 PL_DHashClearEntryStub,
michael@0 208 PL_DHashFinalizeStub
michael@0 209 };
michael@0 210
michael@0 211 // static
michael@0 212 IID2NativeInterfaceMap*
michael@0 213 IID2NativeInterfaceMap::newMap(int size)
michael@0 214 {
michael@0 215 IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(size);
michael@0 216 if (map && map->mTable)
michael@0 217 return map;
michael@0 218 delete map;
michael@0 219 return nullptr;
michael@0 220 }
michael@0 221
michael@0 222 IID2NativeInterfaceMap::IID2NativeInterfaceMap(int size)
michael@0 223 {
michael@0 224 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
michael@0 225 }
michael@0 226
michael@0 227 IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
michael@0 228 {
michael@0 229 if (mTable)
michael@0 230 PL_DHashTableDestroy(mTable);
michael@0 231 }
michael@0 232
michael@0 233 size_t
michael@0 234 IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
michael@0 235 {
michael@0 236 size_t n = 0;
michael@0 237 n += mallocSizeOf(this);
michael@0 238 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
michael@0 239 return n;
michael@0 240 }
michael@0 241
michael@0 242 /* static */ size_t
michael@0 243 IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
michael@0 244 mozilla::MallocSizeOf mallocSizeOf, void *)
michael@0 245 {
michael@0 246 XPCNativeInterface *iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value;
michael@0 247 return iface->SizeOfIncludingThis(mallocSizeOf);
michael@0 248 }
michael@0 249
michael@0 250 /***************************************************************************/
michael@0 251 // implement ClassInfo2NativeSetMap...
michael@0 252
michael@0 253 // static
michael@0 254 ClassInfo2NativeSetMap*
michael@0 255 ClassInfo2NativeSetMap::newMap(int size)
michael@0 256 {
michael@0 257 ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(size);
michael@0 258 if (map && map->mTable)
michael@0 259 return map;
michael@0 260 delete map;
michael@0 261 return nullptr;
michael@0 262 }
michael@0 263
michael@0 264 ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int size)
michael@0 265 {
michael@0 266 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
michael@0 267 sizeof(Entry), size);
michael@0 268 }
michael@0 269
michael@0 270 ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
michael@0 271 {
michael@0 272 if (mTable)
michael@0 273 PL_DHashTableDestroy(mTable);
michael@0 274 }
michael@0 275
michael@0 276 size_t
michael@0 277 ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
michael@0 278 {
michael@0 279 size_t n = 0;
michael@0 280 n += mallocSizeOf(this);
michael@0 281 // The second arg is nullptr because this is a "shallow" measurement of the map.
michael@0 282 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf) : 0;
michael@0 283 return n;
michael@0 284 }
michael@0 285
michael@0 286 /***************************************************************************/
michael@0 287 // implement ClassInfo2WrappedNativeProtoMap...
michael@0 288
michael@0 289 // static
michael@0 290 ClassInfo2WrappedNativeProtoMap*
michael@0 291 ClassInfo2WrappedNativeProtoMap::newMap(int size)
michael@0 292 {
michael@0 293 ClassInfo2WrappedNativeProtoMap* map = new ClassInfo2WrappedNativeProtoMap(size);
michael@0 294 if (map && map->mTable)
michael@0 295 return map;
michael@0 296 // Allocation of the map or the creation of its hash table has
michael@0 297 // failed. This will cause a nullptr deref later when we attempt
michael@0 298 // to use the map, so we abort immediately to provide a more
michael@0 299 // useful crash stack.
michael@0 300 NS_RUNTIMEABORT("Ran out of memory.");
michael@0 301 return nullptr;
michael@0 302 }
michael@0 303
michael@0 304 ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int size)
michael@0 305 {
michael@0 306 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
michael@0 307 sizeof(Entry), size);
michael@0 308 }
michael@0 309
michael@0 310 ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
michael@0 311 {
michael@0 312 if (mTable)
michael@0 313 PL_DHashTableDestroy(mTable);
michael@0 314 }
michael@0 315
michael@0 316 size_t
michael@0 317 ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
michael@0 318 {
michael@0 319 size_t n = 0;
michael@0 320 n += mallocSizeOf(this);
michael@0 321 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
michael@0 322 return n;
michael@0 323 }
michael@0 324
michael@0 325 /* static */ size_t
michael@0 326 ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
michael@0 327 mozilla::MallocSizeOf mallocSizeOf, void *)
michael@0 328 {
michael@0 329 return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value);
michael@0 330 }
michael@0 331
michael@0 332 /***************************************************************************/
michael@0 333 // implement NativeSetMap...
michael@0 334
michael@0 335 bool
michael@0 336 NativeSetMap::Entry::Match(PLDHashTable *table,
michael@0 337 const PLDHashEntryHdr *entry,
michael@0 338 const void *key)
michael@0 339 {
michael@0 340 XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
michael@0 341
michael@0 342 // See the comment in the XPCNativeSetKey declaration in xpcprivate.h.
michael@0 343 if (!Key->IsAKey()) {
michael@0 344 XPCNativeSet* Set1 = (XPCNativeSet*) key;
michael@0 345 XPCNativeSet* Set2 = ((Entry*)entry)->key_value;
michael@0 346
michael@0 347 if (Set1 == Set2)
michael@0 348 return true;
michael@0 349
michael@0 350 uint16_t count = Set1->GetInterfaceCount();
michael@0 351 if (count != Set2->GetInterfaceCount())
michael@0 352 return false;
michael@0 353
michael@0 354 XPCNativeInterface** Current1 = Set1->GetInterfaceArray();
michael@0 355 XPCNativeInterface** Current2 = Set2->GetInterfaceArray();
michael@0 356 for (uint16_t i = 0; i < count; i++) {
michael@0 357 if (*(Current1++) != *(Current2++))
michael@0 358 return false;
michael@0 359 }
michael@0 360
michael@0 361 return true;
michael@0 362 }
michael@0 363
michael@0 364 XPCNativeSet* SetInTable = ((Entry*)entry)->key_value;
michael@0 365 XPCNativeSet* Set = Key->GetBaseSet();
michael@0 366 XPCNativeInterface* Addition = Key->GetAddition();
michael@0 367
michael@0 368 if (!Set) {
michael@0 369 // This is a special case to deal with the invariant that says:
michael@0 370 // "All sets have exactly one nsISupports interface and it comes first."
michael@0 371 // See XPCNativeSet::NewInstance for details.
michael@0 372 //
michael@0 373 // Though we might have a key that represents only one interface, we
michael@0 374 // know that if that one interface were contructed into a set then
michael@0 375 // it would end up really being a set with two interfaces (except for
michael@0 376 // the case where the one interface happened to be nsISupports).
michael@0 377
michael@0 378 return ((SetInTable->GetInterfaceCount() == 1 &&
michael@0 379 SetInTable->GetInterfaceAt(0) == Addition) ||
michael@0 380 (SetInTable->GetInterfaceCount() == 2 &&
michael@0 381 SetInTable->GetInterfaceAt(1) == Addition));
michael@0 382 }
michael@0 383
michael@0 384 if (!Addition && Set == SetInTable)
michael@0 385 return true;
michael@0 386
michael@0 387 uint16_t count = Set->GetInterfaceCount() + (Addition ? 1 : 0);
michael@0 388 if (count != SetInTable->GetInterfaceCount())
michael@0 389 return false;
michael@0 390
michael@0 391 uint16_t Position = Key->GetPosition();
michael@0 392 XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray();
michael@0 393 XPCNativeInterface** Current = Set->GetInterfaceArray();
michael@0 394 for (uint16_t i = 0; i < count; i++) {
michael@0 395 if (Addition && i == Position) {
michael@0 396 if (Addition != *(CurrentInTable++))
michael@0 397 return false;
michael@0 398 } else {
michael@0 399 if (*(Current++) != *(CurrentInTable++))
michael@0 400 return false;
michael@0 401 }
michael@0 402 }
michael@0 403
michael@0 404 return true;
michael@0 405 }
michael@0 406
michael@0 407 const struct PLDHashTableOps NativeSetMap::Entry::sOps =
michael@0 408 {
michael@0 409 PL_DHashAllocTable,
michael@0 410 PL_DHashFreeTable,
michael@0 411 HashNativeKey,
michael@0 412 Match,
michael@0 413 PL_DHashMoveEntryStub,
michael@0 414 PL_DHashClearEntryStub,
michael@0 415 PL_DHashFinalizeStub
michael@0 416 };
michael@0 417
michael@0 418 // static
michael@0 419 NativeSetMap*
michael@0 420 NativeSetMap::newMap(int size)
michael@0 421 {
michael@0 422 NativeSetMap* map = new NativeSetMap(size);
michael@0 423 if (map && map->mTable)
michael@0 424 return map;
michael@0 425 delete map;
michael@0 426 return nullptr;
michael@0 427 }
michael@0 428
michael@0 429 NativeSetMap::NativeSetMap(int size)
michael@0 430 {
michael@0 431 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
michael@0 432 }
michael@0 433
michael@0 434 NativeSetMap::~NativeSetMap()
michael@0 435 {
michael@0 436 if (mTable)
michael@0 437 PL_DHashTableDestroy(mTable);
michael@0 438 }
michael@0 439
michael@0 440 size_t
michael@0 441 NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
michael@0 442 {
michael@0 443 size_t n = 0;
michael@0 444 n += mallocSizeOf(this);
michael@0 445 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
michael@0 446 return n;
michael@0 447 }
michael@0 448
michael@0 449 /* static */ size_t
michael@0 450 NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *)
michael@0 451 {
michael@0 452 XPCNativeSet *set = ((NativeSetMap::Entry*)hdr)->key_value;
michael@0 453 return set->SizeOfIncludingThis(mallocSizeOf);
michael@0 454 }
michael@0 455
michael@0 456 /***************************************************************************/
michael@0 457 // implement IID2ThisTranslatorMap...
michael@0 458
michael@0 459 bool
michael@0 460 IID2ThisTranslatorMap::Entry::Match(PLDHashTable *table,
michael@0 461 const PLDHashEntryHdr *entry,
michael@0 462 const void *key)
michael@0 463 {
michael@0 464 return ((const nsID*)key)->Equals(((Entry*)entry)->key);
michael@0 465 }
michael@0 466
michael@0 467 void
michael@0 468 IID2ThisTranslatorMap::Entry::Clear(PLDHashTable *table, PLDHashEntryHdr *entry)
michael@0 469 {
michael@0 470 static_cast<Entry*>(entry)->value = nullptr;
michael@0 471 memset(entry, 0, table->entrySize);
michael@0 472 }
michael@0 473
michael@0 474 const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
michael@0 475 {
michael@0 476 PL_DHashAllocTable,
michael@0 477 PL_DHashFreeTable,
michael@0 478 HashIIDPtrKey,
michael@0 479 Match,
michael@0 480 PL_DHashMoveEntryStub,
michael@0 481 Clear,
michael@0 482 PL_DHashFinalizeStub
michael@0 483 };
michael@0 484
michael@0 485 // static
michael@0 486 IID2ThisTranslatorMap*
michael@0 487 IID2ThisTranslatorMap::newMap(int size)
michael@0 488 {
michael@0 489 IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(size);
michael@0 490 if (map && map->mTable)
michael@0 491 return map;
michael@0 492 delete map;
michael@0 493 return nullptr;
michael@0 494 }
michael@0 495
michael@0 496 IID2ThisTranslatorMap::IID2ThisTranslatorMap(int size)
michael@0 497 {
michael@0 498 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
michael@0 499 }
michael@0 500
michael@0 501 IID2ThisTranslatorMap::~IID2ThisTranslatorMap()
michael@0 502 {
michael@0 503 if (mTable)
michael@0 504 PL_DHashTableDestroy(mTable);
michael@0 505 }
michael@0 506
michael@0 507 /***************************************************************************/
michael@0 508
michael@0 509 PLDHashNumber
michael@0 510 XPCNativeScriptableSharedMap::Entry::Hash(PLDHashTable *table, const void *key)
michael@0 511 {
michael@0 512 PLDHashNumber h;
michael@0 513 const unsigned char *s;
michael@0 514
michael@0 515 XPCNativeScriptableShared* obj =
michael@0 516 (XPCNativeScriptableShared*) key;
michael@0 517
michael@0 518 // hash together the flags and the classname string, ignore the interfaces
michael@0 519 // bitmap since it's very rare that it's different when flags and classname
michael@0 520 // are the same.
michael@0 521
michael@0 522 h = (PLDHashNumber) obj->GetFlags();
michael@0 523 for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++)
michael@0 524 h = RotateLeft(h, 4) ^ *s;
michael@0 525 return h;
michael@0 526 }
michael@0 527
michael@0 528 bool
michael@0 529 XPCNativeScriptableSharedMap::Entry::Match(PLDHashTable *table,
michael@0 530 const PLDHashEntryHdr *entry,
michael@0 531 const void *key)
michael@0 532 {
michael@0 533 XPCNativeScriptableShared* obj1 =
michael@0 534 ((XPCNativeScriptableSharedMap::Entry*) entry)->key;
michael@0 535
michael@0 536 XPCNativeScriptableShared* obj2 =
michael@0 537 (XPCNativeScriptableShared*) key;
michael@0 538
michael@0 539 // match the flags, the classname string and the interfaces bitmap
michael@0 540
michael@0 541 if (obj1->GetFlags() != obj2->GetFlags() ||
michael@0 542 obj1->GetInterfacesBitmap() != obj2->GetInterfacesBitmap())
michael@0 543 return false;
michael@0 544
michael@0 545 const char* name1 = obj1->GetJSClass()->name;
michael@0 546 const char* name2 = obj2->GetJSClass()->name;
michael@0 547
michael@0 548 if (!name1 || !name2)
michael@0 549 return name1 == name2;
michael@0 550
michael@0 551 return 0 == strcmp(name1, name2);
michael@0 552 }
michael@0 553
michael@0 554 const struct PLDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps =
michael@0 555 {
michael@0 556 PL_DHashAllocTable,
michael@0 557 PL_DHashFreeTable,
michael@0 558 Hash,
michael@0 559 Match,
michael@0 560 PL_DHashMoveEntryStub,
michael@0 561 PL_DHashClearEntryStub,
michael@0 562 PL_DHashFinalizeStub
michael@0 563 };
michael@0 564
michael@0 565 // static
michael@0 566 XPCNativeScriptableSharedMap*
michael@0 567 XPCNativeScriptableSharedMap::newMap(int size)
michael@0 568 {
michael@0 569 XPCNativeScriptableSharedMap* map =
michael@0 570 new XPCNativeScriptableSharedMap(size);
michael@0 571 if (map && map->mTable)
michael@0 572 return map;
michael@0 573 delete map;
michael@0 574 return nullptr;
michael@0 575 }
michael@0 576
michael@0 577 XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int size)
michael@0 578 {
michael@0 579 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
michael@0 580 }
michael@0 581
michael@0 582 XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap()
michael@0 583 {
michael@0 584 if (mTable)
michael@0 585 PL_DHashTableDestroy(mTable);
michael@0 586 }
michael@0 587
michael@0 588 bool
michael@0 589 XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags,
michael@0 590 char* name,
michael@0 591 uint32_t interfacesBitmap,
michael@0 592 XPCNativeScriptableInfo* si)
michael@0 593 {
michael@0 594 NS_PRECONDITION(name,"bad param");
michael@0 595 NS_PRECONDITION(si,"bad param");
michael@0 596
michael@0 597 XPCNativeScriptableShared key(flags, name, interfacesBitmap);
michael@0 598 Entry* entry = (Entry*)
michael@0 599 PL_DHashTableOperate(mTable, &key, PL_DHASH_ADD);
michael@0 600 if (!entry)
michael@0 601 return false;
michael@0 602
michael@0 603 XPCNativeScriptableShared* shared = entry->key;
michael@0 604
michael@0 605 if (!shared) {
michael@0 606 entry->key = shared =
michael@0 607 new XPCNativeScriptableShared(flags, key.TransferNameOwnership(),
michael@0 608 interfacesBitmap);
michael@0 609 if (!shared)
michael@0 610 return false;
michael@0 611 shared->PopulateJSClass();
michael@0 612 }
michael@0 613 si->SetScriptableShared(shared);
michael@0 614 return true;
michael@0 615 }
michael@0 616
michael@0 617 /***************************************************************************/
michael@0 618 // implement XPCWrappedNativeProtoMap...
michael@0 619
michael@0 620 // static
michael@0 621 XPCWrappedNativeProtoMap*
michael@0 622 XPCWrappedNativeProtoMap::newMap(int size)
michael@0 623 {
michael@0 624 XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(size);
michael@0 625 if (map && map->mTable)
michael@0 626 return map;
michael@0 627 delete map;
michael@0 628 return nullptr;
michael@0 629 }
michael@0 630
michael@0 631 XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int size)
michael@0 632 {
michael@0 633 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
michael@0 634 sizeof(PLDHashEntryStub), size);
michael@0 635 }
michael@0 636
michael@0 637 XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()
michael@0 638 {
michael@0 639 if (mTable)
michael@0 640 PL_DHashTableDestroy(mTable);
michael@0 641 }
michael@0 642
michael@0 643 /***************************************************************************/

mercurial