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 2076165 : xptiInterfaceEntry::Create(const char* name, const nsID& iid,
77 : XPTInterfaceDescriptor* aDescriptor,
78 : xptiTypelibGuts* aTypelib)
79 : {
80 2076165 : int namelen = strlen(name);
81 2076165 : return new (XPT_MALLOC(gXPTIStructArena,
82 : sizeof(xptiInterfaceEntry) + namelen))
83 2076165 : xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib);
84 : }
85 :
86 2076165 : 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 2076165 : , mFlags(0)
99 : {
100 2076165 : memcpy(mName, name, nameLength);
101 2076165 : SetResolvedState(PARTIALLY_RESOLVED);
102 2076165 : }
103 :
104 : bool
105 181403 : xptiInterfaceEntry::Resolve()
106 : {
107 362806 : MutexAutoLock lock(xptiInterfaceInfoManager::GetResolveLock());
108 181403 : return ResolveLocked();
109 : }
110 :
111 : bool
112 198067 : xptiInterfaceEntry::ResolveLocked()
113 : {
114 198067 : int resolvedState = GetResolveState();
115 :
116 198067 : if(resolvedState == FULLY_RESOLVED)
117 0 : return true;
118 198067 : if(resolvedState == RESOLVE_FAILED)
119 0 : return false;
120 :
121 198067 : 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 198067 : PRUint16 parent_index = mDescriptor->parent_interface;
127 :
128 198067 : if(parent_index)
129 : {
130 : xptiInterfaceEntry* parent =
131 196671 : mTypelib->GetEntryAt(parent_index - 1);
132 :
133 196671 : if(!parent || !parent->EnsureResolvedLocked())
134 : {
135 0 : SetResolvedState(RESOLVE_FAILED);
136 0 : return false;
137 : }
138 :
139 196671 : mParent = parent;
140 :
141 : mMethodBaseIndex =
142 : parent->mMethodBaseIndex +
143 196671 : parent->mDescriptor->num_methods;
144 :
145 : mConstantBaseIndex =
146 : parent->mConstantBaseIndex +
147 196671 : parent->mDescriptor->num_constants;
148 :
149 : }
150 : LOG_RESOLVE(("+ complete resolve of %s\n", mName));
151 :
152 198067 : SetResolvedState(FULLY_RESOLVED);
153 198067 : return true;
154 : }
155 :
156 : /**************************************************/
157 : // These non-virtual methods handle the delegated nsIInterfaceInfo methods.
158 :
159 : nsresult
160 43656 : xptiInterfaceEntry::GetName(char **name)
161 : {
162 : // It is not necessary to Resolve because this info is read from manifest.
163 43656 : *name = (char*) nsMemory::Clone(mName, PL_strlen(mName)+1);
164 43656 : 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 387295 : xptiInterfaceEntry::IsScriptable(bool* result)
177 : {
178 : // It is not necessary to Resolve because this info is read from manifest.
179 387295 : *result = GetScriptableFlag();
180 387295 : return NS_OK;
181 : }
182 :
183 : nsresult
184 453089 : xptiInterfaceEntry::IsFunction(bool* result)
185 : {
186 453089 : if(!EnsureResolved())
187 0 : return NS_ERROR_UNEXPECTED;
188 :
189 453089 : *result = XPT_ID_IS_FUNCTION(mDescriptor->flags);
190 453089 : return NS_OK;
191 : }
192 :
193 : nsresult
194 159715 : xptiInterfaceEntry::GetMethodCount(uint16* count)
195 : {
196 159715 : if(!EnsureResolved())
197 0 : return NS_ERROR_UNEXPECTED;
198 :
199 : *count = mMethodBaseIndex +
200 159715 : mDescriptor->num_methods;
201 159715 : return NS_OK;
202 : }
203 :
204 : nsresult
205 127133 : xptiInterfaceEntry::GetConstantCount(uint16* count)
206 : {
207 127133 : if(!EnsureResolved())
208 0 : return NS_ERROR_UNEXPECTED;
209 :
210 : *count = mConstantBaseIndex +
211 127133 : mDescriptor->num_constants;
212 127133 : return NS_OK;
213 : }
214 :
215 : nsresult
216 13181921 : xptiInterfaceEntry::GetMethodInfo(uint16 index, const nsXPTMethodInfo** info)
217 : {
218 13181921 : if(!EnsureResolved())
219 0 : return NS_ERROR_UNEXPECTED;
220 :
221 13181921 : if(index < mMethodBaseIndex)
222 1889066 : return mParent->GetMethodInfo(index, info);
223 :
224 11292855 : 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 11292855 : (&mDescriptor->method_descriptors[index - mMethodBaseIndex]);
235 11292855 : 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 648664 : xptiInterfaceEntry::GetConstant(uint16 index, const nsXPTConstant** constant)
271 : {
272 648664 : if(!EnsureResolved())
273 0 : return NS_ERROR_UNEXPECTED;
274 :
275 648664 : if(index < mConstantBaseIndex)
276 240108 : return mParent->GetConstant(index, constant);
277 :
278 408556 : 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 408556 : mConstantBaseIndex]);
292 408556 : return NS_OK;
293 : }
294 :
295 : // this is a private helper
296 :
297 : nsresult
298 2892294 : xptiInterfaceEntry::GetEntryForParam(PRUint16 methodIndex,
299 : const nsXPTParamInfo * param,
300 : xptiInterfaceEntry** entry)
301 : {
302 2892294 : if(!EnsureResolved())
303 0 : return NS_ERROR_UNEXPECTED;
304 :
305 2892294 : if(methodIndex < mMethodBaseIndex)
306 143106 : return mParent->GetEntryForParam(methodIndex, param, entry);
307 :
308 2749188 : if(methodIndex >= mMethodBaseIndex +
309 : mDescriptor->num_methods)
310 : {
311 0 : NS_ERROR("bad param");
312 0 : return NS_ERROR_INVALID_ARG;
313 : }
314 :
315 2749188 : const XPTTypeDescriptor *td = ¶m->type;
316 :
317 5508182 : while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
318 9806 : td = &mDescriptor->additional_types[td->type.additional_type];
319 : }
320 :
321 2749188 : 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 2749188 : GetEntryAt(td->type.iface - 1);
328 :
329 : // This can happen if a declared interface is not available at runtime.
330 2749188 : if(!theEntry)
331 : {
332 0 : NS_WARNING("Declared InterfaceInfo not found");
333 0 : *entry = nsnull;
334 0 : return NS_ERROR_FAILURE;
335 : }
336 :
337 2749188 : *entry = theEntry;
338 2749188 : 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 2749188 : xptiInterfaceEntry::GetIIDForParamNoAlloc(PRUint16 methodIndex,
373 : const nsXPTParamInfo * param,
374 : nsIID *iid)
375 : {
376 : xptiInterfaceEntry* entry;
377 2749188 : nsresult rv = GetEntryForParam(methodIndex, param, &entry);
378 2749188 : if(NS_FAILED(rv))
379 0 : return rv;
380 2749188 : *iid = entry->mIID;
381 2749188 : return NS_OK;
382 : }
383 :
384 : // this is a private helper
385 : nsresult
386 116530 : xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
387 : uint16 dimension,
388 : const XPTTypeDescriptor** type)
389 : {
390 116530 : NS_ASSERTION(IsFullyResolved(), "bad state");
391 :
392 116530 : const XPTTypeDescriptor *td = ¶m->type;
393 : const XPTTypeDescriptor *additional_types =
394 116530 : mDescriptor->additional_types;
395 :
396 233060 : for (uint16 i = 0; i < dimension; i++) {
397 116530 : if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) {
398 0 : NS_ERROR("bad dimension");
399 0 : return NS_ERROR_INVALID_ARG;
400 : }
401 116530 : td = &additional_types[td->type.additional_type];
402 : }
403 :
404 116530 : *type = td;
405 116530 : return NS_OK;
406 : }
407 :
408 : nsresult
409 116556 : xptiInterfaceEntry::GetTypeForParam(uint16 methodIndex,
410 : const nsXPTParamInfo* param,
411 : uint16 dimension,
412 : nsXPTType* type)
413 : {
414 116556 : if(!EnsureResolved())
415 0 : return NS_ERROR_UNEXPECTED;
416 :
417 116556 : if(methodIndex < mMethodBaseIndex)
418 : return mParent->
419 26 : GetTypeForParam(methodIndex, param, dimension, type);
420 :
421 116530 : 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 116530 : if(dimension) {
431 116530 : nsresult rv = GetTypeInArray(param, dimension, &td);
432 116530 : if(NS_FAILED(rv))
433 0 : return rv;
434 : }
435 : else
436 0 : td = ¶m->type;
437 :
438 116530 : *type = nsXPTType(td->prefix);
439 116530 : return NS_OK;
440 : }
441 :
442 : nsresult
443 78316 : xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16 methodIndex,
444 : const nsXPTParamInfo* param,
445 : uint16 dimension,
446 : uint8* argnum)
447 : {
448 78316 : if(!EnsureResolved())
449 0 : return NS_ERROR_UNEXPECTED;
450 :
451 78316 : if(methodIndex < mMethodBaseIndex)
452 : return mParent->
453 22 : GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum);
454 :
455 78294 : 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 78294 : if(dimension) {
465 0 : nsresult rv = GetTypeInArray(param, dimension, &td);
466 0 : if(NS_FAILED(rv))
467 0 : return rv;
468 : }
469 : else
470 78294 : td = ¶m->type;
471 :
472 : // verify that this is a type that has size_is
473 78294 : 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 78294 : *argnum = td->argnum;
484 78294 : return NS_OK;
485 : }
486 :
487 : nsresult
488 33354 : xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16 methodIndex,
489 : const nsXPTParamInfo* param,
490 : uint8* argnum)
491 : {
492 33354 : if(!EnsureResolved())
493 0 : return NS_ERROR_UNEXPECTED;
494 :
495 33354 : if(methodIndex < mMethodBaseIndex)
496 : return mParent->
497 29 : GetInterfaceIsArgNumberForParam(methodIndex, param, argnum);
498 :
499 33325 : if(methodIndex >= mMethodBaseIndex +
500 : mDescriptor->num_methods)
501 : {
502 0 : NS_ERROR("bad index");
503 0 : return NS_ERROR_INVALID_ARG;
504 : }
505 :
506 33325 : const XPTTypeDescriptor *td = ¶m->type;
507 :
508 66662 : while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) {
509 : td = &mDescriptor->
510 12 : additional_types[td->type.additional_type];
511 : }
512 :
513 33325 : 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 33325 : *argnum = td->argnum;
519 33325 : return NS_OK;
520 : }
521 :
522 : /* bool isIID (in nsIIDPtr IID); */
523 : nsresult
524 101000 : xptiInterfaceEntry::IsIID(const nsIID * IID, bool *_retval)
525 : {
526 : // It is not necessary to Resolve because this info is read from manifest.
527 101000 : *_retval = mIID.Equals(*IID);
528 101000 : return NS_OK;
529 : }
530 :
531 : /* void getNameShared ([shared, retval] out string name); */
532 : nsresult
533 523475 : xptiInterfaceEntry::GetNameShared(const char **name)
534 : {
535 : // It is not necessary to Resolve because this info is read from manifest.
536 523475 : *name = mName;
537 523475 : return NS_OK;
538 : }
539 :
540 : /* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */
541 : nsresult
542 4674209 : xptiInterfaceEntry::GetIIDShared(const nsIID * *iid)
543 : {
544 : // It is not necessary to Resolve because this info is read from manifest.
545 4674209 : *iid = &mIID;
546 4674209 : return NS_OK;
547 : }
548 :
549 : /* bool hasAncestor (in nsIIDPtr iid); */
550 : nsresult
551 368931 : xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval)
552 : {
553 368931 : *_retval = false;
554 :
555 994874 : for(xptiInterfaceEntry* current = this;
556 : current;
557 : current = current->mParent)
558 : {
559 789529 : if(current->mIID.Equals(*iid))
560 : {
561 163586 : *_retval = true;
562 163586 : break;
563 : }
564 625943 : if(!current->EnsureResolved())
565 0 : return NS_ERROR_UNEXPECTED;
566 : }
567 :
568 368931 : return NS_OK;
569 : }
570 :
571 : /***************************************************/
572 :
573 : nsresult
574 760753 : xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info)
575 : {
576 : #ifdef DEBUG
577 760753 : xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet()->mTableReentrantMonitor.
578 760753 : AssertCurrentThreadIn();
579 : #endif
580 : LOG_INFO_MONITOR_ENTRY;
581 :
582 760753 : if(!mInfo)
583 : {
584 515090 : mInfo = new xptiInterfaceInfo(this);
585 515090 : if(!mInfo)
586 : {
587 0 : *info = nsnull;
588 0 : return NS_ERROR_OUT_OF_MEMORY;
589 : }
590 : }
591 :
592 760753 : NS_ADDREF(*info = mInfo);
593 760753 : return NS_OK;
594 : }
595 :
596 : void
597 2060955 : xptiInterfaceEntry::LockedInvalidateInterfaceInfo()
598 : {
599 2060955 : if(mInfo)
600 : {
601 25 : mInfo->Invalidate();
602 25 : mInfo = nsnull;
603 : }
604 2060955 : }
605 :
606 : bool
607 122916 : xptiInterfaceInfo::BuildParent()
608 : {
609 : mozilla::ReentrantMonitorAutoEnter monitor(xptiInterfaceInfoManager::GetSingleton()->
610 245832 : GetWorkingSet()->mTableReentrantMonitor);
611 122916 : NS_ASSERTION(mEntry &&
612 : mEntry->IsFullyResolved() &&
613 : !mParent &&
614 : mEntry->Parent(),
615 : "bad BuildParent call");
616 122916 : return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent));
617 : }
618 :
619 : /***************************************************************************/
620 :
621 1109462 : NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo)
622 :
623 515090 : xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry)
624 515090 : : mEntry(entry), mParent(nsnull)
625 : {
626 : LOG_INFO_CREATE(this);
627 515090 : }
628 :
629 514664 : xptiInterfaceInfo::~xptiInterfaceInfo()
630 : {
631 : LOG_INFO_DESTROY(this);
632 514664 : NS_IF_RELEASE(mParent);
633 514664 : NS_ASSERTION(!mEntry, "bad state in dtor");
634 514664 : }
635 :
636 : nsrefcnt
637 2624217 : xptiInterfaceInfo::AddRef(void)
638 : {
639 2624217 : nsrefcnt cnt = NS_AtomicIncrementRefcnt(mRefCnt);
640 2624217 : NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this));
641 2624217 : return cnt;
642 : }
643 :
644 : nsrefcnt
645 2623715 : xptiInterfaceInfo::Release(void)
646 : {
647 2623715 : xptiInterfaceEntry* entry = mEntry;
648 2623715 : nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt);
649 2623715 : NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo");
650 2623715 : if(!cnt)
651 : {
652 : mozilla::ReentrantMonitorAutoEnter monitor(xptiInterfaceInfoManager::
653 514664 : GetSingleton()->GetWorkingSet()->
654 1029328 : 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 514664 : 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 514664 : if(mRefCnt)
669 0 : return 1;
670 :
671 514664 : if(mEntry)
672 : {
673 514664 : mEntry->LockedInterfaceInfoDeathNotification();
674 514664 : mEntry = nsnull;
675 : }
676 :
677 514664 : delete this;
678 514664 : return 0;
679 : }
680 2109051 : return cnt;
681 : }
682 :
683 : /***************************************************************************/
|