merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 28 Oct 2017 23:58:53 +0200
changeset 439628 ed73b55a33120d27efc862eb87d332e167c026f4
parent 439618 d205f9c3b456d1c5cf7c629bd5d424f2562ccc72 (current diff)
parent 439627 c0eb1f08953b31362483a415465d2964a67a5f0c (diff)
child 439636 d58c5cb053be123a9ede85cabce3b060c13cf66d
child 439673 4aa8283cbeaa83cbf18461eaee8b9e6f0de8b7bd
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
ed73b55a3312 / 58.0a1 / 20171028220326 / files
nightly linux64
ed73b55a3312 / 58.0a1 / 20171028220326 / files
nightly mac
ed73b55a3312 / 58.0a1 / 20171028220326 / files
nightly win32
ed73b55a3312 / 58.0a1 / 20171028220326 / files
nightly win64
ed73b55a3312 / 58.0a1 / 20171028220326 / 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. r=merge a=merge MozReview-Commit-ID: 2ZpDkstVKjg
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -122,16 +122,18 @@
 #include "nsDeviceContext.h"
 #include "nsFontMetrics.h"
 #include "Units.h"
 #include "CanvasUtils.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/layers/CanvasClient.h"
+#include "mozilla/layers/WebRenderUserData.h"
+#include "mozilla/layers/WebRenderCanvasRenderer.h"
 #include "mozilla/ServoCSSParser.h"
 
 #undef free // apparently defined by some windows header, clashing with a free()
             // method in SkTypes.h
 #include "SkiaGLGlue.h"
 #ifdef USE_SKIA
 #include "SurfaceTypes.h"
 #include "GLBlitHelper.h"
@@ -6213,16 +6215,74 @@ CanvasRenderingContext2D::GetCanvasLayer
   canvasLayer->SetContentFlags(flags);
 
   mResetLayer = false;
 
   return canvasLayer.forget();
 }
 
 bool
+CanvasRenderingContext2D::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                                    WebRenderCanvasData* aCanvasData)
+{
+  if (mOpaque || mIsSkiaGL) {
+    // If we're opaque then make sure we have a surface so we paint black
+    // instead of transparent.
+    // If we're using SkiaGL, then SkiaGLTex() below needs the target to
+    // be accessible.
+    EnsureTarget();
+  }
+
+  // Don't call EnsureTarget() ... if there isn't already a surface, then
+  // we have nothing to paint and there is no need to create a surface just
+  // to paint nothing. Also, EnsureTarget() can cause creation of a persistent
+  // layer manager which must NOT happen during a paint.
+  if (!mBufferProvider && !IsTargetValid()) {
+    // No DidTransactionCallback will be received, so mark the context clean
+    // now so future invalidations will be dispatched.
+    MarkContextClean();
+    // Clear CanvasRenderer of WebRenderCanvasData
+    aCanvasData->ClearCanvasRenderer();
+    return false;
+  }
+
+  CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
+
+  if(!mResetLayer && renderer) {
+    CanvasInitializeData data;
+
+    if (mIsSkiaGL) {
+      GLuint skiaGLTex = SkiaGLTex();
+      if (skiaGLTex) {
+        SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
+        MOZ_ASSERT(glue);
+        data.mGLContext = glue->GetGLContext();
+        data.mFrontbufferGLTex = skiaGLTex;
+      }
+    }
+    data.mBufferProvider = mBufferProvider;
+
+    if (renderer->IsDataValid(data)) {
+      return true;
+    }
+  }
+
+  renderer = aCanvasData->CreateCanvasRenderer();
+  if (!InitializeCanvasRenderer(aBuilder, renderer)) {
+    // Clear CanvasRenderer of WebRenderCanvasData
+    aCanvasData->ClearCanvasRenderer();
+    return false;
+  }
+
+  MOZ_ASSERT(renderer);
+  mResetLayer = false;
+  return true;
+}
+
+bool
 CanvasRenderingContext2D::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                                    CanvasRenderer* aRenderer)
 {
   CanvasInitializeData data;
   data.mSize = GetSize();
   data.mHasAlpha = !mOpaque;
   data.mPreTransCallback = CanvasRenderingContext2DUserData::PreTransactionCallback;
   data.mPreTransCallbackData = this;
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -462,16 +462,20 @@ public:
   }
 
   virtual void SetIsOpaque(bool aIsOpaque) override;
   bool GetIsOpaque() override { return mOpaque; }
   NS_IMETHOD Reset() override;
   already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          Layer* aOldLayer,
                                          LayerManager* aManager) override;
+
+  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                 WebRenderCanvasData* aCanvasData) override;
+
   bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                 CanvasRenderer* aRenderer) override;
   virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;
   void MarkContextClean() override;
   void MarkContextCleanForFrameCapture() override;
   bool IsContextCleanForFrameCapture() override;
   NS_IMETHOD SetIsIPC(bool aIsIPC) override;
   // this rect is in canvas device space
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -45,16 +45,18 @@
 #include "nsIWidget.h"
 #include "nsIXPConnect.h"
 #include "nsServiceManagerUtils.h"
 #include "SVGObserverUtils.h"
 #include "prenv.h"
 #include "ScopedGLHelpers.h"
 #include "VRManagerChild.h"
 #include "mozilla/layers/TextureClientSharedSurface.h"
