1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code, released
17 : * March 31, 1998.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Netscape Communications Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 1998
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * John Bandhauer <jband@netscape.com> (original author)
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : /* Private maps (hashtables). */
42 :
43 : #include "xpcprivate.h"
44 :
45 : #include "jshash.h"
46 :
47 : /***************************************************************************/
48 : // static shared...
49 :
50 : // Note this is returning the bit pattern of the first part of the nsID, not
51 : // the pointer to the nsID.
52 :
53 : static JSDHashNumber
54 2916826 : HashIIDPtrKey(JSDHashTable *table, const void *key)
55 : {
56 2916826 : return *((JSHashNumber*)key);
57 : }
58 :
59 : static JSBool
60 2522439 : MatchIIDPtrKey(JSDHashTable *table,
61 : const JSDHashEntryHdr *entry,
62 : const void *key)
63 : {
64 : return ((const nsID*)key)->
65 2522439 : Equals(*((const nsID*)((JSDHashEntryStub*)entry)->key));
66 : }
67 :
68 : static JSDHashNumber
69 1281696 : HashNativeKey(JSDHashTable *table, const void *key)
70 : {
71 1281696 : XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
72 :
73 1281696 : JSDHashNumber h = 0;
74 :
75 : XPCNativeSet* Set;
76 : XPCNativeInterface* Addition;
77 : PRUint16 Position;
78 :
79 1281696 : if (Key->IsAKey()) {
80 1281696 : Set = Key->GetBaseSet();
81 1281696 : Addition = Key->GetAddition();
82 1281696 : Position = Key->GetPosition();
83 : } else {
84 0 : Set = (XPCNativeSet*) Key;
85 0 : Addition = nsnull;
86 0 : Position = 0;
87 : }
88 :
89 1281696 : if (!Set) {
90 989461 : NS_ASSERTION(Addition, "bad key");
91 : // This would be an XOR like below.
92 : // But "0 ^ x == x". So it does not matter.
93 989461 : h = (JSHashNumber) NS_PTR_TO_INT32(Addition) >> 2;
94 : } else {
95 292235 : XPCNativeInterface** Current = Set->GetInterfaceArray();
96 292235 : PRUint16 count = Set->GetInterfaceCount();
97 292235 : if (Addition) {
98 188077 : count++;
99 697875 : for (PRUint16 i = 0; i < count; i++) {
100 509798 : if (i == Position)
101 188077 : h ^= (JSHashNumber) NS_PTR_TO_INT32(Addition) >> 2;
102 : else
103 321721 : h ^= (JSHashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
104 : }
105 : } else {
106 420680 : for (PRUint16 i = 0; i < count; i++)
107 316522 : h ^= (JSHashNumber) NS_PTR_TO_INT32(*(Current++)) >> 2;
108 : }
109 : }
110 :
111 1281696 : return h;
112 : }
113 :
114 : /***************************************************************************/
115 : // implement JSObject2WrappedJSMap...
116 :
117 : // static
118 : JSObject2WrappedJSMap*
119 1404 : JSObject2WrappedJSMap::newMap(int size)
120 : {
121 1404 : JSObject2WrappedJSMap* map = new JSObject2WrappedJSMap(size);
122 1404 : if (map && map->mTable)
123 1404 : return map;
124 0 : delete map;
125 0 : return nsnull;
126 : }
127 :
128 1404 : JSObject2WrappedJSMap::JSObject2WrappedJSMap(int size)
129 : {
130 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
131 1404 : sizeof(Entry), size);
132 1404 : }
133 :
134 1403 : JSObject2WrappedJSMap::~JSObject2WrappedJSMap()
135 : {
136 1403 : if (mTable)
137 1403 : JS_DHashTableDestroy(mTable);
138 1403 : }
139 :
140 : size_t
141 3 : JSObject2WrappedJSMap::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
142 : {
143 3 : size_t n = 0;
144 3 : n += mallocSizeOf(this);
145 3 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
146 3 : return n;
147 : }
148 :
149 : /* static */ size_t
150 81 : JSObject2WrappedJSMap::SizeOfEntryExcludingThis(JSDHashEntryHdr *hdr,
151 : JSMallocSizeOfFun mallocSizeOf, void *)
152 : {
153 81 : return mallocSizeOf(((JSObject2WrappedJSMap::Entry*)hdr)->value);
154 : }
155 :
156 : /***************************************************************************/
157 : // implement Native2WrappedNativeMap...
158 :
159 : // static
160 : Native2WrappedNativeMap*
161 15475 : Native2WrappedNativeMap::newMap(int size)
162 : {
163 15475 : Native2WrappedNativeMap* map = new Native2WrappedNativeMap(size);
164 15475 : if (map && map->mTable)
165 15475 : return map;
166 0 : delete map;
167 0 : return nsnull;
168 : }
169 :
170 15475 : Native2WrappedNativeMap::Native2WrappedNativeMap(int size)
171 : {
172 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
173 15475 : sizeof(Entry), size);
174 15475 : }
175 :
176 15471 : Native2WrappedNativeMap::~Native2WrappedNativeMap()
177 : {
178 15471 : if (mTable)
179 15471 : JS_DHashTableDestroy(mTable);
180 15471 : }
181 :
182 : size_t
183 59 : Native2WrappedNativeMap::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
184 : {
185 59 : size_t n = 0;
186 59 : n += mallocSizeOf(this);
187 59 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
188 59 : return n;
189 : }
190 :
191 : /* static */ size_t
192 1865 : Native2WrappedNativeMap::SizeOfEntryExcludingThis(JSDHashEntryHdr *hdr,
193 : JSMallocSizeOfFun mallocSizeOf, void *)
194 : {
195 1865 : return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value);
196 : }
197 :
198 : /***************************************************************************/
199 : // implement IID2WrappedJSClassMap...
200 :
201 : struct JSDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
202 : {
203 : JS_DHashAllocTable,
204 : JS_DHashFreeTable,
205 : HashIIDPtrKey,
206 : MatchIIDPtrKey,
207 : JS_DHashMoveEntryStub,
208 : JS_DHashClearEntryStub,
209 : JS_DHashFinalizeStub
210 : };
211 :
212 : // static
213 : IID2WrappedJSClassMap*
214 1404 : IID2WrappedJSClassMap::newMap(int size)
215 : {
216 1404 : IID2WrappedJSClassMap* map = new IID2WrappedJSClassMap(size);
217 1404 : if (map && map->mTable)
218 1404 : return map;
219 0 : delete map;
220 0 : return nsnull;
221 : }
222 :
223 1404 : IID2WrappedJSClassMap::IID2WrappedJSClassMap(int size)
224 : {
225 1404 : mTable = JS_NewDHashTable(&Entry::sOps, nsnull, sizeof(Entry), size);
226 1404 : }
227 :
228 1403 : IID2WrappedJSClassMap::~IID2WrappedJSClassMap()
229 : {
230 1403 : if (mTable)
231 1403 : JS_DHashTableDestroy(mTable);
232 1403 : }
233 :
234 :
235 : /***************************************************************************/
236 : // implement IID2NativeInterfaceMap...
237 :
238 : struct JSDHashTableOps IID2NativeInterfaceMap::Entry::sOps =
239 : {
240 : JS_DHashAllocTable,
241 : JS_DHashFreeTable,
242 : HashIIDPtrKey,
243 : MatchIIDPtrKey,
244 : JS_DHashMoveEntryStub,
245 : JS_DHashClearEntryStub,
246 : JS_DHashFinalizeStub
247 : };
248 :
249 : // static
250 : IID2NativeInterfaceMap*
251 1404 : IID2NativeInterfaceMap::newMap(int size)
252 : {
253 1404 : IID2NativeInterfaceMap* map = new IID2NativeInterfaceMap(size);
254 1404 : if (map && map->mTable)
255 1404 : return map;
256 0 : delete map;
257 0 : return nsnull;
258 : }
259 :
260 1404 : IID2NativeInterfaceMap::IID2NativeInterfaceMap(int size)
261 : {
262 1404 : mTable = JS_NewDHashTable(&Entry::sOps, nsnull, sizeof(Entry), size);
263 1404 : }
264 :
265 1403 : IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
266 : {
267 1403 : if (mTable)
268 1403 : JS_DHashTableDestroy(mTable);
269 1403 : }
270 :
271 : size_t
272 3 : IID2NativeInterfaceMap::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
273 : {
274 3 : size_t n = 0;
275 3 : n += mallocSizeOf(this);
276 3 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
277 3 : return n;
278 : }
279 :
280 : /* static */ size_t
281 303 : IID2NativeInterfaceMap::SizeOfEntryExcludingThis(JSDHashEntryHdr *hdr,
282 : JSMallocSizeOfFun mallocSizeOf, void *)
283 : {
284 303 : XPCNativeInterface *iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value;
285 303 : return iface->SizeOfIncludingThis(mallocSizeOf);
286 : }
287 :
288 : /***************************************************************************/
289 : // implement ClassInfo2NativeSetMap...
290 :
291 : // static
292 : ClassInfo2NativeSetMap*
293 1404 : ClassInfo2NativeSetMap::newMap(int size)
294 : {
295 1404 : ClassInfo2NativeSetMap* map = new ClassInfo2NativeSetMap(size);
296 1404 : if (map && map->mTable)
297 1404 : return map;
298 0 : delete map;
299 0 : return nsnull;
300 : }
301 :
302 1404 : ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int size)
303 : {
304 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
305 1404 : sizeof(Entry), size);
306 1404 : }
307 :
308 1403 : ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
309 : {
310 1403 : if (mTable)
311 1403 : JS_DHashTableDestroy(mTable);
312 1403 : }
313 :
314 : size_t
315 3 : ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
316 : {
317 3 : size_t n = 0;
318 3 : n += mallocSizeOf(this);
319 : // The second arg is NULL because this is a "shallow" measurement of the map.
320 3 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, NULL, mallocSizeOf) : 0;
321 3 : return n;
322 : }
323 :
324 : /***************************************************************************/
325 : // implement ClassInfo2WrappedNativeProtoMap...
326 :
327 : // static
328 : ClassInfo2WrappedNativeProtoMap*
329 30950 : ClassInfo2WrappedNativeProtoMap::newMap(int size)
330 : {
331 30950 : ClassInfo2WrappedNativeProtoMap* map = new ClassInfo2WrappedNativeProtoMap(size);
332 30950 : if (map && map->mTable)
333 30950 : return map;
334 0 : delete map;
335 0 : return nsnull;
336 : }
337 :
338 30950 : ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int size)
339 : {
340 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
341 30950 : sizeof(Entry), size);
342 30950 : }
343 :
344 30942 : ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
345 : {
346 30942 : if (mTable)
347 30942 : JS_DHashTableDestroy(mTable);
348 30942 : }
349 :
350 : size_t
351 118 : ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
352 : {
353 118 : size_t n = 0;
354 118 : n += mallocSizeOf(this);
355 118 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
356 118 : return n;
357 : }
358 :
359 : /* static */ size_t
360 469 : ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(JSDHashEntryHdr *hdr,
361 : JSMallocSizeOfFun mallocSizeOf, void *)
362 : {
363 469 : return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value);
364 : }
365 :
366 : /***************************************************************************/
367 : // implement NativeSetMap...
368 :
369 : JSBool
370 1090654 : NativeSetMap::Entry::Match(JSDHashTable *table,
371 : const JSDHashEntryHdr *entry,
372 : const void *key)
373 : {
374 1090654 : XPCNativeSetKey* Key = (XPCNativeSetKey*) key;
375 :
376 : // See the comment in the XPCNativeSetKey declaration in xpcprivate.h.
377 1090654 : if (!Key->IsAKey()) {
378 0 : XPCNativeSet* Set1 = (XPCNativeSet*) key;
379 0 : XPCNativeSet* Set2 = ((Entry*)entry)->key_value;
380 :
381 0 : if (Set1 == Set2)
382 0 : return true;
383 :
384 0 : PRUint16 count = Set1->GetInterfaceCount();
385 0 : if (count != Set2->GetInterfaceCount())
386 0 : return false;
387 :
388 0 : XPCNativeInterface** Current1 = Set1->GetInterfaceArray();
389 0 : XPCNativeInterface** Current2 = Set2->GetInterfaceArray();
390 0 : for (PRUint16 i = 0; i < count; i++) {
391 0 : if (*(Current1++) != *(Current2++))
392 0 : return false;
393 : }
394 :
395 0 : return true;
396 : }
397 :
398 1090654 : XPCNativeSet* SetInTable = ((Entry*)entry)->key_value;
399 1090654 : XPCNativeSet* Set = Key->GetBaseSet();
400 1090654 : XPCNativeInterface* Addition = Key->GetAddition();
401 :
402 1090654 : if (!Set) {
403 : // This is a special case to deal with the invariant that says:
404 : // "All sets have exactly one nsISupports interface and it comes first."
405 : // See XPCNativeSet::NewInstance for details.
406 : //
407 : // Though we might have a key that represents only one interface, we
408 : // know that if that one interface were contructed into a set then
409 : // it would end up really being a set with two interfaces (except for
410 : // the case where the one interface happened to be nsISupports).
411 :
412 864487 : return ((SetInTable->GetInterfaceCount() == 1 &&
413 69545 : SetInTable->GetInterfaceAt(0) == Addition) ||
414 794942 : (SetInTable->GetInterfaceCount() == 2 &&
415 1728974 : SetInTable->GetInterfaceAt(1) == Addition));
416 : }
417 :
418 226167 : if (!Addition && Set == SetInTable)
419 0 : return true;
420 :
421 226167 : PRUint16 count = Set->GetInterfaceCount() + (Addition ? 1 : 0);
422 226167 : if (count != SetInTable->GetInterfaceCount())
423 1 : return false;
424 :
425 226166 : PRUint16 Position = Key->GetPosition();
426 226166 : XPCNativeInterface** CurrentInTable = SetInTable->GetInterfaceArray();
427 226166 : XPCNativeInterface** Current = Set->GetInterfaceArray();
428 824202 : for (PRUint16 i = 0; i < count; i++) {
429 610374 : if (Addition && i == Position) {
430 273630 : if (Addition != *(CurrentInTable++))
431 0 : return false;
432 : } else {
433 473559 : if (*(Current++) != *(CurrentInTable++))
434 12338 : return false;
435 : }
436 : }
437 :
438 213828 : return true;
439 : }
440 :
441 : struct JSDHashTableOps NativeSetMap::Entry::sOps =
442 : {
443 : JS_DHashAllocTable,
444 : JS_DHashFreeTable,
445 : HashNativeKey,
446 : Match,
447 : JS_DHashMoveEntryStub,
448 : JS_DHashClearEntryStub,
449 : JS_DHashFinalizeStub
450 : };
451 :
452 : // static
453 : NativeSetMap*
454 1404 : NativeSetMap::newMap(int size)
455 : {
456 1404 : NativeSetMap* map = new NativeSetMap(size);
457 1404 : if (map && map->mTable)
458 1404 : return map;
459 0 : delete map;
460 0 : return nsnull;
461 : }
462 :
463 1404 : NativeSetMap::NativeSetMap(int size)
464 : {
465 1404 : mTable = JS_NewDHashTable(&Entry::sOps, nsnull, sizeof(Entry), size);
466 1404 : }
467 :
468 1403 : NativeSetMap::~NativeSetMap()
469 : {
470 1403 : if (mTable)
471 1403 : JS_DHashTableDestroy(mTable);
472 1403 : }
473 :
474 : size_t
475 3 : NativeSetMap::SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf)
476 : {
477 3 : size_t n = 0;
478 3 : n += mallocSizeOf(this);
479 3 : n += mTable ? JS_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf) : 0;
480 3 : return n;
481 : }
482 :
483 : /* static */ size_t
484 284 : NativeSetMap::SizeOfEntryExcludingThis(JSDHashEntryHdr *hdr, JSMallocSizeOfFun mallocSizeOf, void *)
485 : {
486 284 : XPCNativeSet *set = ((NativeSetMap::Entry*)hdr)->key_value;
487 284 : return set->SizeOfIncludingThis(mallocSizeOf);
488 : }
489 :
490 : /***************************************************************************/
491 : // implement IID2ThisTranslatorMap...
492 :
493 : JSBool
494 3965 : IID2ThisTranslatorMap::Entry::Match(JSDHashTable *table,
495 : const JSDHashEntryHdr *entry,
496 : const void *key)
497 : {
498 3965 : return ((const nsID*)key)->Equals(((Entry*)entry)->key);
499 : }
500 :
501 : void
502 305 : IID2ThisTranslatorMap::Entry::Clear(JSDHashTable *table, JSDHashEntryHdr *entry)
503 : {
504 305 : NS_IF_RELEASE(((Entry*)entry)->value);
505 305 : memset(entry, 0, table->entrySize);
506 305 : }
507 :
508 : struct JSDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
509 : {
510 : JS_DHashAllocTable,
511 : JS_DHashFreeTable,
512 : HashIIDPtrKey,
513 : Match,
514 : JS_DHashMoveEntryStub,
515 : Clear,
516 : JS_DHashFinalizeStub
517 : };
518 :
519 : // static
520 : IID2ThisTranslatorMap*
521 1404 : IID2ThisTranslatorMap::newMap(int size)
522 : {
523 1404 : IID2ThisTranslatorMap* map = new IID2ThisTranslatorMap(size);
524 1404 : if (map && map->mTable)
525 1404 : return map;
526 0 : delete map;
527 0 : return nsnull;
528 : }
529 :
530 1404 : IID2ThisTranslatorMap::IID2ThisTranslatorMap(int size)
531 : {
532 1404 : mTable = JS_NewDHashTable(&Entry::sOps, nsnull, sizeof(Entry), size);
533 1404 : }
534 :
535 1403 : IID2ThisTranslatorMap::~IID2ThisTranslatorMap()
536 : {
537 1403 : if (mTable)
538 1403 : JS_DHashTableDestroy(mTable);
539 1403 : }
540 :
541 : /***************************************************************************/
542 :
543 : JSDHashNumber
544 249788 : XPCNativeScriptableSharedMap::Entry::Hash(JSDHashTable *table, const void *key)
545 : {
546 : JSDHashNumber h;
547 : const unsigned char *s;
548 :
549 : XPCNativeScriptableShared* obj =
550 249788 : (XPCNativeScriptableShared*) key;
551 :
552 : // hash together the flags and the classname string, ignore the interfaces
553 : // bitmap since it's very rare that it's different when flags and classname
554 : // are the same.
555 :
556 249788 : h = (JSDHashNumber) obj->GetFlags();
557 3208185 : for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++)
558 2958397 : h = JS_ROTATE_LEFT32(h, 4) ^ *s;
559 249788 : return h;
560 : }
561 :
562 : JSBool
563 228557 : XPCNativeScriptableSharedMap::Entry::Match(JSDHashTable *table,
564 : const JSDHashEntryHdr *entry,
565 : const void *key)
566 : {
567 : XPCNativeScriptableShared* obj1 =
568 228557 : ((XPCNativeScriptableSharedMap::Entry*) entry)->key;
569 :
570 : XPCNativeScriptableShared* obj2 =
571 228557 : (XPCNativeScriptableShared*) key;
572 :
573 : // match the flags, the classname string and the interfaces bitmap
574 :
575 457114 : if (obj1->GetFlags() != obj2->GetFlags() ||
576 228557 : obj1->GetInterfacesBitmap() != obj2->GetInterfacesBitmap())
577 0 : return false;
578 :
579 228557 : const char* name1 = obj1->GetJSClass()->name;
580 228557 : const char* name2 = obj2->GetJSClass()->name;
581 :
582 228557 : if (!name1 || !name2)
583 0 : return name1 == name2;
584 :
585 228557 : return 0 == strcmp(name1, name2);
586 : }
587 :
588 : struct JSDHashTableOps XPCNativeScriptableSharedMap::Entry::sOps =
589 : {
590 : JS_DHashAllocTable,
591 : JS_DHashFreeTable,
592 : Hash,
593 : Match,
594 : JS_DHashMoveEntryStub,
595 : JS_DHashClearEntryStub,
596 : JS_DHashFinalizeStub
597 : };
598 :
599 : // static
600 : XPCNativeScriptableSharedMap*
601 1404 : XPCNativeScriptableSharedMap::newMap(int size)
602 : {
603 : XPCNativeScriptableSharedMap* map =
604 1404 : new XPCNativeScriptableSharedMap(size);
605 1404 : if (map && map->mTable)
606 1404 : return map;
607 0 : delete map;
608 0 : return nsnull;
609 : }
610 :
611 1404 : XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int size)
612 : {
613 1404 : mTable = JS_NewDHashTable(&Entry::sOps, nsnull, sizeof(Entry), size);
614 1404 : }
615 :
616 1403 : XPCNativeScriptableSharedMap::~XPCNativeScriptableSharedMap()
617 : {
618 1403 : if (mTable)
619 1403 : JS_DHashTableDestroy(mTable);
620 1403 : }
621 :
622 : JSBool
623 249788 : XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags,
624 : char* name,
625 : PRUint32 interfacesBitmap,
626 : XPCNativeScriptableInfo* si)
627 : {
628 249788 : NS_PRECONDITION(name,"bad param");
629 249788 : NS_PRECONDITION(si,"bad param");
630 :
631 499576 : XPCNativeScriptableShared key(flags, name, interfacesBitmap);
632 : Entry* entry = (Entry*)
633 249788 : JS_DHashTableOperate(mTable, &key, JS_DHASH_ADD);
634 249788 : if (!entry)
635 0 : return false;
636 :
637 249788 : XPCNativeScriptableShared* shared = entry->key;
638 :
639 249788 : if (!shared) {
640 : entry->key = shared =
641 : new XPCNativeScriptableShared(flags, key.TransferNameOwnership(),
642 42462 : interfacesBitmap);
643 21231 : if (!shared)
644 0 : return false;
645 21231 : shared->PopulateJSClass();
646 : }
647 249788 : si->SetScriptableShared(shared);
648 249788 : return true;
649 : }
650 :
651 : /***************************************************************************/
652 : // implement XPCWrappedNativeProtoMap...
653 :
654 : // static
655 : XPCWrappedNativeProtoMap*
656 2808 : XPCWrappedNativeProtoMap::newMap(int size)
657 : {
658 2808 : XPCWrappedNativeProtoMap* map = new XPCWrappedNativeProtoMap(size);
659 2808 : if (map && map->mTable)
660 2808 : return map;
661 0 : delete map;
662 0 : return nsnull;
663 : }
664 :
665 2808 : XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int size)
666 : {
667 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
668 2808 : sizeof(JSDHashEntryStub), size);
669 2808 : }
670 :
671 2806 : XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()
672 : {
673 2806 : if (mTable)
674 2806 : JS_DHashTableDestroy(mTable);
675 2806 : }
676 :
677 : /***************************************************************************/
678 : // implement XPCNativeWrapperMap...
679 :
680 : // static
681 : XPCNativeWrapperMap*
682 1404 : XPCNativeWrapperMap::newMap(int size)
683 : {
684 1404 : XPCNativeWrapperMap* map = new XPCNativeWrapperMap(size);
685 1404 : if (map && map->mTable)
686 1404 : return map;
687 0 : delete map;
688 0 : return nsnull;
689 : }
690 :
691 1404 : XPCNativeWrapperMap::XPCNativeWrapperMap(int size)
692 : {
693 : mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
694 1404 : sizeof(JSDHashEntryStub), size);
695 1404 : }
696 :
697 1403 : XPCNativeWrapperMap::~XPCNativeWrapperMap()
698 : {
699 1403 : if (mTable)
700 1403 : JS_DHashTableDestroy(mTable);
701 1403 : }
702 :
703 : /***************************************************************************/
704 : // implement WrappedNative2WrapperMap...
705 :
706 : struct JSDHashTableOps
707 : WrappedNative2WrapperMap::sOps = {
708 : JS_DHashAllocTable,
709 : JS_DHashFreeTable,
710 : JS_DHashVoidPtrKeyStub,
711 : JS_DHashMatchEntryStub,
712 : MoveLink,
713 : ClearLink,
714 : JS_DHashFinalizeStub,
715 : nsnull
716 : };
717 :
718 : // static
719 : void
720 0 : WrappedNative2WrapperMap::ClearLink(JSDHashTable* table,
721 : JSDHashEntryHdr* entry)
722 : {
723 0 : Entry* e = static_cast<Entry*>(entry);
724 0 : e->key = nsnull;
725 0 : PR_REMOVE_LINK(&e->value);
726 0 : memset(e, 0, sizeof(*e));
727 0 : }
728 :
729 : // static
730 : void
731 0 : WrappedNative2WrapperMap::MoveLink(JSDHashTable* table,
732 : const JSDHashEntryHdr* from,
733 : JSDHashEntryHdr* to)
734 : {
735 0 : const Entry* oldEntry = static_cast<const Entry*>(from);
736 0 : Entry* newEntry = static_cast<Entry*>(to);
737 :
738 0 : newEntry->key = oldEntry->key;
739 :
740 : // Now update the list.
741 0 : if (PR_CLIST_IS_EMPTY(&oldEntry->value)) {
742 0 : PR_INIT_CLIST(&newEntry->value);
743 0 : newEntry->value.obj = oldEntry->value.obj;
744 : } else {
745 0 : newEntry->value = oldEntry->value;
746 0 : newEntry->value.next->prev = &newEntry->value;
747 0 : newEntry->value.prev->next = &newEntry->value;
748 : }
749 0 : }
750 :
751 : // static
752 : WrappedNative2WrapperMap*
753 0 : WrappedNative2WrapperMap::newMap(int size)
754 : {
755 0 : WrappedNative2WrapperMap* map = new WrappedNative2WrapperMap(size);
756 0 : if (map && map->mTable)
757 0 : return map;
758 0 : delete map;
759 0 : return nsnull;
760 : }
761 :
762 0 : WrappedNative2WrapperMap::WrappedNative2WrapperMap(int size)
763 : {
764 0 : mTable = JS_NewDHashTable(&sOps, nsnull, sizeof(Entry), size);
765 0 : }
766 :
767 0 : WrappedNative2WrapperMap::~WrappedNative2WrapperMap()
768 : {
769 0 : if (mTable)
770 0 : JS_DHashTableDestroy(mTable);
771 0 : }
772 :
773 : JSObject*
774 0 : WrappedNative2WrapperMap::Add(WrappedNative2WrapperMap* head,
775 : JSObject* wrappedObject,
776 : JSObject* wrapper)
777 : {
778 0 : NS_PRECONDITION(wrappedObject,"bad param");
779 : Entry* entry = (Entry*)
780 0 : JS_DHashTableOperate(mTable, wrappedObject, JS_DHASH_ADD);
781 0 : if (!entry)
782 0 : return nsnull;
783 0 : NS_ASSERTION(!entry->key || this == head, "dangling pointer?");
784 0 : entry->key = wrappedObject;
785 0 : Link* l = &entry->value;
786 :
787 0 : NS_ASSERTION(!l->obj, "Uh, how'd this happen?");
788 :
789 0 : if (!l->next) {
790 : // Initialize the circular list. This case only happens when
791 : // this == head.
792 0 : PR_INIT_CLIST(l);
793 : }
794 :
795 0 : l->obj = wrapper;
796 :
797 0 : if (this != head) {
798 0 : Link* headLink = head->FindLink(wrappedObject);
799 0 : if (!headLink) {
800 : Entry* dummy = (Entry*)
801 0 : JS_DHashTableOperate(head->mTable, wrappedObject, JS_DHASH_ADD);
802 0 : dummy->key = wrappedObject;
803 0 : headLink = &dummy->value;
804 0 : PR_INIT_CLIST(headLink);
805 0 : headLink->obj = nsnull;
806 : }
807 :
808 0 : PR_INSERT_BEFORE(l, headLink);
809 : }
810 :
811 0 : return wrapper;
812 : }
813 :
814 : bool
815 0 : WrappedNative2WrapperMap::AddLink(JSObject* wrappedObject, Link* oldLink)
816 : {
817 : Entry* entry = (Entry*)
818 0 : JS_DHashTableOperate(mTable, wrappedObject, JS_DHASH_ADD);
819 0 : if (!entry)
820 0 : return false;
821 0 : NS_ASSERTION(!entry->key, "Eh? What's happening?");
822 0 : entry->key = wrappedObject;
823 0 : Link* newLink = &entry->value;
824 :
825 0 : PR_INSERT_LINK(newLink, oldLink);
826 0 : PR_REMOVE_AND_INIT_LINK(oldLink);
827 0 : newLink->obj = oldLink->obj;
828 :
829 0 : return true;
830 : }
831 :
832 : /***************************************************************************/
833 : // implement JSObject2JSObjectMap...
834 :
835 : struct JSDHashTableOps
836 : JSObject2JSObjectMap::sOps = {
837 : JS_DHashAllocTable,
838 : JS_DHashFreeTable,
839 : JS_DHashVoidPtrKeyStub,
840 : JS_DHashMatchEntryStub,
841 : JS_DHashMoveEntryStub,
842 : JS_DHashClearEntryStub,
843 : JS_DHashFinalizeStub,
844 : nsnull
845 : };
846 :
847 : /***************************************************************************/
|