1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1999
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Mike McCabe <mccabe@netscape.com>
24 : * John Bandhauer <jband@netscape.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */
41 :
42 : #include "xptiprivate.h"
43 : #include "nsAtomicRefcnt.h"
44 :
45 : using namespace mozilla;
46 :
47 : /***************************************************************************/
48 : // Debug Instrumentation...
49 :
50 : #ifdef SHOW_INFO_COUNT_STATS
51 : static int DEBUG_TotalInfos = 0;
52 : static int DEBUG_CurrentInfos = 0;
53 : static int DEBUG_MaxInfos = 0;
54 : static int DEBUG_ReentrantMonitorEntryCount = 0;
55 :
56 : #define LOG_INFO_CREATE(t) \
57 : DEBUG_TotalInfos++; \
58 : DEBUG_CurrentInfos++; \
59 : if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \
60 : DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */
61 :
62 : #define LOG_INFO_DESTROY(t) \
63 : DEBUG_CurrentInfos-- /* no ';' */
64 :
65 : #define LOG_INFO_MONITOR_ENTRY \
66 : DEBUG_ReentrantMonitorEntryCount++ /* no ';' */
67 :
68 : #else /* SHOW_INFO_COUNT_STATS */
69 :
70 : #define LOG_INFO_CREATE(t) ((void)0)
71 : #define LOG_INFO_DESTROY(t) ((void)0)
72 : #define LOG_INFO_MONITOR_ENTRY ((void)0)
73 : #endif /* SHOW_INFO_COUNT_STATS */
74 :
75 : /* static */ xptiInterfaceEntry*
76 2159718 : xptiInterfaceEntry::Create(const char* name, const nsID& iid,
77 : XPTInterfaceDescriptor* aDescriptor,
78 : xptiTypelibGuts* aTypelib)
79 : {
80 2159718 : int namelen = strlen(name);
81 2159718 : return new (XPT_MALLOC(gXPTIStructArena,
82 : sizeof(xptiInterfaceEntry) + namelen))
83 2159718 : xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib);
84 : }
85 :
86 2159718 : xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
87 : size_t nameLength,
88 : const nsID& iid,
89 : XPTInterfaceDescriptor* aDescriptor,
90 : xptiTypelibGuts* aTypelib)
91 : : mIID(iid)
92 : , mDescriptor(aDescriptor)
93 : , mMethodBaseIndex(0)
94 : , mConstantBaseIndex(0)
95 : , mTypelib(aTypelib)
96 : , mParent(NULL)
97 : , mInfo(NULL)
98 2159718 : , mFlags(0)
99 : {
100 2159718 : memcpy(mName, name, nameLength);
101 2159718 : SetResolvedState(PARTIALLY_RESOLVED);
102 2159718 : }
103 :
104 : bool
105 182456 : xptiInterfaceEntry::Resolve()
106 : {
107 364912 : MutexAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
108 182456 : return ResolveLocked();
109 : }
110 :
111 : bool
112 199259 : xptiInterfaceEntry::ResolveLocked()
113 : {
114 199259 : int resolvedState = GetResolveState();
115 :
116 199259 : if(resolvedState == FULLY_RESOLVED)
117 0 : return true;
118 199259 : if(resolvedState == RESOLVE_FAILED)
119 0 : return false;
120 :
121 199259 : NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!");
122 :
123 : // Finish out resolution by finding parent and Resolving it so
124 : // we can set the info we get from it.
125 :
126 199259 : PRUint16 parent_index = mDescriptor->parent_interface;
127 :
128 199259 : if(parent_index)
129 : {
130 : xptiInterfaceEntry* parent =
131 197824 : mTypelib->GetEntryAt(parent_index - 1);
132 :
133 197824 : if(!parent || !parent->EnsureResolvedLocked())
134 : {
135 0 : SetResolvedState(RESOLVE_FAILED);
136 0 : return false;
137 : }
138 :
139 197824 : mParent = parent;
140 :
141 : mMethodBaseIndex =
142 : parent->mMethodBaseIndex +
143 197824 : parent->mDescriptor->num_methods;
144 :
145 : mConstantBaseIndex =
146 : parent->mConstantBaseIndex +
147 197824 : parent->mDescriptor->num_constants;
148 :
149 : }
150 : LOG_RESOLVE(("+ complete resolve of %s\n", mName));
151 :
152 199259 : SetResolvedState(FULLY_RESOLVED);
153 199259 : return true;
154 : }
155 :
156 : /**************************************************/
157 : // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
158 :
159 : nsresult
160 43735 : xptiInterfaceEntry::GetName(char **name)
161 : {
162 : // It is not necessary to Resolve because this info is read from manifest.
163 43735 : *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
164 43735 : return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
165 : }
166 :
167 : nsresult
168 0 : xptiInterfaceEntry::GetIID(nsIID **iid)
169 : {
170 : // It is not necessary to Resolve because this info is read from manifest.
171 0 : *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID));
172 0 : return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
173 : }
174 :
175 : nsresult
176 394017 : xptiInterfaceEntry::IsScriptable(bool* result)
177 : {
178 : // It is not necessary to Resolve because this info is read from manifest.
179 394017 : *result = GetScriptableFlag();
180 394017 : return NS_OK;
181 : }
182 :
183 : nsresult
184 448172 : xptiInterfaceEntry::IsFunction(bool* result)
185 : {
186 448172 : if(!EnsureResolved())
187 0 : return NS_ERROR_UNEXPECTED;
188 :
189 448172 : *result = XPT_ID_IS_FUNCTION(mDescriptor->flags);
190 448172 : return NS_OK;
191 : }
192 :
193 : nsresult
194 160071 : xptiInterfaceEntry::GetMethodCount(uint16* count)
195 : {
196 160071 : if(!EnsureResolved())
197 0 : return NS_ERROR_UNEXPECTED;
198 :
199 : *count = mMethodBaseIndex +
200 160071 : mDescriptor->num_methods;
201 160071 : return NS_OK;
202 : }
203 :
204 : nsresult
205 127559 : xptiInterfaceEntry::GetConstantCount(uint16* count)
206 : {
207 127559 : if(!EnsureResolved())
208 0 : return NS_ERROR_UNEXPECTED;
209 :
210 : *count = mConstantBaseIndex +
211 127559 : mDescriptor->num_constants;
212 127559 : return NS_OK;
213 : }
214 :
215 : nsresult
216 12603459 : xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
217 : {
218 12603459 : if(!EnsureResolved())
219 0 : return NS_ERROR_UNEXPECTED;
220 :
221 12603459 : if(index < mMethodBaseIndex)
222 1900650 : return mParent->GetMethodInfo(index, info);
223 :
224 10702809 : if(index >= mMethodBaseIndex +
225 : mDescriptor->num_methods)
226 : {
227 0 : NS_ERROR("bad param");
228 0 : *info = NULL;
229 0 : return NS_ERROR_INVALID_ARG;
230 : }
231 :
232 : // else...
233 : *info = reinterpret_cast<nsXPTMethodInfo*>
234 10702809 : (&mDescriptor->method_descriptors[index - mMethodBaseIndex]);
235 10702809 : return NS_OK;
236 : }
237 :
238 : nsresult
239 0 : xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16 *index,
240 : const nsXPTMethodInfo** result)
241 : {
242 0 : if(!EnsureResolved())
243 0 : return NS_ERROR_UNEXPECTED;
244 :
245 : // This is a slow algorithm, but this is not expected to be called much.
246 0 : for(uint16 i = 0; i < mDescriptor->num_methods; ++i)
247 : {
248 : const nsXPTMethodInfo* info;
249 : info = reinterpret_cast<nsXPTMethodInfo*>
250 : (&mDescriptor->
251 0 : method_descriptors[i]);
252 0 : if (PL_strcmp(methodName, info->GetName()) == 0) {
253 0 : *index = i + mMethodBaseIndex;
254 0 : *result = info;
255 0 : return NS_OK;
256 : }
257 : }
258 :
259 0 : if(mParent)
260 0 : return mParent->GetMethodInfoForName(methodName, index, result);
261 : else
262 : {
263 0 : *index = 0;
264 0 : *result = 0;
265 0 : return NS_ERROR_INVALID_ARG;
266 : }
267 : }
268 :
269 : nsresult
270 648174 : xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
271 : {
272 648174 : if(!EnsureResolved())
273 0 : return NS_ERROR_UNEXPECTED;
274 :
275 648174 : if(index < mConstantBaseIndex)
276 239901 : return mParent->GetConstant(index, constant);
277 :
278 408273 : if(index >= mConstantBaseIndex +
279 : mDescriptor->num_constants)
280 : {
281 0 : NS_PRECONDITION(0, "bad param");
282 0 : *constant = NULL;
283 0 : return NS_ERROR_INVALID_ARG;
284 : }
285 :
286 : // else...
287 : *constant =
288 : reinterpret_cast<nsXPTConstant*>
289 : (&mDescriptor->
290 : const_descriptors[index -
291 408273 : mConstantBaseIndex]);
292 408273 : return NS_OK;
293 : }
294 :
295 : // this is a private helper
296 :
297 : nsresult
298 2796225 : xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
299 : const nsXPTParamInfo * param,
300 : xptiInterfaceEntry** entry)
301 : {
302 2796225 : if(!EnsureResolved())
303 0 : return NS_ERROR_UNEXPECTED;
304 :
305 2796225 : if(methodIndex < mMethodBaseIndex)
306 131174 : return mParent->GetEntryForParam(methodIndex, param, entry);
307 :
308 2665051 : if(methodIndex >= mMethodBaseIndex +
309 : mDescriptor->num_methods)
310 : {
311 0 : NS_ERROR("bad param");
312 0 : return NS_ERROR_INVALID_ARG;
313 : }
314 :
315 2665051 : const XPTTypeDescriptor *td = ¶m->type;
316 :
317 5339909 : while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
318 9807 : td = &mDescriptor->additional_types[td->type.additional_type];
319 : }
320 :
321 2665051 : if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) {
322 0 : NS_ERROR("not an interface");
323 0 : return NS_ERROR_INVALID_ARG;
324 : }
325 :
326 : xptiInterfaceEntry* theEntry = mTypelib->
327 2665051 : GetEntryAt(td->type.iface - 1);
328 :
329 : // This can happen if a declared interface is not available at runtime.
330 2665051 : if(!theEntry)
331 : {
332 0 : NS_WARNING("Declared InterfaceInfo not found");
333 0 : *entry = nsnull;
334 0 : return NS_ERROR_FAILURE;
335 : }
336 :
337 2665051 : *entry = theEntry;
338 2665051 : return NS_OK;
339 : }
340 :
341 : nsresult
342 0 : xptiInterfaceEntry::GetInfoForParam(uint16 methodIndex,
343 : const nsXPTParamInfo *param,
344 : nsIInterfaceInfo** info)
345 : {
346 : xptiInterfaceEntry* entry;
347 0 : nsresult rv = GetEntryForParam(methodIndex, param, &entry);
348 0 : if(NS_FAILED(rv))
349 0 : return rv;
350 :
351 : xptiInterfaceInfo* theInfo;
352 0 : rv = entry->GetInterfaceInfo(&theInfo);
353 0 : if(NS_FAILED(rv))
354 0 : return rv;
355 :
356 0 : *info = static_cast<nsIInterfaceInfo*>(theInfo);
357 0 : return NS_OK;
358 : }
359 :
360 : nsresult
361 0 : xptiInterfaceEntry::GetIIDForParam(uint16 methodIndex,
362 : const nsXPTParamInfo* param, nsIID** iid)
363 : {
364 : xptiInterfaceEntry* entry;
365 0 : nsresult rv = GetEntryForParam(methodIndex, param, &entry);
366 0 : if(NS_FAILED(rv))
367 0 : return rv;
368 0 : return entry->GetIID(iid);
369 : }
370 :
371 : nsresult
372 2665051 : xptiInterfaceEntry::GetIIDForParamNoAlloc(PRUint16 methodIndex,
373 : const nsXPTParamInfo * param,
374 : nsIID *iid)
375 : {
376 : xptiInterfaceEntry* entry;
377 2665051 : nsresult rv = GetEntryForParam(methodIndex, param, &entry);
378 2665051 : if(NS_FAILED(rv))
379 0 : return rv;
380 2665051 : *iid = entry->mIID;
381 2665051 : return NS_OK;
382 : }
383 :
384 : // this is a private helper
385 : nsresult
386 116380 : xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
387 : uint16 dimension,
388 : const XPTTypeDescriptor** type)
389 : {
390 116380 : NS_ASSERTION(IsFullyResolved(), "bad state");
391 :
392 116380 : const XPTTypeDescriptor *td = ¶m->type;
393 : const XPTTypeDescriptor *additional_types =
394 116380 : mDescriptor->additional_types;
395 :
396 232760 : for (uint16 i = 0; i < dimension; i++) {
397 116380 : if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
398 0 : NS_ERROR("bad dimension");
399 0 : return NS_ERROR_INVALID_ARG;
400 : }
401 116380 : td = &additional_types[td->type.additional_type];
402 : }
403 :
404 116380 : *type = td;
405 116380 : return NS_OK;
406 : }
407 :
408 : nsresult
409 116406 : xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
410 : const nsXPTParamInfo* param,
411 : uint16 dimension,
412 : nsXPTType* type)
413 : {
414 116406 : if(!EnsureResolved())
415 0 : return NS_ERROR_UNEXPECTED;
416 :
417 116406 : if(methodIndex < mMethodBaseIndex)
418 : return mParent->
419 26 : GetTypeForParam(methodIndex, param, dimension, type);
420 :
421 116380 : if(methodIndex >= mMethodBaseIndex +
422 : mDescriptor->num_methods)
423 : {
424 0 : NS_ERROR("bad index");
425 0 : return NS_ERROR_INVALID_ARG;
426 : }
427 :
428 : const XPTTypeDescriptor *td;
429 :
430 116380 : if(dimension) {
431 116380 : nsresult rv = GetTypeInArray(param, dimension, &td);
432 116380 : if(NS_FAILED(rv))
433 0 : return rv;
434 : }
435 : else
436 0 : td = ¶m->type;
437 :
438 116380 : *type = nsXPTType(td->prefix);
439 116380 : return NS_OK;
440 : }
441 :
442 : nsresult
443 78244 : xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
444 : const nsXPTParamInfo* param,
445 : uint16 dimension,
446 : uint8* argnum)
447 : {
448 78244 : if(!EnsureResolved())
449 0 : return NS_ERROR_UNEXPECTED;
450 :
451 78244 : if(methodIndex < mMethodBaseIndex)
452 : return mParent->
453 22 : GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
454 :
455 78222 : if(methodIndex >= mMethodBaseIndex +
456 : mDescriptor->num_methods)
457 : {
458 0 : NS_ERROR("bad index");
459 0 : return NS_ERROR_INVALID_ARG;
460 : }
461 :
462 : const XPTTypeDescriptor *td;
463 :
464 78222 : if(dimension) {
465 0 : nsresult rv = GetTypeInArray(param, dimension, &td);
466 0 : if(NS_FAILED(rv))
467 0 : return rv;
468 : }
469 : else
470 78222 : td = ¶m->type;
471 :
472 : // verify that this is a type that has size_is
473 78222 : switch (XPT_TDP_TAG(td->prefix)) {
474 : case TD_ARRAY:
475 : case TD_PSTRING_SIZE_IS:
476 : case TD_PWSTRING_SIZE_IS:
477 : break;
478 : default:
479 0 : NS_ERROR("not a size_is");
480 0 : return NS_ERROR_INVALID_ARG;
481 : }
482 :
483 78222 : *argnum = td->argnum;
484 78222 : return NS_OK;
485 : }
486 :
487 : nsresult
488 38159 : xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
489 : const nsXPTParamInfo* param,
490 : uint8* argnum)
491 : {
492 38159 : if(!EnsureResolved())
493 0 : return NS_ERROR_UNEXPECTED;
494 :
495 38159 : if(methodIndex < mMethodBaseIndex)
496 : return mParent->
497 1016 : GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
498 :
499 37143 : if(methodIndex >= mMethodBaseIndex +
500 : mDescriptor->num_methods)
501 : {
502 0 : NS_ERROR("bad index");
503 0 : return NS_ERROR_INVALID_ARG;
504 : }
505 :
506 37143 : const XPTTypeDescriptor *td = ¶m->type;
507 :
508 74298 : while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
509 : td = &mDescriptor->
510 12 : additional_types[td->type.additional_type];
511 : }
512 :
513 37143 : if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) {
514 0 : NS_ERROR("not an iid_is");
515 0 : return NS_ERROR_INVALID_ARG;
516 : }
517 :
518 37143 : *argnum = td->argnum;
519 37143 : return NS_OK;
520 : }
521 :
522 : /* bool isIID (in nsIIDPtr IID); */
523 : nsresult
524 109454 : xptiInterfaceEntry::IsIID(const nsIID * IID, bool *_retval)
525 : {
526 : // It is not necessary to Resolve because this info is read from manifest.
527 109454 : *_retval = mIID.Equals(*IID);
528 109454 : return NS_OK;
529 : }
530 :
531 : /* void getNameShared ([shared, retval] out string name); */
532 : nsresult
533 543837 : xptiInterfaceEntry::GetNameShared(const char **name)
534 : {
535 : // It is not necessary to Resolve because this info is read from manifest.
536 543837 : *name = mName;
537 543837 : return NS_OK;
538 : }
539 :
540 : /* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
541 : nsresult
542 4691180 : xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
543 : {
544 : // It is not necessary to Resolve because this info is read from manifest.
545 4691180 : *iid = &mIID;
546 4691180 : return NS_OK;
547 : }
548 :
549 : /* bool hasAncestor (in nsIIDPtr iid); */
550 : nsresult
551 360310 : xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval)
552 : {
553 360310 : *_retval = false;
554 :
555 974293 : for(xptiInterfaceEntry* current = this;
556 : current;
557 : current = current->mParent)
558 : {
559 780116 : if(current->mIID.Equals(*iid))
560 : {
561 166133 : *_retval = true;
562 166133 : break;
563 : }
564 613983 : if(!current->EnsureResolved())
565 0 : return NS_ERROR_UNEXPECTED;
566 : }
567 :
568 360310 : return NS_OK;
569 : }
570 :
571 : /***************************************************/
572 :
573 : nsresult
574 769010 : xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
575 : {
576 : #ifdef DEBUG
577 769010 : xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet()->mTableReentrantMonitor.
578 769010 : AssertCurrentThreadIn();
579 : #endif
580 : LOG_INFO_MONITOR_ENTRY;
581 :
582 769010 : if(!mInfo)
583 : {
584 519152 : mInfo = new xptiInterfaceInfo(this);
585 519152 : if(!mInfo)
586 : {
587 0 : *info = nsnull;
588 0 : return NS_ERROR_OUT_OF_MEMORY;
589 : }
590 : }
591 :
592 769010 : NS_ADDREF(*info = mInfo);
593 769010 : return NS_OK;
594 : }
595 :
596 : void
597 2144498 : xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
598 : {
599 2144498 : if(mInfo)
600 : {
601 25 : mInfo->Invalidate();
602 25 : mInfo = nsnull;
603 : }
604 2144498 : }
605 :
606 : bool
607 123324 : xptiInterfaceInfo::BuildParent()
608 : {
609 : mozilla::ReentrantMonitorAutoEnter monitor(xptiInterfaceInfoManager::GetSingleton()->
610 246648 : GetWorkingSet()->mTableReentrantMonitor);
611 123324 : NS_ASSERTION(mEntry &&
612 : mEntry->IsFullyResolved() &&
613 : !mParent &&
614 : mEntry->Parent(),
615 : "bad BuildParent call");
616 123324 : return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent));
617 : }
618 :
619 : /***************************************************************************/
620 :
621 1119245 : NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
622 :
623 519152 : xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
624 519152 : : mEntry(entry), mParent(nsnull)
625 : {
626 : LOG_INFO_CREATE(this);
627 519152 : }
628 :
629 518726 : xptiInterfaceInfo::~xptiInterfaceInfo()
630 : {
631 : LOG_INFO_DESTROY(this);
632 518726 : NS_IF_RELEASE(mParent);
633 518726 : NS_ASSERTION(!mEntry, "bad state in dtor");
634 518726 : }
635 :
636 : nsrefcnt
637 2645246 : xptiInterfaceInfo::AddRef(void)
638 : {
639 2645246 : nsrefcnt cnt = NS_AtomicIncrementRefcnt(mRefCnt);
640 2645246 : NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
641 2645246 : return cnt;
642 : }
643 :
644 : nsrefcnt
645 2644744 : xptiInterfaceInfo::Release(void)
646 : {
647 2644744 : xptiInterfaceEntry* entry = mEntry;
648 2644744 : nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt);
649 2644744 : NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
650 2644744 : if(!cnt)
651 : {
652 : mozilla::ReentrantMonitorAutoEnter monitor(xptiInterfaceInfoManager::
653 518726 : GetSingleton()->GetWorkingSet()->
654 1037452 : mTableReentrantMonitor);
655 : LOG_INFO_MONITOR_ENTRY;
656 :
657 : // If GetInterfaceInfo added and *released* a reference before we
658 : // acquired the monitor then 'this' might already be dead. In that
659 : // case we would not want to try to access any instance data. We
660 : // would want to bail immediately. If 'this' is already dead then the
661 : // entry will no longer have a pointer to 'this'. So, we can protect
662 : // ourselves from danger without more aggressive locking.
663 518726 : if(entry && !entry->InterfaceInfoEquals(this))
664 0 : return 0;
665 :
666 : // If GetInterfaceInfo added a reference before we acquired the monitor
667 : // then we want to bail out of here without destorying the object.
668 518726 : if(mRefCnt)
669 0 : return 1;
670 :
671 518726 : if(mEntry)
672 : {
673 518726 : mEntry->LockedInterfaceInfoDeathNotification();
674 518726 : mEntry = nsnull;
675 : }
676 :
677 518726 : delete this;
678 518726 : return 0;
679 : }
680 2126018 : return cnt;
681 : }
682 :
683 : /***************************************************************************/
|