+#include "mozilla/layers/WebRenderUserData.h"
+#include "mozilla/layers/WebRenderCanvasRenderer.h"
 
 // Local
 #include "CanvasUtils.h"
 #include "WebGL1Context.h"
 #include "WebGLActiveInfo.h"
 #include "WebGLBuffer.h"
 #include "WebGLContextLossHandler.h"
 #include "WebGLContextUtils.h"
@@ -1346,16 +1348,38 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
     canvasLayer->SetContentFlags(flags);
 
     mResetLayer = false;
 
     return canvasLayer.forget();
 }
 
 bool
+WebGLContext::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                        WebRenderCanvasData* aCanvasData)
+{
+  CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
+
+  if(!mResetLayer && renderer) {
+    return true;
+  }
+
+  renderer = aCanvasData->CreateCanvasRenderer();
+  if (!InitializeCanvasRenderer(aBuilder, renderer)) {
+    // Clear CanvasRenderer of WebRenderCanvasData
+    aCanvasData->ClearCanvasRenderer();
+    return false;
+  }
+
+  MOZ_ASSERT(renderer);
+  mResetLayer = false;
+  return true;
+}
+
+bool
 WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                        CanvasRenderer* aRenderer)
 {
     if (IsContextLost())
         return false;
 
     CanvasInitializeData data;
     if (aBuilder->IsPaintingToWindow() && mCanvasElement) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -429,16 +429,21 @@ public:
         return ActiveBoundTextureForTarget(texTarget);
     }
 
     void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
 
     already_AddRefed<Layer>
     GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
                    LayerManager* manager) override;
+
+    bool
+    UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                              WebRenderCanvasData* aCanvasData) override;
+
     bool
     InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                              CanvasRenderer* aRenderer) override;
 
     // Note that 'clean' here refers to its invalidation state, not the
     // contents of the buffer.
     void MarkContextClean() override { mInvalidated = false; }
 
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -24,31 +24,33 @@
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
 class CanvasRenderer;
 class Layer;
 class LayerManager;
+class WebRenderCanvasData;
 } // namespace layers
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 } // namespace mozilla
 
 class nsICanvasRenderingContextInternal :
   public nsISupports,
   public nsAPostRefreshObserver
 {
 public:
   typedef mozilla::layers::CanvasLayer CanvasLayer;
   typedef mozilla::layers::CanvasRenderer CanvasRenderer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
+  typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
   void SetCanvasElement(mozilla::dom::HTMLCanvasElement* parentCanvas)
   {
     RemovePostRefreshObserver();
     mCanvasElement = parentCanvas;
     AddPostRefreshObserverIfNecessary();
@@ -135,16 +137,18 @@ public:
   // for possibly reinitializing with SetDimensions/InitializeWithSurface.
   NS_IMETHOD Reset() = 0;
 
   // Return the CanvasLayer for this context, creating
   // one for the given layer manager if not available.
   virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
                                                  Layer *oldLayer,
                                                  LayerManager *manager) = 0;
+  virtual bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                         WebRenderCanvasData* aCanvasData) { return false; }
   virtual bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                         CanvasRenderer* aRenderer) { return true; }
 
   // Return true if the canvas should be forced to be "inactive" to ensure
   // it can be drawn to the screen even if it's too large to be blitted by
   // an accelerated CanvasLayer.
   virtual bool ShouldForceInactiveLayer(LayerManager *manager) { return false; }
 
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -1215,32 +1215,63 @@ HTMLCanvasElement::GetCanvasLayer(nsDisp
     layer->Updated();
     return layer.forget();
   }
 
   return nullptr;
 }
 
 bool
