js/xpconnect/src/XPCMaps.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/xpconnect/src/XPCMaps.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,643 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=99: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* Private maps (hashtables). */
    1.11 +
    1.12 +#include "mozilla/MathAlgorithms.h"
    1.13 +#include "mozilla/MemoryReporting.h"
    1.14 +#include "xpcprivate.h"
    1.15 +
    1.16 +#include "js/HashTable.h"
    1.17 +
    1.18 +using namespace mozilla;
    1.19 +
    1.20 +/***************************************************************************/
    1.21 +// static shared...
    1.22 +
    1.23 +// Note this is returning the bit pattern of the first part of the nsID, not
    1.24 +// the pointer to the nsID.
    1.25 +
    1.26 +static PLDHashNumber
    1.27 +HashIIDPtrKey(PLDHashTable *table, const void *key)
    1.28 +{
    1.29 +    return *((js::HashNumber*)key);
    1.30 +}
    1.31 +
    1.32 +static bool
    1.33 +MatchIIDPtrKey(PLDHashTable *table,
    1.34 +               const PLDHashEntryHdr *entry,
    1.35 +               const void *key)
    1.36 +{
    1.37 +    return ((const nsID*)key)->
    1.38 +                Equals(*((const nsID*)((PLDHashEntryStub*)entry)->key));
    1.39 +}
    1.40 +
    1.41 +static PLDHashNumber
    1.42 +HashNativeKey(PLDHashTable *table, const void *key)
    1.43 +{
    1.44 +    XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
    1.45 +
    1.46 +    PLDHashNumber h = 0;
    1.47 +
    1.48 +    XPCNativeSet*       Set;
    1.49 +    XPCNativeInterface* Addition;
    1.50 +    uint16_t            Position;
    1.51 +
    1.52 +    if (Key->IsAKey()) {
    1.53 +        Set      = Key->GetBaseSet();
    1.54 +        Addition = Key->GetAddition();
    1.55 +        Position = Key->GetPosition();
    1.56 +    } else {
    1.57 +        Set      = (XPCNativeSet*) Key;
    1.58 +        Addition = nullptr;
    1.59 +        Position = 0;
    1.60 +    }
    1.61 +
    1.62 +    if (!Set) {
    1.63 +        MOZ_ASSERT(Addition, "bad key");
    1.64 +        // This would be an XOR like below.
    1.65 +        // But "0 ^ x == x". So it does not matter.
    1.66 +        h = (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2;
    1.67 +    } else {
    1.68 +        XPCNativeInterface** Current = Set->GetInterfaceArray();
    1.69 +        uint16_t count = Set->GetInterfaceCount();
    1.70 +        if (Addition) {
    1.71 +            count++;
    1.72 +            for (uint16_t i = 0; i < count; i++) {
    1.73 +                if (i == Position)
    1.74 +                    h ^= (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2;
    1.75 +                else
    1.76 +                    h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
    1.77 +            }
    1.78 +        } else {
    1.79 +            for (uint16_t i = 0; i < count; i++)
    1.80 +                h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
    1.81 +        }
    1.82 +    }
    1.83 +
    1.84 +    return h;
    1.85 +}
    1.86 +
    1.87 +/***************************************************************************/
    1.88 +// implement JSObject2WrappedJSMap...
    1.89 +
    1.90 +void
    1.91 +JSObject2WrappedJSMap::FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying)
    1.92 +{
    1.93 +    for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
    1.94 +        nsXPCWrappedJS* wrapper = r.front().value();
    1.95 +        MOZ_ASSERT(wrapper, "found a null JS wrapper!");
    1.96 +
    1.97 +        // walk the wrapper chain and find any whose JSObject is to be finalized
    1.98 +        while (wrapper) {
    1.99 +            if (wrapper->IsSubjectToFinalization() && wrapper->IsObjectAboutToBeFinalized())
   1.100 +                dying->AppendElement(wrapper);
   1.101 +            wrapper = wrapper->GetNextWrapper();
   1.102 +        }
   1.103 +    }
   1.104 +}
   1.105 +
   1.106 +void
   1.107 +JSObject2WrappedJSMap::ShutdownMarker()
   1.108 +{
   1.109 +    for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
   1.110 +        nsXPCWrappedJS* wrapper = r.front().value();
   1.111 +        MOZ_ASSERT(wrapper, "found a null JS wrapper!");
   1.112 +        MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!");
   1.113 +        wrapper->SystemIsBeingShutDown();
   1.114 +    }
   1.115 +}
   1.116 +
   1.117 +/***************************************************************************/
   1.118 +// implement Native2WrappedNativeMap...
   1.119 +
   1.120 +// static
   1.121 +Native2WrappedNativeMap*
   1.122 +Native2WrappedNativeMap::newMap(int size)
   1.123 +{
   1.124 +    Native2WrappedNativeMap* map = new Native2WrappedNativeMap(size);
   1.125 +    if (map && map->mTable)
   1.126 +        return map;
   1.127 +    // Allocation of the map or the creation of its hash table has
   1.128 +    // failed. This will cause a nullptr deref later when we attempt
   1.129 +    // to use the map, so we abort immediately to provide a more
   1.130 +    // useful crash stack.
   1.131 +    NS_RUNTIMEABORT("Ran out of memory.");
   1.132 +    return nullptr;
   1.133 +}
   1.134 +
   1.135 +Native2WrappedNativeMap::Native2WrappedNativeMap(int size)
   1.136 +{
   1.137 +    mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
   1.138 +                              sizeof(Entry), size);
   1.139 +}
   1.140 +
   1.141 +Native2WrappedNativeMap::~Native2WrappedNativeMap()
   1.142 +{
   1.143 +    if (mTable)
   1.144 +        PL_DHashTableDestroy(mTable);
   1.145 +}
   1.146 +
   1.147 +size_t
   1.148 +Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
   1.149 +{
   1.150 +    size_t n = 0;
   1.151 +    n += mallocSizeOf(this);
   1.152 +    n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
   1.153 +    return n;
   1.154 +}
   1.155 +
   1.156 +/* static */ size_t
   1.157 +Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
   1.158 +                                                  mozilla::MallocSizeOf mallocSizeOf, void *)
   1.159 +{
   1.160 +    return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value);
   1.161 +}
   1.162 +
   1.163 +/***************************************************************************/
   1.164 +// implement IID2WrappedJSClassMap...
   1.165 +
   1.166 +const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
   1.167 +{
   1.168 +    PL_DHashAllocTable,
   1.169 +    PL_DHashFreeTable,
   1.170 +    HashIIDPtrKey,
   1.171 +    MatchIIDPtrKey,
   1.172 +    PL_DHashMoveEntryStub,
   1.173 +    PL_DHashClearEntryStub,
   1.174 +    PL_DHashFinalizeStub
   1.175 +};
   1.176 +
   1.177 +// static
   1.178 +IID2WrappedJSClassMap*
   1.179 +IID2WrappedJSClassMap::newMap(int size)
   1.180 +{
   1.181 +    IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(size);
   1.182 +    if (map && map->mTable)
   1.183 +        return map;
   1.184 +    delete map;
   1.185 +    return nullptr;
   1.186 +}
   1.187 +
   1.188 +IID2WrappedJSClassMap::IID2WrappedJSClassMap(int size)
   1.189 +{
   1.190 +    mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
   1.191 +}
   1.192 +
   1.193 +IID2WrappedJSClassMap::~IID2WrappedJSClassMap()
   1.194 +{
   1.195 +    if (mTable)
   1.196 +        PL_DHashTableDestroy(mTable);
   1.197 +}
   1.198 +
   1.199 +
   1.200 +/***************************************************************************/
   1.201 +// implement IID2NativeInterfaceMap...
   1.202 +
   1.203 +const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps =
   1.204 +{
   1.205 +    PL_DHashAllocTable,
   1.206 +    PL_DHashFreeTable,
   1.207 +    HashIIDPtrKey,
   1.208 +    MatchIIDPtrKey,
   1.209 +    PL_DHashMoveEntryStub,
   1.210 +    PL_DHashClearEntryStub,
   1.211 +    PL_DHashFinalizeStub
   1.212 +};
   1.213 +
   1.214 +// static
   1.215 +IID2NativeInterfaceMap*
   1.216 +IID2NativeInterfaceMap::newMap(int size)
   1.217 +{
   1.218 +    IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(size);
   1.219 +    if (map && map->mTable)
   1.220 +        return map;
   1.221 +    delete map;
   1.222 +    return nullptr;
   1.223 +}
   1.224 +
   1.225 +IID2NativeInterfaceMap::IID2NativeInterfaceMap(int size)
   1.226 +{
   1.227 +    mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
   1.228 +}
   1.229 +
   1.230 +IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
   1.231 +{
   1.232 +    if (mTable)
   1.233 +        PL_DHashTableDestroy(mTable);
   1.234 +}
   1.235 +
   1.236 +size_t
   1.237 +IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
   1.238 +{
   1.239 +    size_t n = 0;
   1.240 +    n += mallocSizeOf(this);
   1.241 +    n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
   1.242 +    return n;
   1.243 +}
   1.244 +
   1.245 +/* static */ size_t
   1.246 +IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
   1.247 +                                                 mozilla::MallocSizeOf mallocSizeOf, void *)
   1.248 +{
   1.249 +    XPCNativeInterface *iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value;
   1.250 +    return iface->SizeOfIncludingThis(mallocSizeOf);
   1.251 +}
   1.252 +
   1.253 +/***************************************************************************/
   1.254 +// implement ClassInfo2NativeSetMap...
   1.255 +
   1.256 +// static
   1.257 +ClassInfo2NativeSetMap*
   1.258 +ClassInfo2NativeSetMap::newMap(int size)
   1.259 +{
   1.260 +    ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(size);
   1.261 +    if (map && map->mTable)
   1.262 +        return map;
   1.263 +    delete map;
   1.264 +    return nullptr;
   1.265 +}
   1.266 +
   1.267 +ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int size)
   1.268 +{
   1.269 +    mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
   1.270 +                              sizeof(Entry), size);
   1.271 +}
   1.272 +
   1.273 +ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
   1.274 +{
   1.275 +    if (mTable)
   1.276 +        PL_DHashTableDestroy(mTable);
   1.277 +}
   1.278 +
   1.279 +size_t
   1.280 +ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
   1.281 +{
   1.282 +    size_t n = 0;
   1.283 +    n += mallocSizeOf(this);
   1.284 +    // The second arg is nullptr because this is a "shallow" measurement of the map.
   1.285 +    n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf) : 0;
   1.286 +    return n;
   1.287 +}
   1.288 +
   1.289 +/***************************************************************************/
   1.290 +// implement ClassInfo2WrappedNativeProtoMap...
   1.291 +
   1.292 +// static
   1.293 +ClassInfo2WrappedNativeProtoMap*
   1.294 +ClassInfo2WrappedNativeProtoMap::newMap(int size)
   1.295 +{
   1.296 +    ClassInfo2WrappedNativeProtoMap* map = new ClassInfo2WrappedNativeProtoMap(size);
   1.297 +    if (map && map->mTable)
   1.298 +        return map;
   1.299 +    // Allocation of the map or the creation of its hash table has
   1.300 +    // failed. This will cause a nullptr deref later when we attempt
   1.301 +    // to use the map, so we abort immediately to provide a more
   1.302 +    // useful crash stack.
   1.303 +    NS_RUNTIMEABORT("Ran out of memory.");
   1.304 +    return nullptr;
   1.305 +}
   1.306 +
   1.307 +ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int size)
   1.308 +{
   1.309 +    mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
   1.310 +                              sizeof(Entry), size);
   1.311 +}
   1.312 +
   1.313 +ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
   1.314 +{
   1.315 +    if (mTable)
   1.316 +        PL_DHashTableDestroy(mTable);
   1.317 +}
   1.318 +
   1.319 +size_t
   1.320 +ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
   1.321 +{
   1.322 +    size_t n = 0;
   1.323 +    n += mallocSizeOf(this);
   1.324 +    n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
   1.325 +    return n;
   1.326 +}
   1.327 +
   1.328 +/* static */ size_t
   1.329 +ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr,
   1.330 +                                                          mozilla::MallocSizeOf mallocSizeOf, void *)
   1.331 +{
   1.332 +    return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value);
   1.333 +}
   1.334 +
   1.335 +/***************************************************************************/
   1.336 +// implement NativeSetMap...
   1.337 +
   1.338 +bool
   1.339 +NativeSetMap::Entry::Match(PLDHashTable *table,
   1.340 +                           const PLDHashEntryHdr *entry,
   1.341 +                           const void *key)
   1.342 +{
   1.343 +    XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
   1.344 +
   1.345 +    // See the comment in the XPCNativeSetKey declaration in xpcprivate.h.
   1.346 +    if (!Key->IsAKey()) {
   1.347 +        XPCNativeSet* Set1 = (XPCNativeSet*) key;
   1.348 +        XPCNativeSet* Set2 = ((Entry*)entry)->key_value;
   1.349 +
   1.350 +        if (Set1 == Set2)
   1.351 +            return true;
   1.352 +
   1.353 +        uint16_t count = Set1->GetInterfaceCount();
   1.354 +        if (count != Set2->GetInterfaceCount())
   1.355 +            return false;
   1.356 +
   1.357 +        XPCNativeInterface** Current1 = Set1->GetInterfaceArray();
   1.358 +        XPCNativeInterface** Current2 = Set2->GetInterfaceArray();
   1.359 +        for (uint16_t i = 0; i < count; i++) {
   1.360 +            if (*(Current1++) != *(Current2++))
   1.361 +                return false;
   1.362 +        }
   1.363 +
   1.364 +        return true;
   1.365 +    }
   1.366 +
   1.367 +    XPCNativeSet*       SetInTable = ((Entry*)entry)->key_value;
   1.368 +    XPCNativeSet*       Set        = Key->GetBaseSet();
   1.369 +    XPCNativeInterface* Addition   = Key->GetAddition();
   1.370 +
   1.371 +    if (!Set) {
   1.372 +        // This is a special case to deal with the invariant that says:
   1.373 +        // "All sets have exactly one nsISupports interface and it comes first."
   1.374 +        // See XPCNativeSet::NewInstance for details.
   1.375 +        //
   1.376 +        // Though we might have a key that represents only one interface, we
   1.377 +        // know that if that one interface were contructed into a set then
   1.378 +        // it would end up really being a set with two interfaces (except for
   1.379 +        // the case where the one interface happened to be nsISupports).
   1.380 +
   1.381 +        return ((SetInTable->GetInterfaceCount() == 1 &&
   1.382 +                 SetInTable->GetInterfaceAt(0) == Addition) ||
   1.383 +                (SetInTable->GetInterfaceCount() == 2 &&
   1.384 +                 SetInTable->GetInterfaceAt(1) == Addition));
   1.385 +    }
   1.386 +
   1.387 +    if (!Addition && Set == SetInTable)
   1.388 +        return true;
   1.389 +
   1.390 +    uint16_t count = Set->GetInterfaceCount() + (Addition ? 1 : 0);
   1.391 +    if (count != SetInTable->GetInterfaceCount())
   1.392 +        return false;
   1.393 +
   1.394 +    uint16_t Position = Key->GetPosition();
   1.395 +    XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray();
   1.396 +    XPCNativeInterface** Current = Set->GetInterfaceArray();
   1.397 +    for (uint16_t i = 0; i < count; i++) {
   1.398 +        if (Addition && i == Position) {
   1.399 +            if (Addition != *(CurrentInTable++))
   1.400 +                return false;
   1.401 +        } else {
   1.402 +            if (*(Current++) != *(CurrentInTable++))
   1.403 +                return false;
   1.404 +        }
   1.405 +    }
   1.406 +
   1.407 +    return true;
   1.408 +}
   1.409 +
   1.410 +const struct PLDHashTableOps NativeSetMap::Entry::sOps =
   1.411 +{
   1.412 +    PL_DHashAllocTable,
   1.413 +    PL_DHashFreeTable,
   1.414 +    HashNativeKey,
   1.415 +    Match,
   1.416 +    PL_DHashMoveEntryStub,
   1.417 +    PL_DHashClearEntryStub,
   1.418 +    PL_DHashFinalizeStub
   1.419 +};
   1.420 +
   1.421 +// static
   1.422 +NativeSetMap*
   1.423 +NativeSetMap::newMap(int size)
   1.424 +{
   1.425 +    NativeSetMap* map = new NativeSetMap(size);
   1.426 +    if (map && map->mTable)
   1.427 +        return map;
   1.428 +    delete map;
   1.429 +    return nullptr;
   1.430 +}
   1.431 +
   1.432 +NativeSetMap::NativeSetMap(int size)
   1.433 +{
   1.434 +    mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
   1.435 +}
   1.436 +
   1.437 +NativeSetMap::~NativeSetMap()
   1.438 +{
   1.439 +    if (mTable)
   1.440 +        PL_DHashTableDestroy(mTable);
   1.441 +}
   1.442 +
   1.443 +size_t
   1.444 +NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
   1.445 +{
   1.446 +    size_t n = 0;
   1.447 +    n += mallocSizeOf(this);
   1.448 +    n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
   1.449 +    return n;
   1.450 +}
   1.451 +
   1.452 +/* static */ size_t
   1.453 +NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *)
   1.454 +{
   1.455 +    XPCNativeSet *set = ((NativeSetMap::Entry*)hdr)->key_value;
   1.456 +    return set->SizeOfIncludingThis(mallocSizeOf);
   1.457 +}
   1.458 +
   1.459 +/***************************************************************************/
   1.460 +// implement IID2ThisTranslatorMap...
   1.461 +
   1.462 +bool
   1.463 +IID2ThisTranslatorMap::Entry::Match(PLDHashTable *table,
   1.464 +                                    const PLDHashEntryHdr *entry,
   1.465 +                                    const void *key)
   1.466 +{
   1.467 +    return ((const nsID*)key)->Equals(((Entry*)entry)->key);
   1.468 +}
   1.469 +
   1.470 +void
   1.471 +IID2ThisTranslatorMap::Entry::Clear(PLDHashTable *table, PLDHashEntryHdr *entry)
   1.472 +{
   1.473 +    static_cast<Entry*>(entry)->value = nullptr;
   1.474 +    memset(entry, 0, table->entrySize);
   1.475 +}
   1.476 +
   1.477 +const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
   1.478 +{
   1.479 +    PL_DHashAllocTable,
   1.480 +    PL_DHashFreeTable,
   1.481 +    HashIIDPtrKey,
   1.482 +    Match,
   1.483 +    PL_DHashMoveEntryStub,
   1.484 +    Clear,
   1.485 +    PL_DHashFinalizeStub
   1.486 +};
   1.487 +
   1.488 +// static
   1.489 +IID2ThisTranslatorMap*
   1.490 +IID2ThisTranslatorMap::newMap(int size)
   1.491 +{
   1.492 +    IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(size);
   1.493 +    if (map && map->mTable)
   1.494 +        return map;
   1.495 +    delete map;
   1.496 +    return nullptr;
   1.497 +}
   1.498 +
   1.499 +IID2ThisTranslatorMap::IID2ThisTranslatorMap(int size)
   1.500 +{
   1.501 +    mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
   1.502 +}
   1.503 +
   1.504 +IID2ThisTranslatorMap::~IID2ThisTranslatorMap()
   1.505 +{
   1.506 +    if (mTable)
   1.507 +        PL_DHashTableDestroy(mTable);
   1.508 +}
   1.509 +
   1.510 +/***************************************************************************/
   1.511 +
   1.512 +PLDHashNumber
   1.513 +XPCNativeScriptableSharedMap::Entry::Hash(PLDHashTable *table, const void *key)
   1.514 +{
   1.515 +    PLDHashNumber h;
   1.516 +    const unsigned char *s;
   1.517 +
   1.518 +    XPCNativeScriptableShared* obj =
   1.519 +        (XPCNativeScriptableShared*) key;
   1.520 +
   1.521 +    // hash together the flags and the classname string, ignore the interfaces
   1.522 +    // bitmap since it's very rare that it's different when flags and classname
   1.523 +    // are the same.
   1.524 +
   1.525 +    h = (PLDHashNumber) obj->GetFlags();
   1.526 +    for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++)
   1.527 +        h = RotateLeft(h, 4) ^ *s;
   1.528 +    return h;
   1.529 +}
   1.530 +
   1.531 +bool
   1.532 +XPCNativeScriptableSharedMap::Entry::Match(PLDHashTable *table,
   1.533 +                                           const PLDHashEntryHdr *entry,
   1.534 +                                           const void *key)
   1.535 +{
   1.536 +    XPCNativeScriptableShared* obj1 =
   1.537 +        ((XPCNativeScriptableSharedMap::Entry*) entry)->key;
   1.538 +
   1.539 +    XPCNativeScriptableShared* obj2 =
   1.540 +        (XPCNativeScriptableShared*) key;
   1.541 +
   1.542 +    // match the flags, the classname string and the interfaces bitmap
   1.543 +
   1.544 +    if (obj1->GetFlags() != obj2->GetFlags() ||
   1.545 +        obj1->GetInterfacesBitmap() != obj2->GetInterfacesBitmap())
   1.546 +        return false;
   1.547 +
   1.548 +    const char* name1 = obj1->GetJSClass()->name;
   1.549 +    const char* name2 = obj2->GetJSClass()->name;
   1.550 +
   1.551 +    if (!name1 || !name2)
   1.552 +        return name1 == name2;
   1.553 +
   1.554 +    return 0 == strcmp(name1, name2);
   1.555 +}
   1.556 +
   1.557 +const struct PLDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps =
   1.558 +{
   1.559 +    PL_DHashAllocTable,
   1.560 +    PL_DHashFreeTable,
   1.561 +    Hash,
   1.562 +    Match,
   1.563 +    PL_DHashMoveEntryStub,
   1.564 +    PL_DHashClearEntryStub,
   1.565 +    PL_DHashFinalizeStub
   1.566 +};
   1.567 +
   1.568 +// static
   1.569 +XPCNativeScriptableSharedMap*
   1.570 +XPCNativeScriptableSharedMap::newMap(int size)
   1.571 +{
   1.572 +    XPCNativeScriptableSharedMap* map =
   1.573 +        new XPCNativeScriptableSharedMap(size);
   1.574 +    if (map && map->mTable)
   1.575 +        return map;
   1.576 +    delete map;
   1.577 +    return nullptr;
   1.578 +}
   1.579 +
   1.580 +XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int size)
   1.581 +{
   1.582 +    mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size);
   1.583 +}
   1.584 +
   1.585 +XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap()
   1.586 +{
   1.587 +    if (mTable)
   1.588 +        PL_DHashTableDestroy(mTable);
   1.589 +}
   1.590 +
   1.591 +bool
   1.592 +XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags,
   1.593 +                                           char* name,
   1.594 +                                           uint32_t interfacesBitmap,
   1.595 +                                           XPCNativeScriptableInfo* si)
   1.596 +{
   1.597 +    NS_PRECONDITION(name,"bad param");
   1.598 +    NS_PRECONDITION(si,"bad param");
   1.599 +
   1.600 +    XPCNativeScriptableShared key(flags, name, interfacesBitmap);
   1.601 +    Entry* entry = (Entry*)
   1.602 +        PL_DHashTableOperate(mTable, &key, PL_DHASH_ADD);
   1.603 +    if (!entry)
   1.604 +        return false;
   1.605 +
   1.606 +    XPCNativeScriptableShared* shared = entry->key;
   1.607 +
   1.608 +    if (!shared) {
   1.609 +        entry->key = shared =
   1.610 +            new XPCNativeScriptableShared(flags, key.TransferNameOwnership(),
   1.611 +                                          interfacesBitmap);
   1.612 +        if (!shared)
   1.613 +            return false;
   1.614 +        shared->PopulateJSClass();
   1.615 +    }
   1.616 +    si->SetScriptableShared(shared);
   1.617 +    return true;
   1.618 +}
   1.619 +
   1.620 +/***************************************************************************/
   1.621 +// implement XPCWrappedNativeProtoMap...
   1.622 +
   1.623 +// static
   1.624 +XPCWrappedNativeProtoMap*
   1.625 +XPCWrappedNativeProtoMap::newMap(int size)
   1.626 +{
   1.627 +    XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(size);
   1.628 +    if (map && map->mTable)
   1.629 +        return map;
   1.630 +    delete map;
   1.631 +    return nullptr;
   1.632 +}
   1.633 +
   1.634 +XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int size)
   1.635 +{
   1.636 +    mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr,
   1.637 +                              sizeof(PLDHashEntryStub), size);
   1.638 +}
   1.639 +
   1.640 +XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()
   1.641 +{
   1.642 +    if (mTable)
   1.643 +        PL_DHashTableDestroy(mTable);
   1.644 +}
   1.645 +
   1.646 +/***************************************************************************/

mercurial