author | Kyle Huey <khuey@kylehuey.com> |
Fri, 06 Jul 2012 10:28:51 -0700 | |
changeset 98548 | 03c5347327d89a2bc0101546146235858bac22b7 |
parent 98547 | cd58bfdf6c71142ac0368ef79a85420ce19151bd |
child 98549 | 8e47e74e35783bcb609934346dd3f59db6f3875d |
push id | 23064 |
push user | ryanvm@gmail.com |
push date | Sat, 07 Jul 2012 18:54:06 +0000 |
treeherder | mozilla-central@9533b40ff28b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bent, peterv |
bugs | 765936 |
milestone | 16.0a1 |
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/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1277,16 +1277,18 @@ public: * Drop the JS objects held by aScriptObjectHolder. * * @param aScriptObjectHolder the object that holds JS objects that we want to * drop */ static nsresult DropJSObjects(void* aScriptObjectHolder); #ifdef DEBUG + static bool AreJSObjectsHeld(void* aScriptObjectHolder); + static void CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder, nsWrapperCache* aCache); #endif static void PreserveWrapper(nsISupports* aScriptObjectHolder, nsWrapperCache* aCache) { if (!aCache->PreservingWrapper()) {
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -4448,16 +4448,27 @@ nsContentUtils::DropJSObjects(void* aScr NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects"); nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder); if (--sJSGCThingRootCount == 0) { nsLayoutStatics::Release(); } return rv; } +#ifdef DEBUG +/* static */ +bool +nsContentUtils::AreJSObjectsHeld(void* aScriptHolder) +{ + bool isHeld = false; + sXPConnect->TestJSHolder(aScriptHolder, &isHeld); + return isHeld; +} +#endif + /* static */ void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) { nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling); } static bool SchemeIs(nsIURI* aURI, const char* aScheme)
--- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -13,16 +13,17 @@ #include "nsIScriptContext.h" #include "mozilla/storage.h" #include "nsComponentManagerUtils.h" #include "nsIScriptSecurityManager.h" #include "nsCharSeparatedTokenizer.h" #include "nsContentUtils.h" #include "nsDOMClassInfoID.h" +#include "nsGlobalWindow.h" #include "nsHashKeys.h" #include "nsPIDOMWindow.h" #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "nsXPCOMCID.h" #include "AsyncConnectionHelper.h" #include "CheckPermissionsHelper.h" @@ -408,16 +409,18 @@ IDBFactory::OpenCommon(const nsAString& NS_ASSERTION(mWindow || mOwningObject, "Must have one of these!"); nsCOMPtr<nsPIDOMWindow> window; nsCOMPtr<nsIScriptGlobalObject> sgo; JSObject* scriptOwner = nsnull; if (mWindow) { window = mWindow; + scriptOwner = + static_cast<nsGlobalWindow*>(window.get())->FastGetGlobalJSObject(); } else { scriptOwner = mOwningObject; } nsRefPtr<IDBOpenDBRequest> request = IDBOpenDBRequest::Create(window, scriptOwner, aCallingCx); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
--- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -27,27 +27,24 @@ USING_INDEXEDDB_NAMESPACE IDBRequest::IDBRequest() : mResultVal(JSVAL_VOID), mActorParent(nsnull), mErrorCode(NS_OK), mHaveResultOrErrorCode(false), - mRooted(false), mLineNo(0) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); } IDBRequest::~IDBRequest() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - UnrootResultVal(); } // static already_AddRefed<IDBRequest> IDBRequest::Create(nsISupports* aSource, IDBWrapperCache* aOwnerCache, IDBTransaction* aTransaction, JSContext* aCallingCx) @@ -69,25 +66,23 @@ IDBRequest::Create(nsISupports* aSource, void IDBRequest::Reset() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); mResultVal = JSVAL_VOID; mHaveResultOrErrorCode = false; mError = nsnull; - UnrootResultVal(); } nsresult IDBRequest::NotifyHelperCompleted(HelperBase* aHelper) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!"); - NS_ASSERTION(!PreservingWrapper(), "Already rooted?!"); NS_ASSERTION(JSVAL_IS_VOID(mResultVal), "Should be undefined!"); // See if our window is still valid. If not then we're going to pretend that // we never completed. if (NS_FAILED(CheckInnerWindowCorrectness())) { return NS_OK; } @@ -111,17 +106,17 @@ IDBRequest::NotifyHelperCompleted(Helper } JSObject* global = GetParentObject(); NS_ASSERTION(global, "This should never be null!"); JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if (ac.enter(cx, global)) { - RootResultVal(); + AssertIsRooted(); rv = aHelper->GetSuccessResult(cx, &mResultVal); if (NS_FAILED(rv)) { NS_WARNING("GetSuccessResult failed!"); } } else { NS_WARNING("Failed to enter correct compartment!"); @@ -139,17 +134,16 @@ IDBRequest::NotifyHelperCompleted(Helper return rv; } void IDBRequest::NotifyHelperSentResultsToChildProcess(nsresult aRv) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!mHaveResultOrErrorCode, "Already called!"); - NS_ASSERTION(!PreservingWrapper(), "Already rooted?!"); NS_ASSERTION(JSVAL_IS_VOID(mResultVal), "Should be undefined!"); // See if our window is still valid. If not then we're going to pretend that // we never completed. if (NS_FAILED(CheckInnerWindowCorrectness())) { return; } @@ -166,17 +160,16 @@ IDBRequest::SetError(nsresult aRv) NS_ASSERTION(NS_FAILED(aRv), "Er, what?"); NS_ASSERTION(!mError, "Already have an error?"); mHaveResultOrErrorCode = true; mError = DOMError::CreateForNSResult(aRv); mErrorCode = aRv; mResultVal = JSVAL_VOID; - UnrootResultVal(); } #ifdef DEBUG nsresult IDBRequest::GetErrorCode() const { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(mHaveResultOrErrorCode, "Don't call me yet!"); @@ -234,28 +227,16 @@ IDBRequest::CaptureCaller(JSContext* aCx void IDBRequest::FillScriptErrorEvent(nsScriptErrorEvent* aEvent) const { aEvent->lineNr = mLineNo; aEvent->fileName = mFilename.get(); } -void -IDBRequest::RootResultValInternal() -{ - NS_HOLD_JS_OBJECTS(this, IDBRequest); -} - -void -IDBRequest::UnrootResultValInternal() -{ - NS_DROP_JS_OBJECTS(this, IDBRequest); -} - NS_IMETHODIMP IDBRequest::GetReadyState(nsAString& aReadyState) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (mHaveResultOrErrorCode) { aReadyState.AssignLiteral("done"); } @@ -322,17 +303,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_ NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSource) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction, nsPIDOMEventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBRequest, IDBWrapperCache) tmp->mResultVal = JSVAL_VOID; - tmp->UnrootResultVal(); NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(success) NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSource) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(IDBRequest, IDBWrapperCache) // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because @@ -361,18 +341,16 @@ IDBRequest::PreHandleEvent(nsEventChainP aVisitor.mCanHandle = true; aVisitor.mParentTarget = mTransaction; return NS_OK; } IDBOpenDBRequest::~IDBOpenDBRequest() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - UnrootResultVal(); } // static already_AddRefed<IDBOpenDBRequest> IDBOpenDBRequest::Create(nsPIDOMWindow* aOwner, JSObject* aScriptOwner, JSContext* aCallingCx) { @@ -395,28 +373,16 @@ IDBOpenDBRequest::SetTransaction(IDBTran NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!aTransaction || !mTransaction, "Shouldn't have a transaction here!"); mTransaction = aTransaction; } -void -IDBOpenDBRequest::RootResultValInternal() -{ - NS_HOLD_JS_OBJECTS(this, IDBOpenDBRequest); -} - -void -IDBOpenDBRequest::UnrootResultValInternal() -{ - NS_DROP_JS_OBJECTS(this, IDBOpenDBRequest); -} - NS_IMPL_CYCLE_COLLECTION_CLASS(IDBOpenDBRequest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBOpenDBRequest, IDBRequest) NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(upgradeneeded) NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(blocked) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/dom/indexedDB/IDBRequest.h +++ b/dom/indexedDB/IDBRequest.h @@ -82,50 +82,30 @@ public: void CaptureCaller(JSContext* aCx); void FillScriptErrorEvent(nsScriptErrorEvent* aEvent) const; protected: IDBRequest(); ~IDBRequest(); - virtual void RootResultValInternal(); - virtual void UnrootResultValInternal(); - - void RootResultVal() - { - if (!mRooted) { - RootResultValInternal(); - mRooted = true; - } - } - - void UnrootResultVal() - { - if (mRooted) { - UnrootResultValInternal(); - mRooted = false; - } - } - nsCOMPtr<nsISupports> mSource; nsRefPtr<IDBTransaction> mTransaction; NS_DECL_EVENT_HANDLER(success) NS_DECL_EVENT_HANDLER(error) jsval mResultVal; nsCOMPtr<nsIDOMDOMError> mError; IndexedDBRequestParentBase* mActorParent; nsresult mErrorCode; bool mHaveResultOrErrorCode; - bool mRooted; nsString mFilename; PRUint32 mLineNo; }; class IDBOpenDBRequest : public IDBRequest, public nsIIDBOpenDBRequest { @@ -144,19 +124,16 @@ public: void SetTransaction(IDBTransaction* aTransaction); // nsIDOMEventTarget virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); protected: ~IDBOpenDBRequest(); - virtual void RootResultValInternal(); - virtual void UnrootResultValInternal(); - // Only touched on the main thread. NS_DECL_EVENT_HANDLER(blocked) NS_DECL_EVENT_HANDLER(upgradeneeded) }; END_INDEXEDDB_NAMESPACE #endif // mozilla_dom_indexeddb_idbrequest_h__
--- a/dom/indexedDB/IDBWrapperCache.cpp +++ b/dom/indexedDB/IDBWrapperCache.cpp @@ -43,30 +43,33 @@ IDBWrapperCache::~IDBWrapperCache() if (mScriptOwner) { NS_DROP_JS_OBJECTS(this, IDBWrapperCache); } } bool IDBWrapperCache::SetScriptOwner(JSObject* aScriptOwner) { - if (!aScriptOwner) { - NS_ASSERTION(!mScriptOwner, - "Don't null out existing owner, we need to call " - "DropJSObjects!"); - - return true; - } + NS_ASSERTION(aScriptOwner, "This should never be null!"); mScriptOwner = aScriptOwner; nsISupports* thisSupports = NS_CYCLE_COLLECTION_UPCAST(this, IDBWrapperCache); nsXPCOMCycleCollectionParticipant* participant; CallQueryInterface(this, &participant); nsresult rv = nsContentUtils::HoldJSObjects(thisSupports, participant); if (NS_FAILED(rv)) { NS_WARNING("nsContentUtils::HoldJSObjects failed."); mScriptOwner = nsnull; return false; } return true; } + +#ifdef DEBUG +void +IDBWrapperCache::AssertIsRooted() const +{ + NS_ASSERTION(nsContentUtils::AreJSObjectsHeld(const_cast<IDBWrapperCache*>(this)), + "Why aren't we rooted?!"); +} +#endif
--- a/dom/indexedDB/IDBWrapperCache.h +++ b/dom/indexedDB/IDBWrapperCache.h @@ -41,16 +41,24 @@ public: } static IDBWrapperCache* FromSupports(nsISupports* aSupports) { return static_cast<IDBWrapperCache*>( nsDOMEventTargetHelper::FromSupports(aSupports)); } +#ifdef DEBUG + void AssertIsRooted() const; +#else + inline void AssertIsRooted() const + { + } +#endif + protected: IDBWrapperCache() : mScriptOwner(nsnull) { } virtual ~IDBWrapperCache(); private:
--- a/js/xpconnect/idl/nsIXPConnect.idl +++ b/js/xpconnect/idl/nsIXPConnect.idl @@ -669,16 +669,23 @@ interface nsIXPConnect : nsISupports /** * Stop rooting the JS objects held by aHolder. * @param aHolder The object that hold the rooted JS objects. */ [noscript] void removeJSHolder(in voidPtr aHolder); /** + * Test to see if a JS holder is in our hashtable. + * Only available in debug builds. + * @param aHolder The object to test for. + */ + [noscript] bool testJSHolder(in voidPtr aHolder); + + /** * Note aJSContext as a child to the cycle collector. * @param aJSContext The JSContext to note. * @param aCb The cycle collection traversal callback. */ [noscript,notxpcom] void noteJSContext(in JSContextPtr aJSContext, in nsCCTraversalCallbackRef aCb); /**
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -291,16 +291,27 @@ XPCJSRuntime::RemoveJSHolder(void* aHold if (!mJSHolders.ops) return NS_ERROR_OUT_OF_MEMORY; JS_DHashTableOperate(&mJSHolders, aHolder, JS_DHASH_REMOVE); return NS_OK; } +nsresult +XPCJSRuntime::TestJSHolder(void* aHolder, bool* aRetval) +{ + if (!mJSHolders.ops) + return NS_ERROR_OUT_OF_MEMORY; + + *aRetval = !!JS_DHashTableOperate(&mJSHolders, aHolder, JS_DHASH_LOOKUP); + + return NS_OK; +} + // static void XPCJSRuntime::TraceBlackJS(JSTracer* trc, void* data) { XPCJSRuntime* self = (XPCJSRuntime*)data; // Skip this part if XPConnect is shutting down. We get into // bad locking problems with the thread iteration otherwise. if (!self->GetXPConnect()->IsShuttingDown()) {
--- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -2256,16 +2256,27 @@ nsXPConnect::AddJSHolder(void* aHolder, NS_IMETHODIMP nsXPConnect::RemoveJSHolder(void* aHolder) { return mRuntime->RemoveJSHolder(aHolder); } NS_IMETHODIMP +nsXPConnect::TestJSHolder(void* aHolder, bool* aRetval) +{ +#ifdef DEBUG + return mRuntime->TestJSHolder(aHolder, aRetval); +#else + MOZ_ASSERT(false); + return NS_ERROR_FAILURE; +#endif +} + +NS_IMETHODIMP nsXPConnect::SetReportAllJSExceptions(bool newval) { // Ignore if the environment variable was set. if (gReportAllJSExceptions != 1) gReportAllJSExceptions = newval ? 2 : 0; return NS_OK; }
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -758,16 +758,17 @@ public: static void FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, JSBool isCompartmentGC); inline void AddVariantRoot(XPCTraceableVariant* variant); inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS); inline void AddObjectHolderRoot(XPCJSObjectHolder* holder); nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer); nsresult RemoveJSHolder(void* aHolder); + nsresult TestJSHolder(void* aHolder, bool* aRetval); static void SuspectWrappedNative(XPCWrappedNative *wrapper, nsCycleCollectionTraversalCallback &cb); void DebugDump(PRInt16 depth); void SystemIsBeingShutDown();