Bug 1363318 - Part 2: Label FetchBody. r=baku
authorBevis Tseng <btseng@mozilla.com>
Tue, 16 May 2017 18:12:24 +0800
changeset 409643 5e90e289c6f67b218a60ea7aed7993b2d3ad8319
parent 409642 d343ee1e22d265d01f6b9b466863727d3cb2357a
child 409644 8cc412eac3822bf5e63a813f17cc9fed9ec92939
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1363318
milestone55.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
Bug 1363318 - Part 2: Label FetchBody. r=baku
dom/fetch/Fetch.cpp
dom/fetch/Fetch.h
dom/fetch/Request.cpp
dom/fetch/Request.h
dom/fetch/Response.cpp
dom/fetch/Response.h
xpcom/threads/nsProxyRelease.h
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -1120,36 +1120,43 @@ public:
       mWasNotified = true;
       mBody->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr);
     }
     return true;
   }
 };
 
 template <class Derived>
-FetchBody<Derived>::FetchBody()
+FetchBody<Derived>::FetchBody(nsIGlobalObject* aOwner)
   : mWorkerHolder(nullptr)
+  , mOwner(aOwner)
   , mBodyUsed(false)
 #ifdef DEBUG
   , mReadDone(false)
 #endif
 {
+  MOZ_ASSERT(aOwner);
+
   if (!NS_IsMainThread()) {
     mWorkerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(mWorkerPrivate);
+    mMainThreadEventTarget = mWorkerPrivate->MainThreadEventTarget();
   } else {
     mWorkerPrivate = nullptr;
+    mMainThreadEventTarget = aOwner->EventTargetFor(TaskCategory::Other);
   }
+
+  MOZ_ASSERT(mMainThreadEventTarget);
 }
 
 template
-FetchBody<Request>::FetchBody();
+FetchBody<Request>::FetchBody(nsIGlobalObject* aOwner);
 
 template
-FetchBody<Response>::FetchBody();
+FetchBody<Response>::FetchBody(nsIGlobalObject* aOwner);
 
 template <class Derived>
 FetchBody<Derived>::~FetchBody()
 {
 }
 
 // Returns true if addref succeeded.
 // Always succeeds on main thread.
@@ -1236,21 +1243,17 @@ FetchBody<Derived>::BeginConsumeBody()
   // The FetchBody is not thread-safe refcounted. We addref it here and release
   // it once the stream read is finished.
   if (!AddRefObject()) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIRunnable> r = new BeginConsumeBodyRunnable<Derived>(this);
   nsresult rv = NS_OK;
