merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 28 Oct 2017 10:31:58 +0200
changeset 688154 c16bc8097c102cdd2b70d8e7db3656222455a6ed
parent 688135 13a0ffe2798fd1c9beca19f70f2baf9a8e992cb5 (current diff)
parent 688153 ad716d87938ffc58d73a4985def6ec66f68e9c2f (diff)
child 688155 5a79b887c2123e9b1cf40abaa4dcc8beb41d14f1
child 688162 8c89e536e10102404b4184b208a9ea27e9add112
child 688167 cb56eff44d74b5d8753b3aca2944e0c367703bfd
child 688175 8cb78523022e95979ec4d165e31ee21bffe46fa8
child 688186 5937eb6e24b23a319711bc614f3088fa37d6afaf
child 688217 8fe5c82c3dcd998eaa5f9b038d083abc764931af
child 688232 f8447b15340c488e72c3ed6796789f520d5206dc
child 688269 c61587bd8895a2e5e0e63e543796e807864d85e2
child 688656 c688b1e2910d73c0824caffe251fe11fef39a76a
child 689153 de9f281d9150a590157282f4d1ebcb03b6351603
push id86669
push userhikezoe@mozilla.com
push dateSat, 28 Oct 2017 10:13:18 +0000
reviewersmerge, merge
milestone58.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: oIdBL7fmlE
testing/talos/talos/test.py
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -7210,26 +7210,12 @@ EventTarget::IsOnCurrentThreadInfallible
     return false;
   }
 
   return mWorkerPrivate->IsOnCurrentThread();
 }
 
 BEGIN_WORKERS_NAMESPACE
 
-WorkerCrossThreadDispatcher*
-GetWorkerCrossThreadDispatcher(JSContext* aCx, const JS::Value& aWorker)
-{
-  if (!aWorker.isObject()) {
-    return nullptr;
-  }
-
-  JS::Rooted<JSObject*> obj(aCx, &aWorker.toObject());
-  WorkerPrivate* w = nullptr;
-  UNWRAP_OBJECT(Worker, &obj, w);
-  MOZ_ASSERT(w);
-  return w->GetCrossThreadDispatcher();
-}
-
 // Force instantiation.
 template class WorkerPrivateParent<WorkerPrivate>;
 
 END_WORKERS_NAMESPACE
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -361,19 +361,16 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerCrossThreadDispatcher)
 
   // Generically useful function for running a bit of C++ code on the worker
   // thread.
   bool
   PostTask(WorkerTask* aTask);
 };
 
-WorkerCrossThreadDispatcher*
-GetWorkerCrossThreadDispatcher(JSContext* aCx, const JS::Value& aWorker);
-
 // Random unique constant to facilitate JSPrincipal debugging
 const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
 
 bool
 IsWorkerGlobal(JSObject* global);
 
 bool
 IsDebuggerGlobal(JSObject* global);
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -7,17 +7,17 @@
 #include "PathRecording.h"
 #include "RecordingTypes.h"
 
 namespace mozilla {
 namespace gfx {
 
 using namespace std;
 
-DrawEventRecorderPrivate::DrawEventRecorderPrivate()
+DrawEventRecorderPrivate::DrawEventRecorderPrivate() : mExternalFonts(false)
 {
 }
 
 void
 DrawEventRecorderFile::RecordEvent(const RecordedEvent &aEvent)
 {
   WriteElement(mOutputStream, aEvent.mType);
 
@@ -74,29 +74,61 @@ DrawEventRecorderFile::Close()
   mOutputStream.close();
 }
 
 DrawEventRecorderMemory::DrawEventRecorderMemory()
 {
   WriteHeader(mOutputStream);
 }
 
+DrawEventRecorderMemory::DrawEventRecorderMemory(const SerializeResourcesFn &aFn) :
+  mSerializeCallback(aFn)
+{
+  mExternalFonts = true;
+  WriteHeader(mOutputStream);
+}
+
+
 void
 DrawEventRecorderMemory::Flush()
 {
 }
 
+void
+DrawEventRecorderMemory::FlushItem(IntRect aRect)
+{
+  DetatchResources();
+  WriteElement(mIndex, mOutputStream.mLength);
+  mSerializeCallback(mOutputStream, mUnscaledFonts);
+  WriteElement(mIndex, mOutputStream.mLength);
+  ClearResources();
+}
+
+void
+DrawEventRecorderMemory::Finish()
+{
+  size_t indexOffset = mOutputStream.mLength;
+  // write out the index
+  mOutputStream.write(mIndex.mData, mIndex.mLength);
+  mIndex = MemStream();
+  // write out the offset of the Index to the end of the output stream
+  WriteElement(mOutputStream, indexOffset);
+  ClearResources();
+}
+
+
 size_t
 DrawEventRecorderMemory::RecordingSize()
 {
   return mOutputStream.mLength;
 }
 
 void
 DrawEventRecorderMemory::WipeRecording()
 {
   mOutputStream = MemStream();
+  mIndex = MemStream();
 
   WriteHeader(mOutputStream);
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -8,40 +8,52 @@
 
 #include "2D.h"
 #include "RecordedEvent.h"
 #include "RecordingTypes.h"
 #include <ostream>
 #include <fstream>
 
 #include <unordered_set>
+#include <unordered_map>
+#include <functional>
 
 namespace mozilla {
 namespace gfx {
 
 class PathRecording;
 
 class DrawEventRecorderPrivate : public DrawEventRecorder
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate)
   DrawEventRecorderPrivate();
   virtual ~DrawEventRecorderPrivate() { }
-  virtual void Finish() {
+  virtual void Finish() { ClearResources(); }
+  virtual void FlushItem(IntRect) { }
+  void DetatchResources() {
     // The iteration is a bit awkward here because our iterator will
     // be invalidated by the removal
     for (auto font = mStoredFonts.begin(); font != mStoredFonts.end(); ) {
       auto oldFont = font++;
       (*oldFont)->RemoveUserData(reinterpret_cast<UserDataKey*>(this));
     }
     for (auto surface = mStoredSurfaces.begin(); surface != mStoredSurfaces.end(); ) {
       auto oldSurface = surface++;
       (*oldSurface)->RemoveUserData(reinterpret_cast<UserDataKey*>(this));
     }
+    mStoredFonts.clear();
+    mStoredSurfaces.clear();
+  }
 
+  void ClearResources() {
+    mUnscaledFonts.clear();
+    mStoredObjects.clear();
+    mStoredFontData.clear();
+    mUnscaledFontMap.clear();
   }
 
   template<class S>
   void WriteHeader(S& aStream) {
     WriteElement(aStream, kMagicInt);
     WriteElement(aStream, kMajorRevision);
     WriteElement(aStream, kMinorRevision);
   }
@@ -80,23 +92,42 @@ public:
   void AddStoredFontData(const uint64_t aFontDataKey) {
     mStoredFontData.insert(aFontDataKey);
   }
 
   bool HasStoredFontData(const uint64_t aFontDataKey) {
     return mStoredFontData.find(aFontDataKey) != mStoredFontData.end();
   }
 
+  // Returns the index of the UnscaledFont
+  size_t GetUnscaledFontIndex(UnscaledFont *aFont) {
+    auto i = mUnscaledFontMap.find(aFont);
+    size_t index;
+    if (i == mUnscaledFontMap.end()) {
+      mUnscaledFonts.push_back(aFont);
+      index = mUnscaledFonts.size() - 1;
+      mUnscaledFontMap.insert({{aFont, index}});
+    } else {
+      index = i->second;
+    }
+    return index;
+  }
+
+  bool WantsExternalFonts() { return mExternalFonts; }
+
 protected:
   virtual void Flush() = 0;
 
   std::unordered_set<const void*> mStoredObjects;
   std::unordered_set<uint64_t> mStoredFontData;
   std::unordered_set<ScaledFont*> mStoredFonts;
   std::unordered_set<SourceSurface*> mStoredSurfaces;
+  std::vector<RefPtr<UnscaledFont>> mUnscaledFonts;
+  std::unordered_map<UnscaledFont*, size_t> mUnscaledFontMap;
+  bool mExternalFonts;
 };
 
 class DrawEventRecorderFile : public DrawEventRecorderPrivate
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile, override)
   explicit DrawEventRecorderFile(const char *aFilename);
   ~DrawEventRecorderFile();
@@ -123,44 +154,57 @@ public:
   void Close();
 
 private:
   void Flush() override;
 
   std::ofstream mOutputStream;
 };
 
+typedef std::function<void(MemStream &aStream, std::vector<RefPtr<UnscaledFont>> &aUnscaledFonts)> SerializeResourcesFn;
+
 // WARNING: This should not be used in its existing state because
 // it is likely to OOM because of large continguous allocations.
 class DrawEventRecorderMemory final : public DrawEventRecorderPrivate
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderMemory, override)
 
   /**
    * Constructs a DrawEventRecorder that stores the recording in memory.
    */
   DrawEventRecorderMemory();
+  explicit DrawEventRecorderMemory(const SerializeResourcesFn &aSerialize);
 
   void RecordEvent(const RecordedEvent &aEvent) override;
 
   /**
    * @return the current size of the recording (in chars).
    */
   size_t RecordingSize();
 
   /**
    * Wipes the internal recording buffer, but the recorder does NOT forget which
    * objects it has recorded. This can be used so that a recording can be copied
    * and processed in chunks, releasing memory as it goes.
    */
   void WipeRecording();
+  void Finish() override;
+  void FlushItem(IntRect) override;
 
   MemStream mOutputStream;
+  /* The index stream is of the form:
+   * ItemIndex { size_t dataEnd; size_t extraDataEnd; }
+   * It gets concatenated to the end of mOutputStream in Finish()
+   * The last size_t in the stream is offset of the begining of the
+   * index.
+   */
+  MemStream mIndex;
 private:
+  SerializeResourcesFn mSerializeCallback;
   ~DrawEventRecorderMemory() {};
 
   void Flush() override;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/2d/DrawTargetRecording.cpp
+++ b/gfx/2d/DrawTargetRecording.cpp
@@ -327,42 +327,44 @@ DrawTargetRecording::FillGlyphs(ScaledFo
                                 const DrawOptions &aOptions,
                                 const GlyphRenderingOptions *aRenderingOptions)
 {
   EnsurePatternDependenciesStored(aPattern);
 
   UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
   if (!aFont->GetUserData(userDataKey)) {
     UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
-    if (!mRecorder->HasStoredObject(unscaledFont)) {
-      RecordedFontData fontData(unscaledFont);
-      RecordedFontDetails fontDetails;
-      if (fontData.GetFontDetails(fontDetails)) {
-        // Try to serialise the whole font, just in case this is a web font that
-        // is not present on the system.
-        if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
-          mRecorder->RecordEvent(fontData);
-          mRecorder->AddStoredFontData(fontDetails.fontDataKey);
-        }
-        mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
-      } else {
-        // If that fails, record just the font description and try to load it from
-        // the system on the other side.
-        RecordedFontDescriptor fontDesc(unscaledFont);
-        if (fontDesc.IsValid()) {
-          mRecorder->RecordEvent(fontDesc);
-        } else {
-          gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
-        }
+    if (mRecorder->WantsExternalFonts()) {
+      size_t index = mRecorder->GetUnscaledFontIndex(unscaledFont);
+      mRecorder->RecordEvent(RecordedScaledFontCreationByIndex(aFont, index));
+    } else {
+      if (!mRecorder->HasStoredObject(unscaledFont)) {
+	RecordedFontData fontData(unscaledFont);
+	RecordedFontDetails fontDetails;
+	if (fontData.GetFontDetails(fontDetails)) {
+	  // Try to serialise the whole font, just in case this is a web font that
+	  // is not present on the system.
+	  if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) {
+	    mRecorder->RecordEvent(fontData);
+	    mRecorder->AddStoredFontData(fontDetails.fontDataKey);
+	  }
+	  mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
+	} else {
+	  // If that fails, record just the font description and try to load it from
+	  // the system on the other side.
+	  RecordedFontDescriptor fontDesc(unscaledFont);
+	  if (fontDesc.IsValid()) {
+	    mRecorder->RecordEvent(fontDesc);
+	  } else {
+	    gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
+	  }
+	}
+	mRecorder->AddStoredObject(unscaledFont);
       }
-      mRecorder->AddStoredObject(unscaledFont);
     }
-
-    mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
-
     RecordingFontUserData *userData = new RecordingFontUserData;
     userData->refPtr = aFont;
     userData->recorder = mRecorder;
     aFont->AddUserData(userDataKey, userData, &RecordingFontUserDataDestroyFunc);
     userData->recorder->AddScaledFont(aFont);
   }
 
   mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
--- a/gfx/2d/InlineTranslator.cpp
+++ b/gfx/2d/InlineTranslator.cpp
@@ -47,16 +47,17 @@ InlineTranslator::TranslateRecording(cha
       return !eof();
     }
 
     char *mData;
     char *mEnd;
   };
   MemReader reader(aData, aLen);
 
+
   uint32_t magicInt;
   ReadElement(reader, magicInt);
   if (magicInt != mozilla::gfx::kMagicInt) {
     return false;
   }
 
   uint16_t majorRevision;
   ReadElement(reader, majorRevision);
--- a/gfx/2d/InlineTranslator.h
+++ b/gfx/2d/InlineTranslator.h
@@ -71,23 +71,29 @@ public:
 
   ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final
   {
     ScaledFont* result = mScaledFonts.GetWeak(aRefPtr);
     MOZ_ASSERT(result);
     return result;
   }
 
-  UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final
+  UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) override final
   {
     UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr);
     MOZ_ASSERT(result);
     return result;
   }
 
+  virtual UnscaledFont* LookupUnscaledFontByIndex(size_t index) override final
+  {
+    UnscaledFont* result = mUnscaledFontTable[index];
+    return result;
+  }
+
   NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
   {
     NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
     MOZ_ASSERT(result);
     return result;
   }
 
   void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final
@@ -117,16 +123,17 @@ public:
 
   void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final
   {
     mScaledFonts.Put(aRefPtr, aScaledFont);
   }
 
   void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont *aUnscaledFont) final
   {
+    mUnscaledFontTable.push_back(aUnscaledFont);
     mUnscaledFonts.Put(aRefPtr, aUnscaledFont);
   }
 
   void AddNativeFontResource(uint64_t aKey,
                              NativeFontResource *aScaledFontResouce) final
   {
     mNativeFontResources.Put(aKey, aScaledFontResouce);
   }
@@ -174,16 +181,17 @@ public:
   mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
 
   void* GetFontContext() final { return mFontContext; }
 
 private:
   RefPtr<DrawTarget> mBaseDT;
   void*              mFontContext;
 
+  std::vector<RefPtr<UnscaledFont>> mUnscaledFontTable;
   nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
   nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
   nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
   nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
   nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
   nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
   nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
   nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -83,16 +83,18 @@ RecordedEvent::GetEventName(EventType aT
   case GRADIENTSTOPSCREATION:
     return "GradientStopsCreation";
   case GRADIENTSTOPSDESTRUCTION:
     return "GradientStopsDestruction";
   case SNAPSHOT:
     return "Snapshot";
   case SCALEDFONTCREATION:
     return "ScaledFontCreation";
+  case SCALEDFONTCREATIONBYINDEX:
+    return "ScaledFontCreationByIndex";
   case SCALEDFONTDESTRUCTION:
     return "ScaledFontDestruction";
   case MASKSURFACE:
     return "MaskSurface";
   case FILTERNODESETATTRIBUTE:
     return "SetAttribute";
   case FILTERNODESETINPUT:
     return "SetInput";
@@ -110,16 +112,50 @@ RecordedEvent::GetEventName(EventType aT
     return "UnscaledFontCreation";
   case UNSCALEDFONTDESTRUCTION:
     return "UnscaledFontDestruction";
   default:
     return "Unknown";
   }
 }
 
+template<class S>
+void RecordedEvent::RecordUnscaledFontImpl(UnscaledFont *aUnscaledFont, S& aOutput) {
+  RecordedFontData fontData(aUnscaledFont);
+  RecordedFontDetails fontDetails;
+  if (fontData.GetFontDetails(fontDetails)) {
+    // Try to serialise the whole font, just in case this is a web font that
+    // is not present on the system.
+    WriteElement(aOutput, fontData.mType);
+    fontData.RecordToStream(aOutput);
+
+    auto r = RecordedUnscaledFontCreation(aUnscaledFont, fontDetails);
+    WriteElement(aOutput, r.mType);
+    r.RecordToStream(aOutput);
+  } else {
+    // If that fails, record just the font description and try to load it from
+    // the system on the other side.
+    RecordedFontDescriptor fontDesc(aUnscaledFont);
+    if (fontDesc.IsValid()) {
+      WriteElement(aOutput, fontDesc.RecordedEvent::mType);
+      fontDesc.RecordToStream(aOutput);
+    } else {
+      gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
+    }
+  }
+}
+
+void RecordedEvent::RecordUnscaledFont(UnscaledFont *aUnscaledFont, std::ostream *aOutput) {
+  RecordUnscaledFontImpl(aUnscaledFont, *aOutput);
+}
+
+void RecordedEvent::RecordUnscaledFont(UnscaledFont *aUnscaledFont, MemStream &aOutput) {
+  RecordUnscaledFontImpl(aUnscaledFont, aOutput);
+}
+
 already_AddRefed<DrawTarget>
 Translator::CreateDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize,
                              SurfaceFormat aFormat)
 {
   RefPtr<DrawTarget> newDT =
     GetReferenceDrawTarget()->CreateSimilarDrawTarget(aSize, aFormat);
   AddDrawTarget(aRefPtr, newDT);
   return newDT.forget();
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -84,16 +84,17 @@ public:
 
   virtual DrawTarget *LookupDrawTarget(ReferencePtr aRefPtr) = 0;
   virtual Path *LookupPath(ReferencePtr aRefPtr) = 0;
   virtual SourceSurface *LookupSourceSurface(ReferencePtr aRefPtr) = 0;
   virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0;
   virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0;
   virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0;
   virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0;
+  virtual UnscaledFont* LookupUnscaledFontByIndex(size_t aIndex) { return nullptr; }
   virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0;
   virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0;
   virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
   virtual void AddPath(ReferencePtr aRefPtr, Path *aPath) = 0;
   virtual void RemovePath(ReferencePtr aRefPtr) = 0;
   virtual void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface *aPath) = 0;
   virtual void RemoveSourceSurface(ReferencePtr aRefPtr) = 0;
   virtual void AddFilterNode(mozilla::gfx::ReferencePtr aRefPtr, FilterNode *aSurface) = 0;
@@ -236,16 +237,17 @@ public:
     PATHCREATION,
     PATHDESTRUCTION,
     SOURCESURFACECREATION,
     SOURCESURFACEDESTRUCTION,
     GRADIENTSTOPSCREATION,
     GRADIENTSTOPSDESTRUCTION,
     SNAPSHOT,
     SCALEDFONTCREATION,
+    SCALEDFONTCREATIONBYINDEX,
     SCALEDFONTDESTRUCTION,
     MASKSURFACE,
     FILTERNODECREATION,
     FILTERNODEDESTRUCTION,
     DRAWFILTER,
     FILTERNODESETATTRIBUTE,
     FILTERNODESETINPUT,
     CREATESIMILARDRAWTARGET,
@@ -306,16 +308,20 @@ public:
   template<class S, class F>
   static bool DoWithEvent(S &aStream, EventType aType, F f);
 
   EventType GetType() const { return (EventType)mType; }
 protected:
   friend class DrawEventRecorderPrivate;
   friend class DrawEventRecorderFile;
   friend class DrawEventRecorderMemory;
