xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial