summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/src/XPCMaps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/xpconnect/src/XPCMaps.cpp')
-rw-r--r--js/xpconnect/src/XPCMaps.cpp191
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;
+}
+
+/***************************************************************************/