+  static void RecordUnscaledFont(UnscaledFont *aUnscaledFont, std::ostream *aOutput);
+  static void RecordUnscaledFont(UnscaledFont *aUnscaledFont, MemStream &aOutput);
+  template<class S>
+  static void RecordUnscaledFontImpl(UnscaledFont *aUnscaledFont, S &aOutput);
 
   MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType)
   {}
 
   int32_t mType;
   std::vector<Float> mDashPatternStorage;
 };
 
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -17,16 +17,17 @@
 #include "SFNTData.h"
 
 namespace mozilla {
 namespace gfx {
 
 template<class Derived>
 class RecordedEventDerived : public RecordedEvent {
   using RecordedEvent::RecordedEvent;
+  public:
   void RecordToStream(std::ostream &aStream) const {
     static_cast<const Derived*>(this)->Record(aStream);
   }
   void RecordToStream(EventStream& aStream) const {
     static_cast<const Derived*>(this)->Record(aStream);
   }
   void RecordToStream(MemStream &aStream) const {
     SizeCollector size;
@@ -1063,16 +1064,59 @@ private:
   Float mGlyphSize;
   std::vector<uint8_t> mInstanceData;
   std::vector<FontVariation> mVariations;
 
   template<class S>
   MOZ_IMPLICIT RecordedScaledFontCreation(S &aStream);
 };
 
+class RecordedScaledFontCreationByIndex : public RecordedEventDerived<RecordedScaledFontCreationByIndex> {
+public:
+
+  static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
+                                   const FontVariation* aVariations, uint32_t aNumVariations,
+                                   void* aBaton)
+  {
+    auto recordedScaledFontCreation = static_cast<RecordedScaledFontCreation*>(aBaton);
+    recordedScaledFontCreation->SetFontInstanceData(aData, aSize, aVariations, aNumVariations);
+  }
+
+  RecordedScaledFontCreationByIndex(ScaledFont* aScaledFont, size_t aUnscaledFontIndex)
+    : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX)
+    , mRefPtr(aScaledFont)
+    , mUnscaledFontIndex(aUnscaledFontIndex)
+    , mGlyphSize(aScaledFont->GetSize())
+  {
+    aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
+  }
+
+  virtual bool PlayEvent(Translator *aTranslator) const;
+
+  template<class S> void Record(S &aStream) const;
+  virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
+
+  virtual std::string GetName() const { return "ScaledFont Creation"; }
+  virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
+
+  void SetFontInstanceData(const uint8_t *aData, uint32_t aSize);
+
+private:
+  friend class RecordedEvent;
+
+  ReferencePtr mRefPtr;
+  size_t mUnscaledFontIndex;
+  Float mGlyphSize;
+  std::vector<uint8_t> mInstanceData;
+  std::vector<FontVariation> mVariations;
+
+  template<class S>
+  MOZ_IMPLICIT RecordedScaledFontCreationByIndex(S &aStream);
+};
+
 class RecordedScaledFontDestruction : public RecordedEventDerived<RecordedScaledFontDestruction> {
 public:
   MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
     : RecordedEventDerived(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
   virtual bool PlayEvent(Translator *aTranslator) const;
@@ -2950,16 +2994,78 @@ RecordedScaledFontCreation::RecordedScal
   aStream.read((char*)mInstanceData.data(), size);
   size_t numVariations;
   ReadElement(aStream, numVariations);
   mVariations.resize(numVariations);
   aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations);
 }
 
 inline bool
+RecordedScaledFontCreationByIndex::PlayEvent(Translator *aTranslator) const
+{
+  UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFontByIndex(mUnscaledFontIndex);
+  if (!unscaledFont) {
+    gfxDevCrash(LogReason::UnscaledFontNotFound) <<
+      "UnscaledFont lookup failed for key |" << hexa(mUnscaledFontIndex) << "|.";
+    return false;
+  }
+
+  RefPtr<ScaledFont> scaledFont =
+    unscaledFont->CreateScaledFont(mGlyphSize,
+                                   mInstanceData.data(), mInstanceData.size(),
+                                   mVariations.data(), mVariations.size());
+
+  aTranslator->AddScaledFont(mRefPtr, scaledFont);
+  return true;
+}
+
+template<class S>
+void
+RecordedScaledFontCreationByIndex::Record(S &aStream) const
+{
+  WriteElement(aStream, mRefPtr);
+  WriteElement(aStream, mUnscaledFontIndex);
+  WriteElement(aStream, mGlyphSize);
+  WriteElement(aStream, (size_t)mInstanceData.size());
+  aStream.write((char*)mInstanceData.data(), mInstanceData.size());
+  WriteElement(aStream, (size_t)mVariations.size());
+  aStream.write((char*)mVariations.data(), sizeof(FontVariation) * mVariations.size());
+}
+
+inline void
+RecordedScaledFontCreationByIndex::OutputSimpleEventInfo(std::stringstream &aStringStream) const
+{
+  aStringStream << "[" << mRefPtr << "] ScaledFont Created By Index";
+}
+
+inline void
+RecordedScaledFontCreationByIndex::SetFontInstanceData(const uint8_t *aData, uint32_t aSize)
+{
+  mInstanceData.assign(aData, aData + aSize);
+}
+
+template<class S>
+RecordedScaledFontCreationByIndex::RecordedScaledFontCreationByIndex(S &aStream)
+  : RecordedEventDerived(SCALEDFONTCREATIONBYINDEX)
+{
+  ReadElement(aStream, mRefPtr);
+  ReadElement(aStream, mUnscaledFontIndex);
+  ReadElement(aStream, mGlyphSize);
+
+  size_t size;
+  ReadElement(aStream, size);
+  mInstanceData.resize(size);
+  aStream.read((char*)mInstanceData.data(), size);
+  size_t numVariations;
+  ReadElement(aStream, numVariations);
+  mVariations.resize(numVariations);
+  aStream.read((char*)mVariations.data(), sizeof(FontVariation) * numVariations);
+}
+
+inline bool
 RecordedScaledFontDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveScaledFont(mRefPtr);
   return true;
 }
 
 template<class S>
 void
@@ -3164,16 +3270,17 @@ RecordedFilterNodeSetInput::OutputSimple
     f(SOURCESURFACECREATION, RecordedSourceSurfaceCreation); \
     f(SOURCESURFACEDESTRUCTION, RecordedSourceSurfaceDestruction); \
     f(FILTERNODECREATION, RecordedFilterNodeCreation); \
     f(FILTERNODEDESTRUCTION, RecordedFilterNodeDestruction); \
     f(GRADIENTSTOPSCREATION, RecordedGradientStopsCreation); \
     f(GRADIENTSTOPSDESTRUCTION, RecordedGradientStopsDestruction); \
     f(SNAPSHOT, RecordedSnapshot); \
     f(SCALEDFONTCREATION, RecordedScaledFontCreation); \
