diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h index d3b4d04bd79..bfc07a323a0 100644 --- a/js/xpconnect/src/XPCInlines.h +++ b/js/xpconnect/src/XPCInlines.h @@ -17,19 +17,19 @@ inline void XPCJSRuntime::AddVariantRoot(XPCTraceableVariant* variant) { - variant->AddToRootSet(GetMapLock(), &mVariantRoots); + variant->AddToRootSet(&mVariantRoots); } inline void XPCJSRuntime::AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS) { - wrappedJS->AddToRootSet(GetMapLock(), &mWrappedJSRoots); + wrappedJS->AddToRootSet(&mWrappedJSRoots); } inline void XPCJSRuntime::AddObjectHolderRoot(XPCJSObjectHolder* holder) { - holder->AddToRootSet(GetMapLock(), &mObjectHolderRoots); + holder->AddToRootSet(&mObjectHolderRoots); } /***************************************************************************/ diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 2c2f87ff974..d06cf9fe84a 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -629,15 +629,11 @@ void XPCJSRuntime::TraceNativeBlackRoots(JSTracer* trc) roots->TraceJSAll(trc); } - { - XPCAutoLock lock(mMapLock); - - // XPCJSObjectHolders don't participate in cycle collection, so always - // trace them here. - XPCRootSetElem *e; - for (e = mObjectHolderRoots; e; e = e->GetNextRoot()) - static_cast(e)->TraceJS(trc); - } + // XPCJSObjectHolders don't participate in cycle collection, so always + // trace them here. + XPCRootSetElem *e; + for (e = mObjectHolderRoots; e; e = e->GetNextRoot()) + static_cast(e)->TraceJS(trc); dom::TraceBlackJS(trc, JS_GetGCParameter(Runtime(), JSGC_NUMBER), nsXPConnect::XPConnect()->IsShuttingDown()); @@ -645,8 +641,6 @@ void XPCJSRuntime::TraceNativeBlackRoots(JSTracer* trc) void XPCJSRuntime::TraceAdditionalNativeGrayRoots(JSTracer *trc) { - XPCAutoLock lock(mMapLock); - XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(trc, this); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) @@ -706,8 +700,6 @@ CanSkipWrappedJS(nsXPCWrappedJS *wrappedJS) void XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &cb) { - XPCAutoLock lock(mMapLock); - XPCWrappedNativeScope::SuspectAllWrappers(this, cb); for (XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot()) { @@ -735,7 +727,6 @@ XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &c void XPCJSRuntime::UnmarkSkippableJSHolders() { - XPCAutoLock lock(mMapLock); CycleCollectedJSRuntime::UnmarkSkippableJSHolders(); } @@ -840,11 +831,8 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCo MOZ_ASSERT(!self->mDoingFinalization, "bad state"); // mThreadRunningGC indicates that GC is running - { // scoped lock - XPCAutoLock lock(self->GetMapLock()); - MOZ_ASSERT(!self->mThreadRunningGC, "bad state"); - self->mThreadRunningGC = PR_GetCurrentThread(); - } + MOZ_ASSERT(!self->mThreadRunningGC, "bad state"); + self->mThreadRunningGC = PR_GetCurrentThread(); nsTArray* dyingWrappedJSArray = &self->mWrappedJSToReleaseArray; @@ -877,23 +865,16 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCo // mThreadRunningGC indicates that GC is running. // Clear it and notify waiters. - { // scoped lock - XPCAutoLock lock(self->GetMapLock()); - MOZ_ASSERT(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state"); - self->mThreadRunningGC = nullptr; - xpc_NotifyAll(self->GetMapLock()); - } + MOZ_ASSERT(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state"); + self->mThreadRunningGC = nullptr; break; } case JSFINALIZE_COLLECTION_END: { // mThreadRunningGC indicates that GC is running - { // scoped lock - XPCAutoLock lock(self->GetMapLock()); - MOZ_ASSERT(!self->mThreadRunningGC, "bad state"); - self->mThreadRunningGC = PR_GetCurrentThread(); - } + MOZ_ASSERT(!self->mThreadRunningGC, "bad state"); + self->mThreadRunningGC = PR_GetCurrentThread(); // We use this occasion to mark and sweep NativeInterfaces, // NativeSets, and the WrappedNativeJSClasses... @@ -1032,12 +1013,8 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCo // mThreadRunningGC indicates that GC is running. // Clear it and notify waiters. - { // scoped lock - XPCAutoLock lock(self->GetMapLock()); - MOZ_ASSERT(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state"); - self->mThreadRunningGC = nullptr; - xpc_NotifyAll(self->GetMapLock()); - } + MOZ_ASSERT(self->mThreadRunningGC == PR_GetCurrentThread(), "bad state"); + self->mThreadRunningGC = nullptr; break; } @@ -1590,9 +1567,6 @@ XPCJSRuntime::~XPCJSRuntime() if (mNativeSetMap) delete mNativeSetMap; - if (mMapLock) - XPCAutoLock::DestroyLock(mMapLock); - if (mThisTranslatorMap) delete mThisTranslatorMap; @@ -2956,7 +2930,6 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) mNativeScriptableSharedMap(XPCNativeScriptableSharedMap::newMap(XPC_NATIVE_JSCLASS_MAP_SIZE)), mDyingWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DYING_NATIVE_PROTO_MAP_SIZE)), mDetachedWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DETACHED_NATIVE_PROTO_MAP_SIZE)), - mMapLock(XPCAutoLock::NewLock("XPCJSRuntime::mMapLock")), mThreadRunningGC(nullptr), mWrappedJSToReleaseArray(), mNativesToReleaseArray(), @@ -3145,7 +3118,6 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect) self->GetThisTranslatorMap() && self->GetNativeScriptableSharedMap() && self->GetDyingWrappedNativeProtoMap() && - self->GetMapLock() && self->mWatchdogManager) { return self; } @@ -3261,7 +3233,6 @@ XPCJSRuntime::DebugDump(int16_t depth) XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this)); XPC_LOG_INDENT(); XPC_LOG_ALWAYS(("mJSRuntime @ %x", Runtime())); - XPC_LOG_ALWAYS(("mMapLock @ %x", mMapLock)); XPC_LOG_ALWAYS(("mWrappedJSToReleaseArray @ %x with %d wrappers(s)", \ &mWrappedJSToReleaseArray, @@ -3330,12 +3301,10 @@ XPCJSRuntime::DebugDump(int16_t depth) /***************************************************************************/ void -XPCRootSetElem::AddToRootSet(XPCLock *lock, XPCRootSetElem **listHead) +XPCRootSetElem::AddToRootSet(XPCRootSetElem **listHead) { MOZ_ASSERT(!mSelfp, "Must be not linked"); - XPCAutoLock autoLock(lock); - mSelfp = listHead; mNext = *listHead; if (mNext) { @@ -3346,15 +3315,13 @@ XPCRootSetElem::AddToRootSet(XPCLock *lock, XPCRootSetElem **listHead) } void -XPCRootSetElem::RemoveFromRootSet(XPCLock *lock) +XPCRootSetElem::RemoveFromRootSet() { nsXPConnect *xpc = nsXPConnect::XPConnect(); JS::PokeGC(xpc->GetRuntime()->Runtime()); MOZ_ASSERT(mSelfp, "Must be linked"); - XPCAutoLock autoLock(lock); - MOZ_ASSERT(*mSelfp == this, "Link invariant"); *mSelfp = mNext; if (mNext) diff --git a/js/xpconnect/src/XPCVariant.cpp b/js/xpconnect/src/XPCVariant.cpp index 8651f60e8f3..a688bcef6c3 100644 --- a/js/xpconnect/src/XPCVariant.cpp +++ b/js/xpconnect/src/XPCVariant.cpp @@ -63,7 +63,7 @@ XPCTraceableVariant::~XPCTraceableVariant() nsVariant::Cleanup(&mData); if (!JSVAL_IS_NULL(val)) - RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock()); + RemoveFromRootSet(); } void XPCTraceableVariant::TraceJS(JSTracer* trc) @@ -103,7 +103,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant) if (val.isMarkable()) { XPCTraceableVariant *v = static_cast(tmp); - v->RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock()); + v->RemoveFromRootSet(); } tmp->mJSVal = JS::NullValue(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END diff --git a/js/xpconnect/src/XPCWrappedJS.cpp b/js/xpconnect/src/XPCWrappedJS.cpp index 1723246b602..912c4a4078d 100644 --- a/js/xpconnect/src/XPCWrappedJS.cpp +++ b/js/xpconnect/src/XPCWrappedJS.cpp @@ -175,11 +175,6 @@ nsXPCWrappedJS::Release(void) MOZ_CRASH(); NS_PRECONDITION(0 != mRefCnt, "dup release"); - // need to take the map lock here to prevent GetNewOrUsed from trying - // to reuse a wrapper on one thread while it's being destroyed on another - XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); - XPCAutoLock lock(rt->GetMapLock()); - do_decrement: nsrefcnt cnt = --mRefCnt; @@ -191,7 +186,7 @@ do_decrement: } if (1 == cnt) { if (IsValid()) - RemoveFromRootSet(rt->GetMapLock()); + RemoveFromRootSet(); // If we are not the root wrapper or if we are not being used from a // weak reference, then this extra ref is not needed and we can let @@ -274,18 +269,12 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj, if (!rootJSObj) goto return_wrapper; - // look for the root wrapper, and if found, hold the map lock until - // we've added our ref to prevent another thread from destroying it - // under us - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - root = map->Find(rootJSObj); - if (root) { - if ((nullptr != (wrapper = root->Find(aIID))) || - (nullptr != (wrapper = root->FindInherited(aIID)))) { - NS_ADDREF(wrapper); - goto return_wrapper; - } + root = map->Find(rootJSObj); + if (root) { + if ((nullptr != (wrapper = root->Find(aIID))) || + (nullptr != (wrapper = root->FindInherited(aIID)))) { + NS_ADDREF(wrapper); + goto return_wrapper; } } @@ -298,10 +287,7 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj, if (!root) goto return_wrapper; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - map->Add(cx, root); - } + map->Add(cx, root); goto return_wrapper; } else { @@ -320,11 +306,7 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj, release_root = true; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - map->Add(cx, root); - } - + map->Add(cx, root); } } @@ -387,10 +369,8 @@ nsXPCWrappedJS::~nsXPCWrappedJS() // Remove this root wrapper from the map XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); JSObject2WrappedJSMap* map = rt->GetWrappedJSMap(); - if (map) { - XPCAutoLock lock(rt->GetMapLock()); + if (map) map->Remove(this); - } } Unlink(); } @@ -404,14 +384,12 @@ nsXPCWrappedJS::Unlink() if (mRoot == this) { // remove this root wrapper from the map JSObject2WrappedJSMap* map = rt->GetWrappedJSMap(); - if (map) { - XPCAutoLock lock(rt->GetMapLock()); + if (map) map->Remove(this); - } } if (mRefCnt > 1) - RemoveFromRootSet(rt->GetMapLock()); + RemoveFromRootSet(); } mJSObj = nullptr; diff --git a/js/xpconnect/src/XPCWrappedJSClass.cpp b/js/xpconnect/src/XPCWrappedJSClass.cpp index fc0b4cc46c5..7be5a01d1e7 100644 --- a/js/xpconnect/src/XPCWrappedJSClass.cpp +++ b/js/xpconnect/src/XPCWrappedJSClass.cpp @@ -105,12 +105,9 @@ nsXPCWrappedJSClass::GetNewOrUsed(JSContext* cx, REFNSIID aIID, nsXPCWrappedJSClass* clazz = nullptr; XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - IID2WrappedJSClassMap* map = rt->GetWrappedJSClassMap(); - clazz = map->Find(aIID); - NS_IF_ADDREF(clazz); - } + IID2WrappedJSClassMap* map = rt->GetWrappedJSClassMap(); + clazz = map->Find(aIID); + NS_IF_ADDREF(clazz); if (!clazz) { nsCOMPtr info; @@ -141,10 +138,7 @@ nsXPCWrappedJSClass::nsXPCWrappedJSClass(JSContext* cx, REFNSIID aIID, NS_ADDREF(mInfo); NS_ADDREF_THIS(); - { // scoped lock - XPCAutoLock lock(mRuntime->GetMapLock()); - mRuntime->GetWrappedJSClassMap()->Add(this); - } + mRuntime->GetWrappedJSClassMap()->Add(this); uint16_t methodCount; if (NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount))) { @@ -178,10 +172,8 @@ nsXPCWrappedJSClass::~nsXPCWrappedJSClass() if (mDescriptors && mDescriptors != &zero_methods_descriptor) delete [] mDescriptors; if (mRuntime) - { // scoped lock - XPCAutoLock lock(mRuntime->GetMapLock()); mRuntime->GetWrappedJSClassMap()->Remove(this); - } + if (mName) nsMemory::Free(mName); NS_IF_RELEASE(mInfo); @@ -1215,10 +1207,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex, IID2ThisTranslatorMap* map = mRuntime->GetThisTranslatorMap(); - { - XPCAutoLock lock(mRuntime->GetMapLock()); // scoped lock - translator = map->Find(mIID); - } + translator = map->Find(mIID); if (translator) { nsCOMPtr newThis; diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index df292466a3d..9f77409f92d 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -302,18 +302,13 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper, return NS_ERROR_FAILURE; } - XPCLock* mapLock = Scope->GetRuntime()->GetMapLock(); - nsRefPtr wrapper; Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap(); // Some things are nsWrapperCache subclasses but never use the cache, so go // ahead and check our map even if we have a cache and it has no existing // wrapper: we might have an XPCWrappedNative anyway. - { // scoped lock - XPCAutoLock lock(mapLock); - wrapper = map->Find(identity); - } + wrapper = map->Find(identity); if (wrapper) { if (!wrapper->FindTearOff(Interface, false, &rv)) { @@ -404,8 +399,6 @@ XPCWrappedNative::GetNewOrUsed(xpcObjectHelper& helper, if (cached) wrapper = XPCWrappedNative::Get(cached); } else { - // scoped lock - XPCAutoLock lock(mapLock); wrapper = map->Find(identity); } @@ -494,21 +487,16 @@ FinishCreate(XPCWrappedNativeScope* Scope, AutoJSContext cx; MOZ_ASSERT(inWrapper); - XPCLock* mapLock = Scope->GetRuntime()->GetMapLock(); Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap(); nsRefPtr wrapper; - { // scoped lock - - // Deal with the case where the wrapper got created as a side effect - // of one of our calls out of this code (or on another thread). Add() - // returns the (possibly pre-existing) wrapper that ultimately ends up - // in the map, which is what we want. - XPCAutoLock lock(mapLock); - wrapper = map->Add(inWrapper); - if (!wrapper) - return NS_ERROR_FAILURE; - } + // Deal with the case where the wrapper got created as a side effect + // of one of our calls out of this code. Add() returns the (possibly + // pre-existing) wrapper that ultimately ends up in the map, which is + // what we want. + wrapper = map->Add(inWrapper); + if (!wrapper) + return NS_ERROR_FAILURE; if (wrapper == inWrapper) { JSObject *flat = wrapper->GetFlatJSObject(); @@ -539,10 +527,7 @@ FinishCreate(XPCWrappedNativeScope* Scope, "cause a crash in combination with a JS GC. Fix the " "failing PostCreate ASAP!"); - { // scoped lock - XPCAutoLock lock(mapLock); - map->Remove(wrapper); - } + map->Remove(wrapper); // This would be a good place to tell the wrapper not to remove // itself from the map when it dies... See bug 429442. @@ -591,13 +576,10 @@ XPCWrappedNative::GetUsedOnly(nsISupports* Object, Native2WrappedNativeMap* map = Scope->GetWrappedNativeMap(); - { // scoped lock - XPCAutoLock lock(Scope->GetRuntime()->GetMapLock()); - wrapper = map->Find(identity); - if (!wrapper) { - *resultWrapper = nullptr; - return NS_OK; - } + wrapper = map->Find(identity); + if (!wrapper) { + *resultWrapper = nullptr; + return NS_OK; } } @@ -662,9 +644,6 @@ XPCWrappedNative::Destroy() if (scope) { Native2WrappedNativeMap* map = scope->GetWrappedNativeMap(); - // scoped lock - XPCAutoLock lock(GetRuntime()->GetMapLock()); - // Post-1.9 we should not remove this wrapper from the map if it is // uninitialized. map->Remove(this); @@ -1254,43 +1233,40 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope, // Update scope maps. This section modifies global state, so from // here on out we crash if anything fails. - { // scoped lock - Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap(); - Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap(); - XPCAutoLock lock(aOldScope->GetRuntime()->GetMapLock()); + Native2WrappedNativeMap* oldMap = aOldScope->GetWrappedNativeMap(); + Native2WrappedNativeMap* newMap = aNewScope->GetWrappedNativeMap(); - oldMap->Remove(wrapper); + oldMap->Remove(wrapper); - if (wrapper->HasProto()) - wrapper->SetProto(newProto); + if (wrapper->HasProto()) + wrapper->SetProto(newProto); - // If the wrapper has no scriptable or it has a non-shared - // scriptable, then we don't need to mess with it. - // Otherwise... + // If the wrapper has no scriptable or it has a non-shared + // scriptable, then we don't need to mess with it. + // Otherwise... - if (wrapper->mScriptableInfo && - wrapper->mScriptableInfo == oldProto->GetScriptableInfo()) { - // The new proto had better have the same JSClass stuff as - // the old one! We maintain a runtime wide unique map of - // this stuff. So, if these don't match then the caller is - // doing something bad here. + if (wrapper->mScriptableInfo && + wrapper->mScriptableInfo == oldProto->GetScriptableInfo()) { + // The new proto had better have the same JSClass stuff as + // the old one! We maintain a runtime wide unique map of + // this stuff. So, if these don't match then the caller is + // doing something bad here. - MOZ_ASSERT(oldProto->GetScriptableInfo()->GetScriptableShared() == - newProto->GetScriptableInfo()->GetScriptableShared(), - "Changing proto is also changing JSObject Classname or " - "helper's nsIXPScriptable flags. This is not allowed!"); + MOZ_ASSERT(oldProto->GetScriptableInfo()->GetScriptableShared() == + newProto->GetScriptableInfo()->GetScriptableShared(), + "Changing proto is also changing JSObject Classname or " + "helper's nsIXPScriptable flags. This is not allowed!"); - wrapper->UpdateScriptableInfo(newProto->GetScriptableInfo()); - } - - // Crash if the wrapper is already in the new scope. - if (newMap->Find(wrapper->GetIdentityObject())) - MOZ_CRASH(); - - if (!newMap->Add(wrapper)) - MOZ_CRASH(); + wrapper->UpdateScriptableInfo(newProto->GetScriptableInfo()); } + // Crash if the wrapper is already in the new scope. + if (newMap->Find(wrapper->GetIdentityObject())) + MOZ_CRASH(); + + if (!newMap->Add(wrapper)) + MOZ_CRASH(); + RootedObject ww(cx, wrapper->GetWrapper()); if (ww) { RootedObject newwrapper(cx); @@ -1440,7 +1416,6 @@ bool XPCWrappedNative::ExtendSet(XPCNativeInterface* aInterface) { AutoJSContext cx; - // This is only called while locked (during XPCWrappedNative::FindTearOff). if (!mSet->HasInterface(aInterface)) { AutoMarkingNativeSetPtr newSet(cx); @@ -1457,8 +1432,6 @@ XPCWrappedNative::ExtendSet(XPCNativeInterface* aInterface) XPCWrappedNativeTearOff* XPCWrappedNative::LocateTearOff(XPCNativeInterface* aInterface) { - XPCAutoLock al(GetLock()); // hold the lock throughout - for (XPCWrappedNativeTearOffChunk* chunk = &mFirstChunk; chunk != nullptr; chunk = chunk->mNextChunk) { @@ -1482,8 +1455,6 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface, nsresult* pError /* = nullptr */) { AutoJSContext cx; - XPCAutoLock al(GetLock()); // hold the lock throughout - nsresult rv = NS_OK; XPCWrappedNativeTearOff* to; XPCWrappedNativeTearOff* firstAvailable = nullptr; @@ -1559,8 +1530,6 @@ XPCWrappedNative::InitTearOff(XPCWrappedNativeTearOff* aTearOff, { AutoJSContext cx; - // This is only called while locked (during XPCWrappedNative::FindTearOff). - // Determine if the object really does this interface... const nsIID* iid = aInterface->GetIID(); @@ -1576,103 +1545,98 @@ XPCWrappedNative::InitTearOff(XPCWrappedNativeTearOff* aTearOff, return NS_ERROR_NO_INTERFACE; } - // We are about to call out to unlock and other code. + // We are about to call out to other code. // So protect our intended tearoff. aTearOff->SetReserved(); - { // scoped *un*lock - XPCAutoUnlock unlock(GetLock()); + if (NS_FAILED(identity->QueryInterface(*iid, (void**)&obj)) || !obj) { + aTearOff->SetInterface(nullptr); + return NS_ERROR_NO_INTERFACE; + } - if (NS_FAILED(identity->QueryInterface(*iid, (void**)&obj)) || !obj) { + // Guard against trying to build a tearoff for a shared nsIClassInfo. + if (iid->Equals(NS_GET_IID(nsIClassInfo))) { + nsCOMPtr alternate_identity(do_QueryInterface(obj)); + if (alternate_identity.get() != identity) { + NS_RELEASE(obj); aTearOff->SetInterface(nullptr); return NS_ERROR_NO_INTERFACE; } + } - // Guard against trying to build a tearoff for a shared nsIClassInfo. - if (iid->Equals(NS_GET_IID(nsIClassInfo))) { - nsCOMPtr alternate_identity(do_QueryInterface(obj)); - if (alternate_identity.get() != identity) { + // Guard against trying to build a tearoff for an interface that is + // aggregated and is implemented as a nsIXPConnectWrappedJS using this + // self-same JSObject. The XBL system does this. If we mutate the set + // of this wrapper then we will shadow the method that XBL has added to + // the JSObject that it has inserted in the JS proto chain between our + // JSObject and our XPCWrappedNativeProto's JSObject. If we let this + // set mutation happen then the interface's methods will be added to + // our JSObject, but calls on those methods will get routed up to + // native code and into the wrappedJS - which will do a method lookup + // on *our* JSObject and find the same method and make another call + // into an infinite loop. + // see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725 + + // The code in this block also does a check for the double wrapped + // nsIPropertyBag case. + + nsCOMPtr wrappedJS(do_QueryInterface(obj)); + if (wrappedJS) { + RootedObject jso(cx, wrappedJS->GetJSObject()); + if (jso == mFlatJSObject) { + // The implementing JSObject is the same as ours! Just say OK + // without actually extending the set. + // + // XXX It is a little cheesy to have FindTearOff return an + // 'empty' tearoff. But this is the centralized place to do the + // QI activities on the underlying object. *And* most caller to + // FindTearOff only look for a non-null result and ignore the + // actual tearoff returned. The only callers that do use the + // returned tearoff make sure to check for either a non-null + // JSObject or a matching Interface before proceeding. + // I think we can get away with this bit of ugliness. + + NS_RELEASE(obj); + aTearOff->SetInterface(nullptr); + return NS_OK; + } + + // Decide whether or not to expose nsIPropertyBag to calling + // JS code in the double wrapped case. + // + // Our rule here is that when JSObjects are double wrapped and + // exposed to other JSObjects then the nsIPropertyBag interface + // is only exposed on an 'opt-in' basis; i.e. if the underlying + // JSObject wants other JSObjects to be able to see this interface + // then it must implement QueryInterface and not throw an exception + // when asked for nsIPropertyBag. It need not actually *implement* + // nsIPropertyBag - xpconnect will do that work. + + nsXPCWrappedJSClass* clazz; + if (iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso && + NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(cx,*iid,&clazz))&& + clazz) { + RootedObject answer(cx, + clazz->CallQueryInterfaceOnJSObject(cx, jso, *iid)); + NS_RELEASE(clazz); + if (!answer) { NS_RELEASE(obj); aTearOff->SetInterface(nullptr); return NS_ERROR_NO_INTERFACE; } } - - // Guard against trying to build a tearoff for an interface that is - // aggregated and is implemented as a nsIXPConnectWrappedJS using this - // self-same JSObject. The XBL system does this. If we mutate the set - // of this wrapper then we will shadow the method that XBL has added to - // the JSObject that it has inserted in the JS proto chain between our - // JSObject and our XPCWrappedNativeProto's JSObject. If we let this - // set mutation happen then the interface's methods will be added to - // our JSObject, but calls on those methods will get routed up to - // native code and into the wrappedJS - which will do a method lookup - // on *our* JSObject and find the same method and make another call - // into an infinite loop. - // see: http://bugzilla.mozilla.org/show_bug.cgi?id=96725 - - // The code in this block also does a check for the double wrapped - // nsIPropertyBag case. - - nsCOMPtr wrappedJS(do_QueryInterface(obj)); - if (wrappedJS) { - RootedObject jso(cx, wrappedJS->GetJSObject()); - if (jso == mFlatJSObject) { - // The implementing JSObject is the same as ours! Just say OK - // without actually extending the set. - // - // XXX It is a little cheesy to have FindTearOff return an - // 'empty' tearoff. But this is the centralized place to do the - // QI activities on the underlying object. *And* most caller to - // FindTearOff only look for a non-null result and ignore the - // actual tearoff returned. The only callers that do use the - // returned tearoff make sure to check for either a non-null - // JSObject or a matching Interface before proceeding. - // I think we can get away with this bit of ugliness. - - NS_RELEASE(obj); - aTearOff->SetInterface(nullptr); - return NS_OK; - } - - // Decide whether or not to expose nsIPropertyBag to calling - // JS code in the double wrapped case. - // - // Our rule here is that when JSObjects are double wrapped and - // exposed to other JSObjects then the nsIPropertyBag interface - // is only exposed on an 'opt-in' basis; i.e. if the underlying - // JSObject wants other JSObjects to be able to see this interface - // then it must implement QueryInterface and not throw an exception - // when asked for nsIPropertyBag. It need not actually *implement* - // nsIPropertyBag - xpconnect will do that work. - - nsXPCWrappedJSClass* clazz; - if (iid->Equals(NS_GET_IID(nsIPropertyBag)) && jso && - NS_SUCCEEDED(nsXPCWrappedJSClass::GetNewOrUsed(cx,*iid,&clazz))&& - clazz) { - RootedObject answer(cx, - clazz->CallQueryInterfaceOnJSObject(cx, jso, *iid)); - NS_RELEASE(clazz); - if (!answer) { - NS_RELEASE(obj); - aTearOff->SetInterface(nullptr); - return NS_ERROR_NO_INTERFACE; - } - } - } - - nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager(); - if (sm && NS_FAILED(sm-> - CanCreateWrapper(cx, *iid, identity, - GetClassInfo(), GetSecurityInfoAddr()))) { - // the security manager vetoed. It should have set an exception. - NS_RELEASE(obj); - aTearOff->SetInterface(nullptr); - return NS_ERROR_XPC_SECURITY_MANAGER_VETO; - } } - // We are relocked from here on... + + nsIXPCSecurityManager* sm = nsXPConnect::XPConnect()->GetDefaultSecurityManager(); + if (sm && NS_FAILED(sm-> + CanCreateWrapper(cx, *iid, identity, + GetClassInfo(), GetSecurityInfoAddr()))) { + // the security manager vetoed. It should have set an exception. + NS_RELEASE(obj); + aTearOff->SetInterface(nullptr); + return NS_ERROR_XPC_SECURITY_MANAGER_VETO; + } // If this is not already in our set we need to extend our set. // Note: we do not cache the result of the previous call to HasInterface() @@ -1698,8 +1662,6 @@ XPCWrappedNative::InitTearOffJSObject(XPCWrappedNativeTearOff* to) { AutoJSContext cx; - // This is only called while locked (during XPCWrappedNative::FindTearOff). - JSObject* obj = JS_NewObject(cx, Jsvalify(&XPC_WN_Tearoff_JSClass), JS_GetObjectPrototype(cx, mFlatJSObject), mFlatJSObject); @@ -2881,7 +2843,7 @@ XPCJSObjectHolder::XPCJSObjectHolder(JSObject* obj) XPCJSObjectHolder::~XPCJSObjectHolder() { - RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock()); + RemoveFromRootSet(); } void diff --git a/js/xpconnect/src/XPCWrappedNativeInfo.cpp b/js/xpconnect/src/XPCWrappedNativeInfo.cpp index 25038be3427..c99eafb5400 100644 --- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp +++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp @@ -126,10 +126,7 @@ XPCNativeInterface::GetNewOrUsed(const nsIID* iid) if (!map) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - iface = map->Find(*iid); - } + iface = map->Find(*iid); if (iface) return iface; @@ -143,17 +140,14 @@ XPCNativeInterface::GetNewOrUsed(const nsIID* iid) if (!iface) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - XPCNativeInterface* iface2 = map->Add(iface); - if (!iface2) { - NS_ERROR("failed to add our interface!"); - DestroyInstance(iface); - iface = nullptr; - } else if (iface2 != iface) { - DestroyInstance(iface); - iface = iface2; - } + XPCNativeInterface* iface2 = map->Add(iface); + if (!iface2) { + NS_ERROR("failed to add our interface!"); + DestroyInstance(iface); + iface = nullptr; + } else if (iface2 != iface) { + DestroyInstance(iface); + iface = iface2; } return iface; @@ -176,10 +170,7 @@ XPCNativeInterface::GetNewOrUsed(nsIInterfaceInfo* info) if (!map) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - iface = map->Find(*iid); - } + iface = map->Find(*iid); if (iface) return iface; @@ -188,17 +179,14 @@ XPCNativeInterface::GetNewOrUsed(nsIInterfaceInfo* info) if (!iface) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - XPCNativeInterface* iface2 = map->Add(iface); - if (!iface2) { - NS_ERROR("failed to add our interface!"); - DestroyInstance(iface); - iface = nullptr; - } else if (iface2 != iface) { - DestroyInstance(iface); - iface = iface2; - } + XPCNativeInterface* iface2 = map->Add(iface); + if (!iface2) { + NS_ERROR("failed to add our interface!"); + DestroyInstance(iface); + iface = nullptr; + } else if (iface2 != iface) { + DestroyInstance(iface); + iface = iface2; } return iface; @@ -429,10 +417,7 @@ XPCNativeSet::GetNewOrUsed(const nsIID* iid) if (!map) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - set = map->Find(&key); - } + set = map->Find(&key); if (set) return set; @@ -443,17 +428,14 @@ XPCNativeSet::GetNewOrUsed(const nsIID* iid) if (!set) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - XPCNativeSet* set2 = map->Add(&key, set); - if (!set2) { - NS_ERROR("failed to add our set!"); - DestroyInstance(set); - set = nullptr; - } else if (set2 != set) { - DestroyInstance(set); - set = set2; - } + XPCNativeSet* set2 = map->Add(&key, set); + if (!set2) { + NS_ERROR("failed to add our set!"); + DestroyInstance(set); + set = nullptr; + } else if (set2 != set) { + DestroyInstance(set); + set = set2; } return set; @@ -471,10 +453,7 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo* classInfo) if (!map) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - set = map->Find(classInfo); - } + set = map->Find(classInfo); if (set) return set; @@ -537,19 +516,16 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo* classInfo) XPCNativeSetKey key(set, nullptr, 0); - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - XPCNativeSet* set2 = map2->Add(&key, set); - if (!set2) { - NS_ERROR("failed to add our set!"); - DestroyInstance(set); - set = nullptr; - goto out; - } - if (set2 != set) { - DestroyInstance(set); - set = set2; - } + XPCNativeSet* set2 = map2->Add(&key, set); + if (!set2) { + NS_ERROR("failed to add our set!"); + DestroyInstance(set); + set = nullptr; + goto out; + } + if (set2 != set) { + DestroyInstance(set); + set = set2; } } } else @@ -557,10 +533,7 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo* classInfo) } else set = GetNewOrUsed(&NS_GET_IID(nsISupports)); - if (set) - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - + if (set) { #ifdef DEBUG XPCNativeSet* set2 = #endif @@ -585,10 +558,7 @@ XPCNativeSet::ClearCacheEntryForClassInfo(nsIClassInfo* classInfo) XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); ClassInfo2NativeSetMap* map = rt->GetClassInfo2NativeSetMap(); if (map) - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); map->Remove(classInfo); - } } // static @@ -606,10 +576,7 @@ XPCNativeSet::GetNewOrUsed(XPCNativeSet* otherSet, XPCNativeSetKey key(otherSet, newInterface, position); - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - set = map->Find(&key); - } + set = map->Find(&key); if (set) return set; @@ -622,17 +589,14 @@ XPCNativeSet::GetNewOrUsed(XPCNativeSet* otherSet, if (!set) return nullptr; - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - XPCNativeSet* set2 = map->Add(&key, set); - if (!set2) { - NS_ERROR("failed to add our set!"); - DestroyInstance(set); - set = nullptr; - } else if (set2 != set) { - DestroyInstance(set); - set = set2; - } + XPCNativeSet* set2 = map->Add(&key, set); + if (!set2) { + NS_ERROR("failed to add our set!"); + DestroyInstance(set); + set = nullptr; + } else if (set2 != set) { + DestroyInstance(set); + set = set2; } return set; diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp index afd3cbf5def..ef717521c92 100644 --- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -1129,11 +1129,8 @@ XPCNativeScriptableInfo::Construct(const XPCNativeScriptableCreateInfo* sci) XPCJSRuntime* rt = XPCJSRuntime::Get(); XPCNativeScriptableSharedMap* map = rt->GetNativeScriptableSharedMap(); - { // scoped lock - XPCAutoLock lock(rt->GetMapLock()); - success = map->GetNewOrUsed(sci->GetFlags(), name, - sci->GetInterfacesBitmap(), newObj); - } + success = map->GetNewOrUsed(sci->GetFlags(), name, + sci->GetInterfacesBitmap(), newObj); if (!success) { delete newObj; diff --git a/js/xpconnect/src/XPCWrappedNativeProto.cpp b/js/xpconnect/src/XPCWrappedNativeProto.cpp index f178d18d6c8..321e07a74ec 100644 --- a/js/xpconnect/src/XPCWrappedNativeProto.cpp +++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp @@ -133,8 +133,6 @@ XPCWrappedNativeProto::JSProtoObjectFinalized(js::FreeOp *fop, JSObject *obj) { MOZ_ASSERT(obj == mJSProtoObject, "huh?"); - // Map locking is not necessary since we are running gc. - // Only remove this proto from the map if it is the one in the map. ClassInfo2WrappedNativeProtoMap* map = GetScope()->GetWrappedNativeProtoMap(ClassIsMainThreadOnly()); @@ -173,7 +171,6 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCWrappedNativeScope* scope, AutoMarkingWrappedNativeProtoPtr proto(cx); ClassInfo2WrappedNativeProtoMap* map = nullptr; - XPCLock* lock = nullptr; uint32_t ciFlags; if (NS_FAILED(classInfo->GetFlags(&ciFlags))) @@ -181,13 +178,9 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCWrappedNativeScope* scope, bool mainThreadOnly = !!(ciFlags & nsIClassInfo::MAIN_THREAD_ONLY); map = scope->GetWrappedNativeProtoMap(mainThreadOnly); - lock = mainThreadOnly ? nullptr : scope->GetRuntime()->GetMapLock(); - { // scoped lock - XPCAutoLock al(lock); - proto = map->Find(classInfo); - if (proto) - return proto; - } + proto = map->Find(classInfo); + if (proto) + return proto; AutoMarkingNativeSetPtr set(cx); set = XPCNativeSet::GetNewOrUsed(classInfo); @@ -201,10 +194,7 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCWrappedNativeScope* scope, return nullptr; } - { // scoped lock - XPCAutoLock al(lock); - map->Add(classInfo, proto); - } + map->Add(classInfo, proto); return proto; } diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index 8e94f21c8e7..39912f68daa 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -79,9 +79,6 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx, MOZ_ASSERT(aGlobal); MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE)); - // scoped lock - XPCAutoLock lock(XPCJSRuntime::Get()->GetMapLock()); - #ifdef DEBUG for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) MOZ_ASSERT(aGlobal != cur->GetGlobalJSObjectPreserveColor(), "dup object"); @@ -298,10 +295,6 @@ WrappedNativeJSGCThingTracer(PLDHashTable *table, PLDHashEntryHdr *hdr, void XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt) { - // FIXME The lock may not be necessary during tracing as that serializes - // access to JS runtime. See bug 380139. - XPCAutoLock lock(rt->GetMapLock()); - // Do JS_CallTracer for all wrapped natives with external references, as // well as any DOM expando objects. for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { @@ -341,8 +334,6 @@ void XPCWrappedNativeScope::SuspectAllWrappers(XPCJSRuntime* rt, nsCycleCollectionNoteRootCallback& cb) { - XPCAutoLock lock(rt->GetMapLock()); - for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { cur->mWrappedNativeMap->Enumerate(WrappedNativeSuspecter, &cb); if (cur->mDOMExpandoSet) { @@ -356,10 +347,6 @@ XPCWrappedNativeScope::SuspectAllWrappers(XPCJSRuntime* rt, void XPCWrappedNativeScope::StartFinalizationPhaseOfGC(JSFreeOp *fop, XPCJSRuntime* rt) { - // FIXME The lock may not be necessary since we are inside JSGC_MARK_END - // callback and GX serializes access to JS runtime. See bug 380139. - XPCAutoLock lock(rt->GetMapLock()); - // We are in JSGC_MARK_END and JSGC_FINALIZE_END must always follow it // calling FinishedFinalizationPhaseOfGC and clearing gDyingScopes in // KillDyingScopes. @@ -396,12 +383,6 @@ XPCWrappedNativeScope::StartFinalizationPhaseOfGC(JSFreeOp *fop, XPCJSRuntime* r void XPCWrappedNativeScope::FinishedFinalizationPhaseOfGC() { - XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); - - // FIXME The lock may not be necessary since we are inside - // JSGC_FINALIZE_END callback and at this point GC still serializes access - // to JS runtime. See bug 380139. - XPCAutoLock lock(rt->GetMapLock()); KillDyingScopes(); } @@ -483,7 +464,6 @@ XPCWrappedNativeScope::SweepAllWrappedNativeTearOffs() void XPCWrappedNativeScope::KillDyingScopes() { - // always called inside the lock! XPCWrappedNativeScope* cur = gDyingScopes; while (cur) { XPCWrappedNativeScope* next = cur->mNext; @@ -589,9 +569,6 @@ WNProtoSecPolicyClearer(PLDHashTable *table, PLDHashEntryHdr *hdr, nsresult XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies() { - // Hold the lock throughout. - XPCAutoLock lock(XPCJSRuntime::Get()->GetMapLock()); - for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { cur->mWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nullptr); cur->mMainThreadWrappedNativeProtoMap->Enumerate(WNProtoSecPolicyClearer, nullptr); @@ -617,8 +594,6 @@ WNProtoRemover(PLDHashTable *table, PLDHashEntryHdr *hdr, void XPCWrappedNativeScope::RemoveWrappedNativeProtos() { - XPCAutoLock al(XPCJSRuntime::Get()->GetMapLock()); - mWrappedNativeProtoMap->Enumerate(WNProtoRemover, GetRuntime()->GetDetachedWrappedNativeProtoMap()); mMainThreadWrappedNativeProtoMap->Enumerate(WNProtoRemover, @@ -714,9 +689,6 @@ XPCWrappedNativeScope::DebugDump(int16_t depth) size_t XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(MallocSizeOf mallocSizeOf) { - XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance(); - XPCAutoLock lock(rt->GetMapLock()); - size_t n = 0; for (XPCWrappedNativeScope *cur = gScopes; cur; cur = cur->mNext) { n += cur->SizeOfIncludingThis(mallocSizeOf); diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 675fe6e8709..b7e8097548e 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -791,12 +791,9 @@ nsXPConnect::RescueOrphansInScope(JSContext *aJSContext, JSObject *aScopeArg) // might need to rescue. nsTArray > wrappersToMove; - { // scoped lock - XPCAutoLock lock(GetRuntime()->GetMapLock()); - Native2WrappedNativeMap *map = scope->GetWrappedNativeMap(); - wrappersToMove.SetCapacity(map->Count()); - map->Enumerate(MoveableWrapperFinder, &wrappersToMove); - } + Native2WrappedNativeMap *map = scope->GetWrappedNativeMap(); + wrappersToMove.SetCapacity(map->Count()); + map->Enumerate(MoveableWrapperFinder, &wrappersToMove); // Now that we have the wrappers, reparent them to the new scope. for (uint32_t i = 0, stop = wrappersToMove.Length(); i < stop; ++i) { @@ -875,10 +872,7 @@ nsXPConnect::SetFunctionThisTranslator(const nsIID & aIID, { XPCJSRuntime* rt = GetRuntime(); IID2ThisTranslatorMap* map = rt->GetThisTranslatorMap(); - { - XPCAutoLock lock(rt->GetMapLock()); // scoped lock - map->Add(aIID, aTranslator); - } + map->Add(aIID, aTranslator); return NS_OK; } diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index ef04673eec9..0e6af6a1db4 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -81,8 +81,6 @@ #include "mozilla/CycleCollectedJSRuntime.h" #include "mozilla/GuardObjects.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/Mutex.h" -#include "mozilla/ReentrantMonitor.h" #include "mozilla/Util.h" #include @@ -251,120 +249,6 @@ inline JSObject* GetWNExpandoChain(JSObject *obj) return JS_GetReservedSlot(obj, WN_XRAYEXPANDOCHAIN_SLOT).toObjectOrNull(); } -/***************************************************************************/ -// Auto locking support class... - -// We PROMISE to never screw this up. -#ifdef _MSC_VER -#pragma warning(disable : 4355) // OK to pass "this" in member initializer -#endif - -typedef mozilla::ReentrantMonitor XPCLock; - -static inline void xpc_Wait(XPCLock* lock) - { - MOZ_ASSERT(lock, "xpc_Wait called with null lock!"); - lock->Wait(); - } - -static inline void xpc_NotifyAll(XPCLock* lock) - { - MOZ_ASSERT(lock, "xpc_NotifyAll called with null lock!"); - lock->NotifyAll(); - } - -// This is a cloned subset of nsAutoMonitor. We want the use of a monitor - -// mostly because we need reenterability - but we also want to support passing -// a null monitor in without things blowing up. This is used for wrappers that -// are guaranteed to be used only on one thread. We avoid lock overhead by -// using a null monitor. By changing this class we can avoid having multiplte -// code paths or (conditional) manual calls to PR_{Enter,Exit}Monitor. -// -// Note that xpconnect only makes *one* monitor and *mostly* holds it locked -// only through very small critical sections. - -class MOZ_STACK_CLASS XPCAutoLock { -public: - - static XPCLock* NewLock(const char* name) - {return new mozilla::ReentrantMonitor(name);} - static void DestroyLock(XPCLock* lock) - {delete lock;} - - XPCAutoLock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : mLock(lock) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - if (mLock) - mLock->Enter(); - } - - ~XPCAutoLock() - { - if (mLock) { - mLock->Exit(); - } - } - -private: - XPCLock* mLock; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER - - // Not meant to be implemented. This makes it a compiler error to - // construct or assign an XPCAutoLock object incorrectly. - XPCAutoLock(void) {} - XPCAutoLock(XPCAutoLock& /*aMon*/) {} - XPCAutoLock& operator =(XPCAutoLock& /*aMon*/) { - return *this; - } - - // Not meant to be implemented. This makes it a compiler error to - // attempt to create an XPCAutoLock object on the heap. - static void* operator new(size_t /*size*/) CPP_THROW_NEW { - return nullptr; - } - static void operator delete(void* /*memory*/) {} -}; - -/************************************************/ - -class MOZ_STACK_CLASS XPCAutoUnlock { -public: - XPCAutoUnlock(XPCLock* lock MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : mLock(lock) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - if (mLock) { - mLock->Exit(); - } - } - - ~XPCAutoUnlock() - { - if (mLock) - mLock->Enter(); - } - -private: - XPCLock* mLock; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER - - // Not meant to be implemented. This makes it a compiler error to - // construct or assign an XPCAutoUnlock object incorrectly. - XPCAutoUnlock(void) {} - XPCAutoUnlock(XPCAutoUnlock& /*aMon*/) {} - XPCAutoUnlock& operator =(XPCAutoUnlock& /*aMon*/) { - return *this; - } - - // Not meant to be implemented. This makes it a compiler error to - // attempt to create an XPCAutoUnlock object on the heap. - static void* operator new(size_t /*size*/) CPP_THROW_NEW { - return nullptr; - } - static void operator delete(void* /*memory*/) {} -}; - /*************************************************************************** **************************************************************************** * @@ -507,8 +391,8 @@ public: } inline XPCRootSetElem* GetNextRoot() { return mNext; } - void AddToRootSet(XPCLock *lock, XPCRootSetElem **listHead); - void RemoveFromRootSet(XPCLock *lock); + void AddToRootSet(XPCRootSetElem **listHead); + void RemoveFromRootSet(); private: XPCRootSetElem *mNext; @@ -610,8 +494,6 @@ public: XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const {return mDetachedWrappedNativeProtoMap;} - XPCLock* GetMapLock() const {return mMapLock;} - bool OnJSContextNew(JSContext* cx); virtual bool @@ -751,7 +633,6 @@ private: XPCNativeScriptableSharedMap* mNativeScriptableSharedMap; XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap; XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap; - XPCLock* mMapLock; PRThread* mThreadRunningGC; nsTArray mWrappedJSToReleaseArray; nsTArray mNativesToReleaseArray; @@ -1960,16 +1841,12 @@ public: #define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );} bool ClassIsSingleton() GET_IT(SINGLETON) - bool ClassIsThreadSafe() GET_IT(THREADSAFE) bool ClassIsMainThreadOnly() GET_IT(MAIN_THREAD_ONLY) bool ClassIsDOMObject() GET_IT(DOM_OBJECT) bool ClassIsPluginObject() GET_IT(PLUGIN_OBJECT) #undef GET_IT - XPCLock* GetLock() const - {return ClassIsThreadSafe() ? GetRuntime()->GetMapLock() : nullptr;} - void SetScriptableInfo(XPCNativeScriptableInfo* si) {MOZ_ASSERT(!mScriptableInfo, "leak here!"); mScriptableInfo = si;} @@ -2222,15 +2099,11 @@ public: JSObject* GetFlatJSObjectPreserveColor() const {return mFlatJSObject;} - XPCLock* - GetLock() const {return IsValid() && HasProto() ? - GetProto()->GetLock() : nullptr;} - XPCNativeSet* - GetSet() const {XPCAutoLock al(GetLock()); return mSet;} + GetSet() const {return mSet;} void - SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;} + SetSet(XPCNativeSet* set) {mSet = set;} static XPCWrappedNative* Get(JSObject *obj) { MOZ_ASSERT(IS_WN_REFLECTOR(obj));