michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* vim: set ts=8 sts=4 et sw=4 tw=99: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* Private maps (hashtables). */ michael@0: michael@0: #include "mozilla/MathAlgorithms.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "xpcprivate.h" michael@0: michael@0: #include "js/HashTable.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: /***************************************************************************/ michael@0: // static shared... michael@0: michael@0: // Note this is returning the bit pattern of the first part of the nsID, not michael@0: // the pointer to the nsID. michael@0: michael@0: static PLDHashNumber michael@0: HashIIDPtrKey(PLDHashTable *table, const void *key) michael@0: { michael@0: return *((js::HashNumber*)key); michael@0: } michael@0: michael@0: static bool michael@0: MatchIIDPtrKey(PLDHashTable *table, michael@0: const PLDHashEntryHdr *entry, michael@0: const void *key) michael@0: { michael@0: return ((const nsID*)key)-> michael@0: Equals(*((const nsID*)((PLDHashEntryStub*)entry)->key)); michael@0: } michael@0: michael@0: static PLDHashNumber michael@0: HashNativeKey(PLDHashTable *table, const void *key) michael@0: { michael@0: XPCNativeSetKey* Key = (XPCNativeSetKey*) key; michael@0: michael@0: PLDHashNumber h = 0; michael@0: michael@0: XPCNativeSet* Set; michael@0: XPCNativeInterface* Addition; michael@0: uint16_t Position; michael@0: michael@0: if (Key->IsAKey()) { michael@0: Set = Key->GetBaseSet(); michael@0: Addition = Key->GetAddition(); michael@0: Position = Key->GetPosition(); michael@0: } else { michael@0: Set = (XPCNativeSet*) Key; michael@0: Addition = nullptr; michael@0: Position = 0; michael@0: } michael@0: michael@0: if (!Set) { michael@0: MOZ_ASSERT(Addition, "bad key"); michael@0: // This would be an XOR like below. michael@0: // But "0 ^ x == x". So it does not matter. michael@0: h = (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2; michael@0: } else { michael@0: XPCNativeInterface** Current = Set->GetInterfaceArray(); michael@0: uint16_t count = Set->GetInterfaceCount(); michael@0: if (Addition) { michael@0: count++; michael@0: for (uint16_t i = 0; i < count; i++) { michael@0: if (i == Position) michael@0: h ^= (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2; michael@0: else michael@0: h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2; michael@0: } michael@0: } else { michael@0: for (uint16_t i = 0; i < count; i++) michael@0: h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2; michael@0: } michael@0: } michael@0: michael@0: return h; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement JSObject2WrappedJSMap... michael@0: michael@0: void michael@0: JSObject2WrappedJSMap::FindDyingJSObjects(nsTArray* dying) michael@0: { michael@0: for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) { michael@0: nsXPCWrappedJS* wrapper = r.front().value(); michael@0: MOZ_ASSERT(wrapper, "found a null JS wrapper!"); michael@0: michael@0: // walk the wrapper chain and find any whose JSObject is to be finalized michael@0: while (wrapper) { michael@0: if (wrapper->IsSubjectToFinalization() && wrapper->IsObjectAboutToBeFinalized()) michael@0: dying->AppendElement(wrapper); michael@0: wrapper = wrapper->GetNextWrapper(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: JSObject2WrappedJSMap::ShutdownMarker() michael@0: { michael@0: for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) { michael@0: nsXPCWrappedJS* wrapper = r.front().value(); michael@0: MOZ_ASSERT(wrapper, "found a null JS wrapper!"); michael@0: MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!"); michael@0: wrapper->SystemIsBeingShutDown(); michael@0: } michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement Native2WrappedNativeMap... michael@0: michael@0: // static michael@0: Native2WrappedNativeMap* michael@0: Native2WrappedNativeMap::newMap(int size) michael@0: { michael@0: Native2WrappedNativeMap* map = new Native2WrappedNativeMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: // Allocation of the map or the creation of its hash table has michael@0: // failed. This will cause a nullptr deref later when we attempt michael@0: // to use the map, so we abort immediately to provide a more michael@0: // useful crash stack. michael@0: NS_RUNTIMEABORT("Ran out of memory."); michael@0: return nullptr; michael@0: } michael@0: michael@0: Native2WrappedNativeMap::Native2WrappedNativeMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, michael@0: sizeof(Entry), size); michael@0: } michael@0: michael@0: Native2WrappedNativeMap::~Native2WrappedNativeMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: size_t michael@0: Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) michael@0: { michael@0: size_t n = 0; michael@0: n += mallocSizeOf(this); michael@0: n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; michael@0: return n; michael@0: } michael@0: michael@0: /* static */ size_t michael@0: Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, michael@0: mozilla::MallocSizeOf mallocSizeOf, void *) michael@0: { michael@0: return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement IID2WrappedJSClassMap... michael@0: michael@0: const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps = michael@0: { michael@0: PL_DHashAllocTable, michael@0: PL_DHashFreeTable, michael@0: HashIIDPtrKey, michael@0: MatchIIDPtrKey, michael@0: PL_DHashMoveEntryStub, michael@0: PL_DHashClearEntryStub, michael@0: PL_DHashFinalizeStub michael@0: }; michael@0: michael@0: // static michael@0: IID2WrappedJSClassMap* michael@0: IID2WrappedJSClassMap::newMap(int size) michael@0: { michael@0: IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: IID2WrappedJSClassMap::IID2WrappedJSClassMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); michael@0: } michael@0: michael@0: IID2WrappedJSClassMap::~IID2WrappedJSClassMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: michael@0: /***************************************************************************/ michael@0: // implement IID2NativeInterfaceMap... michael@0: michael@0: const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps = michael@0: { michael@0: PL_DHashAllocTable, michael@0: PL_DHashFreeTable, michael@0: HashIIDPtrKey, michael@0: MatchIIDPtrKey, michael@0: PL_DHashMoveEntryStub, michael@0: PL_DHashClearEntryStub, michael@0: PL_DHashFinalizeStub michael@0: }; michael@0: michael@0: // static michael@0: IID2NativeInterfaceMap* michael@0: IID2NativeInterfaceMap::newMap(int size) michael@0: { michael@0: IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: IID2NativeInterfaceMap::IID2NativeInterfaceMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); michael@0: } michael@0: michael@0: IID2NativeInterfaceMap::~IID2NativeInterfaceMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: size_t michael@0: IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) michael@0: { michael@0: size_t n = 0; michael@0: n += mallocSizeOf(this); michael@0: n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; michael@0: return n; michael@0: } michael@0: michael@0: /* static */ size_t michael@0: IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, michael@0: mozilla::MallocSizeOf mallocSizeOf, void *) michael@0: { michael@0: XPCNativeInterface *iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value; michael@0: return iface->SizeOfIncludingThis(mallocSizeOf); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement ClassInfo2NativeSetMap... michael@0: michael@0: // static michael@0: ClassInfo2NativeSetMap* michael@0: ClassInfo2NativeSetMap::newMap(int size) michael@0: { michael@0: ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, michael@0: sizeof(Entry), size); michael@0: } michael@0: michael@0: ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: size_t michael@0: ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) michael@0: { michael@0: size_t n = 0; michael@0: n += mallocSizeOf(this); michael@0: // The second arg is nullptr because this is a "shallow" measurement of the map. michael@0: n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf) : 0; michael@0: return n; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement ClassInfo2WrappedNativeProtoMap... michael@0: michael@0: // static michael@0: ClassInfo2WrappedNativeProtoMap* michael@0: ClassInfo2WrappedNativeProtoMap::newMap(int size) michael@0: { michael@0: ClassInfo2WrappedNativeProtoMap* map = new ClassInfo2WrappedNativeProtoMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: // Allocation of the map or the creation of its hash table has michael@0: // failed. This will cause a nullptr deref later when we attempt michael@0: // to use the map, so we abort immediately to provide a more michael@0: // useful crash stack. michael@0: NS_RUNTIMEABORT("Ran out of memory."); michael@0: return nullptr; michael@0: } michael@0: michael@0: ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, michael@0: sizeof(Entry), size); michael@0: } michael@0: michael@0: ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: size_t michael@0: ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) michael@0: { michael@0: size_t n = 0; michael@0: n += mallocSizeOf(this); michael@0: n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; michael@0: return n; michael@0: } michael@0: michael@0: /* static */ size_t michael@0: ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, michael@0: mozilla::MallocSizeOf mallocSizeOf, void *) michael@0: { michael@0: return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement NativeSetMap... michael@0: michael@0: bool michael@0: NativeSetMap::Entry::Match(PLDHashTable *table, michael@0: const PLDHashEntryHdr *entry, michael@0: const void *key) michael@0: { michael@0: XPCNativeSetKey* Key = (XPCNativeSetKey*) key; michael@0: michael@0: // See the comment in the XPCNativeSetKey declaration in xpcprivate.h. michael@0: if (!Key->IsAKey()) { michael@0: XPCNativeSet* Set1 = (XPCNativeSet*) key; michael@0: XPCNativeSet* Set2 = ((Entry*)entry)->key_value; michael@0: michael@0: if (Set1 == Set2) michael@0: return true; michael@0: michael@0: uint16_t count = Set1->GetInterfaceCount(); michael@0: if (count != Set2->GetInterfaceCount()) michael@0: return false; michael@0: michael@0: XPCNativeInterface** Current1 = Set1->GetInterfaceArray(); michael@0: XPCNativeInterface** Current2 = Set2->GetInterfaceArray(); michael@0: for (uint16_t i = 0; i < count; i++) { michael@0: if (*(Current1++) != *(Current2++)) michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: XPCNativeSet* SetInTable = ((Entry*)entry)->key_value; michael@0: XPCNativeSet* Set = Key->GetBaseSet(); michael@0: XPCNativeInterface* Addition = Key->GetAddition(); michael@0: michael@0: if (!Set) { michael@0: // This is a special case to deal with the invariant that says: michael@0: // "All sets have exactly one nsISupports interface and it comes first." michael@0: // See XPCNativeSet::NewInstance for details. michael@0: // michael@0: // Though we might have a key that represents only one interface, we michael@0: // know that if that one interface were contructed into a set then michael@0: // it would end up really being a set with two interfaces (except for michael@0: // the case where the one interface happened to be nsISupports). michael@0: michael@0: return ((SetInTable->GetInterfaceCount() == 1 && michael@0: SetInTable->GetInterfaceAt(0) == Addition) || michael@0: (SetInTable->GetInterfaceCount() == 2 && michael@0: SetInTable->GetInterfaceAt(1) == Addition)); michael@0: } michael@0: michael@0: if (!Addition && Set == SetInTable) michael@0: return true; michael@0: michael@0: uint16_t count = Set->GetInterfaceCount() + (Addition ? 1 : 0); michael@0: if (count != SetInTable->GetInterfaceCount()) michael@0: return false; michael@0: michael@0: uint16_t Position = Key->GetPosition(); michael@0: XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray(); michael@0: XPCNativeInterface** Current = Set->GetInterfaceArray(); michael@0: for (uint16_t i = 0; i < count; i++) { michael@0: if (Addition && i == Position) { michael@0: if (Addition != *(CurrentInTable++)) michael@0: return false; michael@0: } else { michael@0: if (*(Current++) != *(CurrentInTable++)) michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: const struct PLDHashTableOps NativeSetMap::Entry::sOps = michael@0: { michael@0: PL_DHashAllocTable, michael@0: PL_DHashFreeTable, michael@0: HashNativeKey, michael@0: Match, michael@0: PL_DHashMoveEntryStub, michael@0: PL_DHashClearEntryStub, michael@0: PL_DHashFinalizeStub michael@0: }; michael@0: michael@0: // static michael@0: NativeSetMap* michael@0: NativeSetMap::newMap(int size) michael@0: { michael@0: NativeSetMap* map = new NativeSetMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: NativeSetMap::NativeSetMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); michael@0: } michael@0: michael@0: NativeSetMap::~NativeSetMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: size_t michael@0: NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) michael@0: { michael@0: size_t n = 0; michael@0: n += mallocSizeOf(this); michael@0: n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; michael@0: return n; michael@0: } michael@0: michael@0: /* static */ size_t michael@0: NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *) michael@0: { michael@0: XPCNativeSet *set = ((NativeSetMap::Entry*)hdr)->key_value; michael@0: return set->SizeOfIncludingThis(mallocSizeOf); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement IID2ThisTranslatorMap... michael@0: michael@0: bool michael@0: IID2ThisTranslatorMap::Entry::Match(PLDHashTable *table, michael@0: const PLDHashEntryHdr *entry, michael@0: const void *key) michael@0: { michael@0: return ((const nsID*)key)->Equals(((Entry*)entry)->key); michael@0: } michael@0: michael@0: void michael@0: IID2ThisTranslatorMap::Entry::Clear(PLDHashTable *table, PLDHashEntryHdr *entry) michael@0: { michael@0: static_cast(entry)->value = nullptr; michael@0: memset(entry, 0, table->entrySize); michael@0: } michael@0: michael@0: const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps = michael@0: { michael@0: PL_DHashAllocTable, michael@0: PL_DHashFreeTable, michael@0: HashIIDPtrKey, michael@0: Match, michael@0: PL_DHashMoveEntryStub, michael@0: Clear, michael@0: PL_DHashFinalizeStub michael@0: }; michael@0: michael@0: // static michael@0: IID2ThisTranslatorMap* michael@0: IID2ThisTranslatorMap::newMap(int size) michael@0: { michael@0: IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: IID2ThisTranslatorMap::IID2ThisTranslatorMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); michael@0: } michael@0: michael@0: IID2ThisTranslatorMap::~IID2ThisTranslatorMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: michael@0: PLDHashNumber michael@0: XPCNativeScriptableSharedMap::Entry::Hash(PLDHashTable *table, const void *key) michael@0: { michael@0: PLDHashNumber h; michael@0: const unsigned char *s; michael@0: michael@0: XPCNativeScriptableShared* obj = michael@0: (XPCNativeScriptableShared*) key; michael@0: michael@0: // hash together the flags and the classname string, ignore the interfaces michael@0: // bitmap since it's very rare that it's different when flags and classname michael@0: // are the same. michael@0: michael@0: h = (PLDHashNumber) obj->GetFlags(); michael@0: for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++) michael@0: h = RotateLeft(h, 4) ^ *s; michael@0: return h; michael@0: } michael@0: michael@0: bool michael@0: XPCNativeScriptableSharedMap::Entry::Match(PLDHashTable *table, michael@0: const PLDHashEntryHdr *entry, michael@0: const void *key) michael@0: { michael@0: XPCNativeScriptableShared* obj1 = michael@0: ((XPCNativeScriptableSharedMap::Entry*) entry)->key; michael@0: michael@0: XPCNativeScriptableShared* obj2 = michael@0: (XPCNativeScriptableShared*) key; michael@0: michael@0: // match the flags, the classname string and the interfaces bitmap michael@0: michael@0: if (obj1->GetFlags() != obj2->GetFlags() || michael@0: obj1->GetInterfacesBitmap() != obj2->GetInterfacesBitmap()) michael@0: return false; michael@0: michael@0: const char* name1 = obj1->GetJSClass()->name; michael@0: const char* name2 = obj2->GetJSClass()->name; michael@0: michael@0: if (!name1 || !name2) michael@0: return name1 == name2; michael@0: michael@0: return 0 == strcmp(name1, name2); michael@0: } michael@0: michael@0: const struct PLDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps = michael@0: { michael@0: PL_DHashAllocTable, michael@0: PL_DHashFreeTable, michael@0: Hash, michael@0: Match, michael@0: PL_DHashMoveEntryStub, michael@0: PL_DHashClearEntryStub, michael@0: PL_DHashFinalizeStub michael@0: }; michael@0: michael@0: // static michael@0: XPCNativeScriptableSharedMap* michael@0: XPCNativeScriptableSharedMap::newMap(int size) michael@0: { michael@0: XPCNativeScriptableSharedMap* map = michael@0: new XPCNativeScriptableSharedMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); michael@0: } michael@0: michael@0: XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: bool michael@0: XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags, michael@0: char* name, michael@0: uint32_t interfacesBitmap, michael@0: XPCNativeScriptableInfo* si) michael@0: { michael@0: NS_PRECONDITION(name,"bad param"); michael@0: NS_PRECONDITION(si,"bad param"); michael@0: michael@0: XPCNativeScriptableShared key(flags, name, interfacesBitmap); michael@0: Entry* entry = (Entry*) michael@0: PL_DHashTableOperate(mTable, &key, PL_DHASH_ADD); michael@0: if (!entry) michael@0: return false; michael@0: michael@0: XPCNativeScriptableShared* shared = entry->key; michael@0: michael@0: if (!shared) { michael@0: entry->key = shared = michael@0: new XPCNativeScriptableShared(flags, key.TransferNameOwnership(), michael@0: interfacesBitmap); michael@0: if (!shared) michael@0: return false; michael@0: shared->PopulateJSClass(); michael@0: } michael@0: si->SetScriptableShared(shared); michael@0: return true; michael@0: } michael@0: michael@0: /***************************************************************************/ michael@0: // implement XPCWrappedNativeProtoMap... michael@0: michael@0: // static michael@0: XPCWrappedNativeProtoMap* michael@0: XPCWrappedNativeProtoMap::newMap(int size) michael@0: { michael@0: XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(size); michael@0: if (map && map->mTable) michael@0: return map; michael@0: delete map; michael@0: return nullptr; michael@0: } michael@0: michael@0: XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int size) michael@0: { michael@0: mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, michael@0: sizeof(PLDHashEntryStub), size); michael@0: } michael@0: michael@0: XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap() michael@0: { michael@0: if (mTable) michael@0: PL_DHashTableDestroy(mTable); michael@0: } michael@0: michael@0: /***************************************************************************/