+    f(SCALEDFONTCREATIONBYINDEX, RecordedScaledFontCreationByIndex); \
     f(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction); \
     f(MASKSURFACE, RecordedMaskSurface); \
     f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); \
     f(FILTERNODESETINPUT, RecordedFilterNodeSetInput); \
     f(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget); \
     f(FONTDATA, RecordedFontData); \
     f(FONTDESC, RecordedFontDescriptor); \
     f(PUSHLAYER, RecordedPushLayer); \
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -76,18 +76,19 @@ BufferRecycleBin::RecycleBuffer(UniquePt
   mRecycledBuffers.AppendElement(Move(aBuffer));
 }
 
 UniquePtr<uint8_t[]>
 BufferRecycleBin::GetBuffer(uint32_t aSize)
 {
   MutexAutoLock lock(mLock);
 
-  if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
-    return MakeUnique<uint8_t[]>(aSize);
+  if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize) {
+    return UniquePtr<uint8_t[]>(new (fallible) uint8_t[aSize]);
+  }
 
   uint32_t last = mRecycledBuffers.Length() - 1;
   UniquePtr<uint8_t[]> result = Move(mRecycledBuffers[last]);
   mRecycledBuffers.RemoveElementAt(last);
   return result;
 }
 
 void
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -289,29 +289,22 @@ WebRenderBridgeChild::GetFontKeyForScale
              (aScaledFont->GetType() == gfx::FontType::MAC) ||
              (aScaledFont->GetType() == gfx::FontType::FONTCONFIG));
 
   wr::FontInstanceKey instanceKey = { wr::IdNamespace { 0 }, 0 };
   if (mFontInstanceKeys.Get(aScaledFont, &instanceKey)) {
     return instanceKey;
   }
 
-  RefPtr<gfx::UnscaledFont> unscaled = aScaledFont->GetUnscaledFont();
-  MOZ_ASSERT(unscaled);
-
   wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
 
-  wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0};
-  if (!mFontKeys.Get(unscaled, &fontKey)) {
-    FontFileDataSink sink = { &fontKey, this, &resources };
-    if (!unscaled->GetFontFileData(WriteFontFileData, &sink)) {
-      return instanceKey;
-    }
-
-    mFontKeys.Put(unscaled, fontKey);
+  wr::FontKey fontKey = GetFontKeyForUnscaledFont(aScaledFont->GetUnscaledFont());
+  wr::FontKey nullKey = { wr::IdNamespace { 0 }, 0};
+  if (fontKey == nullKey) {
+    return instanceKey;
   }
 
   instanceKey = GetNextFontInstanceKey();
 
   Maybe<wr::FontInstanceOptions> options;
   Maybe<wr::FontInstancePlatformOptions> platformOptions;
   std::vector<FontVariation> variations;
   aScaledFont->GetWRFontInstanceOptions(&options, &platformOptions, &variations);
@@ -319,16 +312,37 @@ WebRenderBridgeChild::GetFontKeyForScale
   resources.AddFontInstance(instanceKey, fontKey, aScaledFont->GetSize(),
                             options.ptrOr(nullptr), platformOptions.ptrOr(nullptr),
                             Range<const FontVariation>(variations.data(), variations.size()));
   UpdateResources(resources);
 
   mFontInstanceKeys.Put(aScaledFont, instanceKey);
 
   return instanceKey;
+
+}
+
+wr::FontKey
+WebRenderBridgeChild::GetFontKeyForUnscaledFont(gfx::UnscaledFont* aUnscaled)
+{
+  MOZ_ASSERT(!mDestroyed);
+
+  wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0};
+  if (!mFontKeys.Get(aUnscaled, &fontKey)) {
+    wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
+    FontFileDataSink sink = { &fontKey, this, &resources };
+    if (!aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
+      return fontKey;
+    }
+    UpdateResources(resources);
+
+    mFontKeys.Put(aUnscaled, fontKey);
+  }
+
+  return fontKey;
 }
 
 void
 WebRenderBridgeChild::RemoveExpiredFontKeys()
 {
   uint32_t counter = gfx::ScaledFont::DeletionCounter();
   wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
   if (mFontInstanceKeysDeleted != counter) {
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -131,16 +131,17 @@ public:
   void PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<wr::GlyphInstance>& aGlyphs,
                   gfx::ScaledFont* aFont, const wr::ColorF& aColor,
                   const StackingContextHelper& aSc,
                   const wr::LayerRect& aBounds, const wr::LayerRect& aClip,
                   bool aBackfaceVisible,
                   const wr::GlyphOptions* aGlyphOptions = nullptr);
 
   wr::FontInstanceKey GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont);
+  wr::FontKey GetFontKeyForUnscaledFont(gfx::UnscaledFont* aUnscaledFont);
 
   void RemoveExpiredFontKeys();
   void ClearReadLocks();
 
   void BeginClearCachedResources();
   void EndClearCachedResources();
 
   void SetWebRenderLayerManager(WebRenderLayerManager* aManager);
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -777,16 +777,17 @@ WebRenderBridgeParent::RecvAddPipelineId
   }
   MOZ_ASSERT(host->AsWebRenderImageHost());
   WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
   if (!wrHost) {
     return IPC_OK();
   }
 
   wrHost->SetWrBridge(this);
+  wrHost->EnableUseAsyncImagePipeline();
   mAsyncCompositables.Put(wr::AsUint64(aPipelineId), wrHost);
   mAsyncImageManager->AddAsyncImagePipeline(aPipelineId, wrHost);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvRemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId)
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -20,16 +20,18 @@
 #include "nsDisplayListInvalidation.h"
 #include "WebRenderCanvasRenderer.h"
 #include "LayersLogging.h"
 #include "LayerTreeInvalidation.h"
 
 namespace mozilla {
 namespace layers {
 
+using namespace gfx;
+
 void WebRenderCommandBuilder::Destroy()
 {
   mLastCanvasDatas.Clear();
   RemoveUnusedAndResetWebRenderUserData();
 }
 
 void
 WebRenderCommandBuilder::EmptyTransaction()
@@ -495,22 +497,30 @@ WebRenderCommandBuilder::GenerateFallbac
 
   if (needPaint || !fallbackData->GetKey()) {
     gfx::SurfaceFormat format = aItem->GetType() == DisplayItemType::TYPE_MASK ?
                                                       gfx::SurfaceFormat::A8 : gfx::SurfaceFormat::B8G8R8A8;
     if (gfxPrefs::WebRenderBlobImages()) {
       bool snapped;
       bool isOpaque = aItem->GetOpaqueRegion(aDisplayListBuilder, &snapped).Contains(clippedBounds);
 
-      RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
+      RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>([&] (MemStream &aStream, std::vector<RefPtr<UnscaledFont>> &aUnscaledFonts) {
+          size_t count = aUnscaledFonts.size();
+          aStream.write((const char*)&count, sizeof(count));
+          for (auto unscaled : aUnscaledFonts) {
+            wr::FontKey key = mManager->WrBridge()->GetFontKeyForUnscaledFont(unscaled);
+            aStream.write((const char*)&key, sizeof(key));
+          }
+        });
       RefPtr<gfx::DrawTarget> dummyDt =
         gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), format);
       RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize());
       PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder,
                             fallbackData->mBasicLayerManager, mManager, scale);
