Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
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/MathAlgorithms.h"
10 : #include "mozilla/MemoryReporting.h"
11 : #include "xpcprivate.h"
12 :
13 : #include "js/HashTable.h"
14 :
15 : using namespace mozilla;
16 :
17 : /***************************************************************************/
18 : // static shared...
19 :
20 : // Note this is returning the bit pattern of the first part of the nsID, not
21 : // the pointer to the nsID.
22 :
23 : static PLDHashNumber
24 20347 : HashIIDPtrKey(const void* key)
25 : {
26 20347 : return *((js::HashNumber*)key);
27 : }
28 :
29 : static bool
30 15302 : MatchIIDPtrKey(const PLDHashEntryHdr* entry, const void* key)
31 : {
32 : return ((const nsID*)key)->
33 15302 : Equals(*((const nsID*)((PLDHashEntryStub*)entry)->key));
34 : }
35 :
36 : static PLDHashNumber
37 3255 : HashNativeKey(const void* data)
38 : {
39 3255 : return static_cast<const XPCNativeSetKey*>(data)->Hash();
40 : }
41 :
42 : /***************************************************************************/
43 : // implement JSObject2WrappedJSMap...
44 :
45 : void
46 0 : JSObject2WrappedJSMap::UpdateWeakPointersAfterGC()
47 : {
48 : // Check all wrappers and update their JSObject pointer if it has been
49 : // moved. Release any wrappers whose weakly held JSObject has died.
50 :
51 0 : nsTArray<RefPtr<nsXPCWrappedJS>> dying;
52 0 : for (Map::Enum e(mTable); !e.empty(); e.popFront()) {
53 0 : nsXPCWrappedJS* wrapper = e.front().value();
54 0 : MOZ_ASSERT(wrapper, "found a null JS wrapper!");
55 :
56 : // Walk the wrapper chain and update all JSObjects.
57 0 : while (wrapper) {
58 0 : if (wrapper->IsSubjectToFinalization()) {
59 0 : wrapper->UpdateObjectPointerAfterGC();
60 0 : if (!wrapper->GetJSObjectPreserveColor())
61 0 : dying.AppendElement(dont_AddRef(wrapper));
62 : }
63 0 : wrapper = wrapper->GetNextWrapper();
64 : }
65 :
66 : // Remove or update the JSObject key in the table if necessary.
67 0 : JSObject* obj = e.front().key().unbarrieredGet();
68 0 : JS_UpdateWeakPointerAfterGCUnbarriered(&obj);
69 0 : if (!obj)
70 0 : e.removeFront();
71 : else
72 0 : e.front().mutableKey() = obj;
73 : }
74 0 : }
75 :
76 : void
77 0 : JSObject2WrappedJSMap::ShutdownMarker()
78 : {
79 0 : for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) {
80 0 : nsXPCWrappedJS* wrapper = r.front().value();
81 0 : MOZ_ASSERT(wrapper, "found a null JS wrapper!");
82 0 : MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!");
83 0 : wrapper->SystemIsBeingShutDown();
84 : }
85 0 : }
86 :
87 : size_t
88 0 : JSObject2WrappedJSMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
89 : {
90 0 : size_t n = mallocSizeOf(this);
91 0 : n += mTable.sizeOfExcludingThis(mallocSizeOf);
92 0 : return n;
93 : }
94 :
95 : size_t
96 0 : JSObject2WrappedJSMap::SizeOfWrappedJS(mozilla::MallocSizeOf mallocSizeOf) const
97 : {
98 0 : size_t n = 0;
99 0 : for (Map::Range r = mTable.all(); !r.empty(); r.popFront())
100 0 : n += r.front().value()->SizeOfIncludingThis(mallocSizeOf);
101 0 : return n;
102 : }
103 :
104 : /***************************************************************************/
105 : // implement Native2WrappedNativeMap...
106 :
107 : // static
108 : Native2WrappedNativeMap*
109 293 : Native2WrappedNativeMap::newMap(int length)
110 : {
111 293 : return new Native2WrappedNativeMap(length);
112 : }
113 :
114 293 : Native2WrappedNativeMap::Native2WrappedNativeMap(int length)
115 293 : : mTable(PLDHashTable::StubOps(), sizeof(Entry), length)
116 : {
117 293 : }
118 :
119 : size_t
120 0 : Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
121 : {
122 0 : size_t n = mallocSizeOf(this);
123 0 : n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
124 0 : for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
125 0 : auto entry = static_cast<Native2WrappedNativeMap::Entry*>(iter.Get());
126 0 : n += mallocSizeOf(entry->value);
127 : }
128 0 : return n;
129 : }
130 :
131 : /***************************************************************************/
132 : // implement IID2WrappedJSClassMap...
133 :
134 : const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
135 : {
136 : HashIIDPtrKey,
137 : MatchIIDPtrKey,
138 : PLDHashTable::MoveEntryStub,
139 : PLDHashTable::ClearEntryStub
140 : };
141 :
142 : // static
143 : IID2WrappedJSClassMap*
144 3 : IID2WrappedJSClassMap::newMap(int length)
145 : {
146 3 : return new IID2WrappedJSClassMap(length);
147 : }
148 :
149 3 : IID2WrappedJSClassMap::IID2WrappedJSClassMap(int length)
150 3 : : mTable(&Entry::sOps, sizeof(Entry), length)
151 : {
152 3 : }
153 :
154 : /***************************************************************************/
155 : // implement IID2NativeInterfaceMap...
156 :
157 : const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps =
158 : {
159 : HashIIDPtrKey,
160 : MatchIIDPtrKey,
161 : PLDHashTable::MoveEntryStub,
162 : PLDHashTable::ClearEntryStub
163 : };
164 :
165 : // static
166 : IID2NativeInterfaceMap*
167 3 : IID2NativeInterfaceMap::newMap(int length)
168 : {
169 3 : return new IID2NativeInterfaceMap(length);
170 : }
171 :
172 3 : IID2NativeInterfaceMap::IID2NativeInterfaceMap(int length)
173 3 : : mTable(&Entry::sOps, sizeof(Entry), length)
174 : {
175 3 : }
176 :
177 : size_t
178 0 : IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
179 : {
180 0 : size_t n = mallocSizeOf(this);
181 0 : n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
182 0 : for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
183 0 : auto entry = static_cast<IID2NativeInterfaceMap::Entry*>(iter.Get());
184 0 : n += entry->value->SizeOfIncludingThis(mallocSizeOf);
185 : }
186 0 : return n;
187 : }
188 :
189 : /***************************************************************************/
190 : // implement ClassInfo2NativeSetMap...
191 :
192 : // static
193 755 : bool ClassInfo2NativeSetMap::Entry::Match(const PLDHashEntryHdr* aEntry,
194 : const void* aKey)
195 : {
196 755 : return static_cast<const Entry*>(aEntry)->key == aKey;
197 : }
198 :
199 : // static
200 0 : void ClassInfo2NativeSetMap::Entry::Clear(PLDHashTable* aTable,
201 : PLDHashEntryHdr* aEntry)
202 : {
203 0 : auto entry = static_cast<Entry*>(aEntry);
204 0 : NS_RELEASE(entry->value);
205 :
206 0 : entry->key = nullptr;
207 0 : entry->value = nullptr;
208 0 : }
209 :
210 : const PLDHashTableOps ClassInfo2NativeSetMap::Entry::sOps =
211 : {
212 : PLDHashTable::HashVoidPtrKeyStub,
213 : Match,
214 : PLDHashTable::MoveEntryStub,
215 : Clear,
216 : nullptr
217 : };
218 :
219 : // static
220 : ClassInfo2NativeSetMap*
221 3 : ClassInfo2NativeSetMap::newMap(int length)
222 : {
223 3 : return new ClassInfo2NativeSetMap(length);
224 : }
225 :
226 3 : ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int length)
227 3 : : mTable(&ClassInfo2NativeSetMap::Entry::sOps, sizeof(Entry), length)
228 : {
229 3 : }
230 :
231 : size_t
232 0 : ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
233 : {
234 0 : size_t n = mallocSizeOf(this);
235 0 : n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
236 0 : return n;
237 : }
238 :
239 : /***************************************************************************/
240 : // implement ClassInfo2WrappedNativeProtoMap...
241 :
242 : // static
243 : ClassInfo2WrappedNativeProtoMap*
244 293 : ClassInfo2WrappedNativeProtoMap::newMap(int length)
245 : {
246 293 : return new ClassInfo2WrappedNativeProtoMap(length);
247 : }
248 :
249 293 : ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int length)
250 293 : : mTable(PLDHashTable::StubOps(), sizeof(Entry), length)
251 : {
252 293 : }
253 :
254 : size_t
255 0 : ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
256 : {
257 0 : size_t n = mallocSizeOf(this);
258 0 : n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
259 0 : for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
260 0 : auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(iter.Get());
261 0 : n += mallocSizeOf(entry->value);
262 : }
263 0 : return n;
264 : }
265 :
266 : /***************************************************************************/
267 : // implement NativeSetMap...
268 :
269 : bool
270 2407 : NativeSetMap::Entry::Match(const PLDHashEntryHdr* entry, const void* key)
271 : {
272 2407 : auto Key = static_cast<const XPCNativeSetKey*>(key);
273 2407 : XPCNativeSet* SetInTable = ((Entry*)entry)->key_value;
274 2407 : XPCNativeSet* Set = Key->GetBaseSet();
275 2407 : XPCNativeInterface* Addition = Key->GetAddition();
276 :
277 2407 : if (!Set) {
278 : // This is a special case to deal with the invariant that says:
279 : // "All sets have exactly one nsISupports interface and it comes first."
280 : // See XPCNativeSet::NewInstance for details.
281 : //
282 : // Though we might have a key that represents only one interface, we
283 : // know that if that one interface were contructed into a set then
284 : // it would end up really being a set with two interfaces (except for
285 : // the case where the one interface happened to be nsISupports).
286 :
287 2283 : return (SetInTable->GetInterfaceCount() == 1 &&
288 3793 : SetInTable->GetInterfaceAt(0) == Addition) ||
289 1510 : (SetInTable->GetInterfaceCount() == 2 &&
290 2274 : SetInTable->GetInterfaceAt(1) == Addition);
291 : }
292 :
293 888 : if (!Addition && Set == SetInTable)
294 47 : return true;
295 :
296 841 : uint16_t count = Set->GetInterfaceCount();
297 841 : if (count + (Addition ? 1 : 0) != SetInTable->GetInterfaceCount())
298 0 : return false;
299 :
300 841 : XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray();
301 841 : XPCNativeInterface** Current = Set->GetInterfaceArray();
302 2371 : for (uint16_t i = 0; i < count; i++) {
303 1535 : if (*(Current++) != *(CurrentInTable++))
304 5 : return false;
305 : }
306 836 : return !Addition || Addition == *(CurrentInTable++);
307 : }
308 :
309 : const struct PLDHashTableOps NativeSetMap::Entry::sOps =
310 : {
311 : HashNativeKey,
312 : Match,
313 : PLDHashTable::MoveEntryStub,
314 : PLDHashTable::ClearEntryStub
315 : };
316 :
317 : // static
318 : NativeSetMap*
319 3 : NativeSetMap::newMap(int length)
320 : {
321 3 : return new NativeSetMap(length);
322 : }
323 :
324 3 : NativeSetMap::NativeSetMap(int length)
325 3 : : mTable(&Entry::sOps, sizeof(Entry), length)
326 : {
327 3 : }
328 :
329 : size_t
330 0 : NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
331 : {
332 0 : size_t n = mallocSizeOf(this);
333 0 : n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
334 0 : for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
335 0 : auto entry = static_cast<NativeSetMap::Entry*>(iter.Get());
336 0 : n += entry->key_value->SizeOfIncludingThis(mallocSizeOf);
337 : }
338 0 : return n;
339 : }
340 :
341 : /***************************************************************************/
342 : // implement IID2ThisTranslatorMap...
343 :
344 : bool
345 20 : IID2ThisTranslatorMap::Entry::Match(const PLDHashEntryHdr* entry,
346 : const void* key)
347 : {
348 20 : return ((const nsID*)key)->Equals(((Entry*)entry)->key);
349 : }
350 :
351 : void
352 0 : IID2ThisTranslatorMap::Entry::Clear(PLDHashTable* table, PLDHashEntryHdr* entry)
353 : {
354 0 : static_cast<Entry*>(entry)->value = nullptr;
355 0 : memset(entry, 0, table->EntrySize());
356 0 : }
357 :
358 : const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
359 : {
360 : HashIIDPtrKey,
361 : Match,
362 : PLDHashTable::MoveEntryStub,
363 : Clear
364 : };
365 :
366 : // static
367 : IID2ThisTranslatorMap*
368 3 : IID2ThisTranslatorMap::newMap(int length)
369 : {
370 3 : return new IID2ThisTranslatorMap(length);
371 : }
372 :
373 3 : IID2ThisTranslatorMap::IID2ThisTranslatorMap(int length)
374 3 : : mTable(&Entry::sOps, sizeof(Entry), length)
375 : {
376 3 : }
377 :
378 : /***************************************************************************/
379 : // implement XPCWrappedNativeProtoMap...
380 :
381 : // static
382 : XPCWrappedNativeProtoMap*
383 3 : XPCWrappedNativeProtoMap::newMap(int length)
384 : {
385 3 : return new XPCWrappedNativeProtoMap(length);
386 : }
387 :
388 3 : XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int length)
389 3 : : mTable(PLDHashTable::StubOps(), sizeof(PLDHashEntryStub), length)
390 : {
391 3 : }
392 :
393 : /***************************************************************************/
|