+HTMLCanvasElement::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                             WebRenderCanvasData* aCanvasData)
+{
+  if (mCurrentContext) {
+    return mCurrentContext->UpdateWebRenderCanvasData(aBuilder, aCanvasData);
+  }
+  if (mOffscreenCanvas) {
+    CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer();
+
+    if(!mResetLayer && renderer) {
+      return true;
+    }
+
+    renderer = aCanvasData->CreateCanvasRenderer();
+    if (!InitializeCanvasRenderer(aBuilder, renderer)) {
+      // Clear CanvasRenderer of WebRenderCanvasData
+      aCanvasData->ClearCanvasRenderer();
+      return false;
+    }
+
+    MOZ_ASSERT(renderer);
+    mResetLayer = false;
+    return true;
+  }
+
+  // Clear CanvasRenderer of WebRenderCanvasData
+  aCanvasData->ClearCanvasRenderer();
+  return false;
+}
+
+bool
 HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                             CanvasRenderer* aRenderer)
 {
   if (mCurrentContext) {
     return mCurrentContext->InitializeCanvasRenderer(aBuilder, aRenderer);
   }
 
   if (mOffscreenCanvas) {
     CanvasInitializeData data;
     data.mRenderer = GetAsyncCanvasRenderer();
     data.mSize = GetWidthHeight();
     aRenderer->Initialize(data);
     return true;
   }
 
-  return true;
+  return false;
 }
 
 bool
 HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
 {
   if (mCurrentContext) {
     return mCurrentContext->ShouldForceInactiveLayer(aManager);
   }
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -30,16 +30,17 @@ class WebGLContext;
 namespace layers {
 class AsyncCanvasRenderer;
 class CanvasRenderer;
 class CanvasLayer;
 class Image;
 class Layer;
 class LayerManager;
 class SharedSurfaceTextureClient;
+class WebRenderCanvasData;
 } // namespace layers
 namespace gfx {
 class SourceSurface;
 class VRLayerChild;
 } // namespace gfx
 
 namespace dom {
 class BlobCallback;
@@ -122,16 +123,17 @@ class HTMLCanvasElement final : public n
     DEFAULT_CANVAS_HEIGHT = 150
   };
 
   typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
   typedef layers::CanvasRenderer CanvasRenderer;
   typedef layers::CanvasLayer CanvasLayer;
   typedef layers::Layer Layer;
   typedef layers::LayerManager LayerManager;
+  typedef layers::WebRenderCanvasData WebRenderCanvasData;
 
 public:
   explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
@@ -301,16 +303,18 @@ public:
 
   /*
    * Helpers called by various users of Canvas
    */
 
   already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          Layer *aOldLayer,
                                          LayerManager *aManager);
+  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                 WebRenderCanvasData* aCanvasData);
   bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
                                 CanvasRenderer* aRenderer);
   // Should return true if the canvas layer should always be marked inactive.
   // We should return true here if we can't do accelerated compositing with
   // a non-BasicCanvasLayer.
   bool ShouldForceInactiveLayer(LayerManager *aManager);
 
   // Call this whenever we need future changes to the canvas
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -35,17 +35,19 @@ void WebRenderCommandBuilder::Destroy()
 
 void
 WebRenderCommandBuilder::EmptyTransaction()
 {
   // We need to update canvases that might have changed.
   for (auto iter = mLastCanvasDatas.Iter(); !iter.Done(); iter.Next()) {
     RefPtr<WebRenderCanvasData> canvasData = iter.Get()->GetKey();
     WebRenderCanvasRendererAsync* canvas = canvasData->GetCanvasRenderer();
-    canvas->UpdateCompositableClient();
+    if (canvas) {
+      canvas->UpdateCompositableClient();
+    }
   }
 }
 
 bool
 WebRenderCommandBuilder::NeedsEmptyTransaction()
 {
   return !mLastCanvasDatas.IsEmpty();
 }
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -250,20 +250,29 @@ WebRenderCanvasData::~WebRenderCanvasDat
 void
 WebRenderCanvasData::ClearCachedResources()
 {
   if (mCanvasRenderer) {
     mCanvasRenderer->ClearCachedResources();
   }
 }
 
+void
+WebRenderCanvasData::ClearCanvasRenderer()
+{
+  mCanvasRenderer = nullptr;
+}
+
 WebRenderCanvasRendererAsync*
 WebRenderCanvasData::GetCanvasRenderer()
 {
-  if (!mCanvasRenderer) {
-    mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
-  }
+  return mCanvasRenderer.get();
+}
 
+WebRenderCanvasRendererAsync*
+WebRenderCanvasData::CreateCanvasRenderer()
+{
+  mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
   return mCanvasRenderer.get();
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -154,17 +154,19 @@ class WebRenderCanvasData : public WebRe
 public:
   explicit WebRenderCanvasData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem);
   virtual ~WebRenderCanvasData();
 
   virtual WebRenderCanvasData* AsCanvasData() override { return this; }
   virtual UserDataType GetType() override { return UserDataType::eCanvas; }
   static UserDataType Type() { return UserDataType::eCanvas; }
 
+  void ClearCanvasRenderer();
   WebRenderCanvasRendererAsync* GetCanvasRenderer();
+  WebRenderCanvasRendererAsync* CreateCanvasRenderer();
   void ClearCachedResources() override;
 protected:
   UniquePtr<WebRenderCanvasRendererAsync> mCanvasRenderer;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -989,19 +989,17 @@ gfxFontconfigFontFamily::FindStyleVariat
         nsAutoString psname, fullname;
         GetFaceNames(face, mName, psname, fullname);
         const nsAutoString& faceName = !psname.IsEmpty() ? psname : fullname;
 
         gfxFontconfigFontEntry *fontEntry =
             new gfxFontconfigFontEntry(faceName, face, mContainsAppFonts);
         AddFontEntry(fontEntry);
 
-        if (fontEntry->IsUpright() &&
-            fontEntry->Weight() == NS_FONT_WEIGHT_NORMAL &&
-            fontEntry->Stretch() == NS_FONT_STRETCH_NORMAL) {
+        if (fontEntry->IsNormalStyle()) {
             numRegularFaces++;
         }
 
         if (LOG_FONTLIST_ENABLED()) {
             LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
                  " with style: %s weight: %d stretch: %d"
                  " psname: %s fullname: %s",
                  NS_ConvertUTF16toUTF8(fontEntry->Name()).get(),
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -1480,26 +1480,37 @@ gfxFontFamily::FindFontForChar(GlobalFon
                 Script script = GetScriptCode(aMatchData->mCh);
                 MOZ_LOG(log, LogLevel::Debug,\
                        ("(textrun-systemfallback-fonts) char: u+%6.6x "
                         "unicode-range: %d script: %d match: [%s]\n",
                         aMatchData->mCh,
                         unicodeRange, int(script),
                         NS_ConvertUTF16toUTF8(fe->Name()).get()));
             }
+
+            // omitting from original windows code -- family name, lang group, pitch
+            // not available in current FontEntry implementation
+            rank += CalcStyleMatch(fe, aMatchData->mStyle);
+        } else if (!fe->IsNormalStyle()) {
+            // If style/weight/stretch was not Normal, see if we can
+            // fall back to a next-best face (e.g. Arial Black -> Bold,
+            // or Arial Narrow -> Regular).
+            GlobalFontMatch data(aMatchData->mCh, aMatchData->mStyle);
+            SearchAllFontsForChar(&data);
+            if (data.mMatchRank >= RANK_MATCHED_CMAP) {
+                fe = data.mBestMatch;
+                rank = data.mMatchRank;
+            } else {
+                return;
+            }
+        } else {
+            return;
         }
 
         aMatchData->mCmapsTested++;
-        if (rank == 0) {
-            return;
-        }
-
-         // omitting from original windows code -- family name, lang group, pitch
-         // not available in current FontEntry implementation
-        rank += CalcStyleMatch(fe, aMatchData->mStyle);
 
         // xxx - add whether AAT font with morphing info for specific lang groups
 
         if (rank > aMatchData->mMatchRank
             || (rank == aMatchData->mMatchRank &&
                 Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0))
         {
             aMatchData->mBestMatch = fe;
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -138,16 +138,29 @@ public:
     bool IsFixedPitch() const { return mFixedPitch; }
     bool IsItalic() const { return mStyle == NS_FONT_STYLE_ITALIC; }
     bool IsOblique() const { return mStyle == NS_FONT_STYLE_OBLIQUE; }
     bool IsUpright() const { return mStyle == NS_FONT_STYLE_NORMAL; }
     bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
     bool IgnoreGDEF() const { return mIgnoreGDEF; }
     bool IgnoreGSUB() const { return mIgnoreGSUB; }
 
+    // Return whether the face corresponds to "normal" CSS style properties:
+    //    font-style: normal;
+    //    font-weight: normal;
+    //    font-stretch: normal;
+    // If this is false, we might want to fall back to a different face and
+    // possibly apply synthetic styling.
+    bool IsNormalStyle() const
+    {
+        return IsUpright() &&
+               Weight() == NS_FONT_WEIGHT_NORMAL &&
+               Stretch() == NS_FONT_STRETCH_NORMAL;
+    }
+
     // whether a feature is supported by the font (limited to a small set
     // of features for which some form of fallback needs to be implemented)
     virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
     bool SupportsGraphiteFeature(uint32_t aFeatureTag);
 
     // returns a set containing all input glyph ids for a given feature
     const hb_set_t*
     InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
@@ -563,26 +576,24 @@ private:
     gfxFontEntry(const gfxFontEntry&);
     gfxFontEntry& operator=(const gfxFontEntry&);
 };
 
 
 // used when iterating over all fonts looking for a match for a given character
 struct GlobalFontMatch {
     GlobalFontMatch(const uint32_t aCharacter,
-                    mozilla::unicode::Script aRunScript,
                     const gfxFontStyle *aStyle) :
-        mCh(aCharacter), mRunScript(aRunScript), mStyle(aStyle),
+        mCh(aCharacter), mStyle(aStyle),
         mMatchRank(0), mCount(0), mCmapsTested(0)
         {
 
         }
 
     const uint32_t         mCh;          // codepoint to be matched
-    mozilla::unicode::Script mRunScript;   // Unicode script for the codepoint
     const gfxFontStyle*    mStyle;       // style to match
     int32_t                mMatchRank;   // metric indicating closest match
     RefPtr<gfxFontEntry> mBestMatch;   // current best match
     RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
     uint32_t               mCount;       // number of fonts matched
     uint32_t               mCmapsTested; // number of cmaps tested
 };
 
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -610,27 +610,43 @@ gfxPlatformFontList::CommonFontFallback(
                                                        defaultFallbacks);
     numFallbacks = defaultFallbacks.Length();
     for (i = 0; i < numFallbacks; i++) {
         nsAutoString familyName;
         const char *fallbackFamily = defaultFallbacks[i];
 
         familyName.AppendASCII(fallbackFamily);
         gfxFontFamily *fallback = FindFamilyByCanonicalName(familyName);
-        if (!fallback)
+        if (!fallback) {
             continue;
+        }
 
         gfxFontEntry *fontEntry;
         bool needsBold;  // ignored in the system fallback case
 
         // use first font in list that supports a given character
         fontEntry = fallback->FindFontForStyle(*aMatchStyle, needsBold);
-        if (fontEntry && fontEntry->HasCharacter(aCh)) {
-            *aMatchedFamily = fallback;
-            return fontEntry;
+        if (fontEntry) {
+            if (fontEntry->HasCharacter(aCh)) {
+                *aMatchedFamily = fallback;
+                return fontEntry;
+            }
+            // If we requested a styled font (bold and/or italic), and the char
+            // was not available, check other faces of the family.
+            if (!fontEntry->IsNormalStyle()) {
+                // If style/weight/stretch was not Normal, see if we can
+                // fall back to a next-best face (e.g. Arial Black -> Bold,
+                // or Arial Narrow -> Regular).
+                GlobalFontMatch data(aCh, aMatchStyle);
+                fallback->SearchAllFontsForChar(&data);
+                if (data.mBestMatch) {
+                    *aMatchedFamily = fallback;
+                    return data.mBestMatch;
+                }
+            }
         }
     }
 
     return nullptr;
 }
 
 gfxFontEntry*
 gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
@@ -647,17 +663,17 @@ gfxPlatformFontList::GlobalFontFallback(
             PlatformGlobalFontFallback(aCh, aRunScript, aMatchStyle,
                                        aMatchedFamily);
         if (fe) {
             return fe;
         }
     }
 
     // otherwise, try to find it among local fonts
-    GlobalFontMatch data(aCh, aRunScript, aMatchStyle);
+    GlobalFontMatch data(aCh, aMatchStyle);
 
     // iterate over all font families to find a font that support the character
     for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
       RefPtr<gfxFontFamily>& family = iter.Data();
       // evaluate all fonts in this family for a match
       family->FindFontForChar(&data);
     }
 
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -2823,20 +2823,19 @@ gfxFontGroup::GetEllipsisTextRun(int32_t
     }
     // don't let the presence of a cached ellipsis textrun prolong the
     // fontgroup's life
     mCachedEllipsisTextRun->ReleaseFontGroup();
     return mCachedEllipsisTextRun.get();
 }
 
 gfxFont*
-gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
-                                      Script aRunScript)
+gfxFontGroup::FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh)
 {
-    GlobalFontMatch data(aCh, aRunScript, &mStyle);
+    GlobalFontMatch data(aCh, &mStyle);
     aFamily->SearchAllFontsForChar(&data);
     gfxFontEntry* fe = data.mBestMatch;
     if (!fe) {
         return nullptr;
     }
 
     bool needsBold = mStyle.weight >= 600 && !fe->IsBold() &&
                      mStyle.allowSyntheticWeight;
@@ -2925,32 +2924,28 @@ gfxFontGroup::FindFontForChar(uint32_t a
         if (firstFont) {
             if (firstFont->HasCharacter(aCh)) {
                 *aMatchType = gfxTextRange::kFontGroup;
                 return firstFont;
             }
 
             gfxFont* font = nullptr;
             if (mFonts[0].CheckForFallbackFaces()) {
-                font = FindFallbackFaceForChar(mFonts[0].Family(), aCh,
-                                               aRunScript);
+                font = FindFallbackFaceForChar(mFonts[0].Family(), aCh);
             } else if (!firstFont->GetFontEntry()->IsUserFont()) {
                 // For platform fonts (but not userfonts), we may need to do
                 // fallback within the family to handle cases where some faces
                 // such as Italic or Black have reduced character sets compared
                 // to the family's Regular face.
                 gfxFontEntry* fe = firstFont->GetFontEntry();
-                if (!fe->IsUpright() ||
-                    fe->Weight() != NS_FONT_WEIGHT_NORMAL ||
-                    fe->Stretch() != NS_FONT_STRETCH_NORMAL) {
+                if (!fe->IsNormalStyle()) {
                     // If style/weight/stretch was not Normal, see if we can
                     // fall back to a next-best face (e.g. Arial Black -> Bold,
                     // or Arial Narrow -> Regular).
-                    font = FindFallbackFaceForChar(mFonts[0].Family(), aCh,
-                                                   aRunScript);
+                    font = FindFallbackFaceForChar(mFonts[0].Family(), aCh);
                 }
             }
             if (font) {
                 *aMatchType = gfxTextRange::kFontGroup;
                 return font;
             }
         }
 
@@ -3042,31 +3037,29 @@ gfxFontGroup::FindFontForChar(uint32_t a
         }
 
         // check other family faces if needed
         if (ff.CheckForFallbackFaces()) {
             NS_ASSERTION(i == 0 ? true :
                          !mFonts[i-1].CheckForFallbackFaces() ||
                          !mFonts[i-1].Family()->Name().Equals(ff.Family()->Name()),
                          "should only do fallback once per font family");
-            font = FindFallbackFaceForChar(ff.Family(), aCh, aRunScript);
+            font = FindFallbackFaceForChar(ff.Family(), aCh);
             if (font) {
                 *aMatchType = gfxTextRange::kFontGroup;
                 return font;
             }
         } else {
             // For platform fonts, but not user fonts, consider intra-family
             // fallback to handle styles with reduced character sets (see
             // also above).
             fe = ff.FontEntry();
             if (!fe->mIsUserFontContainer && !fe->IsUserFont() &&
-                (!fe->IsUpright() ||
-                 fe->Weight() != NS_FONT_WEIGHT_NORMAL ||
-                 fe->Stretch() != NS_FONT_STRETCH_NORMAL)) {
-                font = FindFallbackFaceForChar(ff.Family(), aCh, aRunScript);
+                !fe->IsNormalStyle()) {
+                font = FindFallbackFaceForChar(ff.Family(), aCh);
                 if (font) {
                     *aMatchType = gfxTextRange::kFontGroup;
                     return font;
                 }
             }
         }
     }
 
@@ -3392,41 +3385,62 @@ gfxFontGroup::WhichPrefFontSupportsChar(
         NS_ASSERTION(families, "no pref font families found");
 
         // find the first pref font that includes the character
         uint32_t  j, numPrefs;
         numPrefs = families->Length();
         for (j = 0; j < numPrefs; j++) {
             // look up the appropriate face
             gfxFontFamily *family = (*families)[j];
-            if (!family) continue;
+            if (!family) {
+                continue;
+            }
 
             // if a pref font is used, it's likely to be used again in the same text run.
             // the style doesn't change so the face lookup can be cached rather than calling
             // FindOrMakeFont repeatedly.  speeds up FindFontForChar lookup times for subsequent
             // pref font lookups
             if (family == mLastPrefFamily && mLastPrefFont->HasCharacter(aCh)) {
                 return mLastPrefFont;
             }
 
             bool needsBold;
             gfxFontEntry *fe = family->FindFontForStyle(mStyle, needsBold);
+            if (!fe) {
+                continue;
+            }
+
             // if ch in cmap, create and return a gfxFont
-            if (fe && fe->HasCharacter(aCh)) {
+            if (fe->HasCharacter(aCh)) {
                 gfxFont* prefFont = fe->FindOrMakeFont(&mStyle, needsBold);
                 if (!prefFont) {
                     continue;
                 }
                 mLastPrefFamily = family;
                 mLastPrefFont = prefFont;
                 mLastPrefLang = charLang;
                 mLastPrefFirstFont = (i == 0 && j == 0);
                 return prefFont;
             }
 
+            // If we requested a styled font (bold and/or italic), and the char
+            // was not available, check the regular face as well.
+            if (!fe->IsNormalStyle()) {
+                // If style/weight/stretch was not Normal, see if we can
+                // fall back to a next-best face (e.g. Arial Black -> Bold,
+                // or Arial Narrow -> Regular).
+                gfxFont* prefFont = FindFallbackFaceForChar(family, aCh);
+                if (prefFont) {
+                    mLastPrefFamily = family;
+                    mLastPrefFont = prefFont;
+                    mLastPrefLang = charLang;
+                    mLastPrefFirstFont = (i == 0 && j == 0);
+                    return prefFont;
+                }
+            }
         }
     }
 
     return nullptr;
 }
 
 gfxFont*
 gfxFontGroup::WhichSystemFontSupportsChar(uint32_t aCh, uint32_t aNextCh,
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -1242,18 +1242,17 @@ protected:
                        uint32_t aScriptRunEnd,
                        Script aRunScript,
                        gfxMissingFontRecorder *aMFR);
 
     // Helper for font-matching:
     // search all faces in a family for a fallback in cases where it's unclear
     // whether the family might have a font for a given character
     gfxFont*
-    FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh,
-                            Script aRunScript);
+    FindFallbackFaceForChar(gfxFontFamily* aFamily, uint32_t aCh);
 
    // helper methods for looking up fonts
 
     // lookup and add a font with a given name (i.e. *not* a generic!)
     void AddPlatformFont(const nsAString& aName,
                          nsTArray<gfxFontFamily*>& aFamilyList);
 
     // do style selection and add entries to list
--- a/js/src/jit/arm64/MoveEmitter-arm64.h
+++ b/js/src/jit/arm64/MoveEmitter-arm64.h
@@ -19,21 +19,20 @@ class CodeGenerator;
 class MoveEmitterARM64
 {
     bool inCycle_;
     MacroAssembler& masm;
 
     // Original stack push value.
     uint32_t pushedAtStart_;
 
-    // These store stack offsets to spill locations, snapshotting
-    // codegen->framePushed_ at the time they were allocated. They are -1 if no
+    // This stores a stack offset to a spill location, snapshotting
+    // codegen->framePushed_ at the time it was allocated. It is -1 if no
     // stack space has been allocated for that particular spill.
     int32_t pushedAtCycle_;
-    int32_t pushedAtSpill_;
 
     void assertDone() {
         MOZ_ASSERT(!inCycle_);
     }
 
     MemOperand cycleSlot();
     MemOperand toMemOperand(const MoveOperand& operand) const;
     ARMRegister toARMReg32(const MoveOperand& operand) const {
@@ -60,18 +59,17 @@ class MoveEmitterARM64
     void breakCycle(const MoveOperand& from, const MoveOperand& to, MoveOp::Type type);
     void completeCycle(const MoveOperand& from, const MoveOperand& to, MoveOp::Type type);
 
   public:
     MoveEmitterARM64(MacroAssembler& masm)
       : inCycle_(false),
         masm(masm),
         pushedAtStart_(masm.framePushed()),
-        pushedAtCycle_(-1),
-        pushedAtSpill_(-1)
+        pushedAtCycle_(-1)
     { }
 
     ~MoveEmitterARM64() {
         assertDone();
     }
 
     void emit(const MoveResolver& moves);
     void finish();
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -136,26 +136,23 @@ public:
     switch(element->GetCurrentContextType()) {
       case CanvasContextType::Canvas2D:
       case CanvasContextType::WebGL1:
       case CanvasContextType::WebGL2:
       {
         bool isRecycled;
         RefPtr<WebRenderCanvasData> canvasData =
           aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderCanvasData>(this, &isRecycled);
+        nsHTMLCanvasFrame* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
+        if (!canvasFrame->UpdateWebRenderCanvasData(aDisplayListBuilder, canvasData)) {
+          return true;
+        }
         WebRenderCanvasRendererAsync* data =
           static_cast<WebRenderCanvasRendererAsync*>(canvasData->GetCanvasRenderer());
-
-        if (!isRecycled) {
-          nsHTMLCanvasFrame* canvasFrame = static_cast<nsHTMLCanvasFrame*>(mFrame);
-          if (!canvasFrame->InitializeCanvasRenderer(aDisplayListBuilder, data)) {
-            return true;
-          }
-        }
-
+        MOZ_ASSERT(data);
         data->UpdateCompositableClient();
 
         // Push IFrame for async image pipeline.
         // XXX Remove this once partial display list update is supported.
 
         /* ScrollingLayersHelper scroller(this, aBuilder, aResources, aSc); */
         nsIntSize canvasSizeInPx = data->GetSize();
         IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx);
@@ -456,21 +453,21 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayL
     RefPtr<ImageLayer> imageLayer = static_cast<ImageLayer*>(layer.get());
     imageLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
   }
 
   return layer.forget();
 }
 
 bool
-nsHTMLCanvasFrame::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
-                                            CanvasRenderer* aRenderer)
+nsHTMLCanvasFrame::UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                             WebRenderCanvasData* aCanvasData)
 {
   HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
-  return element->InitializeCanvasRenderer(aBuilder, aRenderer);
+  return element->UpdateWebRenderCanvasData(aBuilder, aCanvasData);
 }
 
 void
 nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                     const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return;
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -13,30 +13,32 @@
 #include "nsContainerFrame.h"
 #include "nsStringFwd.h"
 #include "FrameLayerBuilder.h"
 
 namespace mozilla {
 namespace layers {
 class Layer;
 class LayerManager;
+class WebRenderCanvasData;
 } // namespace layers
 } // namespace mozilla
 
 class nsPresContext;
 class nsDisplayItem;
 
 nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 class nsHTMLCanvasFrame final : public nsContainerFrame
 {
 public:
   typedef mozilla::layers::CanvasRenderer CanvasRenderer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
+  typedef mozilla::layers::WebRenderCanvasData WebRenderCanvasData;
   typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame)
 
   explicit nsHTMLCanvasFrame(nsStyleContext* aContext)
     : nsContainerFrame(aContext, kClassID)
     , mBorderPadding(GetWritingMode())
@@ -48,18 +50,19 @@ public:
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem,
                                      const ContainerLayerParameters& aContainerParameters);
-  bool InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
-                                CanvasRenderer* aRenderer);
+
+  bool UpdateWebRenderCanvasData(nsDisplayListBuilder* aBuilder,
+                                 WebRenderCanvasData* aCanvasData);
 
   /* get the size of the canvas's image */
   nsIntSize GetCanvasSize();
 
   virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
   virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
   virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
   virtual nsSize GetIntrinsicRatio() override;
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -1,17 +1,17 @@
 == default-size.html default-size-ref.html
 fuzzy-if(Android,8,1000) == size-1.html size-1-ref.html
 
 == empty-transaction-1.html empty-transaction-1-ref.html
 
 == image-rendering-test.html image-rendering-ref.html
 == image-shadow.html image-shadow-ref.html
 
-asserts-if(cocoaWidget,0-2) fails-if(webrender) == size-change-1.html size-change-1-ref.html
+asserts-if(cocoaWidget,0-2) == size-change-1.html size-change-1-ref.html
 
 random-if(cocoaWidget) == subpixel-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
 
 != text-ltr-left.html text-blank.html
 != text-ltr-right.html text-blank.html
 != text-rtl-left.html text-blank.html
 != text-rtl-right.html text-blank.html
 
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -15,16 +15,17 @@
 #include "BaseElf.h"
 #include "CustomElf.h"
 #include "Mappable.h"
 #include "Logging.h"
 #include <inttypes.h>
 
 #if defined(ANDROID)
 #include <sys/syscall.h>
