|
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 HashIIDPtrKey(PLDHashTable *table, const void *key) |
|
25 { |
|
26 return *((js::HashNumber*)key); |
|
27 } |
|
28 |
|
29 static bool |
|
30 MatchIIDPtrKey(PLDHashTable *table, |
|
31 const PLDHashEntryHdr *entry, |
|
32 const void *key) |
|
33 { |
|
34 return ((const nsID*)key)-> |
|
35 Equals(*((const nsID*)((PLDHashEntryStub*)entry)->key)); |
|
36 } |
|
37 |
|
38 static PLDHashNumber |
|
39 HashNativeKey(PLDHashTable *table, const void *key) |
|
40 { |
|
41 XPCNativeSetKey* Key = (XPCNativeSetKey*) key; |
|
42 |
|
43 PLDHashNumber h = 0; |
|
44 |
|
45 XPCNativeSet* Set; |
|
46 XPCNativeInterface* Addition; |
|
47 uint16_t Position; |
|
48 |
|
49 if (Key->IsAKey()) { |
|
50 Set = Key->GetBaseSet(); |
|
51 Addition = Key->GetAddition(); |
|
52 Position = Key->GetPosition(); |
|
53 } else { |
|
54 Set = (XPCNativeSet*) Key; |
|
55 Addition = nullptr; |
|
56 Position = 0; |
|
57 } |
|
58 |
|
59 if (!Set) { |
|
60 MOZ_ASSERT(Addition, "bad key"); |
|
61 // This would be an XOR like below. |
|
62 // But "0 ^ x == x". So it does not matter. |
|
63 h = (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2; |
|
64 } else { |
|
65 XPCNativeInterface** Current = Set->GetInterfaceArray(); |
|
66 uint16_t count = Set->GetInterfaceCount(); |
|
67 if (Addition) { |
|
68 count++; |
|
69 for (uint16_t i = 0; i < count; i++) { |
|
70 if (i == Position) |
|
71 h ^= (js::HashNumber) NS_PTR_TO_INT32(Addition) >> 2; |
|
72 else |
|
73 h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2; |
|
74 } |
|
75 } else { |
|
76 for (uint16_t i = 0; i < count; i++) |
|
77 h ^= (js::HashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2; |
|
78 } |
|
79 } |
|
80 |
|
81 return h; |
|
82 } |
|
83 |
|
84 /***************************************************************************/ |
|
85 // implement JSObject2WrappedJSMap... |
|
86 |
|
87 void |
|
88 JSObject2WrappedJSMap::FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying) |
|
89 { |
|
90 for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) { |
|
91 nsXPCWrappedJS* wrapper = r.front().value(); |
|
92 MOZ_ASSERT(wrapper, "found a null JS wrapper!"); |
|
93 |
|
94 // walk the wrapper chain and find any whose JSObject is to be finalized |
|
95 while (wrapper) { |
|
96 if (wrapper->IsSubjectToFinalization() && wrapper->IsObjectAboutToBeFinalized()) |
|
97 dying->AppendElement(wrapper); |
|
98 wrapper = wrapper->GetNextWrapper(); |
|
99 } |
|
100 } |
|
101 } |
|
102 |
|
103 void |
|
104 JSObject2WrappedJSMap::ShutdownMarker() |
|
105 { |
|
106 for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) { |
|
107 nsXPCWrappedJS* wrapper = r.front().value(); |
|
108 MOZ_ASSERT(wrapper, "found a null JS wrapper!"); |
|
109 MOZ_ASSERT(wrapper->IsValid(), "found an invalid JS wrapper!"); |
|
110 wrapper->SystemIsBeingShutDown(); |
|
111 } |
|
112 } |
|
113 |
|
114 /***************************************************************************/ |
|
115 // implement Native2WrappedNativeMap... |
|
116 |
|
117 // static |
|
118 Native2WrappedNativeMap* |
|
119 Native2WrappedNativeMap::newMap(int size) |
|
120 { |
|
121 Native2WrappedNativeMap* map = new Native2WrappedNativeMap(size); |
|
122 if (map && map->mTable) |
|
123 return map; |
|
124 // Allocation of the map or the creation of its hash table has |
|
125 // failed. This will cause a nullptr deref later when we attempt |
|
126 // to use the map, so we abort immediately to provide a more |
|
127 // useful crash stack. |
|
128 NS_RUNTIMEABORT("Ran out of memory."); |
|
129 return nullptr; |
|
130 } |
|
131 |
|
132 Native2WrappedNativeMap::Native2WrappedNativeMap(int size) |
|
133 { |
|
134 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, |
|
135 sizeof(Entry), size); |
|
136 } |
|
137 |
|
138 Native2WrappedNativeMap::~Native2WrappedNativeMap() |
|
139 { |
|
140 if (mTable) |
|
141 PL_DHashTableDestroy(mTable); |
|
142 } |
|
143 |
|
144 size_t |
|
145 Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) |
|
146 { |
|
147 size_t n = 0; |
|
148 n += mallocSizeOf(this); |
|
149 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; |
|
150 return n; |
|
151 } |
|
152 |
|
153 /* static */ size_t |
|
154 Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, |
|
155 mozilla::MallocSizeOf mallocSizeOf, void *) |
|
156 { |
|
157 return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value); |
|
158 } |
|
159 |
|
160 /***************************************************************************/ |
|
161 // implement IID2WrappedJSClassMap... |
|
162 |
|
163 const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps = |
|
164 { |
|
165 PL_DHashAllocTable, |
|
166 PL_DHashFreeTable, |
|
167 HashIIDPtrKey, |
|
168 MatchIIDPtrKey, |
|
169 PL_DHashMoveEntryStub, |
|
170 PL_DHashClearEntryStub, |
|
171 PL_DHashFinalizeStub |
|
172 }; |
|
173 |
|
174 // static |
|
175 IID2WrappedJSClassMap* |
|
176 IID2WrappedJSClassMap::newMap(int size) |
|
177 { |
|
178 IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(size); |
|
179 if (map && map->mTable) |
|
180 return map; |
|
181 delete map; |
|
182 return nullptr; |
|
183 } |
|
184 |
|
185 IID2WrappedJSClassMap::IID2WrappedJSClassMap(int size) |
|
186 { |
|
187 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); |
|
188 } |
|
189 |
|
190 IID2WrappedJSClassMap::~IID2WrappedJSClassMap() |
|
191 { |
|
192 if (mTable) |
|
193 PL_DHashTableDestroy(mTable); |
|
194 } |
|
195 |
|
196 |
|
197 /***************************************************************************/ |
|
198 // implement IID2NativeInterfaceMap... |
|
199 |
|
200 const struct PLDHashTableOps IID2NativeInterfaceMap::Entry::sOps = |
|
201 { |
|
202 PL_DHashAllocTable, |
|
203 PL_DHashFreeTable, |
|
204 HashIIDPtrKey, |
|
205 MatchIIDPtrKey, |
|
206 PL_DHashMoveEntryStub, |
|
207 PL_DHashClearEntryStub, |
|
208 PL_DHashFinalizeStub |
|
209 }; |
|
210 |
|
211 // static |
|
212 IID2NativeInterfaceMap* |
|
213 IID2NativeInterfaceMap::newMap(int size) |
|
214 { |
|
215 IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(size); |
|
216 if (map && map->mTable) |
|
217 return map; |
|
218 delete map; |
|
219 return nullptr; |
|
220 } |
|
221 |
|
222 IID2NativeInterfaceMap::IID2NativeInterfaceMap(int size) |
|
223 { |
|
224 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); |
|
225 } |
|
226 |
|
227 IID2NativeInterfaceMap::~IID2NativeInterfaceMap() |
|
228 { |
|
229 if (mTable) |
|
230 PL_DHashTableDestroy(mTable); |
|
231 } |
|
232 |
|
233 size_t |
|
234 IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) |
|
235 { |
|
236 size_t n = 0; |
|
237 n += mallocSizeOf(this); |
|
238 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; |
|
239 return n; |
|
240 } |
|
241 |
|
242 /* static */ size_t |
|
243 IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, |
|
244 mozilla::MallocSizeOf mallocSizeOf, void *) |
|
245 { |
|
246 XPCNativeInterface *iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value; |
|
247 return iface->SizeOfIncludingThis(mallocSizeOf); |
|
248 } |
|
249 |
|
250 /***************************************************************************/ |
|
251 // implement ClassInfo2NativeSetMap... |
|
252 |
|
253 // static |
|
254 ClassInfo2NativeSetMap* |
|
255 ClassInfo2NativeSetMap::newMap(int size) |
|
256 { |
|
257 ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(size); |
|
258 if (map && map->mTable) |
|
259 return map; |
|
260 delete map; |
|
261 return nullptr; |
|
262 } |
|
263 |
|
264 ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int size) |
|
265 { |
|
266 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, |
|
267 sizeof(Entry), size); |
|
268 } |
|
269 |
|
270 ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap() |
|
271 { |
|
272 if (mTable) |
|
273 PL_DHashTableDestroy(mTable); |
|
274 } |
|
275 |
|
276 size_t |
|
277 ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) |
|
278 { |
|
279 size_t n = 0; |
|
280 n += mallocSizeOf(this); |
|
281 // The second arg is nullptr because this is a "shallow" measurement of the map. |
|
282 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf) : 0; |
|
283 return n; |
|
284 } |
|
285 |
|
286 /***************************************************************************/ |
|
287 // implement ClassInfo2WrappedNativeProtoMap... |
|
288 |
|
289 // static |
|
290 ClassInfo2WrappedNativeProtoMap* |
|
291 ClassInfo2WrappedNativeProtoMap::newMap(int size) |
|
292 { |
|
293 ClassInfo2WrappedNativeProtoMap* map = new ClassInfo2WrappedNativeProtoMap(size); |
|
294 if (map && map->mTable) |
|
295 return map; |
|
296 // Allocation of the map or the creation of its hash table has |
|
297 // failed. This will cause a nullptr deref later when we attempt |
|
298 // to use the map, so we abort immediately to provide a more |
|
299 // useful crash stack. |
|
300 NS_RUNTIMEABORT("Ran out of memory."); |
|
301 return nullptr; |
|
302 } |
|
303 |
|
304 ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int size) |
|
305 { |
|
306 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, |
|
307 sizeof(Entry), size); |
|
308 } |
|
309 |
|
310 ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap() |
|
311 { |
|
312 if (mTable) |
|
313 PL_DHashTableDestroy(mTable); |
|
314 } |
|
315 |
|
316 size_t |
|
317 ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) |
|
318 { |
|
319 size_t n = 0; |
|
320 n += mallocSizeOf(this); |
|
321 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; |
|
322 return n; |
|
323 } |
|
324 |
|
325 /* static */ size_t |
|
326 ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, |
|
327 mozilla::MallocSizeOf mallocSizeOf, void *) |
|
328 { |
|
329 return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value); |
|
330 } |
|
331 |
|
332 /***************************************************************************/ |
|
333 // implement NativeSetMap... |
|
334 |
|
335 bool |
|
336 NativeSetMap::Entry::Match(PLDHashTable *table, |
|
337 const PLDHashEntryHdr *entry, |
|
338 const void *key) |
|
339 { |
|
340 XPCNativeSetKey* Key = (XPCNativeSetKey*) key; |
|
341 |
|
342 // See the comment in the XPCNativeSetKey declaration in xpcprivate.h. |
|
343 if (!Key->IsAKey()) { |
|
344 XPCNativeSet* Set1 = (XPCNativeSet*) key; |
|
345 XPCNativeSet* Set2 = ((Entry*)entry)->key_value; |
|
346 |
|
347 if (Set1 == Set2) |
|
348 return true; |
|
349 |
|
350 uint16_t count = Set1->GetInterfaceCount(); |
|
351 if (count != Set2->GetInterfaceCount()) |
|
352 return false; |
|
353 |
|
354 XPCNativeInterface** Current1 = Set1->GetInterfaceArray(); |
|
355 XPCNativeInterface** Current2 = Set2->GetInterfaceArray(); |
|
356 for (uint16_t i = 0; i < count; i++) { |
|
357 if (*(Current1++) != *(Current2++)) |
|
358 return false; |
|
359 } |
|
360 |
|
361 return true; |
|
362 } |
|
363 |
|
364 XPCNativeSet* SetInTable = ((Entry*)entry)->key_value; |
|
365 XPCNativeSet* Set = Key->GetBaseSet(); |
|
366 XPCNativeInterface* Addition = Key->GetAddition(); |
|
367 |
|
368 if (!Set) { |
|
369 // This is a special case to deal with the invariant that says: |
|
370 // "All sets have exactly one nsISupports interface and it comes first." |
|
371 // See XPCNativeSet::NewInstance for details. |
|
372 // |
|
373 // Though we might have a key that represents only one interface, we |
|
374 // know that if that one interface were contructed into a set then |
|
375 // it would end up really being a set with two interfaces (except for |
|
376 // the case where the one interface happened to be nsISupports). |
|
377 |
|
378 return ((SetInTable->GetInterfaceCount() == 1 && |
|
379 SetInTable->GetInterfaceAt(0) == Addition) || |
|
380 (SetInTable->GetInterfaceCount() == 2 && |
|
381 SetInTable->GetInterfaceAt(1) == Addition)); |
|
382 } |
|
383 |
|
384 if (!Addition && Set == SetInTable) |
|
385 return true; |
|
386 |
|
387 uint16_t count = Set->GetInterfaceCount() + (Addition ? 1 : 0); |
|
388 if (count != SetInTable->GetInterfaceCount()) |
|
389 return false; |
|
390 |
|
391 uint16_t Position = Key->GetPosition(); |
|
392 XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray(); |
|
393 XPCNativeInterface** Current = Set->GetInterfaceArray(); |
|
394 for (uint16_t i = 0; i < count; i++) { |
|
395 if (Addition && i == Position) { |
|
396 if (Addition != *(CurrentInTable++)) |
|
397 return false; |
|
398 } else { |
|
399 if (*(Current++) != *(CurrentInTable++)) |
|
400 return false; |
|
401 } |
|
402 } |
|
403 |
|
404 return true; |
|
405 } |
|
406 |
|
407 const struct PLDHashTableOps NativeSetMap::Entry::sOps = |
|
408 { |
|
409 PL_DHashAllocTable, |
|
410 PL_DHashFreeTable, |
|
411 HashNativeKey, |
|
412 Match, |
|
413 PL_DHashMoveEntryStub, |
|
414 PL_DHashClearEntryStub, |
|
415 PL_DHashFinalizeStub |
|
416 }; |
|
417 |
|
418 // static |
|
419 NativeSetMap* |
|
420 NativeSetMap::newMap(int size) |
|
421 { |
|
422 NativeSetMap* map = new NativeSetMap(size); |
|
423 if (map && map->mTable) |
|
424 return map; |
|
425 delete map; |
|
426 return nullptr; |
|
427 } |
|
428 |
|
429 NativeSetMap::NativeSetMap(int size) |
|
430 { |
|
431 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); |
|
432 } |
|
433 |
|
434 NativeSetMap::~NativeSetMap() |
|
435 { |
|
436 if (mTable) |
|
437 PL_DHashTableDestroy(mTable); |
|
438 } |
|
439 |
|
440 size_t |
|
441 NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) |
|
442 { |
|
443 size_t n = 0; |
|
444 n += mallocSizeOf(this); |
|
445 n += mTable ? PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0; |
|
446 return n; |
|
447 } |
|
448 |
|
449 /* static */ size_t |
|
450 NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *) |
|
451 { |
|
452 XPCNativeSet *set = ((NativeSetMap::Entry*)hdr)->key_value; |
|
453 return set->SizeOfIncludingThis(mallocSizeOf); |
|
454 } |
|
455 |
|
456 /***************************************************************************/ |
|
457 // implement IID2ThisTranslatorMap... |
|
458 |
|
459 bool |
|
460 IID2ThisTranslatorMap::Entry::Match(PLDHashTable *table, |
|
461 const PLDHashEntryHdr *entry, |
|
462 const void *key) |
|
463 { |
|
464 return ((const nsID*)key)->Equals(((Entry*)entry)->key); |
|
465 } |
|
466 |
|
467 void |
|
468 IID2ThisTranslatorMap::Entry::Clear(PLDHashTable *table, PLDHashEntryHdr *entry) |
|
469 { |
|
470 static_cast<Entry*>(entry)->value = nullptr; |
|
471 memset(entry, 0, table->entrySize); |
|
472 } |
|
473 |
|
474 const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps = |
|
475 { |
|
476 PL_DHashAllocTable, |
|
477 PL_DHashFreeTable, |
|
478 HashIIDPtrKey, |
|
479 Match, |
|
480 PL_DHashMoveEntryStub, |
|
481 Clear, |
|
482 PL_DHashFinalizeStub |
|
483 }; |
|
484 |
|
485 // static |
|
486 IID2ThisTranslatorMap* |
|
487 IID2ThisTranslatorMap::newMap(int size) |
|
488 { |
|
489 IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(size); |
|
490 if (map && map->mTable) |
|
491 return map; |
|
492 delete map; |
|
493 return nullptr; |
|
494 } |
|
495 |
|
496 IID2ThisTranslatorMap::IID2ThisTranslatorMap(int size) |
|
497 { |
|
498 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); |
|
499 } |
|
500 |
|
501 IID2ThisTranslatorMap::~IID2ThisTranslatorMap() |
|
502 { |
|
503 if (mTable) |
|
504 PL_DHashTableDestroy(mTable); |
|
505 } |
|
506 |
|
507 /***************************************************************************/ |
|
508 |
|
509 PLDHashNumber |
|
510 XPCNativeScriptableSharedMap::Entry::Hash(PLDHashTable *table, const void *key) |
|
511 { |
|
512 PLDHashNumber h; |
|
513 const unsigned char *s; |
|
514 |
|
515 XPCNativeScriptableShared* obj = |
|
516 (XPCNativeScriptableShared*) key; |
|
517 |
|
518 // hash together the flags and the classname string, ignore the interfaces |
|
519 // bitmap since it's very rare that it's different when flags and classname |
|
520 // are the same. |
|
521 |
|
522 h = (PLDHashNumber) obj->GetFlags(); |
|
523 for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++) |
|
524 h = RotateLeft(h, 4) ^ *s; |
|
525 return h; |
|
526 } |
|
527 |
|
528 bool |
|
529 XPCNativeScriptableSharedMap::Entry::Match(PLDHashTable *table, |
|
530 const PLDHashEntryHdr *entry, |
|
531 const void *key) |
|
532 { |
|
533 XPCNativeScriptableShared* obj1 = |
|
534 ((XPCNativeScriptableSharedMap::Entry*) entry)->key; |
|
535 |
|
536 XPCNativeScriptableShared* obj2 = |
|
537 (XPCNativeScriptableShared*) key; |
|
538 |
|
539 // match the flags, the classname string and the interfaces bitmap |
|
540 |
|
541 if (obj1->GetFlags() != obj2->GetFlags() || |
|
542 obj1->GetInterfacesBitmap() != obj2->GetInterfacesBitmap()) |
|
543 return false; |
|
544 |
|
545 const char* name1 = obj1->GetJSClass()->name; |
|
546 const char* name2 = obj2->GetJSClass()->name; |
|
547 |
|
548 if (!name1 || !name2) |
|
549 return name1 == name2; |
|
550 |
|
551 return 0 == strcmp(name1, name2); |
|
552 } |
|
553 |
|
554 const struct PLDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps = |
|
555 { |
|
556 PL_DHashAllocTable, |
|
557 PL_DHashFreeTable, |
|
558 Hash, |
|
559 Match, |
|
560 PL_DHashMoveEntryStub, |
|
561 PL_DHashClearEntryStub, |
|
562 PL_DHashFinalizeStub |
|
563 }; |
|
564 |
|
565 // static |
|
566 XPCNativeScriptableSharedMap* |
|
567 XPCNativeScriptableSharedMap::newMap(int size) |
|
568 { |
|
569 XPCNativeScriptableSharedMap* map = |
|
570 new XPCNativeScriptableSharedMap(size); |
|
571 if (map && map->mTable) |
|
572 return map; |
|
573 delete map; |
|
574 return nullptr; |
|
575 } |
|
576 |
|
577 XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int size) |
|
578 { |
|
579 mTable = PL_NewDHashTable(&Entry::sOps, nullptr, sizeof(Entry), size); |
|
580 } |
|
581 |
|
582 XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap() |
|
583 { |
|
584 if (mTable) |
|
585 PL_DHashTableDestroy(mTable); |
|
586 } |
|
587 |
|
588 bool |
|
589 XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags, |
|
590 char* name, |
|
591 uint32_t interfacesBitmap, |
|
592 XPCNativeScriptableInfo* si) |
|
593 { |
|
594 NS_PRECONDITION(name,"bad param"); |
|
595 NS_PRECONDITION(si,"bad param"); |
|
596 |
|
597 XPCNativeScriptableShared key(flags, name, interfacesBitmap); |
|
598 Entry* entry = (Entry*) |
|
599 PL_DHashTableOperate(mTable, &key, PL_DHASH_ADD); |
|
600 if (!entry) |
|
601 return false; |
|
602 |
|
603 XPCNativeScriptableShared* shared = entry->key; |
|
604 |
|
605 if (!shared) { |
|
606 entry->key = shared = |
|
607 new XPCNativeScriptableShared(flags, key.TransferNameOwnership(), |
|
608 interfacesBitmap); |
|
609 if (!shared) |
|
610 return false; |
|
611 shared->PopulateJSClass(); |
|
612 } |
|
613 si->SetScriptableShared(shared); |
|
614 return true; |
|
615 } |
|
616 |
|
617 /***************************************************************************/ |
|
618 // implement XPCWrappedNativeProtoMap... |
|
619 |
|
620 // static |
|
621 XPCWrappedNativeProtoMap* |
|
622 XPCWrappedNativeProtoMap::newMap(int size) |
|
623 { |
|
624 XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(size); |
|
625 if (map && map->mTable) |
|
626 return map; |
|
627 delete map; |
|
628 return nullptr; |
|
629 } |
|
630 |
|
631 XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int size) |
|
632 { |
|
633 mTable = PL_NewDHashTable(PL_DHashGetStubOps(), nullptr, |
|
634 sizeof(PLDHashEntryStub), size); |
|
635 } |
|
636 |
|
637 XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap() |
|
638 { |
|
639 if (mTable) |
|
640 PL_DHashTableDestroy(mTable); |
|
641 } |
|
642 |
|
643 /***************************************************************************/ |