js/xpconnect/src/XPCMaps.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial