Merge mozilla-inbound to mozilla-central a=merge
authorRazvan Maries <rmaries@mozilla.com>
Tue, 19 Mar 2019 23:54:04 +0200
changeset 465070 d15d511d7fed036d69d37cecbacdea779a983a34
parent 465064 4f6d8ed9e94809f911907725a708627e3faaed01 (current diff)
parent 465069 32eb745d3238ebabb76c5880d40ab6f82f4fbd07 (diff)
child 465118 26fafa29a3eb557f9e41ecd9e6821052475055ce
child 465358 0ce0c7c9a1b6fcddd54643ff05599f3b2ce1d6c7
push id35731
push userrmaries@mozilla.com
push dateTue, 19 Mar 2019 21:55:14 +0000
treeherdermozilla-central@d15d511d7fed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
d15d511d7fed / 68.0a1 / 20190319215514 / files
nightly linux64
d15d511d7fed / 68.0a1 / 20190319215514 / files
nightly mac
d15d511d7fed / 68.0a1 / 20190319215514 / files
nightly win32
d15d511d7fed / 68.0a1 / 20190319215514 / files
nightly win64
d15d511d7fed / 68.0a1 / 20190319215514 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central a=merge
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/QuotaObject.h"
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
+#include "mozilla/Logging.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsISimpleEnumerator.h"
 #include "nsNetUtil.h"
 #include "nsRefPtrHashtable.h"
@@ -2166,19 +2167,19 @@ class LSRequestBase : public DatastoreOp
  protected:
   // Common nsIRunnable implementation that subclasses may not override.
   NS_IMETHOD
   Run() final;
 
   // IPDL methods.
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
+  mozilla::ipc::IPCResult RecvCancel() override;
+
  private:
-  mozilla::ipc::IPCResult RecvCancel() final;
-
   mozilla::ipc::IPCResult RecvFinish() final;
 };
 
 class PrepareDatastoreOp : public LSRequestBase, public OpenDirectoryListener {
   class LoadDataOp;
 
   enum class NestedState {
     // The nesting has not yet taken place. Next step is
@@ -2338,16 +2339,18 @@ class PrepareDatastoreOp : public LSRequ
 
   void CleanupMetadata();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // IPDL overrides.
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
+  mozilla::ipc::IPCResult RecvCancel() final;
+
   // OpenDirectoryListener overrides.
   void DirectoryLockAcquired(DirectoryLock* aLock) override;
 
   void DirectoryLockFailed() override;
 };
 
 class PrepareDatastoreOp::LoadDataOp final
     : public ConnectionDatastoreOperationBase {
@@ -2734,16 +2737,18 @@ typedef nsDataHashtable<nsCStringHashKey
 // Can only be touched on the Quota Manager I/O thread.
 StaticAutoPtr<UsageHashtable> gUsages;
 
 StaticAutoPtr<ArchivedOriginHashtable> gArchivedOrigins;
 
 // Can only be touched on the Quota Manager I/O thread.
 bool gInitializedShadowStorage = false;
 
+LazyLogModule gLogger("LocalStorage");
+
 bool IsOnConnectionThread() {
   MOZ_ASSERT(gConnectionThread);
   return gConnectionThread->IsOnConnectionThread();
 }
 
 void AssertIsOnConnectionThread() {
   MOZ_ASSERT(gConnectionThread);
   gConnectionThread->AssertIsOnConnectionThread();
@@ -5716,16 +5721,62 @@ void LSRequestBase::ActorDestroy(ActorDe
   AssertIsOnOwningThread();
 
   NoteComplete();
 }
 
 mozilla::ipc::IPCResult LSRequestBase::RecvCancel() {
   AssertIsOnOwningThread();
 
+  if (MOZ_LOG_TEST(gLogger, LogLevel::Info)) {
+    MOZ_LOG(gLogger, LogLevel::Info, ("LSRequestBase::RecvCancel"));
+
+    nsCString state;
+
+    switch (mState) {
+      case State::Initial:
+        state.AssignLiteral("Initial");
+        break;
+
+      case State::Opening:
+        state.AssignLiteral("Opening");
+        break;
+
+      case State::Nesting:
+        state.AssignLiteral("Nesting");
+        break;
+
+      case State::SendingReadyMessage:
+        state.AssignLiteral("SendingReadyMessage");
+        break;
+
+      case State::WaitingForFinish:
+        state.AssignLiteral("WaitingForFinish");
+        break;
+
+      case State::SendingResults:
+        state.AssignLiteral("SendingResults");
+        break;
+
+      case State::Completed:
+        state.AssignLiteral("Completed");
+        break;
+
+      default:
+        MOZ_CRASH("Bad state!");
+    }
+
+    MOZ_LOG(gLogger, LogLevel::Info, ("  mState: %s", state.get()));
+  }
+
+  const char* crashOnCancel = PR_GetEnv("LSNG_CRASH_ON_CANCEL");
+  if (crashOnCancel) {
+    MOZ_CRASH("LSNG: Crash on cancel.");
+  }
+
   IProtocol* mgr = Manager();
   if (!PBackgroundLSRequestParent::Send__delete__(this, NS_ERROR_FAILURE)) {
     return IPC_FAIL_NO_REASON(mgr);
   }
 
   return IPC_OK();
 }
 
@@ -6675,16 +6726,75 @@ void PrepareDatastoreOp::ActorDestroy(Ac
 
   LSRequestBase::ActorDestroy(aWhy);
 
   if (mLoadDataOp) {
     mLoadDataOp->NoteComplete();
   }
 }
 
+mozilla::ipc::IPCResult PrepareDatastoreOp::RecvCancel() {
+  AssertIsOnOwningThread();
+
+  if (MOZ_LOG_TEST(gLogger, LogLevel::Info)) {
+    MOZ_LOG(gLogger, LogLevel::Info, ("PrepareDatastoreOp::RecvCancel"));
+
+    nsCString nestedState;
+
+    switch (mNestedState) {
+      case NestedState::BeforeNesting:
+        nestedState.AssignLiteral("BeforeNesting");
+        break;
+
+      case NestedState::CheckExistingOperations:
+        nestedState.AssignLiteral("CheckExistingOperations");
+        break;
+
+      case NestedState::CheckClosingDatastore:
+        nestedState.AssignLiteral("CheckClosingDatastore");
+        break;
+
+      case NestedState::PreparationPending:
+        nestedState.AssignLiteral("PreparationPending");
+        break;
+
+      case NestedState::QuotaManagerPending:
+        nestedState.AssignLiteral("QuotaManagerPending");
+        break;
+
+      case NestedState::DirectoryOpenPending:
+        nestedState.AssignLiteral("DirectoryOpenPending");
+        break;
+
+      case NestedState::DatabaseWorkOpen:
+        nestedState.AssignLiteral("DatabaseWorkOpen");
+        break;
+
+      case NestedState::BeginLoadData:
+        nestedState.AssignLiteral("BeginLoadData");
+        break;
+
+      case NestedState::DatabaseWorkLoadData:
+        nestedState.AssignLiteral("DatabaseWorkLoadData");
+        break;
+
+      case NestedState::AfterNesting:
+        nestedState.AssignLiteral("AfterNesting");
+        break;
+
+      default:
+        MOZ_CRASH("Bad state!");
+    }
+
+    MOZ_LOG(gLogger, LogLevel::Info, ("  mNestedState: %s", nestedState.get()));
+  }
+
+  return LSRequestBase::RecvCancel();
+}
+
 void PrepareDatastoreOp::DirectoryLockAcquired(DirectoryLock* aLock) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mState == State::Nesting);
   MOZ_ASSERT(mNestedState == NestedState::DirectoryOpenPending);
   MOZ_ASSERT(!mDirectoryLock);
 
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnBackgroundThread()) ||
       !MayProceed()) {
--- a/dom/localstorage/LSObject.cpp
+++ b/dom/localstorage/LSObject.cpp
@@ -13,16 +13,28 @@
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsThread.h"
 
+/**
+ * Automatically cancel and abort synchronous LocalStorage requests (for example
+ * datastore preparation) if they take this long.  We've chosen a value that is
+ * long enough that it is unlikely for the problem to be falsely triggered by
+ * slow system I/O.  We've also chosen a value long enough so that automated
+ * tests should time out and fail if LocalStorage hangs.  Also, this value is
+ * long enough so that testers can notice the (content process) hang; we want to
+ * know about the hangs, not hide them.  On the other hand this value is less
+ * than 60 seconds which is used by nsTerminator to crash a hung main process.
+ */
+#define FAILSAFE_CANCEL_SYNC_OP_MS 50000
+
 namespace mozilla {
 namespace dom {
 
 namespace {
 
 class RequestHelper;
 
 StaticMutex gRequestHelperMutex;
@@ -132,27 +144,29 @@ class RequestHelper final : public Runna
   // __destroy__ method.
   LSRequestChild* mActor;
   const LSRequestParams mParams;
   LSRequestResponse mResponse;
   nsresult mResultCode;
   State mState;
   // Control flag for the nested event loop; once set to false, the loop ends.
   bool mWaiting;
+  bool mCancelled;
 
  public:
   RequestHelper(LSObject* aObject, const LSRequestParams& aParams)
       : Runnable("dom::RequestHelper"),
         mObject(aObject),
         mOwningEventTarget(GetCurrentThreadEventTarget()),
         mActor(nullptr),
         mParams(aParams),
         mResultCode(NS_OK),
         mState(State::Initial),
-        mWaiting(true) {}
+        mWaiting(true),
+        mCancelled(false) {}
 
   bool IsOnOwningThread() const {
     MOZ_ASSERT(mOwningEventTarget);
 
     bool current;
     return NS_SUCCEEDED(mOwningEventTarget->IsOnCurrentThread(&current)) &&
            current;
   }
@@ -1073,32 +1087,51 @@ nsresult RequestHelper::StartAndReturnRe
         gSyncLoopEventTarget = nullptr;
       });
 
       rv = domFileThread->Dispatch(this, NS_DISPATCH_NORMAL);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
+      nsCOMPtr<nsITimer> timer = NS_NewTimer();
+
+      MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(mNestedEventTarget));
+
+      MOZ_ALWAYS_SUCCEEDS(timer->InitWithNamedFuncCallback(
+          [](nsITimer* aTimer, void* aClosure) {
+            auto helper = static_cast<RequestHelper*>(aClosure);
+
+            helper->mCancelled = true;
+          },
+          this, FAILSAFE_CANCEL_SYNC_OP_MS, nsITimer::TYPE_ONE_SHOT,
+          "RequestHelper::StartAndReturnResponse::SpinEventLoopTimer"));
+
       MOZ_ALWAYS_TRUE(SpinEventLoopUntil(
           [&]() {
+            if (mCancelled) {
+              return true;
+            }
+
             if (!mWaiting) {
               return true;
             }
 
             {
               StaticMutexAutoLock lock(gRequestHelperMutex);
               if (NS_WARN_IF(gPendingSyncMessage)) {
                 return true;
               }
             }
 
             return false;
           },
           thread));
+
+      MOZ_ALWAYS_SUCCEEDS(timer->Cancel());
     }
 
     // If mWaiting is still set to true, it means that the event loop spinning
     // was aborted and we need to cancel the request in the parent since we
     // don't care about the result anymore.
     // We can check mWaiting here because it's only ever touched on the main
     // thread.
     if (NS_WARN_IF(mWaiting)) {
--- a/js/src/gc/Policy.h
+++ b/js/src/gc/Policy.h
@@ -59,17 +59,17 @@ namespace JS {
 template <typename T>
 struct GCPolicy<T*> : public js::InternalGCPointerPolicy<T*> {};
 template <typename T>
 struct GCPolicy<T* const> : public js::InternalGCPointerPolicy<T* const> {};
 
 template <typename T>
 struct GCPolicy<js::HeapPtr<T>> {
   static void trace(JSTracer* trc, js::HeapPtr<T>* thingp, const char* name) {
-    js::TraceEdge(trc, thingp, name);
+    js::TraceNullableEdge(trc, thingp, name);
   }
   static bool needsSweep(js::HeapPtr<T>* thingp) {
     return js::gc::IsAboutToBeFinalized(thingp);
   }
 };
 
 template <typename T>
 struct GCPolicy<js::ReadBarriered<T>> {
--- a/js/src/jit/arm64/Architecture-arm64.h
+++ b/js/src/jit/arm64/Architecture-arm64.h
@@ -389,20 +389,22 @@ class FloatRegisters {
 // In bytes: slots needed for potential memory->memory move spills.
 //   +8 for cycles
 //   +8 for gpr spills
 //   +8 for double spills
 static const uint32_t ION_FRAME_SLACK_SIZE = 24;
 
 static const uint32_t ShadowStackSpace = 0;
 
-// TODO:
-// This constant needs to be updated to account for whatever near/far branching
-// strategy is used by ARM64.
-static const uint32_t JumpImmediateRange = UINT32_MAX;
+// When our only strategy for far jumps is to encode the offset directly, and
+// not insert any jump islands during assembly for even further jumps, then the
+// architecture restricts us to -2^27 .. 2^27-4, to fit into a signed 28-bit
+// value.  We further reduce this range to allow the far-jump inserting code to
+// have some breathing room.
+static const uint32_t JumpImmediateRange = ((1 << 27) - (20 * 1024 * 1024));
 
 static const uint32_t ABIStackAlignment = 16;
 static const uint32_t CodeAlignment = 16;
 static const bool StackKeptAligned = false;
 
 // Although sp is only usable if 16-byte alignment is kept,
 // the Pseudo-StackPointer enables use of 8-byte alignment.
 static const uint32_t StackAlignment = 8;