author | Ehsan Akhgari <ehsan@mozilla.com> |
Mon, 11 Apr 2011 02:07:25 -0400 | |
changeset 67825 | db98c4f4634761d23f2b481f57e912b4b36615ce |
parent 67824 | 704e425c1a6bad2b206fa5c06998902050b5d363 |
child 67826 | f79edc2f8714d33d5855509df40f1f67266f29d5 |
push id | 1 |
push user | root |
push date | Tue, 26 Apr 2011 22:38:44 +0000 |
treeherder | mozilla-beta@bfdb6e623a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 627985, 614480 |
milestone | 2.2a1pre |
backs out | c509d8f8f423778ab4e30aad0fd67638d115cb4c |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp +++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfo.cpp @@ -614,20 +614,17 @@ xptiInterfaceEntry::HasAncestor(const ns return NS_OK; } /***************************************************/ nsresult xptiInterfaceEntry::GetInterfaceInfo(xptiInterfaceInfo** info) { -#ifdef DEBUG - xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet()->mTableLock. - AssertCurrentThreadOwns(); -#endif + MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor()); LOG_INFO_MONITOR_ENTRY; if(!mInfo) { mInfo = new xptiInterfaceInfo(this); if(!mInfo) { *info = nsnull; @@ -644,29 +641,16 @@ xptiInterfaceEntry::LockedInvalidateInte { if(mInfo) { mInfo->Invalidate(); mInfo = nsnull; } } -PRBool -xptiInterfaceInfo::BuildParent() -{ - mozilla::MutexAutoLock lock(xptiInterfaceInfoManager::GetSingleton()-> - GetWorkingSet()->mTableLock); - NS_ASSERTION(mEntry && - mEntry->IsFullyResolved() && - !mParent && - mEntry->Parent(), - "bad BuildParent call"); - return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent)); -} - /***************************************************************************/ NS_IMPL_QUERY_INTERFACE1(xptiInterfaceInfo, nsIInterfaceInfo) xptiInterfaceInfo::xptiInterfaceInfo(xptiInterfaceEntry* entry) : mEntry(entry), mParent(nsnull) { LOG_INFO_CREATE(this); @@ -690,45 +674,37 @@ xptiInterfaceInfo::AddRef(void) nsrefcnt xptiInterfaceInfo::Release(void) { xptiInterfaceEntry* entry = mEntry; nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, cnt, "xptiInterfaceInfo"); if(!cnt) { - // Need to exit the lock before calling |delete this|, since - // that release mParent, which can re-enter this function. - { - mozilla::MutexAutoLock lock(xptiInterfaceInfoManager:: - GetSingleton()->GetWorkingSet()-> - mTableLock); - LOG_INFO_MONITOR_ENTRY; + MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor()); + LOG_INFO_MONITOR_ENTRY; + + // If GetInterfaceInfo added and *released* a reference before we + // acquired the monitor then 'this' might already be dead. In that + // case we would not want to try to access any instance data. We + // would want to bail immediately. If 'this' is already dead then the + // entry will no longer have a pointer to 'this'. So, we can protect + // ourselves from danger without more aggressive locking. + if(entry && !entry->InterfaceInfoEquals(this)) + return 0; - // If GetInterfaceInfo added and *released* a reference - // before we acquired the monitor then 'this' might already - // be dead. In that case we would not want to try to access - // any instance data. We would want to bail immediately. If - // 'this' is already dead then the entry will no longer have - // a pointer to 'this'. So, we can protect ourselves from - // danger without more aggressive locking. - if(entry && !entry->InterfaceInfoEquals(this)) - return 0; - - // If GetInterfaceInfo added a reference before we acquired - // the monitor then we want to bail out of here without - // destorying the object. - if(mRefCnt) - return 1; - - if(mEntry) - { - mEntry->LockedInterfaceInfoDeathNotification(); - mEntry = nsnull; - } + // If GetInterfaceInfo added a reference before we acquired the monitor + // then we want to bail out of here without destorying the object. + if(mRefCnt) + return 1; + + if(mEntry) + { + mEntry->LockedInterfaceInfoDeathNotification(); + mEntry = nsnull; } delete this; return 0; } return cnt; }
--- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp +++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp @@ -75,16 +75,18 @@ void xptiInterfaceInfoManager::FreeInterfaceInfoManager() { NS_IF_RELEASE(gInterfaceInfoManager); } xptiInterfaceInfoManager::xptiInterfaceInfoManager() : mWorkingSet(), mResolveLock("xptiInterfaceInfoManager.mResolveLock"), + mAutoRegLock("xptiInterfaceInfoManager.mAutoRegLock"), // FIXME: unused! + mInfoMonitor("xptiInterfaceInfoManager.mInfoMonitor"), mAdditionalManagersLock( "xptiInterfaceInfoManager.mAdditionalManagersLock") { } xptiInterfaceInfoManager::~xptiInterfaceInfoManager() { // We only do this on shutdown of the service. @@ -228,17 +230,16 @@ xptiInterfaceInfoManager::RegisterXPTHea { if (aHeader->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) { NS_ASSERTION(!aHeader->num_interfaces,"bad libxpt"); LOG_AUTOREG((" file is version %d.%d Type file of version %d.0 or higher can not be read.\n", (int)header->major_version, (int)header->minor_version, (int)XPT_MAJOR_INCOMPATIBLE_VERSION)); } xptiTypelibGuts* typelib = xptiTypelibGuts::Create(aHeader); - MutexAutoLock lock(mWorkingSet.mTableLock); for(PRUint16 k = 0; k < aHeader->num_interfaces; k++) VerifyAndAddEntryIfNew(aHeader->interface_directory + k, k, typelib); } void xptiInterfaceInfoManager::RegisterInputStream(nsIInputStream* aStream) { XPTHeader* header = ReadXPTFileFromInputStream(aStream); @@ -249,17 +250,16 @@ xptiInterfaceInfoManager::RegisterInputS void xptiInterfaceInfoManager::VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface, PRUint16 idx, xptiTypelibGuts* typelib) { if (!iface->interface_descriptor) return; - mWorkingSet.mTableLock.AssertCurrentThreadOwns(); xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->iid); if (entry) { // XXX validate this info to find possible inconsistencies LOG_AUTOREG((" ignoring repeated interface: %s\n", iface->name)); return; } // Build a new xptiInterfaceEntry object and hook it up. @@ -301,65 +301,61 @@ EntryToInfo(xptiInterfaceEntry* entry, n // Transfer the AddRef done by GetInterfaceInfo. *_retval = static_cast<nsIInterfaceInfo*>(info); return NS_OK; } xptiInterfaceEntry* xptiInterfaceInfoManager::GetInterfaceEntryForIID(const nsIID *iid) { - MutexAutoLock lock(mWorkingSet.mTableLock); return mWorkingSet.mIIDTable.Get(*iid); } /* nsIInterfaceInfo getInfoForIID (in nsIIDPtr iid); */ NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForIID(const nsIID * iid, nsIInterfaceInfo **_retval) { NS_ASSERTION(iid, "bad param"); NS_ASSERTION(_retval, "bad param"); - MutexAutoLock lock(mWorkingSet.mTableLock); - xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid); + xptiInterfaceEntry* entry = GetInterfaceEntryForIID(iid); return EntryToInfo(entry, _retval); } /* nsIInterfaceInfo getInfoForName (in string name); */ NS_IMETHODIMP xptiInterfaceInfoManager::GetInfoForName(const char *name, nsIInterfaceInfo **_retval) { NS_ASSERTION(name, "bad param"); NS_ASSERTION(_retval, "bad param"); - MutexAutoLock lock(mWorkingSet.mTableLock); xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name); return EntryToInfo(entry, _retval); } /* nsIIDPtr getIIDForName (in string name); */ NS_IMETHODIMP xptiInterfaceInfoManager::GetIIDForName(const char *name, nsIID * *_retval) { NS_ASSERTION(name, "bad param"); NS_ASSERTION(_retval, "bad param"); - MutexAutoLock lock(mWorkingSet.mTableLock); + xptiInterfaceEntry* entry = mWorkingSet.mNameTable.Get(name); if (!entry) { *_retval = nsnull; return NS_ERROR_FAILURE; } return entry->GetIID(_retval); } /* string getNameForIID (in nsIIDPtr iid); */ NS_IMETHODIMP xptiInterfaceInfoManager::GetNameForIID(const nsIID * iid, char **_retval) { NS_ASSERTION(iid, "bad param"); NS_ASSERTION(_retval, "bad param"); - MutexAutoLock lock(mWorkingSet.mTableLock); xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(*iid); if (!entry) { *_retval = nsnull; return NS_ERROR_FAILURE; } return entry->GetName(_retval); } @@ -383,17 +379,16 @@ NS_IMETHODIMP xptiInterfaceInfoManager:: // the table using an nsISupportsArray and builds an enumerator for that. // We can afford this transient cost. nsCOMPtr<nsISupportsArray> array; NS_NewISupportsArray(getter_AddRefs(array)); if (!array) return NS_ERROR_UNEXPECTED; - MutexAutoLock lock(mWorkingSet.mTableLock); mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayAppender, array); return array->Enumerate(_retval); } struct ArrayAndPrefix { nsISupportsArray* array; @@ -419,17 +414,16 @@ xpti_ArrayPrefixAppender(const char* key /* nsIEnumerator enumerateInterfacesWhoseNamesStartWith (in string prefix); */ NS_IMETHODIMP xptiInterfaceInfoManager::EnumerateInterfacesWhoseNamesStartWith(const char *prefix, nsIEnumerator **_retval) { nsCOMPtr<nsISupportsArray> array; NS_NewISupportsArray(getter_AddRefs(array)); if (!array) return NS_ERROR_UNEXPECTED; - MutexAutoLock lock(mWorkingSet.mTableLock); ArrayAndPrefix args = {array, prefix, PL_strlen(prefix)}; mWorkingSet.mNameTable.EnumerateRead(xpti_ArrayPrefixAppender, &args); return array->Enumerate(_retval); } /* void autoRegisterInterfaces (); */ NS_IMETHODIMP xptiInterfaceInfoManager::AutoRegisterInterfaces()
--- a/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp +++ b/xpcom/reflect/xptinfo/src/xptiTypelibGuts.cpp @@ -36,18 +36,16 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* Implementation of xptiTypelibGuts. */ #include "xptiprivate.h" -using namespace mozilla; - // static xptiTypelibGuts* xptiTypelibGuts::Create(XPTHeader* aHeader) { NS_ASSERTION(aHeader, "bad param"); void* place = XPT_MALLOC(gXPTIStructArena, sizeof(xptiTypelibGuts) + (sizeof(xptiInterfaceEntry*) * @@ -70,21 +68,18 @@ xptiTypelibGuts::GetEntryAt(PRUint16 i) if (r) return r; XPTInterfaceDirectoryEntry* iface = mHeader->interface_directory + i; xptiWorkingSet* set = xptiInterfaceInfoManager::GetSingleton()->GetWorkingSet(); - { - MutexAutoLock lock(set->mTableLock); - if (iface->iid.Equals(zeroIID)) - r = set->mNameTable.Get(iface->name); - else - r = set->mIIDTable.Get(iface->iid); - } + if (iface->iid.Equals(zeroIID)) + r = set->mNameTable.Get(iface->name); + else + r = set->mIIDTable.Get(iface->iid); if (r) SetEntryAt(i, r); return r; }
--- a/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp +++ b/xpcom/reflect/xptinfo/src/xptiWorkingSet.cpp @@ -43,17 +43,16 @@ #include "nsString.h" using namespace mozilla; #define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 1) #define XPTI_HASHTABLE_SIZE 2048 xptiWorkingSet::xptiWorkingSet() - : mTableLock("xptiWorkingSet::mTableLock") { MOZ_COUNT_CTOR(xptiWorkingSet); mIIDTable.Init(XPTI_HASHTABLE_SIZE); mNameTable.Init(XPTI_HASHTABLE_SIZE); gXPTIStructArena = XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double), "xptiWorkingSet structs"); @@ -64,17 +63,17 @@ xpti_Invalidator(const char* keyname, xp { entry->LockedInvalidateInterfaceInfo(); return PL_DHASH_NEXT; } void xptiWorkingSet::InvalidateInterfaceInfos() { - MutexAutoLock lock(mTableLock); + MonitorAutoEnter lock(xptiInterfaceInfoManager::GetInfoMonitor()); mNameTable.EnumerateRead(xpti_Invalidator, NULL); } xptiWorkingSet::~xptiWorkingSet() { MOZ_COUNT_DTOR(xptiWorkingSet); // Only destroy the arena if we're doing leak stats. Why waste shutdown
--- a/xpcom/reflect/xptinfo/src/xptiprivate.h +++ b/xpcom/reflect/xptinfo/src/xptiprivate.h @@ -175,21 +175,16 @@ public: PRBool DirectoryAtMatchesPersistentDescriptor(PRUint32 i, const char* desc); private: PRUint32 mFileCount; PRUint32 mMaxFileCount; public: // XXX make these private with accessors - // mTableLock must be held across: - // * any read from or write to mIIDTable or mNameTable - // * any writing to the links between an xptiInterfaceEntry - // and its xptiInterfaceInfo (mEntry/mInfo) - mozilla::Mutex mTableLock; nsDataHashtable<nsIDHashKey, xptiInterfaceEntry*> mIIDTable; nsDataHashtable<nsDepCharHashKey, xptiInterfaceEntry*> mNameTable; }; /***************************************************************************/ // This class exists to help xptiInterfaceInfo store a 4-state (2 bit) value // and a set of bitflags in one 8bit value. See below. @@ -406,17 +401,25 @@ private: return mParent || !mEntry->Parent() || BuildParent(); } PRBool EnsureResolved() { return mEntry && mEntry->EnsureResolved(); } - PRBool BuildParent(); + PRBool BuildParent() + { + NS_ASSERTION(mEntry && + mEntry->IsFullyResolved() && + !mParent && + mEntry->Parent(), + "bad BuildParent call"); + return NS_SUCCEEDED(mEntry->Parent()->GetInterfaceInfo(&mParent)); + } xptiInterfaceInfo(); // not implemented private: xptiInterfaceEntry* mEntry; xptiInterfaceInfo* mParent; }; @@ -443,16 +446,28 @@ public: xptiWorkingSet* GetWorkingSet() {return &mWorkingSet;} static Mutex& GetResolveLock(xptiInterfaceInfoManager* self = nsnull) { self = self ? self : GetSingleton(); return self->mResolveLock; } + static Mutex& GetAutoRegLock(xptiInterfaceInfoManager* self = nsnull) + { + self = self ? self : GetSingleton(); + return self->mAutoRegLock; + } + + static Monitor& GetInfoMonitor(xptiInterfaceInfoManager* self = nsnull) + { + self = self ? self : GetSingleton(); + return self->mInfoMonitor; + } + xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid); private: xptiInterfaceInfoManager(); ~xptiInterfaceInfoManager(); void RegisterXPTHeader(XPTHeader* aHeader); @@ -462,13 +477,15 @@ private: // idx is the index of this interface in the XPTHeader void VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface, PRUint16 idx, xptiTypelibGuts* typelib); private: xptiWorkingSet mWorkingSet; Mutex mResolveLock; + Mutex mAutoRegLock; + Monitor mInfoMonitor; Mutex mAdditionalManagersLock; nsCOMArray<nsISupports> mAdditionalManagers; }; #endif /* xptiprivate_h___ */