+#include <math.h>
 
 #include <android/api-level.h>
 #if __ANDROID_API__ < 8
 /* Android API < 8 doesn't provide sigaltstack */
 
 extern "C" {
 
 inline int sigaltstack(const stack_t *ss, stack_t *oss) {
@@ -326,35 +327,16 @@ SystemElf::~SystemElf()
   ElfLoader::Singleton.lastError = dlerror();
   ElfLoader::Singleton.Forget(this);
 }
 
 void *
 SystemElf::GetSymbolPtr(const char *symbol) const
 {
   void *sym = dlsym(dlhandle, symbol);
-  // Various bits of Gecko use isnanf, which gcc is happy to compile into
-  // inlined code using floating-point comparisons.  clang, on the other hand,
-  // does not use inline code and generates full calls to isnanf.
-  //
-  // libm.so on Android defines isnanf as weak.  dlsym always returns null for
-  // weak symbols.  Which means that we'll never be able to resolve the symbol
-  // that clang generates here.  However, said weak symbol for isnanf is just
-  // an alias for __isnanf, which is the real definition.  So if we're asked
-  // for isnanf and we can't find it, try looking for __isnanf instead.  The
-  // actual system linker uses alternate resolution interfaces and therefore
-  // does not encounter this issue.
-  //
-  // See also https://bugs.chromium.org/p/chromium/issues/detail?id=376828,
-  // from which this comment and this fix are adapted.
-  if (!sym &&
-      !strcmp(symbol, "isnanf") &&
-      !strcmp(GetName(), "libm.so")) {
-    sym = dlsym(dlhandle, "__isnanf");
-  }
   DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol, sym);
   ElfLoader::Singleton.lastError = dlerror();
   return sym;
 }
 
 Mappable *
 SystemElf::GetMappable() const
 {
@@ -571,31 +553,35 @@ ElfLoader::Init()
    * static initializer. */
   if (dladdr(_DYNAMIC, &info) != 0) {
     self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase);
   }
 #if defined(ANDROID)
   if (dladdr(FunctionPtr(syscall), &info) != 0) {
     libc = LoadedElf::Create(info.dli_fname, info.dli_fbase);
   }
