XPCMaps.cpp (6634B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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/. */ 6 7 /* Private maps (hashtables). */ 8 9 #include "mozilla/MemoryReporting.h" 10 #include "xpcprivate.h" 11 #include "XPCMaps.h" 12 13 #include "js/HashTable.h" 14 15 using namespace mozilla; 16 17 /***************************************************************************/ 18 // implement JSObject2WrappedJSMap... 19 20 void JSObject2WrappedJSMap::UpdateWeakPointersAfterGC(JSTracer* trc) { 21 // Check all wrappers and update their JSObject pointer if it has been 22 // moved. Release any wrappers whose weakly held JSObject has died. 23 24 nsTArray<RefPtr<nsXPCWrappedJS>> dying; 25 for (auto iter = mTable.modIter(); !iter.done(); iter.next()) { 26 nsXPCWrappedJS* wrapper = iter.get().value(); 27 MOZ_ASSERT(wrapper, "found a null JS wrapper!"); 28 29 // There's no need to walk the entire chain, because only the root can be 30 // subject to finalization due to the double release behavior in Release. 31 // See the comment at the top of XPCWrappedJS.cpp about nsXPCWrappedJS 32 // lifetime. 33 if (wrapper && wrapper->IsSubjectToFinalization()) { 34 wrapper->UpdateObjectPointerAfterGC(trc); 35 if (!wrapper->GetJSObjectPreserveColor()) { 36 dying.AppendElement(dont_AddRef(wrapper)); 37 } 38 } 39 40 // Remove or update the JSObject key in the table if necessary. 41 if (!JS_UpdateWeakPointerAfterGC(trc, &iter.get().mutableKey())) { 42 iter.remove(); 43 } 44 } 45 } 46 47 void JSObject2WrappedJSMap::ShutdownMarker() { 48 for (auto iter = mTable.iter(); !iter.done(); iter.next()) { 49 nsXPCWrappedJS* wrapper = iter.get().value(); 50 MOZ_ASSERT(wrapper, "found a null JS wrapper!"); 51 MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!"); 52 wrapper->SystemIsBeingShutDown(); 53 } 54 } 55 56 size_t JSObject2WrappedJSMap::SizeOfIncludingThis( 57 mozilla::MallocSizeOf mallocSizeOf) const { 58 size_t n = mallocSizeOf(this); 59 n += mTable.shallowSizeOfExcludingThis(mallocSizeOf); 60 return n; 61 } 62 63 size_t JSObject2WrappedJSMap::SizeOfWrappedJS( 64 mozilla::MallocSizeOf mallocSizeOf) const { 65 size_t n = 0; 66 for (auto iter = mTable.iter(); !iter.done(); iter.next()) { 67 n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf); 68 } 69 return n; 70 } 71 72 /***************************************************************************/ 73 // implement Native2WrappedNativeMap... 74 75 Native2WrappedNativeMap::Native2WrappedNativeMap() 76 : mMap(XPC_NATIVE_MAP_LENGTH) {} 77 78 size_t Native2WrappedNativeMap::SizeOfIncludingThis( 79 mozilla::MallocSizeOf mallocSizeOf) const { 80 size_t n = mallocSizeOf(this); 81 n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); 82 for (auto iter = mMap.iter(); !iter.done(); iter.next()) { 83 n += mallocSizeOf(iter.get().value()); 84 } 85 return n; 86 } 87 88 /***************************************************************************/ 89 // implement IID2NativeInterfaceMap... 90 91 IID2NativeInterfaceMap::IID2NativeInterfaceMap() 92 : mMap(XPC_NATIVE_INTERFACE_MAP_LENGTH) {} 93 94 size_t IID2NativeInterfaceMap::SizeOfIncludingThis( 95 mozilla::MallocSizeOf mallocSizeOf) const { 96 size_t n = mallocSizeOf(this); 97 n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); 98 for (auto iter = mMap.iter(); !iter.done(); iter.next()) { 99 n += iter.get().value()->SizeOfIncludingThis(mallocSizeOf); 100 } 101 return n; 102 } 103 104 /***************************************************************************/ 105 // implement ClassInfo2NativeSetMap... 106 107 ClassInfo2NativeSetMap::ClassInfo2NativeSetMap() 108 : mMap(XPC_NATIVE_SET_MAP_LENGTH) {} 109 110 size_t ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis( 111 mozilla::MallocSizeOf mallocSizeOf) { 112 size_t n = mallocSizeOf(this); 113 n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); 114 return n; 115 } 116 117 /***************************************************************************/ 118 // implement ClassInfo2WrappedNativeProtoMap... 119 120 ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap() 121 : mMap(XPC_NATIVE_PROTO_MAP_LENGTH) {} 122 123 size_t ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis( 124 mozilla::MallocSizeOf mallocSizeOf) const { 125 size_t n = mallocSizeOf(this); 126 n += mMap.shallowSizeOfExcludingThis(mallocSizeOf); 127 for (auto iter = mMap.iter(); !iter.done(); iter.next()) { 128 n += mallocSizeOf(iter.get().value()); 129 } 130 return n; 131 } 132 133 /***************************************************************************/ 134 // implement NativeSetMap... 135 136 bool NativeSetHasher::match(Key key, Lookup lookup) { 137 // The |key| argument is for the existing table entry and |lookup| is the 138 // value passed by the caller that is being compared with it. 139 XPCNativeSet* SetInTable = key; 140 XPCNativeSet* Set = lookup->GetBaseSet(); 141 XPCNativeInterface* Addition = lookup->GetAddition(); 142 143 if (!Set) { 144 // This is a special case to deal with the invariant that says: 145 // "All sets have exactly one nsISupports interface and it comes first." 146 // See XPCNativeSet::NewInstance for details. 147 // 148 // Though we might have a key that represents only one interface, we 149 // know that if that one interface were contructed into a set then 150 // it would end up really being a set with two interfaces (except for 151 // the case where the one interface happened to be nsISupports). 152 153 return (SetInTable->GetInterfaceCount() == 1 && 154 SetInTable->GetInterfaceAt(0) == Addition) || 155 (SetInTable->GetInterfaceCount() == 2 && 156 SetInTable->GetInterfaceAt(1) == Addition); 157 } 158 159 if (!Addition && Set == SetInTable) { 160 return true; 161 } 162 163 uint16_t count = Set->GetInterfaceCount(); 164 if (count + (Addition ? 1 : 0) != SetInTable->GetInterfaceCount()) { 165 return false; 166 } 167 168 XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray(); 169 XPCNativeInterface** Current = Set->GetInterfaceArray(); 170 for (uint16_t i = 0; i < count; i++) { 171 if (*(Current++) != *(CurrentInTable++)) { 172 return false; 173 } 174 } 175 return !Addition || Addition == *(CurrentInTable++); 176 } 177 178 NativeSetMap::NativeSetMap() : mSet(XPC_NATIVE_SET_MAP_LENGTH) {} 179 180 size_t NativeSetMap::SizeOfIncludingThis( 181 mozilla::MallocSizeOf mallocSizeOf) const { 182 size_t n = mallocSizeOf(this); 183 n += mSet.shallowSizeOfExcludingThis(mallocSizeOf); 184 for (auto iter = mSet.iter(); !iter.done(); iter.next()) { 185 n += iter.get()->SizeOfIncludingThis(mallocSizeOf); 186 } 187 return n; 188 } 189 190 /***************************************************************************/