|
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 #ifndef xpcmaps_h___ |
|
10 #define xpcmaps_h___ |
|
11 |
|
12 #include "mozilla/MemoryReporting.h" |
|
13 |
|
14 |
|
15 // Maps... |
|
16 |
|
17 // Note that most of the declarations for hash table entries begin with |
|
18 // a pointer to something or another. This makes them look enough like |
|
19 // the PLDHashEntryStub struct that the default OPs (PL_DHashGetStubOps()) |
|
20 // just do the right thing for most of our needs. |
|
21 |
|
22 // no virtuals in the maps - all the common stuff inlined |
|
23 // templates could be used to good effect here. |
|
24 |
|
25 /*************************/ |
|
26 |
|
27 class JSObject2WrappedJSMap |
|
28 { |
|
29 typedef js::HashMap<JSObject*, nsXPCWrappedJS*, js::PointerHasher<JSObject*, 3>, |
|
30 js::SystemAllocPolicy> Map; |
|
31 |
|
32 public: |
|
33 static JSObject2WrappedJSMap* newMap(int size) { |
|
34 JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap(); |
|
35 if (map && map->mTable.init(size)) |
|
36 return map; |
|
37 delete map; |
|
38 return nullptr; |
|
39 } |
|
40 |
|
41 inline nsXPCWrappedJS* Find(JSObject* Obj) { |
|
42 NS_PRECONDITION(Obj,"bad param"); |
|
43 Map::Ptr p = mTable.lookup(Obj); |
|
44 return p ? p->value() : nullptr; |
|
45 } |
|
46 |
|
47 inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) { |
|
48 NS_PRECONDITION(wrapper,"bad param"); |
|
49 JSObject* obj = wrapper->GetJSObjectPreserveColor(); |
|
50 Map::AddPtr p = mTable.lookupForAdd(obj); |
|
51 if (p) |
|
52 return p->value(); |
|
53 if (!mTable.add(p, obj, wrapper)) |
|
54 return nullptr; |
|
55 JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this); |
|
56 return wrapper; |
|
57 } |
|
58 |
|
59 inline void Remove(nsXPCWrappedJS* wrapper) { |
|
60 NS_PRECONDITION(wrapper,"bad param"); |
|
61 mTable.remove(wrapper->GetJSObjectPreserveColor()); |
|
62 } |
|
63 |
|
64 inline uint32_t Count() {return mTable.count();} |
|
65 |
|
66 inline void Dump(int16_t depth) { |
|
67 for (Map::Range r = mTable.all(); !r.empty(); r.popFront()) |
|
68 r.front().value()->DebugDump(depth); |
|
69 } |
|
70 |
|
71 void FindDyingJSObjects(nsTArray<nsXPCWrappedJS*>* dying); |
|
72 |
|
73 void ShutdownMarker(); |
|
74 |
|
75 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) { |
|
76 size_t n = mallocSizeOf(this); |
|
77 n += mTable.sizeOfExcludingThis(mallocSizeOf); |
|
78 return n; |
|
79 } |
|
80 |
|
81 private: |
|
82 JSObject2WrappedJSMap() {} |
|
83 |
|
84 /* |
|
85 * This function is called during minor GCs for each key in the HashMap that |
|
86 * has been moved. |
|
87 */ |
|
88 static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { |
|
89 JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(data); |
|
90 JSObject *prior = key; |
|
91 JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key"); |
|
92 self->mTable.rekeyIfMoved(prior, key); |
|
93 } |
|
94 |
|
95 Map mTable; |
|
96 }; |
|
97 |
|
98 /*************************/ |
|
99 |
|
100 class Native2WrappedNativeMap |
|
101 { |
|
102 public: |
|
103 struct Entry : public PLDHashEntryHdr |
|
104 { |
|
105 nsISupports* key; |
|
106 XPCWrappedNative* value; |
|
107 }; |
|
108 |
|
109 static Native2WrappedNativeMap* newMap(int size); |
|
110 |
|
111 inline XPCWrappedNative* Find(nsISupports* Obj) |
|
112 { |
|
113 NS_PRECONDITION(Obj,"bad param"); |
|
114 Entry* entry = (Entry*) |
|
115 PL_DHashTableOperate(mTable, Obj, PL_DHASH_LOOKUP); |
|
116 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
117 return nullptr; |
|
118 return entry->value; |
|
119 } |
|
120 |
|
121 inline XPCWrappedNative* Add(XPCWrappedNative* wrapper) |
|
122 { |
|
123 NS_PRECONDITION(wrapper,"bad param"); |
|
124 nsISupports* obj = wrapper->GetIdentityObject(); |
|
125 MOZ_ASSERT(!Find(obj), "wrapper already in new scope!"); |
|
126 Entry* entry = (Entry*) |
|
127 PL_DHashTableOperate(mTable, obj, PL_DHASH_ADD); |
|
128 if (!entry) |
|
129 return nullptr; |
|
130 if (entry->key) |
|
131 return entry->value; |
|
132 entry->key = obj; |
|
133 entry->value = wrapper; |
|
134 return wrapper; |
|
135 } |
|
136 |
|
137 inline void Remove(XPCWrappedNative* wrapper) |
|
138 { |
|
139 NS_PRECONDITION(wrapper,"bad param"); |
|
140 #ifdef DEBUG |
|
141 XPCWrappedNative* wrapperInMap = Find(wrapper->GetIdentityObject()); |
|
142 MOZ_ASSERT(!wrapperInMap || wrapperInMap == wrapper, |
|
143 "About to remove a different wrapper with the same " |
|
144 "nsISupports identity! This will most likely cause serious " |
|
145 "problems!"); |
|
146 #endif |
|
147 PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE); |
|
148 } |
|
149 |
|
150 inline uint32_t Count() {return mTable->entryCount;} |
|
151 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
152 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
153 |
|
154 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
155 |
|
156 ~Native2WrappedNativeMap(); |
|
157 private: |
|
158 Native2WrappedNativeMap(); // no implementation |
|
159 Native2WrappedNativeMap(int size); |
|
160 |
|
161 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
|
162 |
|
163 private: |
|
164 PLDHashTable *mTable; |
|
165 }; |
|
166 |
|
167 /*************************/ |
|
168 |
|
169 class IID2WrappedJSClassMap |
|
170 { |
|
171 public: |
|
172 struct Entry : public PLDHashEntryHdr |
|
173 { |
|
174 const nsIID* key; |
|
175 nsXPCWrappedJSClass* value; |
|
176 |
|
177 static const struct PLDHashTableOps sOps; |
|
178 }; |
|
179 |
|
180 static IID2WrappedJSClassMap* newMap(int size); |
|
181 |
|
182 inline nsXPCWrappedJSClass* Find(REFNSIID iid) |
|
183 { |
|
184 Entry* entry = (Entry*) |
|
185 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
|
186 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
187 return nullptr; |
|
188 return entry->value; |
|
189 } |
|
190 |
|
191 inline nsXPCWrappedJSClass* Add(nsXPCWrappedJSClass* clazz) |
|
192 { |
|
193 NS_PRECONDITION(clazz,"bad param"); |
|
194 const nsIID* iid = &clazz->GetIID(); |
|
195 Entry* entry = (Entry*) |
|
196 PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); |
|
197 if (!entry) |
|
198 return nullptr; |
|
199 if (entry->key) |
|
200 return entry->value; |
|
201 entry->key = iid; |
|
202 entry->value = clazz; |
|
203 return clazz; |
|
204 } |
|
205 |
|
206 inline void Remove(nsXPCWrappedJSClass* clazz) |
|
207 { |
|
208 NS_PRECONDITION(clazz,"bad param"); |
|
209 PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE); |
|
210 } |
|
211 |
|
212 inline uint32_t Count() {return mTable->entryCount;} |
|
213 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
214 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
215 |
|
216 ~IID2WrappedJSClassMap(); |
|
217 private: |
|
218 IID2WrappedJSClassMap(); // no implementation |
|
219 IID2WrappedJSClassMap(int size); |
|
220 private: |
|
221 PLDHashTable *mTable; |
|
222 }; |
|
223 |
|
224 /*************************/ |
|
225 |
|
226 class IID2NativeInterfaceMap |
|
227 { |
|
228 public: |
|
229 struct Entry : public PLDHashEntryHdr |
|
230 { |
|
231 const nsIID* key; |
|
232 XPCNativeInterface* value; |
|
233 |
|
234 static const struct PLDHashTableOps sOps; |
|
235 }; |
|
236 |
|
237 static IID2NativeInterfaceMap* newMap(int size); |
|
238 |
|
239 inline XPCNativeInterface* Find(REFNSIID iid) |
|
240 { |
|
241 Entry* entry = (Entry*) |
|
242 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
|
243 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
244 return nullptr; |
|
245 return entry->value; |
|
246 } |
|
247 |
|
248 inline XPCNativeInterface* Add(XPCNativeInterface* iface) |
|
249 { |
|
250 NS_PRECONDITION(iface,"bad param"); |
|
251 const nsIID* iid = iface->GetIID(); |
|
252 Entry* entry = (Entry*) |
|
253 PL_DHashTableOperate(mTable, iid, PL_DHASH_ADD); |
|
254 if (!entry) |
|
255 return nullptr; |
|
256 if (entry->key) |
|
257 return entry->value; |
|
258 entry->key = iid; |
|
259 entry->value = iface; |
|
260 return iface; |
|
261 } |
|
262 |
|
263 inline void Remove(XPCNativeInterface* iface) |
|
264 { |
|
265 NS_PRECONDITION(iface,"bad param"); |
|
266 PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE); |
|
267 } |
|
268 |
|
269 inline uint32_t Count() {return mTable->entryCount;} |
|
270 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
271 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
272 |
|
273 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
274 |
|
275 ~IID2NativeInterfaceMap(); |
|
276 private: |
|
277 IID2NativeInterfaceMap(); // no implementation |
|
278 IID2NativeInterfaceMap(int size); |
|
279 |
|
280 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
|
281 |
|
282 private: |
|
283 PLDHashTable *mTable; |
|
284 }; |
|
285 |
|
286 /*************************/ |
|
287 |
|
288 class ClassInfo2NativeSetMap |
|
289 { |
|
290 public: |
|
291 struct Entry : public PLDHashEntryHdr |
|
292 { |
|
293 nsIClassInfo* key; |
|
294 XPCNativeSet* value; |
|
295 }; |
|
296 |
|
297 static ClassInfo2NativeSetMap* newMap(int size); |
|
298 |
|
299 inline XPCNativeSet* Find(nsIClassInfo* info) |
|
300 { |
|
301 Entry* entry = (Entry*) |
|
302 PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); |
|
303 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
304 return nullptr; |
|
305 return entry->value; |
|
306 } |
|
307 |
|
308 inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set) |
|
309 { |
|
310 NS_PRECONDITION(info,"bad param"); |
|
311 Entry* entry = (Entry*) |
|
312 PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); |
|
313 if (!entry) |
|
314 return nullptr; |
|
315 if (entry->key) |
|
316 return entry->value; |
|
317 entry->key = info; |
|
318 entry->value = set; |
|
319 return set; |
|
320 } |
|
321 |
|
322 inline void Remove(nsIClassInfo* info) |
|
323 { |
|
324 NS_PRECONDITION(info,"bad param"); |
|
325 PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); |
|
326 } |
|
327 |
|
328 inline uint32_t Count() {return mTable->entryCount;} |
|
329 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
330 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
331 |
|
332 // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets. |
|
333 // So we don't want to count those XPCNativeSets, because they are better |
|
334 // counted elsewhere (i.e. in XPCJSRuntime::mNativeSetMap, which holds |
|
335 // pointers to *all* XPCNativeSets). Hence the "Shallow". |
|
336 size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
337 |
|
338 ~ClassInfo2NativeSetMap(); |
|
339 private: |
|
340 ClassInfo2NativeSetMap(); // no implementation |
|
341 ClassInfo2NativeSetMap(int size); |
|
342 private: |
|
343 PLDHashTable *mTable; |
|
344 }; |
|
345 |
|
346 /*************************/ |
|
347 |
|
348 class ClassInfo2WrappedNativeProtoMap |
|
349 { |
|
350 public: |
|
351 struct Entry : public PLDHashEntryHdr |
|
352 { |
|
353 nsIClassInfo* key; |
|
354 XPCWrappedNativeProto* value; |
|
355 }; |
|
356 |
|
357 static ClassInfo2WrappedNativeProtoMap* newMap(int size); |
|
358 |
|
359 inline XPCWrappedNativeProto* Find(nsIClassInfo* info) |
|
360 { |
|
361 Entry* entry = (Entry*) |
|
362 PL_DHashTableOperate(mTable, info, PL_DHASH_LOOKUP); |
|
363 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
364 return nullptr; |
|
365 return entry->value; |
|
366 } |
|
367 |
|
368 inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto) |
|
369 { |
|
370 NS_PRECONDITION(info,"bad param"); |
|
371 Entry* entry = (Entry*) |
|
372 PL_DHashTableOperate(mTable, info, PL_DHASH_ADD); |
|
373 if (!entry) |
|
374 return nullptr; |
|
375 if (entry->key) |
|
376 return entry->value; |
|
377 entry->key = info; |
|
378 entry->value = proto; |
|
379 return proto; |
|
380 } |
|
381 |
|
382 inline void Remove(nsIClassInfo* info) |
|
383 { |
|
384 NS_PRECONDITION(info,"bad param"); |
|
385 PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE); |
|
386 } |
|
387 |
|
388 inline uint32_t Count() {return mTable->entryCount;} |
|
389 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
390 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
391 |
|
392 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
393 |
|
394 ~ClassInfo2WrappedNativeProtoMap(); |
|
395 private: |
|
396 ClassInfo2WrappedNativeProtoMap(); // no implementation |
|
397 ClassInfo2WrappedNativeProtoMap(int size); |
|
398 |
|
399 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
|
400 |
|
401 private: |
|
402 PLDHashTable *mTable; |
|
403 }; |
|
404 |
|
405 /*************************/ |
|
406 |
|
407 class NativeSetMap |
|
408 { |
|
409 public: |
|
410 struct Entry : public PLDHashEntryHdr |
|
411 { |
|
412 XPCNativeSet* key_value; |
|
413 |
|
414 static bool |
|
415 Match(PLDHashTable *table, |
|
416 const PLDHashEntryHdr *entry, |
|
417 const void *key); |
|
418 |
|
419 static const struct PLDHashTableOps sOps; |
|
420 }; |
|
421 |
|
422 static NativeSetMap* newMap(int size); |
|
423 |
|
424 inline XPCNativeSet* Find(XPCNativeSetKey* key) |
|
425 { |
|
426 Entry* entry = (Entry*) |
|
427 PL_DHashTableOperate(mTable, key, PL_DHASH_LOOKUP); |
|
428 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
429 return nullptr; |
|
430 return entry->key_value; |
|
431 } |
|
432 |
|
433 inline XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set) |
|
434 { |
|
435 NS_PRECONDITION(key,"bad param"); |
|
436 NS_PRECONDITION(set,"bad param"); |
|
437 Entry* entry = (Entry*) |
|
438 PL_DHashTableOperate(mTable, key, PL_DHASH_ADD); |
|
439 if (!entry) |
|
440 return nullptr; |
|
441 if (entry->key_value) |
|
442 return entry->key_value; |
|
443 entry->key_value = set; |
|
444 return set; |
|
445 } |
|
446 |
|
447 inline XPCNativeSet* Add(XPCNativeSet* set) |
|
448 { |
|
449 XPCNativeSetKey key(set, nullptr, 0); |
|
450 return Add(&key, set); |
|
451 } |
|
452 |
|
453 inline void Remove(XPCNativeSet* set) |
|
454 { |
|
455 NS_PRECONDITION(set,"bad param"); |
|
456 |
|
457 XPCNativeSetKey key(set, nullptr, 0); |
|
458 PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE); |
|
459 } |
|
460 |
|
461 inline uint32_t Count() {return mTable->entryCount;} |
|
462 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
463 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
464 |
|
465 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); |
|
466 |
|
467 ~NativeSetMap(); |
|
468 private: |
|
469 NativeSetMap(); // no implementation |
|
470 NativeSetMap(int size); |
|
471 |
|
472 static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr *hdr, mozilla::MallocSizeOf mallocSizeOf, void *); |
|
473 |
|
474 private: |
|
475 PLDHashTable *mTable; |
|
476 }; |
|
477 |
|
478 /***************************************************************************/ |
|
479 |
|
480 class IID2ThisTranslatorMap |
|
481 { |
|
482 public: |
|
483 struct Entry : public PLDHashEntryHdr |
|
484 { |
|
485 nsIID key; |
|
486 nsCOMPtr<nsIXPCFunctionThisTranslator> value; |
|
487 |
|
488 static bool |
|
489 Match(PLDHashTable *table, |
|
490 const PLDHashEntryHdr *entry, |
|
491 const void *key); |
|
492 |
|
493 static void |
|
494 Clear(PLDHashTable *table, PLDHashEntryHdr *entry); |
|
495 |
|
496 static const struct PLDHashTableOps sOps; |
|
497 }; |
|
498 |
|
499 static IID2ThisTranslatorMap* newMap(int size); |
|
500 |
|
501 inline nsIXPCFunctionThisTranslator* Find(REFNSIID iid) |
|
502 { |
|
503 Entry* entry = (Entry*) |
|
504 PL_DHashTableOperate(mTable, &iid, PL_DHASH_LOOKUP); |
|
505 if (PL_DHASH_ENTRY_IS_FREE(entry)) |
|
506 return nullptr; |
|
507 return entry->value; |
|
508 } |
|
509 |
|
510 inline nsIXPCFunctionThisTranslator* Add(REFNSIID iid, |
|
511 nsIXPCFunctionThisTranslator* obj) |
|
512 { |
|
513 |
|
514 Entry* entry = (Entry*) |
|
515 PL_DHashTableOperate(mTable, &iid, PL_DHASH_ADD); |
|
516 if (!entry) |
|
517 return nullptr; |
|
518 entry->value = obj; |
|
519 entry->key = iid; |
|
520 return obj; |
|
521 } |
|
522 |
|
523 inline void Remove(REFNSIID iid) |
|
524 { |
|
525 PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE); |
|
526 } |
|
527 |
|
528 inline uint32_t Count() {return mTable->entryCount;} |
|
529 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
530 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
531 |
|
532 ~IID2ThisTranslatorMap(); |
|
533 private: |
|
534 IID2ThisTranslatorMap(); // no implementation |
|
535 IID2ThisTranslatorMap(int size); |
|
536 private: |
|
537 PLDHashTable *mTable; |
|
538 }; |
|
539 |
|
540 /***************************************************************************/ |
|
541 |
|
542 class XPCNativeScriptableSharedMap |
|
543 { |
|
544 public: |
|
545 struct Entry : public PLDHashEntryHdr |
|
546 { |
|
547 XPCNativeScriptableShared* key; |
|
548 |
|
549 static PLDHashNumber |
|
550 Hash(PLDHashTable *table, const void *key); |
|
551 |
|
552 static bool |
|
553 Match(PLDHashTable *table, |
|
554 const PLDHashEntryHdr *entry, |
|
555 const void *key); |
|
556 |
|
557 static const struct PLDHashTableOps sOps; |
|
558 }; |
|
559 |
|
560 static XPCNativeScriptableSharedMap* newMap(int size); |
|
561 |
|
562 bool GetNewOrUsed(uint32_t flags, char* name, uint32_t interfacesBitmap, |
|
563 XPCNativeScriptableInfo* si); |
|
564 |
|
565 inline uint32_t Count() {return mTable->entryCount;} |
|
566 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
567 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
568 |
|
569 ~XPCNativeScriptableSharedMap(); |
|
570 private: |
|
571 XPCNativeScriptableSharedMap(); // no implementation |
|
572 XPCNativeScriptableSharedMap(int size); |
|
573 private: |
|
574 PLDHashTable *mTable; |
|
575 }; |
|
576 |
|
577 /***************************************************************************/ |
|
578 |
|
579 class XPCWrappedNativeProtoMap |
|
580 { |
|
581 public: |
|
582 static XPCWrappedNativeProtoMap* newMap(int size); |
|
583 |
|
584 inline XPCWrappedNativeProto* Add(XPCWrappedNativeProto* proto) |
|
585 { |
|
586 NS_PRECONDITION(proto,"bad param"); |
|
587 PLDHashEntryStub* entry = (PLDHashEntryStub*) |
|
588 PL_DHashTableOperate(mTable, proto, PL_DHASH_ADD); |
|
589 if (!entry) |
|
590 return nullptr; |
|
591 if (entry->key) |
|
592 return (XPCWrappedNativeProto*) entry->key; |
|
593 entry->key = proto; |
|
594 return proto; |
|
595 } |
|
596 |
|
597 inline void Remove(XPCWrappedNativeProto* proto) |
|
598 { |
|
599 NS_PRECONDITION(proto,"bad param"); |
|
600 PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE); |
|
601 } |
|
602 |
|
603 inline uint32_t Count() {return mTable->entryCount;} |
|
604 inline uint32_t Enumerate(PLDHashEnumerator f, void *arg) |
|
605 {return PL_DHashTableEnumerate(mTable, f, arg);} |
|
606 |
|
607 ~XPCWrappedNativeProtoMap(); |
|
608 private: |
|
609 XPCWrappedNativeProtoMap(); // no implementation |
|
610 XPCWrappedNativeProtoMap(int size); |
|
611 private: |
|
612 PLDHashTable *mTable; |
|
613 }; |
|
614 |
|
615 /***************************************************************************/ |
|
616 |
|
617 class JSObject2JSObjectMap |
|
618 { |
|
619 typedef js::HashMap<JSObject *, JS::Heap<JSObject *>, js::PointerHasher<JSObject *, 3>, |
|
620 js::SystemAllocPolicy> Map; |
|
621 |
|
622 public: |
|
623 static JSObject2JSObjectMap* newMap(int size) { |
|
624 JSObject2JSObjectMap* map = new JSObject2JSObjectMap(); |
|
625 if (map && map->mTable.init(size)) |
|
626 return map; |
|
627 delete map; |
|
628 return nullptr; |
|
629 } |
|
630 |
|
631 inline JSObject* Find(JSObject* key) { |
|
632 NS_PRECONDITION(key, "bad param"); |
|
633 if (Map::Ptr p = mTable.lookup(key)) |
|
634 return p->value(); |
|
635 return nullptr; |
|
636 } |
|
637 |
|
638 /* Note: If the entry already exists, return the old value. */ |
|
639 inline JSObject* Add(JSContext *cx, JSObject *key, JSObject *value) { |
|
640 NS_PRECONDITION(key,"bad param"); |
|
641 Map::AddPtr p = mTable.lookupForAdd(key); |
|
642 if (p) |
|
643 return p->value(); |
|
644 if (!mTable.add(p, key, value)) |
|
645 return nullptr; |
|
646 MOZ_ASSERT(xpc::GetCompartmentPrivate(key)->scope->mWaiverWrapperMap == this); |
|
647 JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this); |
|
648 return value; |
|
649 } |
|
650 |
|
651 inline void Remove(JSObject* key) { |
|
652 NS_PRECONDITION(key,"bad param"); |
|
653 mTable.remove(key); |
|
654 } |
|
655 |
|
656 inline uint32_t Count() { return mTable.count(); } |
|
657 |
|
658 void Sweep() { |
|
659 for (Map::Enum e(mTable); !e.empty(); e.popFront()) { |
|
660 JSObject *updated = e.front().key(); |
|
661 if (JS_IsAboutToBeFinalizedUnbarriered(&updated) || JS_IsAboutToBeFinalized(&e.front().value())) |
|
662 e.removeFront(); |
|
663 else if (updated != e.front().key()) |
|
664 e.rekeyFront(updated); |
|
665 } |
|
666 } |
|
667 |
|
668 void Reparent(JSContext *aCx, JSObject *aNewInnerArg) { |
|
669 JS::RootedObject aNewInner(aCx, aNewInnerArg); |
|
670 for (Map::Enum e(mTable); !e.empty(); e.popFront()) { |
|
671 /* |
|
672 * We reparent wrappers that have as their parent an inner window |
|
673 * whose outer has the new inner window as its current inner. |
|
674 */ |
|
675 JS::RootedObject wrapper(aCx, e.front().value()); |
|
676 JS::RootedObject parent(aCx, JS_GetParent(wrapper)); |
|
677 JS::RootedObject outer(aCx, JS_ObjectToOuterObject(aCx, parent)); |
|
678 if (outer) { |
|
679 JSObject *inner = JS_ObjectToInnerObject(aCx, outer); |
|
680 if (inner == aNewInner && inner != parent) |
|
681 JS_SetParent(aCx, wrapper, aNewInner); |
|
682 } else { |
|
683 JS_ClearPendingException(aCx); |
|
684 } |
|
685 } |
|
686 } |
|
687 |
|
688 private: |
|
689 JSObject2JSObjectMap() {} |
|
690 |
|
691 /* |
|
692 * This function is called during minor GCs for each key in the HashMap that |
|
693 * has been moved. |
|
694 */ |
|
695 static void KeyMarkCallback(JSTracer *trc, JSObject *key, void *data) { |
|
696 /* |
|
697 * To stop the barriers on the values of mTable firing while we are |
|
698 * marking the store buffer, we cast the table to one that is |
|
699 * binary-equivatlent but without the barriers, and update that. |
|
700 */ |
|
701 typedef js::HashMap<JSObject *, JSObject *, js::PointerHasher<JSObject *, 3>, |
|
702 js::SystemAllocPolicy> UnbarrieredMap; |
|
703 JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(data); |
|
704 UnbarrieredMap &table = reinterpret_cast<UnbarrieredMap &>(self->mTable); |
|
705 |
|
706 JSObject *prior = key; |
|
707 JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key"); |
|
708 table.rekeyIfMoved(prior, key); |
|
709 } |
|
710 |
|
711 Map mTable; |
|
712 }; |
|
713 |
|
714 #endif /* xpcmaps_h___ */ |