-  if (mWorkerPrivate) {
-    rv = mWorkerPrivate->DispatchToMainThread(r.forget());
-  } else {
-    rv = NS_DispatchToMainThread(r.forget());
-  }
+  mMainThreadEventTarget->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     ReleaseObject();
     return rv;
   }
   return NS_OK;
 }
 
 /*
@@ -1271,17 +1274,18 @@ FetchBody<Derived>::BeginConsumeBodyMain
     rv = NS_NewCStringInputStream(getter_AddRefs(stream), EmptyCString());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
   }
 
   nsCOMPtr<nsIInputStreamPump> pump;
   rv = NS_NewInputStreamPump(getter_AddRefs(pump),
-                             stream);
+                             stream, -1, -1, 0, 0, false,
+                             mMainThreadEventTarget);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   RefPtr<ConsumeBodyDoneObserver<Derived>> p = new ConsumeBodyDoneObserver<Derived>(this);
 
   nsCOMPtr<nsIStreamListener> listener;
   if (mConsumeType == CONSUME_BLOB) {
@@ -1294,17 +1298,18 @@ FetchBody<Derived>::BeginConsumeBodyMain
     // it's system or content not in private Browsing.
     if (principalInfo &&
         (principalInfo->type() == mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo ||
          (principalInfo->type() == mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
           principalInfo->get_ContentPrincipalInfo().attrs().mPrivateBrowsingId == 0))) {
       type = MutableBlobStorage::eCouldBeInTemporaryFile;
     }
 
-    listener = new MutableBlobStreamListener(type, nullptr, mMimeType, p);
+    listener = new MutableBlobStreamListener(type, nullptr, mMimeType, p,
+                                             mMainThreadEventTarget);
   } else {
     nsCOMPtr<nsIStreamLoader> loader;
     rv = NS_NewStreamLoader(getter_AddRefs(loader), p);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
     listener = loader;
@@ -1312,17 +1317,18 @@ FetchBody<Derived>::BeginConsumeBodyMain
 
   rv = pump->AsyncRead(listener, nullptr);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   // Now that everything succeeded, we can assign the pump to a pointer that
   // stays alive for the lifetime of the FetchBody.
-  mConsumeBodyPump = new nsMainThreadPtrHolder<nsIInputStreamPump>(pump);
+  mConsumeBodyPump =
+    new nsMainThreadPtrHolder<nsIInputStreamPump>(pump, mMainThreadEventTarget);
   // It is ok for retargeting to fail and reads to happen on the main thread.
   autoReject.DontFail();
 
   // Try to retarget, otherwise fall back to main thread.
   nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(pump);
   if (rr) {
     nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     rv = rr->RetargetDeliveryTo(sts);
--- a/dom/fetch/Fetch.h
+++ b/dom/fetch/Fetch.h
@@ -18,16 +18,17 @@
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/dom/workers/bindings/WorkerHolder.h"
 
 class nsIGlobalObject;
+class nsIEventTarget;
 
 namespace mozilla {
 namespace dom {
 
 class BlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString;
 class BlobImpl;
 class InternalRequest;
 class OwningBlobOrArrayBufferViewOrArrayBufferOrFormDataOrURLSearchParamsOrUSVString;
@@ -164,17 +165,19 @@ public:
   // Always set whenever the FetchBody is created on the worker thread.
   workers::WorkerPrivate* mWorkerPrivate;
 
   // Set when consuming the body is attempted on a worker.
   // Unset when consumption is done/aborted.
   nsAutoPtr<workers::WorkerHolder> mWorkerHolder;
 
 protected:
-  FetchBody();
+  nsCOMPtr<nsIGlobalObject> mOwner;
+
+  explicit FetchBody(nsIGlobalObject* aOwner);
 
   virtual ~FetchBody();
 
   void
   SetMimeType();
 private:
   enum ConsumeType
   {
@@ -228,14 +231,17 @@ private:
   // Only touched on target thread.
   ConsumeType mConsumeType;
   RefPtr<Promise> mConsumePromise;
 #ifdef DEBUG
   bool mReadDone;
 #endif
 
   nsMainThreadPtrHandle<nsIInputStreamPump> mConsumeBodyPump;
+
+  // The main-thread event target for runnable dispatching.
+  nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Fetch_h
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -28,18 +28,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(Request
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
-  : FetchBody<Request>()
-  , mOwner(aOwner)
+  : FetchBody<Request>(aOwner)
   , mRequest(aRequest)
 {
   MOZ_ASSERT(aRequest->Headers()->Guard() == HeadersGuardEnum::Immutable ||
              aRequest->Headers()->Guard() == HeadersGuardEnum::Request ||
              aRequest->Headers()->Guard() == HeadersGuardEnum::Request_no_cors);
   SetMimeType();
 }
 
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -151,17 +151,16 @@ public:
   GetPrincipalInfo() const
   {
     return mRequest->GetPrincipalInfo();
   }
 
 private:
   ~Request();
 
-  nsCOMPtr<nsIGlobalObject> mOwner;
   RefPtr<InternalRequest> mRequest;
   // Lazily created.
   RefPtr<Headers> mHeaders;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/fetch/Response.cpp
+++ b/dom/fetch/Response.cpp
@@ -29,18 +29,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(Respons
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Response, mOwner, mHeaders)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Response)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse)
-  : FetchBody<Response>()
-  , mOwner(aGlobal)
+  : FetchBody<Response>(aGlobal)
   , mInternalResponse(aInternalResponse)
 {
   MOZ_ASSERT(aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Immutable ||
              aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Response);
   SetMimeType();
 }
 
 Response::~Response()
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -132,17 +132,16 @@ public:
   SetBody(nsIInputStream* aBody, int64_t aBodySize);
 
   already_AddRefed<InternalResponse>
   GetInternalResponse() const;
 
 private:
   ~Response();
 
-  nsCOMPtr<nsIGlobalObject> mOwner;
   RefPtr<InternalResponse> mInternalResponse;
   // Lazily created
   RefPtr<Headers> mHeaders;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/xpcom/threads/nsProxyRelease.h
+++ b/xpcom/threads/nsProxyRelease.h
@@ -227,41 +227,49 @@ template<class T>
 class nsMainThreadPtrHolder final
 {
 public:
   // We can only acquire a pointer on the main thread. We to fail fast for
   // threading bugs, so by default we assert if our pointer is used or acquired
   // off-main-thread. But some consumers need to use the same pointer for
   // multiple classes, some of which are main-thread-only and some of which
   // aren't. So we allow them to explicitly disable this strict checking.
-  explicit nsMainThreadPtrHolder(T* aPtr, bool aStrict = true)
+  explicit nsMainThreadPtrHolder(T* aPtr, bool aStrict = true,
+                                 nsIEventTarget* aMainThreadEventTarget = nullptr)
     : mRawPtr(nullptr)
     , mStrict(aStrict)
+    , mMainThreadEventTarget(aMainThreadEventTarget)
   {
     // We can only AddRef our pointer on the main thread, which means that the
     // holder must be constructed on the main thread.
     MOZ_ASSERT(!mStrict || NS_IsMainThread());
     NS_IF_ADDREF(mRawPtr = aPtr);
   }
-  explicit nsMainThreadPtrHolder(already_AddRefed<T> aPtr, bool aString = true)
+  explicit nsMainThreadPtrHolder(already_AddRefed<T> aPtr, bool aString = true,
+                                 nsIEventTarget* aMainThreadEventTarget = nullptr)
     : mRawPtr(aPtr.take())
     , mStrict(aString)
+    , mMainThreadEventTarget(aMainThreadEventTarget)
   {
     // Since we don't need to AddRef the pointer, this constructor is safe to
     // call on any thread.
   }
 
 private:
   // We can be released on any thread.
   ~nsMainThreadPtrHolder()
   {
     if (NS_IsMainThread()) {
       NS_IF_RELEASE(mRawPtr);
     } else if (mRawPtr) {
-      NS_ReleaseOnMainThread(dont_AddRef(mRawPtr));
+      if (!mMainThreadEventTarget) {
+        mMainThreadEventTarget = do_GetMainThread();
+      }
+      MOZ_ASSERT(mMainThreadEventTarget);
+      NS_ProxyRelease(mMainThreadEventTarget, dont_AddRef(mRawPtr));
     }
   }
 
 public:
   T* get()
   {
     // Nobody should be touching the raw pointer off-main-thread.
     if (mStrict && MOZ_UNLIKELY(!NS_IsMainThread())) {
@@ -284,16 +292,18 @@ public:
 
 private:
   // Our wrapped pointer.
   T* mRawPtr;
 
   // Whether to strictly enforce thread invariants in this class.
   bool mStrict;
 
+  nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
+
   // Copy constructor and operator= not implemented. Once constructed, the
   // holder is immutable.
   T& operator=(nsMainThreadPtrHolder& aOther);
   nsMainThreadPtrHolder(const nsMainThreadPtrHolder& aOther);
 };
 
 template<class T>
 class nsMainThreadPtrHandle