diff options
Diffstat (limited to 'js/xpconnect/src/XPCMaps.cpp')
-rw-r--r-- | js/xpconnect/src/XPCMaps.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/js/xpconnect/src/XPCMaps.cpp b/js/xpconnect/src/XPCMaps.cpp new file mode 100644 index 0000000000..e2d2857a82 --- /dev/null +++ b/js/xpconnect/src/XPCMaps.cpp @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Private maps (hashtables). */ + +#include "mozilla/MathAlgorithms.h" +#include "mozilla/MemoryReporting.h" +#include "xpcprivate.h" +#include "XPCMaps.h" + +#include "js/HashTable.h" + +using namespace mozilla; + +/***************************************************************************/ +// implement JSObject2WrappedJSMap... + +void JSObject2WrappedJSMap::UpdateWeakPointersAfterGC(JSTracer* trc) { + // Check all wrappers and update their JSObject pointer if it has been + // moved. Release any wrappers whose weakly held JSObject has died. + + nsTArray<RefPtr<nsXPCWrappedJS>> dying; + for (auto iter = mTable.modIter(); !iter.done(); iter.next()) { + nsXPCWrappedJS* wrapper = iter.get().value(); + MOZ_ASSERT(wrapper, "found a null JS wrapper!"); + + // There's no need to walk the entire chain, because only the root can be + // subject to finalization due to the double release behavior in Release. + // See the comment at the top of XPCWrappedJS.cpp about nsXPCWrappedJS + // lifetime. + if (wrapper && wrapper->IsSubjectToFinalization()) { + wrapper->UpdateObjectPointerAfterGC(trc); + if (!wrapper->GetJSObjectPreserveColor()) { + dying.AppendElement(dont_AddRef(wrapper)); + } + } + + // Remove or update the JSObject key in the table if necessary. + if (!JS_UpdateWeakPointerAfterGC(trc, &iter.get().mutableKey())) { + iter.remove(); + } + } +} + +void JSObject2WrappedJSMap::ShutdownMarker() { + for (auto iter = mTable.iter(); !iter.done(); iter.next()) { + nsXPCWrappedJS* wrapper = iter.get().value(); + MOZ_ASSERT(wrapper, "found a null JS wrapper!"); + MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!"); + wrapper->SystemIsBeingShutDown(); + } +} + +size_t JSObject2WrappedJSMap::SizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = mallocSizeOf(this); + n += mTable.shallowSizeOfExcludingThis(mallocSizeOf); + return n; +} + +size_t JSObject2WrappedJSMap::SizeOfWrappedJS( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = 0; + for (auto iter = mTable.iter(); !iter.done(); iter.next()) { + n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf); + } + return n; +} + +/***************************************************************************/ +// implement Native2WrappedNativeMap... + +Native2WrappedNativeMap::Native2WrappedNativeMap() + : mMap(XPC_NATIVE_MAP_LENGTH) {} + +size_t Native2WrappedNativeMap::SizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = mallocSizeOf(this); + n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); + for (auto iter = mMap.iter(); !iter.done(); iter.next()) { + n += mallocSizeOf(iter.get().value()); + } + return n; +} + +/***************************************************************************/ +// implement IID2NativeInterfaceMap... + +IID2NativeInterfaceMap::IID2NativeInterfaceMap() + : mMap(XPC_NATIVE_INTERFACE_MAP_LENGTH) {} + +size_t IID2NativeInterfaceMap::SizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = mallocSizeOf(this); + n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); + for (auto iter = mMap.iter(); !iter.done(); iter.next()) { + n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf); + } + return n; +} + +/***************************************************************************/ +// implement ClassInfo2NativeSetMap... + +ClassInfo2NativeSetMap::ClassInfo2NativeSetMap() + : mMap(XPC_NATIVE_SET_MAP_LENGTH) {} + +size_t ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) { + size_t n = mallocSizeOf(this); + n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); + return n; +} + +/***************************************************************************/ +// implement ClassInfo2WrappedNativeProtoMap... + +ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap() + : mMap(XPC_NATIVE_PROTO_MAP_LENGTH) {} + +size_t ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = mallocSizeOf(this); + n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); + for (auto iter = mMap.iter(); !iter.done(); iter.next()) { + n += mallocSizeOf(iter.get().value()); + } + return n; +} + +/***************************************************************************/ +// implement NativeSetMap... + +bool NativeSetHasher::match(Key key, Lookup lookup) { + // The |key| argument is for the existing table entry and |lookup| is the + // value passed by the caller that is being compared with it. + XPCNativeSet* SetInTable = key; + XPCNativeSet* Set = lookup->GetBaseSet(); + XPCNativeInterface* Addition = lookup->GetAddition(); + + if (!Set) { + // This is a special case to deal with the invariant that says: + // "All sets have exactly one nsISupports interface and it comes first." + // See XPCNativeSet::NewInstance for details. + // + // Though we might have a key that represents only one interface, we + // know that if that one interface were contructed into a set then + // it would end up really being a set with two interfaces (except for + // the case where the one interface happened to be nsISupports). + + return (SetInTable->GetInterfaceCount() == 1 && + SetInTable->GetInterfaceAt(0) == Addition) || + (SetInTable->GetInterfaceCount() == 2 && + SetInTable->GetInterfaceAt(1) == Addition); + } + + if (!Addition && Set == SetInTable) { + return true; + } + + uint16_t count = Set->GetInterfaceCount(); + if (count + (Addition ? 1 : 0) != SetInTable->GetInterfaceCount()) { + return false; + } + + XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray(); + XPCNativeInterface** Current = Set->GetInterfaceArray(); + for (uint16_t i = 0; i < count; i++) { + if (*(Current++) != *(CurrentInTable++)) { + return false; + } + } + return !Addition || Addition == *(CurrentInTable++); +} + +NativeSetMap::NativeSetMap() : mSet(XPC_NATIVE_SET_MAP_LENGTH) {} + +size_t NativeSetMap::SizeOfIncludingThis( + mozilla::MallocSizeOf mallocSizeOf) const { + size_t n = mallocSizeOf(this); + n += mSet.shallowSizeOfExcludingThis(mallocSizeOf); + for (auto iter = mSet.iter(); !iter.done(); iter.next()) { + n += iter.get()->SizeOfIncludingThis(mallocSizeOf); + } + return n; +} + +/***************************************************************************/ |