+      recorder->FlushItem(IntRect());
       recorder->Finish();
 
       Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
       wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
       wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
       if (!aResources.AddBlobImage(key, descriptor, bytes)) {
         return nullptr;
       }
--- a/gfx/layers/wr/WebRenderImageHost.cpp
+++ b/gfx/layers/wr/WebRenderImageHost.cpp
@@ -24,16 +24,17 @@ namespace layers {
 
 class ISurfaceAllocator;
 
 WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo)
   : CompositableHost(aTextureInfo)
   , ImageComposite()
   , mWrBridge(nullptr)
   , mWrBridgeBindings(0)
+  , mUseAsyncImagePipeline(false)
 {}
 
 WebRenderImageHost::~WebRenderImageHost()
 {
   MOZ_ASSERT(!mWrBridge);
 }
 
 void
@@ -183,17 +184,17 @@ WebRenderImageHost::GetAsTextureHostForC
 void
 WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture)
 {
   if (aTexture == mCurrentTextureHost.get()) {
     return;
   }
 
   if (mWrBridge &&
-      !mAsyncRef &&
+      !mUseAsyncImagePipeline &&
       !!mCurrentTextureHost &&
       mCurrentTextureHost != aTexture &&
       mCurrentTextureHost->AsWebRenderTextureHost()) {
     MOZ_ASSERT(mWrBridge->AsyncImageManager());
     wr::PipelineId piplineId = mWrBridge->PipelineId();
     wr::Epoch epoch = mWrBridge->WrEpoch();
     mWrBridge->AsyncImageManager()->HoldExternalImage(
       piplineId,
--- a/gfx/layers/wr/WebRenderImageHost.h
+++ b/gfx/layers/wr/WebRenderImageHost.h
@@ -68,27 +68,33 @@ public:
   virtual WebRenderImageHost* AsWebRenderImageHost() override { return this; }
 
   TextureHost* GetAsTextureHostForComposite();
 
   void SetWrBridge(WebRenderBridgeParent* aWrBridge);
 
   void ClearWrBridge();
 
+  void EnableUseAsyncImagePipeline()
+  {
+    mUseAsyncImagePipeline = true;
+  }
+
   TextureHost* GetCurrentTextureHost() { return mCurrentTextureHost; }
 
 protected:
   // ImageComposite
   virtual TimeStamp GetCompositionTime() const override;
 
   void SetCurrentTextureHost(TextureHost* aTexture);
 
   WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge;
 
   uint32_t mWrBridgeBindings;
+  bool mUseAsyncImagePipeline;
 
   CompositableTextureHostRef mCurrentTextureHost;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_GFX_WEBRENDERIMAGEHOST_H
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -8,28 +8,112 @@
 #include "mozilla/Range.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/InlineTranslator.h"
 #include "mozilla/gfx/RecordedEvent.h"
 #include "WebRenderTypes.h"
 #include "webrender_ffi.h"
 
 #include <iostream>
+#include <unordered_map>
 
 #ifdef MOZ_ENABLE_FREETYPE
 #include "mozilla/ThreadLocal.h"
 #endif
 
+namespace std {
+  template <>
+    struct hash<mozilla::wr::FontKey>{
+      public :
+        size_t operator()(const mozilla::wr::FontKey &key ) const
+        {
+          return hash<size_t>()(mozilla::wr::AsUint64(key));
+        }
+    };
+};
+
+
+
 namespace mozilla {
+
+using namespace gfx;
+
 namespace wr {
 
 #ifdef MOZ_ENABLE_FREETYPE
 static MOZ_THREAD_LOCAL(FT_Library) sFTLibrary;
 #endif
 
+struct FontTemplate {
+  void *mData;
+  size_t mSize;
+  int mIndex;
+  const VecU8 *mVec;
+  RefPtr<UnscaledFont> mUnscaledFont;
+};
+
+// we need to do special things for linux so that we have fonts per backend
+std::unordered_map<FontKey, FontTemplate> sFontDataTable;
+
+extern "C" {
+void
+AddFontData(wr::FontKey aKey, void *aData, size_t aSize, int aIndex, ArcVecU8 *aVec) {
+  auto i = sFontDataTable.find(aKey);
+  if (i == sFontDataTable.end()) {
+    FontTemplate font;
+    font.mData = aData;
+    font.mSize = aSize;
+    font.mIndex = aIndex;
+    font.mVec = wr_add_ref_arc(aVec);
+    sFontDataTable[aKey] = font;
+  }
+}
+
+void
+DeleteFontData(wr::FontKey aKey) {
+  auto i = sFontDataTable.find(aKey);
+  if (i != sFontDataTable.end()) {
+    sFontDataTable.erase(i);
+    wr_dec_ref_arc(i->second.mVec);
+  }
+}
+}
+
+RefPtr<UnscaledFont>
+GetUnscaledFont(Translator *aTranslator, wr::FontKey key) {
+  MOZ_ASSERT(sFontDataTable.find(key) != sFontDataTable.end());
+  auto &data = sFontDataTable[key];
+  if (data.mUnscaledFont) {
+    return data.mUnscaledFont;
+  }
+  FontType type =
+#ifdef XP_MACOSX
+    FontType::MAC;
+#elif XP_WIN
+    FontType::DWRITE;
+#elif ANDROID
+    FontType::FREETYPE;
+#else
+    FontType::FONTCONFIG;
+#endif
+  // makes a copy of the data
+  RefPtr<NativeFontResource> fontResource = Factory::CreateNativeFontResource((uint8_t*)data.mData, data.mSize,
+                                                                              aTranslator->GetReferenceDrawTarget()->GetBackendType(),
+                                                                              type,
+                                                                              aTranslator->GetFontContext());
+  RefPtr<UnscaledFont> unscaledFont;
+  if (fontResource) {
+    // Instance data is only needed for GDI fonts which webrender does not
+    // support.
+    unscaledFont = fontResource->CreateUnscaledFont(data.mIndex, nullptr, 0);
+  }
+  data.mUnscaledFont = unscaledFont;
+  return unscaledFont;
+}
+
 static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
                                 gfx::IntSize aSize,
                                 gfx::SurfaceFormat aFormat,
                                 const uint16_t *aTileSize,
                                 const mozilla::wr::TileOffset *aTileOffset,
                                 Range<uint8_t> aOutput)
 {
   MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
@@ -81,19 +165,53 @@ static bool Moz2DRenderCallback(const Ra
     gfx::Tile tile;
     tile.mDrawTarget = dt;
     tile.mTileOrigin = gfx::IntPoint(aTileOffset->x * *aTileSize, aTileOffset->y * *aTileSize);
     tileset.mTiles = &tile;
     tileset.mTileCount = 1;
     dt = gfx::Factory::CreateTiledDrawTarget(tileset);
   }
 
-  gfx::InlineTranslator translator(dt, fontContext);
+  struct Reader {
+    const uint8_t *buf;
+    size_t len;
+    size_t pos;
+
+    Reader(const uint8_t *buf, size_t len) : buf(buf), len(len), pos(0) {}
+
+    size_t ReadSize() {
+      size_t ret;
+      MOZ_RELEASE_ASSERT(pos + sizeof(ret) <= len);
+      memcpy(&ret, buf + pos, sizeof(ret));
+      pos += sizeof(ret);
+      return ret;
+    }
+  };
+  //XXX: Make safe
+  size_t indexOffset = *(size_t*)(aBlob.end().get()-sizeof(size_t));
+  Reader reader(aBlob.begin().get()+indexOffset, aBlob.length()-sizeof(size_t)-indexOffset);
 
-  auto ret = translator.TranslateRecording((char*)aBlob.begin().get(), aBlob.length());
+  bool ret;
+  size_t offset = 0;
+  while (reader.pos < reader.len) {
+    size_t end = reader.ReadSize();
+    size_t extra_end = reader.ReadSize();
+
+    gfx::InlineTranslator translator(dt, fontContext);
+
+    size_t count = *(size_t*)(aBlob.begin().get() + end);
+    for (size_t i = 0; i < count; i++) {
+      wr::FontKey key = *(wr::FontKey*)(aBlob.begin() + end + sizeof(count) + sizeof(wr::FontKey)*i).get();
+      RefPtr<UnscaledFont> font = GetUnscaledFont(&translator, key);
+      translator.AddUnscaledFont(0, font);
+    }
+    Range<const uint8_t> blob(aBlob.begin() + offset, aBlob.begin() + end);
+    ret = translator.TranslateRecording((char*)blob.begin().get(), blob.length());
+    offset = extra_end;
+  }
 
 #if 0
   static int i = 0;
   char filename[40];
   sprintf(filename, "out%d.png", i++);
   gfxUtils::WriteAsPNG(dt, filename);
 #endif
 
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -33,17 +33,17 @@ type WrEpoch = Epoch;
 /// cbindgen:derive-neq=true
 type WrIdNamespace = IdNamespace;
 
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrPipelineId = PipelineId;
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrImageKey = ImageKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
-type WrFontKey = FontKey;
+pub type WrFontKey = FontKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrFontInstanceKey = FontInstanceKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrYuvColorSpace = YuvColorSpace;
 
 fn make_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
     if ptr.is_null() {
         &[]
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -1,13 +1,15 @@
+#![allow(improper_ctypes)] // this is needed so that rustc doesn't complain about passing the &Arc<Vec> to an extern function
 use webrender_api::*;
 use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb};
 use rayon::ThreadPool;
 
 use std::collections::hash_map::{HashMap, Entry};
+use std::mem;
 use std::ptr;
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::sync::Arc;
 
 pub struct Moz2dImageRenderer {
     blob_commands: HashMap<ImageKey, (Arc<BlobImageData>, Option<TileSize>)>,
 
     // The images rendered in the current frame (not kept here between frames)
@@ -21,32 +23,74 @@ pub struct Moz2dImageRenderer {
 
 fn option_to_nullable<T>(option: &Option<T>) -> *const T {
     match option {
         &Some(ref x) => { x as *const T }
         &None => { ptr::null() }
     }
 }
 
+fn to_usize(slice: &[u8]) -> usize {
+    convert_from_bytes(slice)
+}
+
+fn convert_from_bytes<T>(slice: &[u8]) -> T {
+    assert!(mem::size_of::<T>() <= slice.len());
+    let mut ret: T;
+    unsafe {
+        ret = mem::uninitialized();
+        ptr::copy_nonoverlapping(slice.as_ptr(),
+                                 &mut ret as *mut T as *mut u8,
+                                 mem::size_of::<T>());
+    }
+    ret
+}
+
+struct BufReader<'a>
+{
+    buf: &'a[u8],
+    pos: usize,
+}
+
+impl<'a> BufReader<'a> {
+    fn new(buf: &'a[u8]) -> BufReader<'a> {
+        BufReader{ buf: buf, pos: 0 }
+    }
+
+    fn read<T>(&mut self) -> T {
+        let ret = convert_from_bytes(&self.buf[self.pos..]);
+        self.pos += mem::size_of::<T>();
+        ret
+    }
+
+    fn read_font_key(&mut self) -> FontKey {
+        self.read()
+    }
+
+    fn read_usize(&mut self) -> usize {
+        self.read()
+    }
+}
+
 impl BlobImageRenderer for Moz2dImageRenderer {
     fn add(&mut self, key: ImageKey, data: BlobImageData, tiling: Option<TileSize>) {
         self.blob_commands.insert(key, (Arc::new(data), tiling));
     }
 
     fn update(&mut self, key: ImageKey, data: BlobImageData, _dirty_rect: Option<DeviceUintRect>) {
         let entry = self.blob_commands.get_mut(&key).unwrap();
         entry.0 = Arc::new(data);
     }
 
     fn delete(&mut self, key: ImageKey) {
         self.blob_commands.remove(&key);
     }
 
     fn request(&mut self,
-               _resources: &BlobImageResources,
+               resources: &BlobImageResources,
                request: BlobImageRequest,
                descriptor: &BlobImageDescriptor,
                _dirty_rect: Option<DeviceUintRect>) {
         debug_assert!(!self.rendered_images.contains_key(&request));
         // TODO: implement tiling.
 
         // Add None in the map of rendered images. This makes it possible to differentiate
         // between commands that aren't finished yet (entry in the map is equal to None) and
@@ -56,16 +100,39 @@ impl BlobImageRenderer for Moz2dImageRen
 
         let tx = self.tx.clone();
         let descriptor = descriptor.clone();
         let blob = &self.blob_commands[&request.key];
         let tile_size = blob.1;
         let commands = Arc::clone(&blob.0);
 
 
+        fn process_fonts(mut extra_data: BufReader, resources: &BlobImageResources) {
+            let font_count = extra_data.read_usize();
+            for _ in 0..font_count {
+                let key = extra_data.read_font_key();
+                let template = resources.get_font_data(key);
+                if let &FontTemplate::Raw(ref data, ref index) = template {
+                    unsafe { AddFontData(key, data.as_ptr(), data.len(), *index, data); }
+                }
+                resources.get_font_data(key);
+            }
+        }
+        let index_offset_pos = commands.len()-mem::size_of::<usize>();
+
+        let index_offset = to_usize(&commands[index_offset_pos..]);
+        {
+            let mut index = BufReader::new(&commands[index_offset..index_offset_pos]);
+            while index.pos < index.buf.len() {
+                let end = index.read_usize();
+                let extra_end = index.read_usize();
+                process_fonts(BufReader::new(&commands[end..extra_end]), resources);
+            }
+        }
+
         self.workers.spawn(move || {
             let buf_size = (descriptor.width
                 * descriptor.height
                 * descriptor.format.bytes_per_pixel()) as usize;
             let mut output = vec![255u8; buf_size];
 
             let result = unsafe {
                 if wr_moz2d_render_cb(
@@ -115,24 +182,31 @@ impl BlobImageRenderer for Moz2dImageRen
                 return result
             }
             self.rendered_images.insert(req, Some(result));
         }
 
         // If we break out of the loop above it means the channel closed unexpectedly.
         Err(BlobImageError::Other("Channel closed".into()))
     }
-
-    fn delete_font(&mut self, _font: FontKey) {
+    fn delete_font(&mut self, font: FontKey) {
+        unsafe { DeleteFontData(font); }
     }
 
     fn delete_font_instance(&mut self, _key: FontInstanceKey) {
     }
 }
 
+use bindings::WrFontKey;
+extern "C" {
+    #[allow(improper_ctypes)]
+    fn AddFontData(key: WrFontKey, data: *const u8, size: usize, index: u32, vec: &Arc<Vec<u8>>);
+    fn DeleteFontData(key: WrFontKey);
+}
+
 impl Moz2dImageRenderer {
     pub fn new(workers: Arc<ThreadPool>) -> Self {
         let (tx, rx) = channel();
         Moz2dImageRenderer {
             blob_commands: HashMap::new(),
             rendered_images: HashMap::new(),
             workers: workers,
             tx: tx,
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -34,17 +34,17 @@ if CONFIG['OS_TARGET'] == 'Darwin' and (
         CONFIG['MOZ_MEMORY']):
     SOURCES += [
         'zone.c',
     ]
 
 Library('memory')
 
 if CONFIG['OS_TARGET'] == 'Android' and CONFIG['CC_TYPE'] == 'clang':
-    CFLAGS += [
+    CXXFLAGS += [
         '-Wno-tautological-pointer-compare',
     ]
 
 FINAL_LIBRARY = 'mozglue'
 
 if CONFIG['_MSC_VER']:
     CXXFLAGS += ['-wd4273'] # inconsistent dll linkage (bug 558163)
 
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -252,16 +252,19 @@ static const DllBlockInfo sWindowsDllBlo
   { "nahimicmsidevprops.dll", UNVERSIONED },
 
   // Bug 1268470 - crashes with Kaspersky Lab on Windows 8
   { "klsihk64.dll", MAKE_VERSION(14, 0, 456, 0xffff), DllBlockInfo::BLOCK_WIN8_ONLY },
 
   // Bug 1407337, crashes with OpenSC < 0.16.0
   { "onepin-opensc-pkcs11.dll", MAKE_VERSION(0, 15, 0xffff, 0xffff) },
 
+  // Avecto Privilege Guard causes crashes, bug 1385542
+  { "pghook.dll", ALL_VERSIONS },
+
   { nullptr, 0 }
 };
 
 #ifndef STATUS_DLL_NOT_FOUND
 #define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L)
 #endif
 
 // define this for very verbose dll load debug spew
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -326,16 +326,35 @@ 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
 {
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -3619,16 +3619,20 @@ HttpChannelChild::OverrideWithSynthesize
   if (!mSynthesizedInput) {
     rv = NS_NewCStringInputStream(getter_AddRefs(mSynthesizedInput),
                                   EmptyCString());
     NS_ENSURE_SUCCESS_VOID(rv);
   }
 
   if (nsHttpChannel::WillRedirect(mResponseHead)) {
     mShouldInterceptSubsequentRedirect = true;
+    if (mInterceptListener) {
+      mInterceptListener->Cleanup();
+      mInterceptListener = nullptr;
+    }
     // Continue with the original cross-process request
     rv = ContinueAsyncOpen();
     return;
   }
 
   // For progress we trust the content-length for the "maximum" size.
   // We can't determine the full size from the stream itself since we
   // only receive the data incrementally.  We can't trust Available()
--- a/taskcluster/ci/test/mochitest.yml
+++ b/taskcluster/ci/test/mochitest.yml
@@ -33,27 +33,26 @@ mochitest:
             android.*: xlarge
             default: default
     chunks:
         by-test-platform:
             android-4.3-arm7-api-16/debug: 48
             android.*: 20
             linux.*/debug: 16
             linux64-asan/opt: 10
-            linux64-*cov/opt: 10
+            linux64-.*cov/opt: 10
             default: 5
     e10s:
         by-test-platform:
             linux64-jsdcov/opt: false
             windows7-32/debug: both
             default: true
     max-run-time:
         by-test-platform:
             android-4.3-arm7-api-16/debug: 7200
-            linux64-jsdcov/opt: 10800
             default: 5400
     allow-software-gl-layers: false
     tier:
         by-test-platform:
             windows10-64-asan.*: 3
             default: default
     mozharness:
         mochitest-flavor: plain
@@ -91,17 +90,16 @@ mochitest-browser-chrome:
             linux64-jsdcov/opt: mochitest/browser-chrome-coverage
             default: mochitest/browser-chrome-chunked
     treeherder-symbol: tc-M(bc)
     loopback-video: true
     chunks:
         by-test-platform:
             linux.*/debug: 16
             linux64-asan/opt: 16
-            linux64-jsdcov/opt: 35
             default: 7
     e10s:
         by-test-platform:
             linux64-jsdcov/opt: false
             windows7-32/debug: both
             default: true
     max-run-time:
         by-test-platform:
--- a/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini
+++ b/testing/web-platform/meta/service-workers/service-worker/redirected-response.https.html.ini
@@ -1,19 +1,8 @@
 [redirected-response.https.html]
   type: testharness
-  disabled:
-    if debug and os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1411528
-  expected:
-    if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH
-    if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH
-    if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): CRASH
-    if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH
-    if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH
-    if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): CRASH
-    if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): CRASH
-    if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): CRASH
   [mode: "follow", no mode change]
     expected: FAIL
 
   [Fetch should not follow the redirect response 21 times.]
     expected: FAIL