+  if (dladdr(FunctionPtr<int (*)(double)>(isnan), &info) != 0) {
+    libm = LoadedElf::Create(info.dli_fname, info.dli_fbase);
+  }
 #endif
 }
 
 ElfLoader::~ElfLoader()
 {
   LibHandleList list;
 
   if (!Singleton.IsShutdownExpected()) {
     MOZ_CRASH("Unexpected shutdown");
   }
 
   /* Release self_elf and libc */
   self_elf = nullptr;
 #if defined(ANDROID)
   libc = nullptr;
+  libm = nullptr;
 #endif
 
   AutoLock lock(&handlesMutex);
   /* Build up a list of all library handles with direct (external) references.
    * We actually skip system library handles because we want to keep at least
    * some of these open. Most notably, Mozilla codebase keeps a few libgnome
    * libraries deliberately open because of the mess that libORBit destruction
    * is. dlclose()ing these libraries actually leads to problems. */
--- a/mozglue/linker/ElfLoader.h
+++ b/mozglue/linker/ElfLoader.h
@@ -468,16 +468,19 @@ private:
   RefPtr<LibHandle> self_elf;
 
 #if defined(ANDROID)
   /* System loader handle for the libc. This is used to resolve weak symbols
    * that some libcs contain that the Android linker won't dlsym(). Normally,
    * we wouldn't treat non-Android differently, but glibc uses versioned
    * symbols which this linker doesn't support. */
   RefPtr<LibHandle> libc;
+
+  /* And for libm. */
+  RefPtr<LibHandle> libm;
 #endif
 
   /* Bookkeeping */
   typedef std::vector<LibHandle *> LibHandleList;
   LibHandleList handles;
 
   pthread_mutex_t handlesMutex;