Merge inbound to mozilla-central r=merge a=merge
authorCiure Andrei <aciure@mozilla.com>
Mon, 27 Nov 2017 11:46:41 +0200
changeset 438252 cad9c9573579698c223b4b6cb53ca723cd930ad2
parent 438243 da90245d47b17c750560dedb5cbe1973181166e3 (current diff)
parent 438251 163e415d22df1847d49320a83bacbf166adef7cb (diff)
child 438279 733e8e93c516b6b391f32f29eb08e0ab3d99fe1b
child 438330 e576f9269c5745636fff03b12e21030d7c8cad23
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersmerge, merge
milestone59.0a1
Merge inbound to mozilla-central r=merge a=merge
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -10,16 +10,17 @@
 #include "Layers.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaFormatReader.h"
 #include "MediaResource.h"
 #include "MediaShutdownManager.h"
 #include "VideoFrameContainer.h"
 #include "VideoUtils.h"
 #include "mozilla/AbstractThread.h"
+#include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/AudioTrack.h"
 #include "mozilla/dom/AudioTrackList.h"
 #include "mozilla/dom/VideoTrack.h"
@@ -198,40 +199,42 @@ class MediaDecoder::BackgroundVideoDecod
     }
   private:
     ~BackgroundVideoDecodingPermissionObserver() {
       MOZ_ASSERT(!mIsRegisteredForEvent);
     }
 
     void EnableEvent() const
     {
-      nsCOMPtr<nsPIDOMWindowOuter> win = GetOwnerWindow();
-      if (!win) {
+      nsIDocument* doc = GetOwnerDoc();
+      if (!doc) {
         return;
       }
-      nsContentUtils::DispatchEventOnlyToChrome(
-        GetOwnerDoc(), ToSupports(win),
-        NS_LITERAL_STRING("UnselectedTabHover:Enable"),
-        /* Bubbles */ true,
-        /* Cancelable */ false,
-        /* DefaultAction */ nullptr);
+
+      RefPtr<AsyncEventDispatcher> asyncDispatcher =
+        new AsyncEventDispatcher(doc,
+                                 NS_LITERAL_STRING("UnselectedTabHover:Enable"),
+                                 /* Bubbles */ true,
+                                 /* OnlyChromeDispatch */ true);
+      asyncDispatcher->PostDOMEvent();
     }
 
     void DisableEvent() const
     {
-      nsCOMPtr<nsPIDOMWindowOuter> win = GetOwnerWindow();
-      if (!win) {
+      nsIDocument* doc = GetOwnerDoc();
+      if (!doc) {
         return;
       }
-      nsContentUtils::DispatchEventOnlyToChrome(
-        GetOwnerDoc(), ToSupports(win),
-        NS_LITERAL_STRING("UnselectedTabHover:Disable"),
-        /* Bubbles */ true,
-        /* Cancelable */ false,
-        /* DefaultAction */ nullptr);
+
+      RefPtr<AsyncEventDispatcher> asyncDispatcher =
+        new AsyncEventDispatcher(doc,
+                                 NS_LITERAL_STRING("UnselectedTabHover:Disable"),
+                                 /* Bubbles */ true,
+                                 /* OnlyChromeDispatch */ true);
+      asyncDispatcher->PostDOMEvent();
     }
 
     already_AddRefed<nsPIDOMWindowOuter> GetOwnerWindow() const
     {
       nsIDocument* doc = GetOwnerDoc();
       if (!doc) {
         return nullptr;
       }
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-52374
+52375
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -43514,16 +43514,17 @@ sclerotic
 scoff/MDRSZG
 scoffer/M
 scofflaw/MS
 scold/MDSGJ
 scolding/M
 scoliosis/M
 sconce/SM
 scone/MS
+scooch/DGS
 scoop/MDSG
 scoopful/MS
 scoot/DRSZG
 scooter/M
 scope/MGDS
 scorbutic
 scorch/MDRSZG
 scorcher/M
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -302,16 +302,19 @@ DrawTargetSkia::~DrawTargetSkia()
     mColorSpace = nullptr;
   }
 #endif
 }
 
 already_AddRefed<SourceSurface>
 DrawTargetSkia::Snapshot()
 {
+  // Without this lock, this could cause us to get out a snapshot and race with
+  // Snapshot::~Snapshot() actually destroying itself.
+  MutexAutoLock lock(*mSnapshotLock);
   RefPtr<SourceSurfaceSkia> snapshot = mSnapshot;
   if (mSurface && !snapshot) {
     snapshot = new SourceSurfaceSkia();
     sk_sp<SkImage> image;
     // If the surface is raster, making a snapshot may trigger a pixel copy.
     // Instead, try to directly make a raster image referencing the surface pixels.
     SkPixmap pixmap;
     if (mSurface->peekPixels(&pixmap)) {
--- a/js/src/gc/Cell.h
+++ b/js/src/gc/Cell.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef gc_Cell_h
 #define gc_Cell_h
 
 #include "gc/GCEnum.h"
 #include "gc/Heap.h"
 #include "js/GCAnnotations.h"
+#include "js/TraceKind.h"
 
 namespace JS {
 
 namespace shadow {
 struct Zone;
 } /* namespace shadow */
 
 enum class TraceKind;
@@ -70,16 +71,33 @@ struct Cell
     // The StoreBuffer used to record incoming pointers from the tenured heap.
     // This will return nullptr for a tenured cell.
     inline StoreBuffer* storeBuffer() const;
 
     inline JS::TraceKind getTraceKind() const;
 
     static MOZ_ALWAYS_INLINE bool needWriteBarrierPre(JS::Zone* zone);
 
+    template <class T>
+    inline bool is() const {
+        return getTraceKind() == JS::MapTypeToTraceKind<T>::kind;
+    }
+
+    template<class T>
+    inline T* as() {
+        MOZ_ASSERT(is<T>());
+        return static_cast<T*>(this);
+    }
+
+    template <class T>
+    inline const T* as() const {
+        MOZ_ASSERT(is<T>());
+        return static_cast<const T*>(this);
+    }
+
 #ifdef DEBUG
     inline bool isAligned() const;
     void dump(GenericPrinter& out) const;
     void dump() const;
 #endif
 
   protected:
     uintptr_t address() const;
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -44,17 +44,18 @@ enum class State {
     D(NonIncrementalRequested) \
     D(AbortRequested) \
     D(Unused1) \
     D(IncrementalDisabled) \
     D(ModeChange) \
     D(MallocBytesTrigger) \
     D(GCBytesTrigger) \
     D(ZoneChange) \
-    D(CompartmentRevived)
+    D(CompartmentRevived) \
+    D(GrayRootBufferingFailed)
 enum class AbortReason {
 #define MAKE_REASON(name) name,
     GC_ABORT_REASONS(MAKE_REASON)
 #undef MAKE_REASON
 };
 
 #define JS_FOR_EACH_ZEAL_MODE(D)       \
     D(RootsChange, 1)                  \
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -685,19 +685,19 @@ CheckGrayMarkingTracer::checkCell(Cell* 
         failures++;
 
         fprintf(stderr, "Found black to gray edge to ");
         dumpCellInfo(cell);
         fprintf(stderr, "\n");
         dumpCellPath();
 
 #ifdef DEBUG
-        if (cell->getTraceKind() == JS::TraceKind::Object) {
+        if (cell->is<JSObject>()) {
             fprintf(stderr, "\n");
-            DumpObject(static_cast<JSObject*>(cell), stderr);
+            DumpObject(cell->as<JSObject>(), stderr);
         }
 #endif
     }
 }
 
 bool
 CheckGrayMarkingTracer::check(AutoLockForExclusiveAccess& lock)
 {
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -6951,16 +6951,17 @@ GCRuntime::incrementalCollectSlice(Slice
       case State::Mark:
         for (const CooperatingContext& target : rt->cooperatingContexts())
             AutoGCRooter::traceAllWrappers(target, &marker);
 
         /* If we needed delayed marking for gray roots, then collect until done. */
         if (!hasBufferedGrayRoots()) {
             budget.makeUnlimited();
             isIncremental = false;
+            stats().nonincremental(AbortReason::GrayRootBufferingFailed);
         }
 
         if (drainMarkStack(budget, gcstats::PhaseKind::MARK) == NotFinished)
             break;
 
         MOZ_ASSERT(marker.isDrained());
 
         /*
@@ -8263,17 +8264,17 @@ JS::AssertGCThingMustBeTenured(JSObject*
                (!IsNurseryAllocable(obj->asTenured().getAllocKind()) ||
                 obj->getClass()->hasFinalize()));
 }
 
 JS_FRIEND_API(void)
 JS::AssertGCThingIsNotAnObjectSubclass(Cell* cell)
 {
     MOZ_ASSERT(cell);
-    MOZ_ASSERT(cell->getTraceKind() != JS::TraceKind::Object);
+    MOZ_ASSERT(!cell->is<JSObject>());
 }
 
 JS_FRIEND_API(void)
 js::gc::AssertGCThingHasType(js::gc::Cell* cell, JS::TraceKind kind)
 {
     if (!cell) {
         MOZ_ASSERT(kind == JS::TraceKind::Null);
         return;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5182,37 +5182,37 @@ GetScriptReferentCell(JSObject* obj)
     return static_cast<gc::Cell*>(obj->as<NativeObject>().getPrivate());
 }
 
 static inline DebuggerScriptReferent
 GetScriptReferent(JSObject* obj)
 {
     MOZ_ASSERT(obj->getClass() == &DebuggerScript_class);
     if (gc::Cell* cell = GetScriptReferentCell(obj)) {
-        if (cell->getTraceKind() == JS::TraceKind::Script)
-            return AsVariant(static_cast<JSScript*>(cell));
-        MOZ_ASSERT(cell->getTraceKind() == JS::TraceKind::Object);
+        if (cell->is<JSScript>())
+            return AsVariant(cell->as<JSScript>());
+        MOZ_ASSERT(cell->is<JSObject>());
         return AsVariant(&static_cast<NativeObject*>(cell)->as<WasmInstanceObject>());
     }
     return AsVariant(static_cast<JSScript*>(nullptr));
 }
 
 void
 DebuggerScript_trace(JSTracer* trc, JSObject* obj)
 {
     /* This comes from a private pointer, so no barrier needed. */
     gc::Cell* cell = GetScriptReferentCell(obj);
     if (cell) {
-        if (cell->getTraceKind() == JS::TraceKind::Script) {
-            JSScript* script = static_cast<JSScript*>(cell);
+        if (cell->is<JSScript>()) {
+            JSScript* script = cell->as<JSScript>();
             TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &script,
                                                        "Debugger.Script script referent");
             obj->as<NativeObject>().setPrivateUnbarriered(script);
         } else {
-            JSObject* wasm = static_cast<JSObject*>(cell);
+            JSObject* wasm = cell->as<JSObject>();
             TraceManuallyBarrieredCrossCompartmentEdge(trc, obj, &wasm,
                                                        "Debugger.Script wasm referent");
             MOZ_ASSERT(wasm->is<WasmInstanceObject>());
             obj->as<NativeObject>().setPrivateUnbarriered(wasm);
         }
     }
 }
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3069,20 +3069,22 @@ TransformGfxRectToAncestor(nsIFrame *aFr
     }
   }
   // Fill out the axis-alignment flag
   if (aPreservesAxisAlignedRectangles) {
     Matrix matrix2d;
     *aPreservesAxisAlignedRectangles =
       ctm.Is2D(&matrix2d) && matrix2d.PreservesAxisAlignedRectangles();
   }
-  Rect maxBounds = Rect(-std::numeric_limits<float>::max() * 0.5,
-                        -std::numeric_limits<float>::max() * 0.5,
-                        std::numeric_limits<float>::max(),
-                        std::numeric_limits<float>::max());
+  const nsIFrame* ancestor = aOutAncestor ? *aOutAncestor : aAncestor;
+  float factor = ancestor->PresContext()->AppUnitsPerDevPixel();
+  Rect maxBounds = Rect(float(nscoord_MIN) / factor * 0.5,
+                        float(nscoord_MIN) / factor * 0.5,
+                        float(nscoord_MAX) / factor,
+                        float(nscoord_MAX) / factor);
   return ctm.TransformAndClipBounds(aRect, maxBounds);
 }
 
 static SVGTextFrame*
 GetContainingSVGTextFrame(nsIFrame* aFrame)
 {
   if (!nsSVGUtils::IsInSVGTextSubtree(aFrame)) {
     return nullptr;
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2735,32 +2735,39 @@ nsIFrame::BuildDisplayListForStackingCon
       return;
     }
   }
 
   if (disp->mWillChangeBitField != 0) {
     aBuilder->AddToWillChangeBudget(this, GetSize());
   }
 
+  // For preserves3d, use the dirty rect already installed on the
+  // builder, since aDirtyRect maybe distorted for transforms along
+  // the chain.
+  nsRect visibleRect = aBuilder->GetVisibleRect();
+  nsRect dirtyRect = aBuilder->GetDirtyRect();
+
   bool extend3DContext = Extend3DContext(disp, effectSet);
   Maybe<nsDisplayListBuilder::AutoPreserves3DContext> autoPreserves3DContext;
   if (extend3DContext && !Combines3DTransformWithAncestors(disp)) {
     // Start a new preserves3d context to keep informations on
     // nsDisplayListBuilder.
     autoPreserves3DContext.emplace(aBuilder);
     // Save dirty rect on the builder to avoid being distorted for
     // multiple transforms along the chain.
     aBuilder->SavePreserves3DRect();
-  }
-
-  // For preserves3d, use the dirty rect already installed on the
-  // builder, since aDirtyRect maybe distorted for transforms along
-  // the chain.
-  nsRect visibleRect = aBuilder->GetVisibleRect();
-  nsRect dirtyRect = aBuilder->GetDirtyRect();
+
+    // We rebuild everything within preserve-3d and don't try
+    // to retain, so override the dirty rect now.
+    if (aBuilder->IsRetainingDisplayList()) {
+      dirtyRect = visibleRect;
+      aBuilder->MarkFrameModifiedDuringBuilding(this);
+    }
+  }
 
   bool inTransform = aBuilder->IsInTransform();
   bool isTransformed = IsTransformed(disp);
   bool hasPerspective = HasPerspective(disp);
   // reset blend mode so we can keep track if this stacking context needs have
   // a nsDisplayBlendContainer. Set the blend mode back when the routine exits
   // so we keep track if the parent stacking context needs a container too.
   AutoSaveRestoreContainsBlendMode autoRestoreBlendMode(*aBuilder);
@@ -2803,17 +2810,19 @@ nsIFrame::BuildDisplayListForStackingCon
         dirtyRect.SetEmpty();
         visibleRect.SetEmpty();
       }
     }
     inTransform = true;
   }
 
   bool hasOverrideDirtyRect = false;
-  if (HasOverrideDirtyRegion() && !aBuilder->InInvalidSubtree()) {
+  // If we have an override dirty region, and neither us nor our ancestors are
+  // modified, then use it.
+  if (HasOverrideDirtyRegion() && !aBuilder->InInvalidSubtree() && !IsFrameModified()) {
     nsDisplayListBuilder::DisplayListBuildingData* data =
       GetProperty(nsDisplayListBuilder::DisplayListBuildingRect());
     if (data) {
       dirtyRect = data->mDirtyRect.Intersect(visibleRect);
       hasOverrideDirtyRect = true;
     }
   }
   // Always build the entire display list if we previously had a blend