1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,641 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* Implementation of xptiInterfaceEntry and xptiInterfaceInfo. */ 1.10 + 1.11 +#include "xptiprivate.h" 1.12 +#include "mozilla/XPTInterfaceInfoManager.h" 1.13 + 1.14 +using namespace mozilla; 1.15 + 1.16 +/***************************************************************************/ 1.17 +// Debug Instrumentation... 1.18 + 1.19 +#ifdef SHOW_INFO_COUNT_STATS 1.20 +static int DEBUG_TotalInfos = 0; 1.21 +static int DEBUG_CurrentInfos = 0; 1.22 +static int DEBUG_MaxInfos = 0; 1.23 +static int DEBUG_ReentrantMonitorEntryCount = 0; 1.24 + 1.25 +#define LOG_INFO_CREATE(t) \ 1.26 + DEBUG_TotalInfos++; \ 1.27 + DEBUG_CurrentInfos++; \ 1.28 + if(DEBUG_MaxInfos < DEBUG_CurrentInfos) \ 1.29 + DEBUG_MaxInfos = DEBUG_CurrentInfos /* no ';' */ 1.30 + 1.31 +#define LOG_INFO_DESTROY(t) \ 1.32 + DEBUG_CurrentInfos-- /* no ';' */ 1.33 + 1.34 +#define LOG_INFO_MONITOR_ENTRY \ 1.35 + DEBUG_ReentrantMonitorEntryCount++ /* no ';' */ 1.36 + 1.37 +#else /* SHOW_INFO_COUNT_STATS */ 1.38 + 1.39 +#define LOG_INFO_CREATE(t) ((void)0) 1.40 +#define LOG_INFO_DESTROY(t) ((void)0) 1.41 +#define LOG_INFO_MONITOR_ENTRY ((void)0) 1.42 +#endif /* SHOW_INFO_COUNT_STATS */ 1.43 + 1.44 +/* static */ xptiInterfaceEntry* 1.45 +xptiInterfaceEntry::Create(const char* name, const nsID& iid, 1.46 + XPTInterfaceDescriptor* aDescriptor, 1.47 + xptiTypelibGuts* aTypelib) 1.48 +{ 1.49 + int namelen = strlen(name); 1.50 + return new (XPT_MALLOC(gXPTIStructArena, 1.51 + sizeof(xptiInterfaceEntry) + namelen)) 1.52 + xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib); 1.53 +} 1.54 + 1.55 +xptiInterfaceEntry::xptiInterfaceEntry(const char* name, 1.56 + size_t nameLength, 1.57 + const nsID& iid, 1.58 + XPTInterfaceDescriptor* aDescriptor, 1.59 + xptiTypelibGuts* aTypelib) 1.60 + : mIID(iid) 1.61 + , mDescriptor(aDescriptor) 1.62 + , mMethodBaseIndex(0) 1.63 + , mConstantBaseIndex(0) 1.64 + , mTypelib(aTypelib) 1.65 + , mParent(nullptr) 1.66 + , mInfo(nullptr) 1.67 + , mFlags(0) 1.68 +{ 1.69 + memcpy(mName, name, nameLength); 1.70 + SetResolvedState(PARTIALLY_RESOLVED); 1.71 +} 1.72 + 1.73 +bool 1.74 +xptiInterfaceEntry::Resolve() 1.75 +{ 1.76 + MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock()); 1.77 + return ResolveLocked(); 1.78 +} 1.79 + 1.80 +bool 1.81 +xptiInterfaceEntry::ResolveLocked() 1.82 +{ 1.83 + int resolvedState = GetResolveState(); 1.84 + 1.85 + if(resolvedState == FULLY_RESOLVED) 1.86 + return true; 1.87 + if(resolvedState == RESOLVE_FAILED) 1.88 + return false; 1.89 + 1.90 + NS_ASSERTION(GetResolveState() == PARTIALLY_RESOLVED, "bad state!"); 1.91 + 1.92 + // Finish out resolution by finding parent and Resolving it so 1.93 + // we can set the info we get from it. 1.94 + 1.95 + uint16_t parent_index = mDescriptor->parent_interface; 1.96 + 1.97 + if(parent_index) 1.98 + { 1.99 + xptiInterfaceEntry* parent = 1.100 + mTypelib->GetEntryAt(parent_index - 1); 1.101 + 1.102 + if(!parent || !parent->EnsureResolvedLocked()) 1.103 + { 1.104 + SetResolvedState(RESOLVE_FAILED); 1.105 + return false; 1.106 + } 1.107 + 1.108 + mParent = parent; 1.109 + 1.110 + mMethodBaseIndex = 1.111 + parent->mMethodBaseIndex + 1.112 + parent->mDescriptor->num_methods; 1.113 + 1.114 + mConstantBaseIndex = 1.115 + parent->mConstantBaseIndex + 1.116 + parent->mDescriptor->num_constants; 1.117 + 1.118 + } 1.119 + LOG_RESOLVE(("+ complete resolve of %s\n", mName)); 1.120 + 1.121 + SetResolvedState(FULLY_RESOLVED); 1.122 + return true; 1.123 +} 1.124 + 1.125 +/**************************************************/ 1.126 +// These non-virtual methods handle the delegated nsIInterfaceInfo methods. 1.127 + 1.128 +nsresult 1.129 +xptiInterfaceEntry::GetName(char **name) 1.130 +{ 1.131 + // It is not necessary to Resolve because this info is read from manifest. 1.132 + *name = (char*) nsMemory::Clone(mName, strlen(mName)+1); 1.133 + return *name ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.134 +} 1.135 + 1.136 +nsresult 1.137 +xptiInterfaceEntry::GetIID(nsIID **iid) 1.138 +{ 1.139 + // It is not necessary to Resolve because this info is read from manifest. 1.140 + *iid = (nsIID*) nsMemory::Clone(&mIID, sizeof(nsIID)); 1.141 + return *iid ? NS_OK : NS_ERROR_OUT_OF_MEMORY; 1.142 +} 1.143 + 1.144 +nsresult 1.145 +xptiInterfaceEntry::IsScriptable(bool* result) 1.146 +{ 1.147 + // It is not necessary to Resolve because this info is read from manifest. 1.148 + *result = GetScriptableFlag(); 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +nsresult 1.153 +xptiInterfaceEntry::IsFunction(bool* result) 1.154 +{ 1.155 + if(!EnsureResolved()) 1.156 + return NS_ERROR_UNEXPECTED; 1.157 + 1.158 + *result = XPT_ID_IS_FUNCTION(mDescriptor->flags); 1.159 + return NS_OK; 1.160 +} 1.161 + 1.162 +nsresult 1.163 +xptiInterfaceEntry::GetMethodCount(uint16_t* count) 1.164 +{ 1.165 + if(!EnsureResolved()) 1.166 + return NS_ERROR_UNEXPECTED; 1.167 + 1.168 + *count = mMethodBaseIndex + 1.169 + mDescriptor->num_methods; 1.170 + return NS_OK; 1.171 +} 1.172 + 1.173 +nsresult 1.174 +xptiInterfaceEntry::GetConstantCount(uint16_t* count) 1.175 +{ 1.176 + if(!EnsureResolved()) 1.177 + return NS_ERROR_UNEXPECTED; 1.178 + 1.179 + *count = mConstantBaseIndex + 1.180 + mDescriptor->num_constants; 1.181 + return NS_OK; 1.182 +} 1.183 + 1.184 +nsresult 1.185 +xptiInterfaceEntry::GetMethodInfo(uint16_t index, const nsXPTMethodInfo** info) 1.186 +{ 1.187 + if(!EnsureResolved()) 1.188 + return NS_ERROR_UNEXPECTED; 1.189 + 1.190 + if(index < mMethodBaseIndex) 1.191 + return mParent->GetMethodInfo(index, info); 1.192 + 1.193 + if(index >= mMethodBaseIndex + 1.194 + mDescriptor->num_methods) 1.195 + { 1.196 + NS_ERROR("bad param"); 1.197 + *info = nullptr; 1.198 + return NS_ERROR_INVALID_ARG; 1.199 + } 1.200 + 1.201 + // else... 1.202 + *info = reinterpret_cast<nsXPTMethodInfo*> 1.203 + (&mDescriptor->method_descriptors[index - mMethodBaseIndex]); 1.204 + return NS_OK; 1.205 +} 1.206 + 1.207 +nsresult 1.208 +xptiInterfaceEntry::GetMethodInfoForName(const char* methodName, uint16_t *index, 1.209 + const nsXPTMethodInfo** result) 1.210 +{ 1.211 + if(!EnsureResolved()) 1.212 + return NS_ERROR_UNEXPECTED; 1.213 + 1.214 + // This is a slow algorithm, but this is not expected to be called much. 1.215 + for(uint16_t i = 0; i < mDescriptor->num_methods; ++i) 1.216 + { 1.217 + const nsXPTMethodInfo* info; 1.218 + info = reinterpret_cast<nsXPTMethodInfo*> 1.219 + (&mDescriptor-> 1.220 + method_descriptors[i]); 1.221 + if (PL_strcmp(methodName, info->GetName()) == 0) { 1.222 + *index = i + mMethodBaseIndex; 1.223 + *result = info; 1.224 + return NS_OK; 1.225 + } 1.226 + } 1.227 + 1.228 + if(mParent) 1.229 + return mParent->GetMethodInfoForName(methodName, index, result); 1.230 + else 1.231 + { 1.232 + *index = 0; 1.233 + *result = 0; 1.234 + return NS_ERROR_INVALID_ARG; 1.235 + } 1.236 +} 1.237 + 1.238 +nsresult 1.239 +xptiInterfaceEntry::GetConstant(uint16_t index, const nsXPTConstant** constant) 1.240 +{ 1.241 + if(!EnsureResolved()) 1.242 + return NS_ERROR_UNEXPECTED; 1.243 + 1.244 + if(index < mConstantBaseIndex) 1.245 + return mParent->GetConstant(index, constant); 1.246 + 1.247 + if(index >= mConstantBaseIndex + 1.248 + mDescriptor->num_constants) 1.249 + { 1.250 + NS_PRECONDITION(0, "bad param"); 1.251 + *constant = nullptr; 1.252 + return NS_ERROR_INVALID_ARG; 1.253 + } 1.254 + 1.255 + // else... 1.256 + *constant = 1.257 + reinterpret_cast<nsXPTConstant*> 1.258 + (&mDescriptor-> 1.259 + const_descriptors[index - 1.260 + mConstantBaseIndex]); 1.261 + return NS_OK; 1.262 +} 1.263 + 1.264 +// this is a private helper 1.265 + 1.266 +nsresult 1.267 +xptiInterfaceEntry::GetEntryForParam(uint16_t methodIndex, 1.268 + const nsXPTParamInfo * param, 1.269 + xptiInterfaceEntry** entry) 1.270 +{ 1.271 + if(!EnsureResolved()) 1.272 + return NS_ERROR_UNEXPECTED; 1.273 + 1.274 + if(methodIndex < mMethodBaseIndex) 1.275 + return mParent->GetEntryForParam(methodIndex, param, entry); 1.276 + 1.277 + if(methodIndex >= mMethodBaseIndex + 1.278 + mDescriptor->num_methods) 1.279 + { 1.280 + NS_ERROR("bad param"); 1.281 + return NS_ERROR_INVALID_ARG; 1.282 + } 1.283 + 1.284 + const XPTTypeDescriptor *td = ¶m->type; 1.285 + 1.286 + while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { 1.287 + td = &mDescriptor->additional_types[td->type.additional_type]; 1.288 + } 1.289 + 1.290 + if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_TYPE) { 1.291 + NS_ERROR("not an interface"); 1.292 + return NS_ERROR_INVALID_ARG; 1.293 + } 1.294 + 1.295 + xptiInterfaceEntry* theEntry = mTypelib-> 1.296 + GetEntryAt(td->type.iface - 1); 1.297 + 1.298 + // This can happen if a declared interface is not available at runtime. 1.299 + if(!theEntry) 1.300 + { 1.301 + NS_WARNING("Declared InterfaceInfo not found"); 1.302 + *entry = nullptr; 1.303 + return NS_ERROR_FAILURE; 1.304 + } 1.305 + 1.306 + *entry = theEntry; 1.307 + return NS_OK; 1.308 +} 1.309 + 1.310 +nsresult 1.311 +xptiInterfaceEntry::GetInfoForParam(uint16_t methodIndex, 1.312 + const nsXPTParamInfo *param, 1.313 + nsIInterfaceInfo** info) 1.314 +{ 1.315 + xptiInterfaceEntry* entry; 1.316 + nsresult rv = GetEntryForParam(methodIndex, param, &entry); 1.317 + if(NS_FAILED(rv)) 1.318 + return rv; 1.319 + 1.320 + *info = entry->InterfaceInfo().take(); 1.321 + 1.322 + return NS_OK; 1.323 +} 1.324 + 1.325 +nsresult 1.326 +xptiInterfaceEntry::GetIIDForParam(uint16_t methodIndex, 1.327 + const nsXPTParamInfo* param, nsIID** iid) 1.328 +{ 1.329 + xptiInterfaceEntry* entry; 1.330 + nsresult rv = GetEntryForParam(methodIndex, param, &entry); 1.331 + if(NS_FAILED(rv)) 1.332 + return rv; 1.333 + return entry->GetIID(iid); 1.334 +} 1.335 + 1.336 +nsresult 1.337 +xptiInterfaceEntry::GetIIDForParamNoAlloc(uint16_t methodIndex, 1.338 + const nsXPTParamInfo * param, 1.339 + nsIID *iid) 1.340 +{ 1.341 + xptiInterfaceEntry* entry; 1.342 + nsresult rv = GetEntryForParam(methodIndex, param, &entry); 1.343 + if(NS_FAILED(rv)) 1.344 + return rv; 1.345 + *iid = entry->mIID; 1.346 + return NS_OK; 1.347 +} 1.348 + 1.349 +// this is a private helper 1.350 +nsresult 1.351 +xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param, 1.352 + uint16_t dimension, 1.353 + const XPTTypeDescriptor** type) 1.354 +{ 1.355 + NS_ASSERTION(IsFullyResolved(), "bad state"); 1.356 + 1.357 + const XPTTypeDescriptor *td = ¶m->type; 1.358 + const XPTTypeDescriptor *additional_types = 1.359 + mDescriptor->additional_types; 1.360 + 1.361 + for (uint16_t i = 0; i < dimension; i++) { 1.362 + if(XPT_TDP_TAG(td->prefix) != TD_ARRAY) { 1.363 + NS_ERROR("bad dimension"); 1.364 + return NS_ERROR_INVALID_ARG; 1.365 + } 1.366 + td = &additional_types[td->type.additional_type]; 1.367 + } 1.368 + 1.369 + *type = td; 1.370 + return NS_OK; 1.371 +} 1.372 + 1.373 +nsresult 1.374 +xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex, 1.375 + const nsXPTParamInfo* param, 1.376 + uint16_t dimension, 1.377 + nsXPTType* type) 1.378 +{ 1.379 + if(!EnsureResolved()) 1.380 + return NS_ERROR_UNEXPECTED; 1.381 + 1.382 + if(methodIndex < mMethodBaseIndex) 1.383 + return mParent-> 1.384 + GetTypeForParam(methodIndex, param, dimension, type); 1.385 + 1.386 + if(methodIndex >= mMethodBaseIndex + 1.387 + mDescriptor->num_methods) 1.388 + { 1.389 + NS_ERROR("bad index"); 1.390 + return NS_ERROR_INVALID_ARG; 1.391 + } 1.392 + 1.393 + const XPTTypeDescriptor *td; 1.394 + 1.395 + if(dimension) { 1.396 + nsresult rv = GetTypeInArray(param, dimension, &td); 1.397 + if(NS_FAILED(rv)) 1.398 + return rv; 1.399 + } 1.400 + else 1.401 + td = ¶m->type; 1.402 + 1.403 + *type = nsXPTType(td->prefix); 1.404 + return NS_OK; 1.405 +} 1.406 + 1.407 +nsresult 1.408 +xptiInterfaceEntry::GetSizeIsArgNumberForParam(uint16_t methodIndex, 1.409 + const nsXPTParamInfo* param, 1.410 + uint16_t dimension, 1.411 + uint8_t* argnum) 1.412 +{ 1.413 + if(!EnsureResolved()) 1.414 + return NS_ERROR_UNEXPECTED; 1.415 + 1.416 + if(methodIndex < mMethodBaseIndex) 1.417 + return mParent-> 1.418 + GetSizeIsArgNumberForParam(methodIndex, param, dimension, argnum); 1.419 + 1.420 + if(methodIndex >= mMethodBaseIndex + 1.421 + mDescriptor->num_methods) 1.422 + { 1.423 + NS_ERROR("bad index"); 1.424 + return NS_ERROR_INVALID_ARG; 1.425 + } 1.426 + 1.427 + const XPTTypeDescriptor *td; 1.428 + 1.429 + if(dimension) { 1.430 + nsresult rv = GetTypeInArray(param, dimension, &td); 1.431 + if(NS_FAILED(rv)) 1.432 + return rv; 1.433 + } 1.434 + else 1.435 + td = ¶m->type; 1.436 + 1.437 + // verify that this is a type that has size_is 1.438 + switch (XPT_TDP_TAG(td->prefix)) { 1.439 + case TD_ARRAY: 1.440 + case TD_PSTRING_SIZE_IS: 1.441 + case TD_PWSTRING_SIZE_IS: 1.442 + break; 1.443 + default: 1.444 + NS_ERROR("not a size_is"); 1.445 + return NS_ERROR_INVALID_ARG; 1.446 + } 1.447 + 1.448 + *argnum = td->argnum; 1.449 + return NS_OK; 1.450 +} 1.451 + 1.452 +nsresult 1.453 +xptiInterfaceEntry::GetInterfaceIsArgNumberForParam(uint16_t methodIndex, 1.454 + const nsXPTParamInfo* param, 1.455 + uint8_t* argnum) 1.456 +{ 1.457 + if(!EnsureResolved()) 1.458 + return NS_ERROR_UNEXPECTED; 1.459 + 1.460 + if(methodIndex < mMethodBaseIndex) 1.461 + return mParent-> 1.462 + GetInterfaceIsArgNumberForParam(methodIndex, param, argnum); 1.463 + 1.464 + if(methodIndex >= mMethodBaseIndex + 1.465 + mDescriptor->num_methods) 1.466 + { 1.467 + NS_ERROR("bad index"); 1.468 + return NS_ERROR_INVALID_ARG; 1.469 + } 1.470 + 1.471 + const XPTTypeDescriptor *td = ¶m->type; 1.472 + 1.473 + while (XPT_TDP_TAG(td->prefix) == TD_ARRAY) { 1.474 + td = &mDescriptor-> 1.475 + additional_types[td->type.additional_type]; 1.476 + } 1.477 + 1.478 + if(XPT_TDP_TAG(td->prefix) != TD_INTERFACE_IS_TYPE) { 1.479 + NS_ERROR("not an iid_is"); 1.480 + return NS_ERROR_INVALID_ARG; 1.481 + } 1.482 + 1.483 + *argnum = td->argnum; 1.484 + return NS_OK; 1.485 +} 1.486 + 1.487 +/* bool isIID (in nsIIDPtr IID); */ 1.488 +nsresult 1.489 +xptiInterfaceEntry::IsIID(const nsIID * IID, bool *_retval) 1.490 +{ 1.491 + // It is not necessary to Resolve because this info is read from manifest. 1.492 + *_retval = mIID.Equals(*IID); 1.493 + return NS_OK; 1.494 +} 1.495 + 1.496 +/* void getNameShared ([shared, retval] out string name); */ 1.497 +nsresult 1.498 +xptiInterfaceEntry::GetNameShared(const char **name) 1.499 +{ 1.500 + // It is not necessary to Resolve because this info is read from manifest. 1.501 + *name = mName; 1.502 + return NS_OK; 1.503 +} 1.504 + 1.505 +/* void getIIDShared ([shared, retval] out nsIIDPtrShared iid); */ 1.506 +nsresult 1.507 +xptiInterfaceEntry::GetIIDShared(const nsIID * *iid) 1.508 +{ 1.509 + // It is not necessary to Resolve because this info is read from manifest. 1.510 + *iid = &mIID; 1.511 + return NS_OK; 1.512 +} 1.513 + 1.514 +/* bool hasAncestor (in nsIIDPtr iid); */ 1.515 +nsresult 1.516 +xptiInterfaceEntry::HasAncestor(const nsIID * iid, bool *_retval) 1.517 +{ 1.518 + *_retval = false; 1.519 + 1.520 + for(xptiInterfaceEntry* current = this; 1.521 + current; 1.522 + current = current->mParent) 1.523 + { 1.524 + if(current->mIID.Equals(*iid)) 1.525 + { 1.526 + *_retval = true; 1.527 + break; 1.528 + } 1.529 + if(!current->EnsureResolved()) 1.530 + return NS_ERROR_UNEXPECTED; 1.531 + } 1.532 + 1.533 + return NS_OK; 1.534 +} 1.535 + 1.536 +/***************************************************/ 1.537 + 1.538 +already_AddRefed<xptiInterfaceInfo> 1.539 +xptiInterfaceEntry::InterfaceInfo() 1.540 +{ 1.541 +#ifdef DEBUG 1.542 + XPTInterfaceInfoManager::GetSingleton()->mWorkingSet.mTableReentrantMonitor. 1.543 + AssertCurrentThreadIn(); 1.544 +#endif 1.545 + LOG_INFO_MONITOR_ENTRY; 1.546 + 1.547 + if(!mInfo) 1.548 + { 1.549 + mInfo = new xptiInterfaceInfo(this); 1.550 + } 1.551 + 1.552 + nsRefPtr<xptiInterfaceInfo> info = mInfo; 1.553 + return info.forget(); 1.554 +} 1.555 + 1.556 +void 1.557 +xptiInterfaceEntry::LockedInvalidateInterfaceInfo() 1.558 +{ 1.559 + if(mInfo) 1.560 + { 1.561 + mInfo->Invalidate(); 1.562 + mInfo = nullptr; 1.563 + } 1.564 +} 1.565 + 1.566 +bool 1.567 +xptiInterfaceInfo::BuildParent() 1.568 +{ 1.569 + mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager::GetSingleton()-> 1.570 + mWorkingSet.mTableReentrantMonitor); 1.571 + NS_ASSERTION(mEntry && 1.572 + mEntry->IsFullyResolved() && 1.573 + !mParent && 1.574 + mEntry->Parent(), 1.575 + "bad BuildParent call"); 1.576 + mParent = mEntry->Parent()->InterfaceInfo().take(); 1.577 + return true; 1.578 +} 1.579 + 1.580 +/***************************************************************************/ 1.581 + 1.582 +NS_IMPL_QUERY_INTERFACE(xptiInterfaceInfo, nsIInterfaceInfo) 1.583 + 1.584 +xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry) 1.585 + : mEntry(entry), mParent(nullptr) 1.586 +{ 1.587 + LOG_INFO_CREATE(this); 1.588 +} 1.589 + 1.590 +xptiInterfaceInfo::~xptiInterfaceInfo() 1.591 +{ 1.592 + LOG_INFO_DESTROY(this); 1.593 + NS_IF_RELEASE(mParent); 1.594 + NS_ASSERTION(!mEntry, "bad state in dtor"); 1.595 +} 1.596 + 1.597 +MozExternalRefCountType 1.598 +xptiInterfaceInfo::AddRef(void) 1.599 +{ 1.600 + nsrefcnt cnt = ++mRefCnt; 1.601 + NS_LOG_ADDREF(this, cnt, "xptiInterfaceInfo", sizeof(*this)); 1.602 + return cnt; 1.603 +} 1.604 + 1.605 +MozExternalRefCountType 1.606 +xptiInterfaceInfo::Release(void) 1.607 +{ 1.608 + xptiInterfaceEntry* entry = mEntry; 1.609 + nsrefcnt cnt = --mRefCnt; 1.610 + NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo"); 1.611 + if(!cnt) 1.612 + { 1.613 + mozilla::ReentrantMonitorAutoEnter monitor(XPTInterfaceInfoManager:: 1.614 + GetSingleton()->mWorkingSet. 1.615 + mTableReentrantMonitor); 1.616 + LOG_INFO_MONITOR_ENTRY; 1.617 + 1.618 + // If InterfaceInfo added and *released* a reference before we 1.619 + // acquired the monitor then 'this' might already be dead. In that 1.620 + // case we would not want to try to access any instance data. We 1.621 + // would want to bail immediately. If 'this' is already dead then the 1.622 + // entry will no longer have a pointer to 'this'. So, we can protect 1.623 + // ourselves from danger without more aggressive locking. 1.624 + if(entry && !entry->InterfaceInfoEquals(this)) 1.625 + return 0; 1.626 + 1.627 + // If InterfaceInfo added a reference before we acquired the monitor 1.628 + // then we want to bail out of here without destorying the object. 1.629 + if(mRefCnt) 1.630 + return 1; 1.631 + 1.632 + if(mEntry) 1.633 + { 1.634 + mEntry->LockedInterfaceInfoDeathNotification(); 1.635 + mEntry = nullptr; 1.636 + } 1.637 + 1.638 + delete this; 1.639 + return 0; 1.640 + } 1.641 + return cnt; 1.642 +} 1.643 + 1.644 +/***************************************************************************/