Merge autoland to mozilla-central. a=merge
authorMarian-Vasile Laza <mlaza@mozilla.com>
Wed, 10 Aug 2022 12:42:17 +0300
changeset 626637 f75c79d52f563f19c2baa22d60341564a9d31546
parent 626627 7c06102ca11cdadc7f7e3ca9b481b1a454fa16b4 (current diff)
parent 626636 1995acac9f11fb8c9bfad8b71d6c32f26ed57e18 (diff)
child 626654 05b0321c4c16281470a5a893d85de37580a94e76
push id40108
push usermlaza@mozilla.com
push dateWed, 10 Aug 2022 09:45:30 +0000
treeherdermozilla-central@f75c79d52f56 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone105.0a1
first release with
nightly linux32
f75c79d52f56 / 105.0a1 / 20220810094530 / files
nightly linux64
f75c79d52f56 / 105.0a1 / 20220810094530 / files
nightly mac
f75c79d52f56 / 105.0a1 / 20220810094530 / files
nightly win32
f75c79d52f56 / 105.0a1 / 20220810094530 / files
nightly win64
f75c79d52f56 / 105.0a1 / 20220810094530 / 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 autoland to mozilla-central. a=merge
--- a/dom/canvas/DrawTargetWebgl.cpp
+++ b/dom/canvas/DrawTargetWebgl.cpp
@@ -19,35 +19,35 @@
 
 #include "ClientWebGLContext.h"
 #include "WebGLChild.h"
 
 #include "gfxPlatform.h"
 
 namespace mozilla::gfx {
 
-// Inserts (allocated) a rectangle of the requested size into the tree.
+// Inserts (allocates) a rectangle of the requested size into the tree.
 Maybe<IntPoint> TexturePacker::Insert(const IntSize& aSize) {
   // Check if the available space could possibly fit the requested size. If
   // not, there is no reason to continue searching within this sub-tree.
   if (mAvailable < std::min(aSize.width, aSize.height) ||
       mBounds.width < aSize.width || mBounds.height < aSize.height) {
     return Nothing();
   }
-  if (mChildren[0]) {
+  if (mChildren) {
     // If this node has children, then try to insert into each of the children
     // in turn.
-    Maybe<IntPoint> inserted = mChildren[0]->Insert(aSize);
+    Maybe<IntPoint> inserted = mChildren[0].Insert(aSize);
     if (!inserted) {
-      inserted = mChildren[1]->Insert(aSize);
+      inserted = mChildren[1].Insert(aSize);
     }
     // If the insertion succeeded, adjust the available state to reflect the
     // remaining space in the children.
     if (inserted) {
-      mAvailable = std::max(mChildren[0]->mAvailable, mChildren[1]->mAvailable);
+      mAvailable = std::max(mChildren[0].mAvailable, mChildren[1].mAvailable);
       if (!mAvailable) {
         DiscardChildren();
       }
     }
     return inserted;
   }
   // If we get here, we've encountered a leaf node. First check if its size is
   // exactly the requested size. If so, mark the node as unavailable and return
@@ -55,39 +55,39 @@ Maybe<IntPoint> TexturePacker::Insert(co
   if (mBounds.Size() == aSize) {
     mAvailable = 0;
     return Some(mBounds.TopLeft());
   }
   // The node is larger than the requested size. Choose the axis which has the
   // most excess space beyond the requested size and split it so that at least
   // one of the children matches the requested size for that axis.
   if (mBounds.width - aSize.width > mBounds.height - aSize.height) {
-    mChildren[0].reset(new TexturePacker(
-        IntRect(mBounds.x, mBounds.y, aSize.width, mBounds.height)));
-    mChildren[1].reset(new TexturePacker(
-        IntRect(mBounds.x + aSize.width, mBounds.y, mBounds.width - aSize.width,
-                mBounds.height)));
+    mChildren.reset(new TexturePacker[2]{
+        TexturePacker(
+            IntRect(mBounds.x, mBounds.y, aSize.width, mBounds.height)),
+        TexturePacker(IntRect(mBounds.x + aSize.width, mBounds.y,
+                              mBounds.width - aSize.width, mBounds.height))});
   } else {
-    mChildren[0].reset(new TexturePacker(
-        IntRect(mBounds.x, mBounds.y, mBounds.width, aSize.height)));
-    mChildren[1].reset(new TexturePacker(
-        IntRect(mBounds.x, mBounds.y + aSize.height, mBounds.width,
-                mBounds.height - aSize.height)));
+    mChildren.reset(new TexturePacker[2]{
+        TexturePacker(
+            IntRect(mBounds.x, mBounds.y, mBounds.width, aSize.height)),
+        TexturePacker(IntRect(mBounds.x, mBounds.y + aSize.height,
+                              mBounds.width, mBounds.height - aSize.height))});
   }
   // After splitting, try to insert into the first child, which should usually
   // be big enough to accomodate the request. Adjust the available state to the
   // remaining space.
-  Maybe<IntPoint> inserted = mChildren[0]->Insert(aSize);
-  mAvailable = std::max(mChildren[0]->mAvailable, mChildren[1]->mAvailable);
+  Maybe<IntPoint> inserted = mChildren[0].Insert(aSize);
+  mAvailable = std::max(mChildren[0].mAvailable, mChildren[1].mAvailable);
   return inserted;
 }
 
 // Removes (frees) a rectangle with the given bounds from the tree.
 bool TexturePacker::Remove(const IntRect& aBounds) {
-  if (!mChildren[0]) {
+  if (!mChildren) {
     // If there are no children, we encountered a leaf node. Non-zero available
     // state means that this node was already removed previously. Also, if the
     // bounds don't contain the request, and assuming the tree was previously
     // split during insertion, then this node is not the node we're searching
     // for.
     if (mAvailable > 0 || !mBounds.Contains(aBounds)) {
       return false;
     }
@@ -102,49 +102,51 @@ bool TexturePacker::Remove(const IntRect
     // needs to be subdivided until it has a child node that exactly matches.
     // Choose the axis to split with the largest amount of excess space. Within
     // that axis, choose the larger of the space before or after the subrect as
     // the split point to the new children.
     if (mBounds.width - aBounds.width > mBounds.height - aBounds.height) {
       int split = aBounds.x - mBounds.x > mBounds.XMost() - aBounds.XMost()
                       ? aBounds.x
                       : aBounds.XMost();
-      mChildren[0].reset(new TexturePacker(
-          IntRect(mBounds.x, mBounds.y, split - mBounds.x, mBounds.height),
-          false));
-      mChildren[1].reset(new TexturePacker(
-          IntRect(split, mBounds.y, mBounds.XMost() - split, mBounds.height),
-          false));
+      mChildren.reset(new TexturePacker[2]{
+          TexturePacker(
+              IntRect(mBounds.x, mBounds.y, split - mBounds.x, mBounds.height),
+              false),
+          TexturePacker(IntRect(split, mBounds.y, mBounds.XMost() - split,
+                                mBounds.height),
+                        false)});
     } else {
       int split = aBounds.y - mBounds.y > mBounds.YMost() - aBounds.YMost()
                       ? aBounds.y
                       : aBounds.YMost();
-      mChildren[0].reset(new TexturePacker(
-          IntRect(mBounds.x, mBounds.y, mBounds.width, split - mBounds.y),
-          false));
-      mChildren[1].reset(new TexturePacker(
-          IntRect(mBounds.x, split, mBounds.width, mBounds.YMost() - split),
-          false));
+      mChildren.reset(new TexturePacker[2]{
+          TexturePacker(
+              IntRect(mBounds.x, mBounds.y, mBounds.width, split - mBounds.y),
+              false),
+          TexturePacker(
+              IntRect(mBounds.x, split, mBounds.width, mBounds.YMost() - split),
+              false)});
     }
   }
   // We've encountered a branch node. Determine which of the two child nodes
   // would possibly contain the removed bounds. We first check which axis the
   // children were split on and then whether the removed bounds on that axis
   // are past the start of the second child. Proceed to recurse into that
   // child node for removal.
-  bool next = mChildren[0]->mBounds.x < mChildren[1]->mBounds.x
-                  ? aBounds.x >= mChildren[1]->mBounds.x
-                  : aBounds.y >= mChildren[1]->mBounds.y;
-  bool removed = mChildren[next ? 1 : 0]->Remove(aBounds);
+  bool next = mChildren[0].mBounds.x < mChildren[1].mBounds.x
+                  ? aBounds.x >= mChildren[1].mBounds.x
+                  : aBounds.y >= mChildren[1].mBounds.y;
+  bool removed = mChildren[next ? 1 : 0].Remove(aBounds);
   if (removed) {
-    if (mChildren[0]->IsFullyAvailable() && mChildren[1]->IsFullyAvailable()) {
+    if (mChildren[0].IsFullyAvailable() && mChildren[1].IsFullyAvailable()) {
       DiscardChildren();
       mAvailable = std::min(mBounds.width, mBounds.height);
     } else {
-      mAvailable = std::max(mChildren[0]->mAvailable, mChildren[1]->mAvailable);
+      mAvailable = std::max(mChildren[0].mAvailable, mChildren[1].mAvailable);
     }
   }
   return removed;
 }
 
 SharedTexture::SharedTexture(const IntSize& aSize, SurfaceFormat aFormat,
                              const RefPtr<WebGLTextureJS>& aTexture)
     : mPacker(IntRect(IntPoint(0, 0), aSize)),
@@ -1948,17 +1950,17 @@ PathCacheEntry::PathCacheEntry(const SkP
 // texture handle is valid to determine if it will need to render the text run
 // or just reuse the cached texture.
 already_AddRefed<PathCacheEntry> PathCache::FindOrInsertEntry(
     const SkPath& aPath, const Pattern* aPattern,
     const StrokeOptions* aStrokeOptions, const Matrix& aTransform,
     const IntRect& aBounds, const Point& aOrigin, float aSigma) {
   HashNumber hash =
       PathCacheEntry::HashPath(aPath, aPattern, aTransform, aBounds);
-  for (const RefPtr<PathCacheEntry>& entry : mEntries) {
+  for (const RefPtr<PathCacheEntry>& entry : GetChain(hash)) {
     if (entry->MatchesPath(aPath, aPattern, aStrokeOptions, aTransform, aBounds,
                            aOrigin, hash, aSigma)) {
       return do_AddRef(entry);
     }
   }
   Pattern* pattern = nullptr;
   if (aPattern) {
     pattern = aPattern->CloneWeak();
@@ -1971,17 +1973,17 @@ already_AddRefed<PathCacheEntry> PathCac
     strokeOptions = aStrokeOptions->Clone();
     if (!strokeOptions) {
       return nullptr;
     }
   }
   RefPtr<PathCacheEntry> entry =
       new PathCacheEntry(aPath, pattern, strokeOptions, aTransform, aBounds,
                          aOrigin, hash, aSigma);
-  mEntries.insertFront(entry);
+  Insert(entry);
   return entry.forget();
 }
 
 void DrawTargetWebgl::Fill(const Path* aPath, const Pattern& aPattern,
                            const DrawOptions& aOptions) {
   if (!aPath || aPath->GetBackendType() != BackendType::SKIA) {
     return;
   }
@@ -2411,119 +2413,168 @@ void DrawTargetWebgl::StrokeGlyphs(Scale
     // blend with the over op.
     MarkSkiaChanged();
   } else {
     MarkSkiaChanged(aOptions);
   }
   mSkia->StrokeGlyphs(aFont, aBuffer, aPattern, aStrokeOptions, aOptions);
 }
 
+// Depending on whether we enable subpixel position for a given font, Skia may
+// round transformed coordinates differently on each axis. By default, text is
+// subpixel quantized horizontally and snapped to a whole integer vertical
+// baseline. Axis-flip transforms instead snap to horizontal boundaries while
+// subpixel quantizing along the vertical. For other types of transforms, Skia
+// just applies subpixel quantization to both axes.
+// We must duplicate the amount of quantization Skia applies carefully as a
+// boundary value such as 0.49 may round to 0.5 with subpixel quantization,
+// but if Skia actually snapped it to a whole integer instead, it would round
+// down to 0. If a subsequent glyph with offset 0.51 came in, we might
+// mistakenly round it down to 0.5, whereas Skia would round it up to 1. Thus
+// we would alias 0.49 and 0.51 to the same cache entry, while Skia would
+// actually snap the offset to 0 or 1, depending, resulting in mismatched
+// hinting.
+static inline IntPoint QuantizeScale(ScaledFont* aFont,
+                                     const Matrix& aTransform) {
+  if (!aFont->UseSubpixelPosition()) {
+    return {1, 1};
+  }
+  if (aTransform._12 == 0) {
+    // Glyphs are rendered subpixel horizontally, so snap vertically.
+    return {4, 1};
+  }
+  if (aTransform._11 == 0) {
+    // Glyphs are rendered subpixel vertically, so snap horizontally.
+    return {1, 4};
+  }
+  // The transform isn't aligned, so don't snap.
+  return {4, 4};
+}
+
 // Skia only supports subpixel positioning to the nearest 1/4 fraction. It
 // would be wasteful to attempt to cache text runs with positioning that is
 // anymore precise than this. To prevent this cache bloat, we quantize the
 // transformed glyph positions to the nearest 1/4. The scaling factor for
 // the quantization is baked into the transform, so that if subpixel rounding
 // is used on a given axis, then the axis will be multiplied by 4 before
 // rounding. Since the quantized position is not used for rasterization, the
 // transform is safe to modify as such.
 static inline IntPoint QuantizePosition(const Matrix& aTransform,
                                         const IntPoint& aOffset,
                                         const Point& aPosition) {
   return RoundedToInt(aTransform.TransformPoint(aPosition)) - aOffset;
 }
 
+// Get a quantized starting offset for the glyph buffer. We want this offset
+// to encapsulate the transform and buffer offset while still preserving the
+// relative subpixel positions of the glyphs this offset is subtracted from.
+static inline IntPoint QuantizeOffset(const Matrix& aTransform,
+                                      const IntPoint& aQuantizeScale,
+                                      const GlyphBuffer& aBuffer) {
+  IntPoint offset =
+      RoundedToInt(aTransform.TransformPoint(aBuffer.mGlyphs[0].mPosition));
+  offset.x &= ~(aQuantizeScale.x - 1);
+  offset.y &= ~(aQuantizeScale.y - 1);
+  return offset;
+}
+
 // Hashes a glyph buffer to a single hash value that can be used for quick
 // comparisons. Each glyph position is transformed and quantized before
 // hashing.
 HashNumber GlyphCacheEntry::HashGlyphs(const GlyphBuffer& aBuffer,
-                                       const Matrix& aTransform) {
+                                       const Matrix& aTransform,
+                                       const IntPoint& aQuantizeScale) {
   HashNumber hash = 0;
-  IntPoint offset =
-      TruncatedToInt(aTransform.TransformPoint(aBuffer.mGlyphs[0].mPosition));
+  IntPoint offset = QuantizeOffset(aTransform, aQuantizeScale, aBuffer);
   for (size_t i = 0; i < aBuffer.mNumGlyphs; i++) {
     const Glyph& glyph = aBuffer.mGlyphs[i];
     hash = AddToHash(hash, glyph.mIndex);
     IntPoint pos = QuantizePosition(aTransform, offset, glyph.mPosition);
     hash = AddToHash(hash, pos.x);
     hash = AddToHash(hash, pos.y);
   }
   return hash;
 }
 
 // Determines if an existing glyph cache entry matches an incoming text run.
 bool GlyphCacheEntry::MatchesGlyphs(const GlyphBuffer& aBuffer,
                                     const DeviceColor& aColor,
                                     const Matrix& aTransform,
-                                    const IntRect& aBounds, HashNumber aHash) {
+                                    const IntPoint& aQuantizeScale,
+                                    HashNumber aHash) {
   // First check if the hash matches to quickly reject the text run before any
-  // more expensive checking. If it matches, then check if the color, transform,
-  // and bounds are the same.
+  // more expensive checking. If it matches, then check if the color and
+  // transform are the same.
   if (aHash != mHash || aBuffer.mNumGlyphs != mBuffer.mNumGlyphs ||
-      aColor != mColor || !HasMatchingScale(aTransform, mTransform) ||
-      aBounds.Size() != mBounds.Size()) {
+      aColor != mColor || !HasMatchingScale(aTransform, mTransform)) {
     return false;
   }
-  IntPoint offset =
-      TruncatedToInt(aTransform.TransformPoint(aBuffer.mGlyphs[0].mPosition));
-  if (aBounds.TopLeft() - offset != mBounds.TopLeft()) {
-    return false;
-  }
+  IntPoint offset = QuantizeOffset(aTransform, aQuantizeScale, aBuffer);
   // Finally check if all glyphs and their quantized positions match.
   for (size_t i = 0; i < aBuffer.mNumGlyphs; i++) {
     const Glyph& dst = mBuffer.mGlyphs[i];
     const Glyph& src = aBuffer.mGlyphs[i];
     if (dst.mIndex != src.mIndex ||
         dst.mPosition !=
             Point(QuantizePosition(aTransform, offset, src.mPosition))) {
       return false;
     }
   }
   return true;
 }
 
 GlyphCacheEntry::GlyphCacheEntry(const GlyphBuffer& aBuffer,
                                  const DeviceColor& aColor,
                                  const Matrix& aTransform,
+                                 const IntPoint& aQuantizeScale,
                                  const IntRect& aBounds, HashNumber aHash)
     : CacheEntryImpl<GlyphCacheEntry>(aTransform, aBounds, aHash),
       mColor(aColor) {
   // Store a copy of the glyph buffer with positions already quantized for fast
   // comparison later.
   Glyph* glyphs = new Glyph[aBuffer.mNumGlyphs];
-  IntPoint offset =
-      TruncatedToInt(aTransform.TransformPoint(aBuffer.mGlyphs[0].mPosition));
-  mBounds -= offset;
+  IntPoint offset = QuantizeOffset(aTransform, aQuantizeScale, aBuffer);
+  // Make the bounds relative to the offset so we can add a new offset later.
+  mBounds -= IntPoint(offset.x / aQuantizeScale.x, offset.y / aQuantizeScale.y);
   for (size_t i = 0; i < aBuffer.mNumGlyphs; i++) {
     Glyph& dst = glyphs[i];
     const Glyph& src = aBuffer.mGlyphs[i];
     dst.mIndex = src.mIndex;
     dst.mPosition = Point(QuantizePosition(aTransform, offset, src.mPosition));
   }
   mBuffer.mGlyphs = glyphs;
   mBuffer.mNumGlyphs = aBuffer.mNumGlyphs;
 }
 
 GlyphCacheEntry::~GlyphCacheEntry() { delete[] mBuffer.mGlyphs; }
 
-// Attempt to find a matching entry in the glyph cache. If one isn't found,
-// a new entry will be created. The caller should check whether the contained
-// texture handle is valid to determine if it will need to render the text run
-// or just reuse the cached texture.
-already_AddRefed<GlyphCacheEntry> GlyphCache::FindOrInsertEntry(
+// Attempt to find a matching entry in the glyph cache. The caller should check
+// whether the contained texture handle is valid to determine if it will need to
+// render the text run or just reuse the cached texture.
+already_AddRefed<GlyphCacheEntry> GlyphCache::FindEntry(
     const GlyphBuffer& aBuffer, const DeviceColor& aColor,
-    const Matrix& aTransform, const IntRect& aBounds) {
-  HashNumber hash = GlyphCacheEntry::HashGlyphs(aBuffer, aTransform);
-  for (const RefPtr<GlyphCacheEntry>& entry : mEntries) {
-    if (entry->MatchesGlyphs(aBuffer, aColor, aTransform, aBounds, hash)) {
+    const Matrix& aTransform, const IntPoint& aQuantizeScale,
+    HashNumber aHash) {
+  for (const RefPtr<GlyphCacheEntry>& entry : GetChain(aHash)) {
+    if (entry->MatchesGlyphs(aBuffer, aColor, aTransform, aQuantizeScale,
+                             aHash)) {
       return do_AddRef(entry);
     }
   }
-  RefPtr<GlyphCacheEntry> entry =
-      new GlyphCacheEntry(aBuffer, aColor, aTransform, aBounds, hash);
-  mEntries.insertFront(entry);
+  return nullptr;
+}
+
+// Insert a new entry in the glyph cache.
+already_AddRefed<GlyphCacheEntry> GlyphCache::InsertEntry(
+    const GlyphBuffer& aBuffer, const DeviceColor& aColor,
+    const Matrix& aTransform, const IntPoint& aQuantizeScale,
+    const IntRect& aBounds, HashNumber aHash) {
+  RefPtr<GlyphCacheEntry> entry = new GlyphCacheEntry(
+      aBuffer, aColor, aTransform, aQuantizeScale, aBounds, aHash);
+  Insert(entry);
   return entry.forget();
 }
 
 GlyphCache::GlyphCache(ScaledFont* aFont) : mFont(aFont) {}
 
 static void ReleaseGlyphCache(void* aPtr) {
   delete static_cast<GlyphCache*>(aPtr);
 }
@@ -2560,78 +2611,31 @@ static bool CheckForColorGlyphs(const Re
       gray |= gray << 16;
       if (color != gray) return true;
     }
     data += stride;
   }
   return false;
 }
 
+// Draws glyphs to the WebGL target by trying to generate a cached texture for
+// the text run that can be subsequently reused to quickly render the text run
+// without using any software surfaces.
 bool DrawTargetWebgl::SharedContext::FillGlyphsAccel(
     ScaledFont* aFont, const GlyphBuffer& aBuffer, const Pattern& aPattern,
     const DrawOptions& aOptions, bool aUseSubpixelAA) {
-  // Draws glyphs to the WebGL target by trying to generate a cached texture for
-  // the text run that can be subsequently reused to quickly render the text run
-  // without using any software surfaces.
-  // Get the local bounds of the text run.
-  Maybe<Rect> bounds = mCurrentTarget->mSkia->GetGlyphLocalBounds(
-      aFont, aBuffer, aPattern, nullptr, aOptions);
-  if (!bounds) {
-    return false;
-  }
-
-  // Transform the local bounds into device space so that we know how big
-  // the cached texture will be.
-  const Matrix& currentTransform = GetTransform();
-  Rect xformBounds = currentTransform.TransformBounds(*bounds).Intersect(
-      Rect(IntRect(IntPoint(), mViewportSize)));
-  if (xformBounds.IsEmpty()) {
-    return true;
-  }
-  // Ensure there is a clear border around the text.
-  xformBounds.Inflate(2);
-  IntRect intBounds = RoundedOut(xformBounds);
-
   // Whether the font may use bitmaps. If so, we need to render the glyphs with
   // color as grayscale bitmaps will use the color while color emoji will not,
   // with no easy way to know ahead of time. We currently have to check the
   // rasterized result to see if there are any color glyphs. To render subpixel
   // masks, we need to know that the rasterized result actually represents a
   // subpixel mask rather than try to interpret it as a normal RGBA result such
   // as for color emoji.
   bool useBitmaps = aFont->MayUseBitmaps();
 
-  // Depending on whether we enable subpixel position for a given font, Skia may
-  // round transformed coordinates differently on each axis. By default, text is
-  // subpixel quantized horizontally and snapped to a whole integer vertical
-  // baseline. Axis-flip transforms instead snap to horizontal boundaries while
-  // subpixel quantizing along the vertical. For other types of transforms, Skia
-  // just applies subpixel quantization to both axes.
-  // We must duplicate the amount of quantization Skia applies carefully as a
-  // boundary value such as 0.49 may round to 0.5 with subpixel quantization,
-  // but if Skia actually snapped it to a whole integer instead, it would round
-  // down to 0. If a subsequent glyph with offset 0.51 came in, we might
-  // mistakenly round it down to 0.5, whereas Skia would round it up to 1. Thus
-  // we would alias 0.49 and 0.51 to the same cache entry, while Skia would
-  // actually snap the offset to 0 or 1, depending, resulting in mismatched
-  // hinting.
-  Matrix quantizeTransform = currentTransform;
-  if (aFont->UseSubpixelPosition()) {
-    if (currentTransform._12 == 0) {
-      // Glyphs are rendered subpixel horizontally, so snap vertically.
-      quantizeTransform.PostScale(4, 1);
-    } else if (currentTransform._11 == 0) {
-      // Glyphs are rendered subpixel vertically, so snap horizontally.
-      quantizeTransform.PostScale(1, 4);
-    } else {
-      // The transform isn't aligned, so don't snap.
-      quantizeTransform.PostScale(4, 4);
-    }
-  }
-
   // Look for an existing glyph cache on the font. If not there, create it.
   GlyphCache* cache =
       static_cast<GlyphCache*>(aFont->GetUserData(&mGlyphCacheKey));
   if (!cache) {
     cache = new GlyphCache(aFont);
     aFont->AddUserData(&mGlyphCacheKey, cache, ReleaseGlyphCache);
     mGlyphCaches.insertFront(cache);
   }
@@ -2646,26 +2650,64 @@ bool DrawTargetWebgl::SharedContext::Fil
                      color.b >= 0.33f && color.r + color.g + color.b >= 2.0f;
 #else
   // On other platforms, we assume no color-dependent dilation.
   const bool lightOnDark = true;
 #endif
   // If the font has bitmaps, use the color directly. Otherwise, the texture
   // will hold a grayscale mask, so encode the key's subpixel and light-or-dark
   // state in the color.
-  RefPtr<GlyphCacheEntry> entry = cache->FindOrInsertEntry(
-      aBuffer,
+  const Matrix& currentTransform = GetTransform();
+  IntPoint quantizeScale = QuantizeScale(aFont, currentTransform);
+  Matrix quantizeTransform = currentTransform;
+  quantizeTransform.PostScale(quantizeScale.x, quantizeScale.y);
+  HashNumber hash =
+      GlyphCacheEntry::HashGlyphs(aBuffer, quantizeTransform, quantizeScale);
+  DeviceColor colorOrMask =
       useBitmaps
           ? color
-          : DeviceColor::Mask(aUseSubpixelAA ? 1 : 0, lightOnDark ? 1 : 0),
-      quantizeTransform, intBounds);
+          : DeviceColor::Mask(aUseSubpixelAA ? 1 : 0, lightOnDark ? 1 : 0);
+  RefPtr<GlyphCacheEntry> entry = cache->FindEntry(
+      aBuffer, colorOrMask, quantizeTransform, quantizeScale, hash);
   if (!entry) {
-    return false;
+    // For small text runs, bounds computations can be expensive relative to the
+    // cost of looking up a cache result. Avoid doing local bounds computations
+    // until actually inserting the entry into the cache.
+    Maybe<Rect> bounds = mCurrentTarget->mSkia->GetGlyphLocalBounds(
+        aFont, aBuffer, aPattern, nullptr, aOptions);
+    if (!bounds) {
+      return true;
+    }
+    // Transform the local bounds into device space so that we know how big
+    // the cached texture will be.
+    Rect xformBounds = currentTransform.TransformBounds(*bounds).Intersect(
+        Rect(IntRect(IntPoint(), mViewportSize)));
+    if (xformBounds.IsEmpty()) {
+      return true;
+    }
+    // Ensure there is a clear border around the text.
+    xformBounds.Inflate(2);
+    IntRect intBounds = RoundedOut(xformBounds);
+    entry = cache->InsertEntry(aBuffer, colorOrMask, quantizeTransform,
+                               quantizeScale, intBounds, hash);
+    if (!entry) {
+      return false;
+    }
   }
 
+  // The bounds of the entry may have a different transform offset from the
+  // bounds of the currently drawn text run. The entry bounds are relative to
+  // the entry's quantized offset already, so just move the bounds to the new
+  // offset.
+  IntRect intBounds = entry->GetBounds();
+  IntPoint newOffset =
+      QuantizeOffset(quantizeTransform, quantizeScale, aBuffer);
+  intBounds +=
+      IntPoint(newOffset.x / quantizeScale.x, newOffset.y / quantizeScale.y);
+
   RefPtr<TextureHandle> handle = entry->GetHandle();
   if (handle && handle->IsValid()) {
     // If there is an entry with a valid cached texture handle, then try
     // to draw with that. If that for some reason failed, then fall back
     // to using the Skia target as that means we were preventing from
     // drawing to the WebGL context based on something other than the
     // texture.
     SurfacePattern pattern(nullptr, ExtendMode::CLAMP,
--- a/dom/canvas/DrawTargetWebglInternal.h
+++ b/dom/canvas/DrawTargetWebglInternal.h
@@ -26,27 +26,24 @@ class TexturePacker {
 
   Maybe<IntPoint> Insert(const IntSize& aSize);
 
   bool Remove(const IntRect& aBounds);
 
   const IntRect& GetBounds() const { return mBounds; }
 
  private:
-  bool IsLeaf() const { return !mChildren[0]; }
+  bool IsLeaf() const { return !mChildren; }
   bool IsFullyAvailable() const { return IsLeaf() && mAvailable > 0; }
 
-  void DiscardChildren() {
-    mChildren[0] = nullptr;
-    mChildren[1] = nullptr;
-  }
+  void DiscardChildren() { mChildren.reset(); }
 
   // If applicable, the two children produced by picking a single axis split
   // within the node's bounds and subdividing the bounds there.
-  UniquePtr<TexturePacker> mChildren[2];
+  UniquePtr<TexturePacker[]> mChildren;
   // The bounds enclosing this node and any children within it.
   IntRect mBounds;
   // For a leaf node, specifies the size of the smallest dimension available to
   // allocate. For a branch node, specifies largest potential available size of
   // all children. This can be used during the allocation process to rapidly
   // reject certain sub-trees without having to search all the way to a leaf
   // node if we know that largest available size within the sub-tree wouldn't
   // fit the requested size.
@@ -96,36 +93,45 @@ template <typename T>
 class CacheEntryImpl : public CacheEntry, public LinkedListElement<RefPtr<T>> {
   typedef LinkedListElement<RefPtr<T>> ListType;
 
  public:
   CacheEntryImpl(const Matrix& aTransform, const IntRect& aBounds,
                  HashNumber aHash)
       : CacheEntry(aTransform, aBounds, aHash) {}
 
- protected:
   void RemoveFromList() override {
     if (ListType::isInList()) {
       ListType::remove();
     }
   }
 };
 
 // CacheImpl manages a list of CacheEntry.
 template <typename T>
 class CacheImpl {
+  typedef LinkedList<RefPtr<T>> ListType;
+
+  static constexpr size_t kNumChains = 17;
+
  public:
   ~CacheImpl() {
-    while (RefPtr<T> entry = mEntries.popLast()) {
-      entry->Unlink();
+    for (size_t i = 0; i < kNumChains; ++i) {
+      while (RefPtr<T> entry = mChains[i].popLast()) {
+        entry->Unlink();
+      }
     }
   }
 
  protected:
-  LinkedList<RefPtr<T>> mEntries;
+  ListType& GetChain(HashNumber aHash) { return mChains[aHash % kNumChains]; }
+
+  void Insert(T* aEntry) { GetChain(aEntry->GetHash()).insertFront(aEntry); }
+
+  ListType mChains[kNumChains];
 };
 
 // TextureHandle is an abstract base class for supplying textures to drawing
 // commands that may be backed by different resource types (such as a shared
 // or standalone texture). It may be further linked to use-specific metadata
 // such as for shadow drawing or for cached entries in the glyph cache.
 class TextureHandle : public RefCounted<TextureHandle>,
                       public LinkedListElement<RefPtr<TextureHandle>> {
@@ -299,28 +305,29 @@ class StandaloneTexture : public Texture
 // GlyphCacheEntry stores rendering metadata for a rendered text run, as well
 // the handle to the texture it was rendered into, so that it can be located
 // for reuse under similar rendering circumstances.
 class GlyphCacheEntry : public CacheEntryImpl<GlyphCacheEntry> {
  public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphCacheEntry, override)
 
   GlyphCacheEntry(const GlyphBuffer& aBuffer, const DeviceColor& aColor,
-                  const Matrix& aTransform, const IntRect& aBounds,
-                  HashNumber aHash);
+                  const Matrix& aTransform, const IntPoint& aQuantizeScale,
+                  const IntRect& aBounds, HashNumber aHash);
   ~GlyphCacheEntry();
 
   const GlyphBuffer& GetGlyphBuffer() const { return mBuffer; }
 
   bool MatchesGlyphs(const GlyphBuffer& aBuffer, const DeviceColor& aColor,
-                     const Matrix& aTransform, const IntRect& aBounds,
+                     const Matrix& aTransform, const IntPoint& aQuantizeScale,
                      HashNumber aHash);
 
   static HashNumber HashGlyphs(const GlyphBuffer& aBuffer,
-                               const Matrix& aTransform);
+                               const Matrix& aTransform,
+                               const IntPoint& aQuantizeScale);
 
  private:
   // The glyph keys used to render the text run.
   GlyphBuffer mBuffer = {nullptr, 0};
   // The color of the text run.
   DeviceColor mColor;
 };
 
@@ -331,19 +338,28 @@ class GlyphCacheEntry : public CacheEntr
 // inserted into a new GlyphCacheEntry to represent it.
 class GlyphCache : public LinkedListElement<GlyphCache>,
                    public CacheImpl<GlyphCacheEntry> {
  public:
   explicit GlyphCache(ScaledFont* aFont);
 
   ScaledFont* GetFont() const { return mFont; }
 
-  already_AddRefed<GlyphCacheEntry> FindOrInsertEntry(
-      const GlyphBuffer& aBuffer, const DeviceColor& aColor,
-      const Matrix& aTransform, const IntRect& aBounds);
+  already_AddRefed<GlyphCacheEntry> FindEntry(const GlyphBuffer& aBuffer,
+                                              const DeviceColor& aColor,
+                                              const Matrix& aTransform,
+                                              const IntPoint& aQuantizeScale,
+                                              HashNumber aHash);
+
+  already_AddRefed<GlyphCacheEntry> InsertEntry(const GlyphBuffer& aBuffer,
+                                                const DeviceColor& aColor,
+                                                const Matrix& aTransform,
+                                                const IntPoint& aQuantizeScale,
+                                                const IntRect& aBounds,
+                                                HashNumber aHash);
 
  private:
   // Weak pointer to the owning font
   ScaledFont* mFont;
 };
 
 // PathCacheEntry stores a rasterized version of a supplied path with a given
 // pattern.
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -588,27 +588,26 @@ ProcessID GetTelemetryProcessID(const ns
   // WebExtensions process into a separate bucket, to make sure we can analyze
   // it separately and avoid skewing normal content process metrics.
   return remoteType == EXTENSION_REMOTE_TYPE ? ProcessID::Extension
                                              : ProcessID::Content;
 }
 
 }  // anonymous namespace
 
-UniquePtr<nsTHashMap<nsUint32HashKey, ContentParent*>>
+StaticAutoPtr<nsTHashMap<nsUint32HashKey, ContentParent*>>
     ContentParent::sJSPluginContentParents;
-UniquePtr<nsTArray<ContentParent*>> ContentParent::sPrivateContent;
-UniquePtr<LinkedList<ContentParent>> ContentParent::sContentParents;
+StaticAutoPtr<LinkedList<ContentParent>> ContentParent::sContentParents;
 StaticRefPtr<ContentParent> ContentParent::sRecycledE10SProcess;
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
-UniquePtr<SandboxBrokerPolicyFactory>
+StaticAutoPtr<SandboxBrokerPolicyFactory>
     ContentParent::sSandboxBrokerPolicyFactory;
 #endif
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
-UniquePtr<std::vector<std::string>> ContentParent::sMacSandboxParams;
+StaticAutoPtr<std::vector<std::string>> ContentParent::sMacSandboxParams;
 #endif
 
 // Set to true when the first content process gets created.
 static bool sCreatedFirstContentProcess = false;
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
 // True when we're running the process selection code, and do not expect to
 // enter code paths where processes may die.
@@ -671,21 +670,21 @@ void ContentParent::StartUp() {
   ClientManager::Startup();
 
   Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
                                        kFissionEnforceBlockList);
   Preferences::RegisterCallbackAndCall(&OnFissionBlocklistPrefChange,
                                        kFissionOmitBlockListValues);
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
-  sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
+  sSandboxBrokerPolicyFactory = new SandboxBrokerPolicyFactory();
 #endif
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
-  sMacSandboxParams = MakeUnique<std::vector<std::string>>();
+  sMacSandboxParams = new std::vector<std::string>();
 #endif
 }
 
 /*static*/
 void ContentParent::ShutDown() {
   // For the most, we rely on normal process shutdown and
   // ClearOnShutdown() to clean up our state.
 
@@ -1176,18 +1175,17 @@ bool ContentParent::WaitForLaunchSync(Pr
 
 /*static*/
 already_AddRefed<ContentParent> ContentParent::GetNewOrUsedJSPluginProcess(
     uint32_t aPluginID, const hal::ProcessPriority& aPriority) {
   RefPtr<ContentParent> p;
   if (sJSPluginContentParents) {
     p = sJSPluginContentParents->Get(aPluginID);
   } else {
-    sJSPluginContentParents =
-        MakeUnique<nsTHashMap<nsUint32HashKey, ContentParent*>>();
+    sJSPluginContentParents = new nsTHashMap<nsUint32HashKey, ContentParent*>();
   }
 
   if (p) {
     return p.forget();
   }
 
   p = new ContentParent(aPluginID);
 
@@ -1898,17 +1896,16 @@ void ContentParent::RemoveFromPool(nsTAr
   MOZ_DIAGNOSTIC_ASSERT(mIsInPool);
   aPool.RemoveElement(this);
   mIsInPool = false;
 }
 
 void ContentParent::AssertNotInPool() {
   MOZ_RELEASE_ASSERT(!mIsInPool);
 
-  MOZ_RELEASE_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
   MOZ_RELEASE_ASSERT(sRecycledE10SProcess != this);
   if (IsForJSPlugin()) {
     MOZ_RELEASE_ASSERT(!sJSPluginContentParents ||
                        !sJSPluginContentParents->Get(mJSPluginID));
   } else {
     MOZ_RELEASE_ASSERT(
         !sBrowserContentParents ||
         !sBrowserContentParents->Contains(mRemoteType) ||
@@ -1929,23 +1926,16 @@ void ContentParent::RemoveFromList() {
       sJSPluginContentParents->Remove(mJSPluginID);
       if (!sJSPluginContentParents->Count()) {
         sJSPluginContentParents = nullptr;
       }
     }
     return;
   }
 
-  if (sPrivateContent) {
-    sPrivateContent->RemoveElement(this);
-    if (!sPrivateContent->Length()) {
-      sPrivateContent = nullptr;
-    }
-  }
-
   if (!mIsInPool) {
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     AssertNotInPool();
 #endif
     return;
   }
 
   // Ensure that this BrowsingContextGroup is no longer used to host new
@@ -2841,17 +2831,17 @@ ContentParent::ContentParent(const nsACS
   MOZ_DIAGNOSTIC_ASSERT(!IsForJSPlugin(),
                         "XXX(nika): How are we creating a JSPlugin?");
 
   mRemoteTypeIsolationPrincipal =
       CreateRemoteTypeIsolationPrincipal(aRemoteType);
 
   // Insert ourselves into the global linked list of ContentParent objects.
   if (!sContentParents) {
-    sContentParents = MakeUnique<LinkedList<ContentParent>>();
+    sContentParents = new LinkedList<ContentParent>();
   }
   sContentParents->insertBack(this);
 
   mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
 
 #if defined(XP_WIN)
   // Request Windows message deferral behavior on our side of the PContent
   // channel. Generally only applies to the situation where we get caught in
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -23,16 +23,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/DataMutex.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/MozPromise.h"
+#include "mozilla/StaticPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsClassHashtable.h"
 #include "nsTHashMap.h"
 #include "nsTHashSet.h"
 #include "nsPluginTags.h"
 #include "nsHashKeys.h"
@@ -691,37 +692,36 @@ class ContentParent final : public PCont
    * currently available to host *new* tabs/frames of that type.
    *
    * If a content process is identified as troubled or dead, it will be
    * removed from this list, but will still be in the sContentParents list for
    * the GetAll/GetAllEvenIfDead APIs.
    */
   static nsClassHashtable<nsCStringHashKey, nsTArray<ContentParent*>>*
       sBrowserContentParents;
-  static UniquePtr<nsTArray<ContentParent*>> sPrivateContent;
-  static UniquePtr<nsTHashMap<nsUint32HashKey, ContentParent*>>
+  static mozilla::StaticAutoPtr<nsTHashMap<nsUint32HashKey, ContentParent*>>
       sJSPluginContentParents;
-  static UniquePtr<LinkedList<ContentParent>> sContentParents;
+  static mozilla::StaticAutoPtr<LinkedList<ContentParent>> sContentParents;
 
   /**
    * In order to avoid rapidly creating and destroying content processes when
    * running under e10s, we may keep alive a single unused "web" content
    * process if it previously had a very short lifetime.
    *
    * This process will be re-used during process selection, avoiding spawning a
    * new process, if the "web" remote type is being requested.
    */
   static StaticRefPtr<ContentParent> sRecycledE10SProcess;
 
   void AddShutdownBlockers();
   void RemoveShutdownBlockers();
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
   // Cached Mac sandbox params used when launching content processes.
-  static UniquePtr<std::vector<std::string>> sMacSandboxParams;
+  static mozilla::StaticAutoPtr<std::vector<std::string>> sMacSandboxParams;
 #endif
 
   // Set aLoadUri to true to load aURIToLoad and to false to only create the
   // window. aURIToLoad should always be provided, if available, to ensure
   // compatibility with GeckoView.
   mozilla::ipc::IPCResult CommonCreateWindow(
       PBrowserParent* aThisTab, BrowsingContext& aParent, bool aSetOpener,
       const uint32_t& aChromeFlags, const bool& aCalledFromJS,
@@ -1586,17 +1586,17 @@ class ContentParent final : public PCont
 
   PProcessHangMonitorParent* mHangMonitorActor;
 
   UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard;
   UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
 
 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
   mozilla::UniquePtr<SandboxBroker> mSandboxBroker;
-  static mozilla::UniquePtr<SandboxBrokerPolicyFactory>
+  static mozilla::StaticAutoPtr<SandboxBrokerPolicyFactory>
       sSandboxBrokerPolicyFactory;
 #endif
 
   // This hashtable is used to run GetFilesHelper objects in the parent process.
   // GetFilesHelper can be aborted by receiving RecvDeleteGetFilesRequest.
   nsRefPtrHashtable<nsIDHashKey, GetFilesHelper> mGetFilesPendingRequests;
 
   nsTHashSet<nsCString> mActivePermissionKeys;
--- a/layout/reftests/transform/reftest.list
+++ b/layout/reftests/transform/reftest.list
@@ -154,17 +154,17 @@ fuzzy-if(winWidget,0-1,0-1000) == 156921
 
 test-pref(layout.css.zoom-transform-hack.enabled,true) == zoom-hack-1.html zoom-hack-ref.html
 test-pref(layout.css.zoom-transform-hack.enabled,false) != zoom-hack-1.html zoom-hack-ref.html
 test-pref(layout.css.zoom-transform-hack.enabled,true) == zoom-hack-2.html zoom-hack-ref.html
 
 == transform-anon-block-1.html transform-anon-block-1-ref.html
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) == partial-prerender-expansion-translate.html partial-prerender-expansion-ref.html
 test-pref(layout.animation.prerender.partial,true) == partial-prerender-translate-1.html about:blank
-test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-43,0-1800) fuzzy-if(Android,0-255,0-7000) == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html
+test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-59,0-1800) fuzzy-if(Android,0-255,0-7000) == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") random == partial-prerender-translate-3.html partial-prerender-translate-3-ref.html # bug 1642575
 # This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly handle ancestor's transform values
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-4.html partial-prerender-expansion-ref.html
 # This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism does inproperly handle position:fixed scroll target
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-5.html partial-prerender-translate-5-ref.html
 random-if(useDrawSnapshot) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-46,0-1250) fuzzy-if(Android,0-255,0-9900) random-if(gtkWidget&&isDebugBuild) == partial-prerender-translate-6.html partial-prerender-translate-6-ref.html
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-4,0-1200) == partial-prerender-translate-7.html partial-prerender-translate-2-ref.html
 # This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly clip transform in iframes.
@@ -176,9 +176,9 @@ test-pref(layout.animation.prerender.par
 skip test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-12.html partial-prerender-translate-2-ref.html # bug 1666692 for WebRender
 # This reftest heavily depends on layout.animation.prerender.viewport-ratio-limit
 # and reftest viewport size (800, 1000).
 skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)||Android) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(!layersGPUAccelerated,0-75,0-2683) == partial-prerender-expansion-rotate.html partial-prerender-expansion-ref.html
 skip-if(useDrawSnapshot) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") pref(dom.meta-viewport.enabled,true) pref(apz.allow_zooming,true) == partial-prerender-expansion-with-resolution-1.html partial-prerender-expansion-with-resolution-ref.html
 skip test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") pref(dom.meta-viewport.enabled,true) pref(apz.allow_zooming,true) == partial-prerender-expansion-with-resolution-2.html partial-prerender-expansion-with-resolution-ref.html # bug 1650039 for WebRender
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(Android,0-255,0-400) == partial-prerender-in-svg-1.html partial-prerender-in-svg-1-ref.html
 test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-in-svg-2.html partial-prerender-in-svg-1-ref.html # Reuse partial-prerender-in-svg-1-ref.html since the result should look same as partial-prerender-in-svg-1.html
-test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-44,0-400) fuzzy-if(Android,0-255,0-2000) == partial-prerender-in-svg-3.html partial-prerender-in-svg-3-ref.html
+test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy(0-62,0-400) fuzzy-if(Android,0-255,0-2000) == partial-prerender-in-svg-3.html partial-prerender-in-svg-3-ref.html
--- a/modules/fdlibm/README.mozilla
+++ b/modules/fdlibm/README.mozilla
@@ -8,12 +8,12 @@ Each file is downloaded separately, as c
 resources.
 
 The in-tree copy is updated by running
   sh update.sh
 or
   sh update.sh <sha-commit>
 from within the modules/fdlibm directory.
 
-Current version: [commit cf4707bb2f78ecf56ba350bdc24e3135b4339622 (2019-09-25T18:50:57Z)].
+Current version: [commit 369ea0520a3061c07400d7cd32172efb6af39815 (2022-08-04T17:33:34Z)].
 
 patches 01-18 fixes files to be usable within mozilla-central tree.
 See https://bugzilla.mozilla.org/show_bug.cgi?id=933257
--- a/modules/fdlibm/patches/01_remove_unused_declarations_from_fdlibm_h.patch
+++ b/modules/fdlibm/patches/01_remove_unused_declarations_from_fdlibm_h.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/fdlibm.h b/modules/fdlibm/src/fdlibm.h
 --- a/modules/fdlibm/src/fdlibm.h
 +++ b/modules/fdlibm/src/fdlibm.h
-@@ -12,499 +12,49 @@
+@@ -12,504 +12,51 @@
  /*
   * from: @(#)fdlibm.h 5.1 93/09/24
   * $FreeBSD$
   */
  
  #ifndef _MATH_H_
  #define	_MATH_H_
  
@@ -22,21 +22,21 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -	double		__ud;
 -} __infinity;
 -
 -extern const union __nan_un {
 -	unsigned char	__uc[sizeof(float)];
 -	float		__uf;
 -} __nan;
 -
--#if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
+-#if __GNUC_PREREQ__(3, 3)
 -#define	__MATH_BUILTIN_CONSTANTS
 -#endif
 -
--#if __GNUC_PREREQ__(3, 0) && !defined(__INTEL_COMPILER)
+-#if __GNUC_PREREQ__(3, 0)
 -#define	__MATH_BUILTIN_RELOPS
 -#endif
 -
 -#ifdef __MATH_BUILTIN_CONSTANTS
 -#define	HUGE_VAL	__builtin_huge_val()
 -#else
 -#define	HUGE_VAL	(__infinity.__ud)
 -#endif
@@ -65,31 +65,21 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -
 -/* Symbolic constants to classify floating point numbers. */
 -#define	FP_INFINITE	0x01
 -#define	FP_NAN		0x02
 -#define	FP_NORMAL	0x04
 -#define	FP_SUBNORMAL	0x08
 -#define	FP_ZERO		0x10
 -
--#if (__STDC_VERSION__ >= 201112L && defined(__clang__)) || \
--    __has_extension(c_generic_selections)
--#define	__fp_type_select(x, f, d, ld) _Generic((x),			\
+-#if __STDC_VERSION__ >= 201112L || __has_extension(c_generic_selections)
+-#define	__fp_type_select(x, f, d, ld) __extension__ _Generic((x),	\
 -    float: f(x),							\
 -    double: d(x),							\
--    long double: ld(x),							\
--    volatile float: f(x),						\
--    volatile double: d(x),						\
--    volatile long double: ld(x),					\
--    volatile const float: f(x),						\
--    volatile const double: d(x),					\
--    volatile const long double: ld(x),					\
--    const float: f(x),							\
--    const double: d(x),							\
--    const long double: ld(x))
+-    long double: ld(x))
 -#elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus)
 -#define	__fp_type_select(x, f, d, ld) __builtin_choose_expr(		\
 -    __builtin_types_compatible_p(__typeof(x), long double), ld(x),	\
 -    __builtin_choose_expr(						\
 -    __builtin_types_compatible_p(__typeof(x), double), d(x),		\
 -    __builtin_choose_expr(						\
 -    __builtin_types_compatible_p(__typeof(x), float), f(x), (void)0)))
 -#else
@@ -203,16 +193,22 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -static __inline int
 -__inline_isnanl(__const long double __x)
 -{
 -
 -	return (__x != __x);
 -}
 -
 -/*
+- * Define the following aliases, for compatibility with glibc and CUDA.
+- */
+-#define __isnan __inline_isnan
+-#define __isnanf __inline_isnanf
+-
+-/*
 - * Version 2 of the Single UNIX Specification (UNIX98) defined isnan() and
 - * isinf() as functions taking double.  C99, and the subsequent POSIX revisions
 - * (SUSv3, POSIX.1-2001, define it as a macro that accepts any real floating
 - * point type.  If we are targeting SUSv2 and C99 or C11 (or C++11) then we
 - * expose the newer definition, assuming that the language spec takes
 - * precedence over the operating system interface spec.
 - */
 -#if	__XSI_VISIBLE > 0 && __XSI_VISIBLE < 600 && __ISO_C_VISIBLE < 1999
@@ -221,41 +217,39 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -int	isinf(double);
 -int	isnan(double);
 -#endif
 -
  double	acos(double);
  double	asin(double);
  double	atan(double);
  double	atan2(double, double);
--double	cos(double);
--double	sin(double);
--double	tan(double);
+ double	cos(double);
+ double	sin(double);
+ double	tan(double);
  
  double	cosh(double);
  double	sinh(double);
  double	tanh(double);
  
  double	exp(double);
 -double	frexp(double, int *);	/* fundamentally !__pure2 */
 -double	ldexp(double, int);
  double	log(double);
  double	log10(double);
 -double	modf(double, double *);	/* fundamentally !__pure2 */
  
  double	pow(double, double);
 -double	sqrt(double);
+ 
+ double	ceil(double);
+-double	fabs(double) __pure2;
 +double	fabs(double);
- 
--double	ceil(double);
--double	fabs(double) __pure2;
  double	floor(double);
 -double	fmod(double, double);
-+double	trunc(double);
-+double	ceil(double);
  
 -/*
 - * These functions are not in C90.
 - */
 -#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE
  double	acosh(double);
  double	asinh(double);
  double	atanh(double);
@@ -305,17 +299,17 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -double	fmax(double, double) __pure2;
 -double	fmin(double, double) __pure2;
 +double	copysign(double, double);
  double	nearbyint(double);
 -double	round(double);
 -double	scalbln(double, long);
  double	scalbn(double, int);
 -double	tgamma(double);
--double	trunc(double);
+ double	trunc(double);
 -#endif
 -
 -/*
 - * BSD math library entry points
 - */
 -#if __BSD_VISIBLE
 -double	drem(double, double);
 -int	finite(double) __pure2;
@@ -369,17 +363,17 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -float	fmodf(float, float);
 -float	roundf(float);
 -
 -float	erff(float);
 -float	erfcf(float);
 -float	hypotf(float, float);
 -float	lgammaf(float);
 -float	tgammaf(float);
- 
+-
 -float	acoshf(float);
 -float	asinhf(float);
 -float	atanhf(float);
 -float	cbrtf(float);
 -float	logbf(float);
 -float	copysignf(float, float) __pure2;
 -long long llrintf(float);
 -long long llroundf(float);
@@ -495,13 +489,22 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -long double	truncl(long double);
 -#endif /* __ISO_C_VISIBLE >= 1999 */
 -
 -#if __BSD_VISIBLE
 -long double	lgammal_r(long double, int *);
 -void		sincos(double, double *, double *);
 -void		sincosf(float, float *, float *);
 -void		sincosl(long double, long double *, long double *);
+-double		cospi(double);
+-float		cospif(float);
+-long double 	cospil(long double);
+-double		sinpi(double);
+-float		sinpif(float);
+-long double 	sinpil(long double);
+-double		tanpi(double);
+-float		tanpif(float);
+-long double	tanpil(long double);
 -#endif
 -
 -__END_DECLS
 -
  #endif /* !_MATH_H_ */
--- a/modules/fdlibm/patches/02_change_include_guard_in_fdlibm_h.patch
+++ b/modules/fdlibm/patches/02_change_include_guard_in_fdlibm_h.patch
@@ -14,22 +14,22 @@ diff --git a/modules/fdlibm/src/fdlibm.h
 -#define	_MATH_H_
 +#ifndef mozilla_imported_fdlibm_h
 +#define mozilla_imported_fdlibm_h
  
  double	acos(double);
  double	asin(double);
  double	atan(double);
  double	atan2(double, double);
- 
- double	cosh(double);
- double	sinh(double);
-@@ -52,9 +52,9 @@ double	scalbn(double, int);
+ double	cos(double);
+ double	sin(double);
+ double	tan(double);
+@@ -54,9 +54,9 @@ double	scalbn(double, int);
+ double	trunc(double);
  
  float	ceilf(float);
  float	floorf(float);
- 
  float	nearbyintf(float);
  float	rintf(float);
  float	truncf(float);
  
 -#endif /* !_MATH_H_ */
 +#endif /* mozilla_imported_fdlibm_h */
--- a/modules/fdlibm/patches/03_put_fdlibm_functions_into_fdlibm_namespace.patch
+++ b/modules/fdlibm/patches/03_put_fdlibm_functions_into_fdlibm_namespace.patch
@@ -11,24 +11,24 @@ diff --git a/modules/fdlibm/src/fdlibm.h
  #define mozilla_imported_fdlibm_h
  
 +namespace fdlibm {
 +
  double	acos(double);
  double	asin(double);
  double	atan(double);
  double	atan2(double, double);
+ double	cos(double);
+ double	sin(double);
+ double	tan(double);
  
- double	cosh(double);
- double	sinh(double);
- double	tanh(double);
-@@ -52,9 +54,11 @@ double	scalbn(double, int);
+@@ -54,9 +56,11 @@ double	scalbn(double, int);
+ double	trunc(double);
  
  float	ceilf(float);
  float	floorf(float);
- 
  float	nearbyintf(float);
  float	rintf(float);
  float	truncf(float);
  
 +} /* namespace fdlibm */
 +
  #endif /* mozilla_imported_fdlibm_h */
--- a/modules/fdlibm/patches/04_include_fdlibm_h_from_math_private_h.patch
+++ b/modules/fdlibm/patches/04_include_fdlibm_h_from_math_private_h.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/e_acos.cpp b/modules/fdlibm/src/e_acos.cpp
 --- a/modules/fdlibm/src/e_acos.cpp
 +++ b/modules/fdlibm/src/e_acos.cpp
-@@ -35,17 +35,16 @@
+@@ -35,17 +35,16 @@ __FBSDID("$FreeBSD$");
   *	if x is NaN, return x itself;
   *	if |x|>1, return NaN with invalid signal.
   *
   * Function needed: sqrt
   */
  
  #include <float.h>
  
@@ -17,17 +17,17 @@ diff --git a/modules/fdlibm/src/e_acos.c
  one=  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
  pi =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
  pio2_hi =  1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */
  static volatile double
  pio2_lo =  6.12323399573676603587e-17; /* 0x3C91A626, 0x33145C07 */
 diff --git a/modules/fdlibm/src/e_acosh.cpp b/modules/fdlibm/src/e_acosh.cpp
 --- a/modules/fdlibm/src/e_acosh.cpp
 +++ b/modules/fdlibm/src/e_acosh.cpp
-@@ -26,17 +26,16 @@
+@@ -26,17 +26,16 @@ __FBSDID("$FreeBSD$");
   *
   * Special cases:
   *	acosh(x) is NaN with signal if x<1.
   *	acosh(NaN) is NaN without signal.
   */
  
  #include <float.h>
  
@@ -38,17 +38,17 @@ diff --git a/modules/fdlibm/src/e_acosh.
  one	= 1.0,
  ln2	= 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
  
  double
  __ieee754_acosh(double x)
 diff --git a/modules/fdlibm/src/e_asin.cpp b/modules/fdlibm/src/e_asin.cpp
 --- a/modules/fdlibm/src/e_asin.cpp
 +++ b/modules/fdlibm/src/e_asin.cpp
-@@ -41,17 +41,16 @@
+@@ -41,17 +41,16 @@ __FBSDID("$FreeBSD$");
   * Special cases:
   *	if x is NaN, return x itself;
   *	if |x|>1, return NaN with invalid signal.
   *
   */
  
  #include <float.h>
  
@@ -59,17 +59,17 @@ diff --git a/modules/fdlibm/src/e_asin.c
  one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
  huge =  1.000e+300,
  pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
  pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
  pio4_hi =  7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
 diff --git a/modules/fdlibm/src/e_atan2.cpp b/modules/fdlibm/src/e_atan2.cpp
 --- a/modules/fdlibm/src/e_atan2.cpp
 +++ b/modules/fdlibm/src/e_atan2.cpp
-@@ -39,17 +39,16 @@
+@@ -39,17 +39,16 @@ __FBSDID("$FreeBSD$");
   * The hexadecimal values are the intended ones for the following 
   * constants. The decimal values may be used, provided that the 
   * compiler will convert from decimal to binary accurately enough 
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
  
@@ -80,17 +80,17 @@ diff --git a/modules/fdlibm/src/e_atan2.
  tiny  = 1.0e-300;
  static const double
  zero  = 0.0,
  pi_o_4  = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
  pi_o_2  = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
 diff --git a/modules/fdlibm/src/e_atanh.cpp b/modules/fdlibm/src/e_atanh.cpp
 --- a/modules/fdlibm/src/e_atanh.cpp
 +++ b/modules/fdlibm/src/e_atanh.cpp
-@@ -30,17 +30,16 @@
+@@ -30,17 +30,16 @@ __FBSDID("$FreeBSD$");
   *	atanh(x) is NaN if |x| > 1 with signal;
   *	atanh(NaN) is that NaN with no signal;
   *	atanh(+-1) is +-INF with signal.
   *
   */
  
  #include <float.h>
  
@@ -101,17 +101,17 @@ diff --git a/modules/fdlibm/src/e_atanh.
  static const double zero = 0.0;
  
  double
  __ieee754_atanh(double x)
  {
 diff --git a/modules/fdlibm/src/e_cosh.cpp b/modules/fdlibm/src/e_cosh.cpp
 --- a/modules/fdlibm/src/e_cosh.cpp
 +++ b/modules/fdlibm/src/e_cosh.cpp
-@@ -32,17 +32,16 @@
+@@ -32,17 +32,16 @@ __FBSDID("$FreeBSD$");
   *
   * Special cases:
   *	cosh(x) is |x| if x is +INF, -INF, or NaN.
   *	only cosh(0)=1 is exact for finite x.
   */
  
  #include <float.h>
  
@@ -122,17 +122,17 @@ diff --git a/modules/fdlibm/src/e_cosh.c
  
  double
  __ieee754_cosh(double x)
  {
  	double t,w;
 diff --git a/modules/fdlibm/src/e_exp.cpp b/modules/fdlibm/src/e_exp.cpp
 --- a/modules/fdlibm/src/e_exp.cpp
 +++ b/modules/fdlibm/src/e_exp.cpp
-@@ -73,17 +73,16 @@
+@@ -73,17 +73,16 @@ __FBSDID("$FreeBSD$");
   * The hexadecimal values are the intended ones for the following 
   * constants. The decimal values may be used, provided that the 
   * compiler will convert from decimal to binary accurately enough
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
  
@@ -143,17 +143,17 @@ diff --git a/modules/fdlibm/src/e_exp.cp
  one	= 1.0,
  halF[2]	= {0.5,-0.5,},
  o_threshold=  7.09782712893383973096e+02,  /* 0x40862E42, 0xFEFA39EF */
  u_threshold= -7.45133219101941108420e+02,  /* 0xc0874910, 0xD52D3051 */
  ln2HI[2]   ={ 6.93147180369123816490e-01,  /* 0x3fe62e42, 0xfee00000 */
 diff --git a/modules/fdlibm/src/e_hypot.cpp b/modules/fdlibm/src/e_hypot.cpp
 --- a/modules/fdlibm/src/e_hypot.cpp
 +++ b/modules/fdlibm/src/e_hypot.cpp
-@@ -43,17 +43,16 @@
+@@ -43,17 +43,16 @@ __FBSDID("$FreeBSD$");
   *
   * Accuracy:
   * 	hypot(x,y) returns sqrt(x^2+y^2) with error less 
   * 	than 1 ulps (units in the last place) 
   */
  
  #include <float.h>
  
@@ -164,17 +164,17 @@ diff --git a/modules/fdlibm/src/e_hypot.
  __ieee754_hypot(double x, double y)
  {
  	double a,b,t1,t2,y1,y2,w;
  	int32_t j,k,ha,hb;
  
 diff --git a/modules/fdlibm/src/e_log.cpp b/modules/fdlibm/src/e_log.cpp
 --- a/modules/fdlibm/src/e_log.cpp
 +++ b/modules/fdlibm/src/e_log.cpp
-@@ -62,17 +62,16 @@
+@@ -62,17 +62,16 @@ __FBSDID("$FreeBSD$");
   * The hexadecimal values are the intended ones for the following 
   * constants. The decimal values may be used, provided that the 
   * compiler will convert from decimal to binary accurately enough 
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
  
@@ -185,17 +185,17 @@ diff --git a/modules/fdlibm/src/e_log.cp
  ln2_hi  =  6.93147180369123816490e-01,	/* 3fe62e42 fee00000 */
  ln2_lo  =  1.90821492927058770002e-10,	/* 3dea39ef 35793c76 */
  two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
  Lg1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
  Lg2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
 diff --git a/modules/fdlibm/src/e_log10.cpp b/modules/fdlibm/src/e_log10.cpp
 --- a/modules/fdlibm/src/e_log10.cpp
 +++ b/modules/fdlibm/src/e_log10.cpp
-@@ -19,17 +19,16 @@
+@@ -19,17 +19,16 @@ __FBSDID("$FreeBSD$");
   * comments.
   *
   *    log10(x) = (f - 0.5*f*f + k_log1p(f)) / ln10 + k * log10(2)
   * in not-quite-routine extra precision.
   */
  
  #include <float.h>
  
@@ -206,17 +206,17 @@ diff --git a/modules/fdlibm/src/e_log10.
  static const double
  two54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
  ivln10hi   =  4.34294481878168880939e-01, /* 0x3fdbcb7b, 0x15200000 */
  ivln10lo   =  2.50829467116452752298e-11, /* 0x3dbb9438, 0xca9aadd5 */
  log10_2hi  =  3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
 diff --git a/modules/fdlibm/src/e_log2.cpp b/modules/fdlibm/src/e_log2.cpp
 --- a/modules/fdlibm/src/e_log2.cpp
 +++ b/modules/fdlibm/src/e_log2.cpp
-@@ -21,17 +21,16 @@
+@@ -21,17 +21,16 @@ __FBSDID("$FreeBSD$");
   * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel,
   * then does the combining and scaling steps
   *    log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k
   * in not-quite-routine extra precision.
   */
  
  #include <float.h>
  
@@ -227,17 +227,17 @@ diff --git a/modules/fdlibm/src/e_log2.c
  static const double
  two54      =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
  ivln2hi    =  1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */
  ivln2lo    =  1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */
  
 diff --git a/modules/fdlibm/src/e_pow.cpp b/modules/fdlibm/src/e_pow.cpp
 --- a/modules/fdlibm/src/e_pow.cpp
 +++ b/modules/fdlibm/src/e_pow.cpp
-@@ -53,17 +53,16 @@
+@@ -53,17 +53,16 @@ __FBSDID("$FreeBSD$");
   * Constants :
   * The hexadecimal values are the intended ones for the following
   * constants. The decimal values may be used, provided that the
   * compiler will convert from decimal to binary accurately enough
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
@@ -245,20 +245,41 @@ diff --git a/modules/fdlibm/src/e_pow.cp
  #include "math_private.h"
  
  static const double
  bp[] = {1.0, 1.5,},
  dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
  dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
  zero    =  0.0,
  half    =  0.5,
+diff --git a/modules/fdlibm/src/e_rem_pio2.cpp b/modules/fdlibm/src/e_rem_pio2.cpp
+--- a/modules/fdlibm/src/e_rem_pio2.cpp
++++ b/modules/fdlibm/src/e_rem_pio2.cpp
+@@ -19,17 +19,16 @@ __FBSDID("$FreeBSD$");
+ /* __ieee754_rem_pio2(x,y)
+  * 
+  * return the remainder of x rem pi/2 in y[0]+y[1] 
+  * use __kernel_rem_pio2()
+  */
+ 
+ #include <float.h>
+ 
+-#include "math.h"
+ #include "math_private.h"
+ 
+ /*
+  * invpio2:  53 bits of 2/pi
+  * pio2_1:   first  33 bit of pi/2
+  * pio2_1t:  pi/2 - pio2_1
+  * pio2_2:   second 33 bit of pi/2
+  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
 diff --git a/modules/fdlibm/src/e_sinh.cpp b/modules/fdlibm/src/e_sinh.cpp
 --- a/modules/fdlibm/src/e_sinh.cpp
 +++ b/modules/fdlibm/src/e_sinh.cpp
-@@ -29,17 +29,16 @@
+@@ -29,17 +29,16 @@ __FBSDID("$FreeBSD$");
   *
   * Special cases:
   *	sinh(x) is |x| if x is +INF, -INF, or NaN.
   *	only sinh(0)=0 is exact for finite x.
   */
  
  #include <float.h>
  
@@ -266,16 +287,37 @@ diff --git a/modules/fdlibm/src/e_sinh.c
  #include "math_private.h"
  
  static const double one = 1.0, shuge = 1.0e307;
  
  double
  __ieee754_sinh(double x)
  {
  	double t,h;
+diff --git a/modules/fdlibm/src/k_cos.cpp b/modules/fdlibm/src/k_cos.cpp
+--- a/modules/fdlibm/src/k_cos.cpp
++++ b/modules/fdlibm/src/k_cos.cpp
+@@ -48,17 +48,16 @@ __FBSDID("$FreeBSD$");
+  *	   and tmp having the same precision as x.  If they have extra
+  *	   precision due to compiler bugs, then the extra precision is
+  *	   only good provided it is retained in all terms of the final
+  *	   expression for cos().  Retention happens in all cases tested
+  *	   under FreeBSD, so don't pessimize things by forcibly clipping
+  *	   any extra precision in w.
+  */
+ 
+-#include "math.h"
+ #include "math_private.h"
+ 
+ static const double
+ one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+ C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+ C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+ C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+ C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
 diff --git a/modules/fdlibm/src/k_exp.cpp b/modules/fdlibm/src/k_exp.cpp
 --- a/modules/fdlibm/src/k_exp.cpp
 +++ b/modules/fdlibm/src/k_exp.cpp
 @@ -26,17 +26,16 @@
   * SUCH DAMAGE.
   */
  
  #include <sys/cdefs.h>
@@ -287,16 +329,79 @@ diff --git a/modules/fdlibm/src/k_exp.cp
  #include "math_private.h"
  
  static const uint32_t k = 1799;		/* constant for reduction */
  static const double kln2 =  1246.97177782734161156;	/* k * ln2 */
  
  /*
   * Compute exp(x), scaled to avoid spurious overflow.  An exponent is
   * returned separately in 'expt'.
+diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
+--- a/modules/fdlibm/src/k_rem_pio2.cpp
++++ b/modules/fdlibm/src/k_rem_pio2.cpp
+@@ -126,17 +126,16 @@ __FBSDID("$FreeBSD$");
+  * The hexadecimal values are the intended ones for the following 
+  * constants. The decimal values may be used, provided that the 
+  * compiler will convert from decimal to binary accurately enough 
+  * to produce the hexadecimal values shown.
+  */
+ 
+ #include <float.h>
+ 
+-#include "math.h"
+ #include "math_private.h"
+ 
+ static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
+ 
+ /*
+  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
+  *
+  *		integer array, contains the (24*i)-th to (24*i+23)-th 
+diff --git a/modules/fdlibm/src/k_sin.cpp b/modules/fdlibm/src/k_sin.cpp
+--- a/modules/fdlibm/src/k_sin.cpp
++++ b/modules/fdlibm/src/k_sin.cpp
+@@ -39,17 +39,16 @@ __FBSDID("$FreeBSD$");
+  *		    ~ sin(x) + (1-x*x/2)*y
+  *	   For better accuracy, let 
+  *		     3      2      2      2      2
+  *		r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+  *	   then                   3    2
+  *		sin(x) = x + (S1*x + (x *(r-y/2)+y))
+  */
+ 
+-#include "math.h"
+ #include "math_private.h"
+ 
+ static const double
+ half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+ S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+ S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+ S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+ S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+diff --git a/modules/fdlibm/src/k_tan.cpp b/modules/fdlibm/src/k_tan.cpp
+--- a/modules/fdlibm/src/k_tan.cpp
++++ b/modules/fdlibm/src/k_tan.cpp
+@@ -44,17 +44,16 @@ __FBSDID("$FreeBSD$");
+  *		 		    3    2
+  *		tan(x+y) = x + (T1*x + (x *(r+y)+y))
+  *
+  *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
+  *		tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
+  *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
+  */
+ 
+-#include "math.h"
+ #include "math_private.h"
+ static const double xxx[] = {
+ 		 3.33333333333334091986e-01,	/* 3FD55555, 55555563 */
+ 		 1.33333333333201242699e-01,	/* 3FC11111, 1110FE7A */
+ 		 5.39682539762260521377e-02,	/* 3FABA1BA, 1BB341FE */
+ 		 2.18694882948595424599e-02,	/* 3F9664F4, 8406D637 */
+ 		 8.86323982359930005737e-03,	/* 3F8226E3, E96E8493 */
+ 		 3.59207910759131235356e-03,	/* 3F6D6D22, C9560328 */
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
 @@ -15,16 +15,18 @@
   */
  
  #ifndef _MATH_PRIVATE_H_
  #define	_MATH_PRIVATE_H_
@@ -312,17 +417,17 @@ diff --git a/modules/fdlibm/src/math_pri
   *	ix0 = *(n0+(int*)&x);			* high word of x *
   *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
   * to dig two 32 bit words out of the 64 bit IEEE floating point
   * value.  That is non-ANSI, and, moreover, the gcc instruction
   * scheduler gets it wrong.  We instead use the following macros.
 diff --git a/modules/fdlibm/src/s_asinh.cpp b/modules/fdlibm/src/s_asinh.cpp
 --- a/modules/fdlibm/src/s_asinh.cpp
 +++ b/modules/fdlibm/src/s_asinh.cpp
-@@ -21,17 +21,16 @@
+@@ -21,17 +21,16 @@ __FBSDID("$FreeBSD$");
   *	asinh(x) := x  if  1+x*x=1,
   *		 := sign(x)*(log(x)+ln2)) for large |x|, else
   *		 := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
   *		 := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
   */
  
  #include <float.h>
  
@@ -333,17 +438,17 @@ diff --git a/modules/fdlibm/src/s_asinh.
  one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
  ln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
  huge=  1.00000000000000000000e+300;
  
  double
 diff --git a/modules/fdlibm/src/s_atan.cpp b/modules/fdlibm/src/s_atan.cpp
 --- a/modules/fdlibm/src/s_atan.cpp
 +++ b/modules/fdlibm/src/s_atan.cpp
-@@ -30,17 +30,16 @@
+@@ -30,17 +30,16 @@ __FBSDID("$FreeBSD$");
   * The hexadecimal values are the intended ones for the following
   * constants. The decimal values may be used, provided that the
   * compiler will convert from decimal to binary accurately enough
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
  
@@ -375,17 +480,17 @@ diff --git a/modules/fdlibm/src/s_cbrt.c
   * Return cube root of x
   */
  static const u_int32_t
  	B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */
  	B2 = 696219795; /* B2 = (1023-1023/3-54/3-0.03306235651)*2**20 */
 diff --git a/modules/fdlibm/src/s_ceil.cpp b/modules/fdlibm/src/s_ceil.cpp
 --- a/modules/fdlibm/src/s_ceil.cpp
 +++ b/modules/fdlibm/src/s_ceil.cpp
-@@ -19,17 +19,16 @@
+@@ -19,17 +19,16 @@ __FBSDID("$FreeBSD$");
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to ceil(x).
   */
  
  #include <float.h>
  
@@ -435,20 +540,41 @@ diff --git a/modules/fdlibm/src/s_copysi
  #include "math_private.h"
  
  double
  copysign(double x, double y)
  {
  	u_int32_t hx,hy;
  	GET_HIGH_WORD(hx,x);
  	GET_HIGH_WORD(hy,y);
+diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
+--- a/modules/fdlibm/src/s_cos.cpp
++++ b/modules/fdlibm/src/s_cos.cpp
+@@ -41,17 +41,16 @@ __FBSDID("$FreeBSD$");
+  *      trig(NaN)    is that NaN;
+  *
+  * Accuracy:
+  *	TRIG(x) returns trig(x) nearly rounded
+  */
+ 
+ #include <float.h>
+ 
+-#include "math.h"
+ #define INLINE_REM_PIO2
+ #include "math_private.h"
+ #include "e_rem_pio2.c"
+ 
+ double
+ cos(double x)
+ {
+ 	double y[2],z=0.0;
 diff --git a/modules/fdlibm/src/s_expm1.cpp b/modules/fdlibm/src/s_expm1.cpp
 --- a/modules/fdlibm/src/s_expm1.cpp
 +++ b/modules/fdlibm/src/s_expm1.cpp
-@@ -105,17 +105,16 @@
+@@ -105,17 +105,16 @@ __FBSDID("$FreeBSD$");
   * The hexadecimal values are the intended ones for the following
   * constants. The decimal values may be used, provided that the
   * compiler will convert from decimal to binary accurately enough
   * to produce the hexadecimal values shown.
   */
  
  #include <float.h>
  
@@ -480,17 +606,17 @@ diff --git a/modules/fdlibm/src/s_fabs.c
  fabs(double x)
  {
  	u_int32_t high;
  	GET_HIGH_WORD(high,x);
  	SET_HIGH_WORD(x,high&0x7fffffff);
 diff --git a/modules/fdlibm/src/s_floor.cpp b/modules/fdlibm/src/s_floor.cpp
 --- a/modules/fdlibm/src/s_floor.cpp
 +++ b/modules/fdlibm/src/s_floor.cpp
-@@ -19,17 +19,16 @@
+@@ -19,17 +19,16 @@ __FBSDID("$FreeBSD$");
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to floor(x).
   */
  
  #include <float.h>
  
@@ -501,17 +627,17 @@ diff --git a/modules/fdlibm/src/s_floor.
  
  double
  floor(double x)
  {
  	int32_t i0,i1,j0;
 diff --git a/modules/fdlibm/src/s_floorf.cpp b/modules/fdlibm/src/s_floorf.cpp
 --- a/modules/fdlibm/src/s_floorf.cpp
 +++ b/modules/fdlibm/src/s_floorf.cpp
-@@ -20,17 +20,16 @@
+@@ -20,17 +20,16 @@ __FBSDID("$FreeBSD$");
   * floorf(x)
   * Return x rounded toward -inf to integral value
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to floorf(x).
   */
  
@@ -522,17 +648,17 @@ diff --git a/modules/fdlibm/src/s_floorf
  
  float
  floorf(float x)
  {
  	int32_t i0,j0;
 diff --git a/modules/fdlibm/src/s_log1p.cpp b/modules/fdlibm/src/s_log1p.cpp
 --- a/modules/fdlibm/src/s_log1p.cpp
 +++ b/modules/fdlibm/src/s_log1p.cpp
-@@ -75,17 +75,16 @@
+@@ -75,17 +75,16 @@ __FBSDID("$FreeBSD$");
   *		if(u==1.0) return x ; else
   *			   return log(u)*(x/(u-1.0));
   *
   *	 See HP-15C Advanced Functions Handbook, p.193.
   */
  
  #include <float.h>
  
@@ -543,39 +669,40 @@ diff --git a/modules/fdlibm/src/s_log1p.
  ln2_hi  =  6.93147180369123816490e-01,	/* 3fe62e42 fee00000 */
  ln2_lo  =  1.90821492927058770002e-10,	/* 3dea39ef 35793c76 */
  two54   =  1.80143985094819840000e+16,  /* 43500000 00000000 */
  Lp1 = 6.666666666666735130e-01,  /* 3FE55555 55555593 */
  Lp2 = 3.999999999940941908e-01,  /* 3FD99999 9997FA04 */
 diff --git a/modules/fdlibm/src/s_nearbyint.cpp b/modules/fdlibm/src/s_nearbyint.cpp
 --- a/modules/fdlibm/src/s_nearbyint.cpp
 +++ b/modules/fdlibm/src/s_nearbyint.cpp
-@@ -25,17 +25,17 @@
+@@ -25,17 +25,18 @@
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  
  #include <sys/cdefs.h>
  __FBSDID("$FreeBSD$");
  
  #include <fenv.h>
 -#include <math.h>
++
 +#include "math_private.h"
  
  /*
   * We save and restore the floating-point environment to avoid raising
   * an inexact exception.  We can get away with using fesetenv()
   * instead of feclearexcept()/feupdateenv() to restore the environment
   * because the only exception defined for rint() is overflow, and
   * rounding can't overflow as long as emax >= p.
   *
 diff --git a/modules/fdlibm/src/s_rint.cpp b/modules/fdlibm/src/s_rint.cpp
 --- a/modules/fdlibm/src/s_rint.cpp
 +++ b/modules/fdlibm/src/s_rint.cpp
-@@ -20,17 +20,16 @@
+@@ -20,17 +20,16 @@ __FBSDID("$FreeBSD$");
   * Method:
   *	Using floating addition.
   * Exception:
   *	Inexact flag raised if x not equal to rint(x).
   */
  
  #include <float.h>
  
@@ -607,38 +734,84 @@ diff --git a/modules/fdlibm/src/s_rintf.
  TWO23[2]={
    8.3886080000e+06, /* 0x4b000000 */
   -8.3886080000e+06, /* 0xcb000000 */
  };
  
 diff --git a/modules/fdlibm/src/s_scalbn.cpp b/modules/fdlibm/src/s_scalbn.cpp
 --- a/modules/fdlibm/src/s_scalbn.cpp
 +++ b/modules/fdlibm/src/s_scalbn.cpp
-@@ -17,17 +17,16 @@
-  * scalbn (double x, int n)
-  * scalbn(x,n) returns x* 2**n  computed by  exponent
-  * manipulation rather than by actually performing an
-  * exponentiation or a multiplication.
+@@ -2,19 +2,20 @@
+  * Copyright (c) 2005-2020 Rich Felker, et al.
+  *
+  * SPDX-License-Identifier: MIT
+  *
+  * Please see https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+  * for all contributors to musl.
+  */
+ #include <float.h>
+-#include <math.h>
+ #include <stdint.h>
+ 
++#include "math_private.h"
++
+ double scalbn(double x, int n)
+ {
+ 	union {double f; uint64_t i;} u;
+ 	double_t y = x;
+ 
+ 	if (n > 1023) {
+ 		y *= 0x1p1023;
+ 		n -= 1023;
+diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
+--- a/modules/fdlibm/src/s_sin.cpp
++++ b/modules/fdlibm/src/s_sin.cpp
+@@ -41,17 +41,16 @@ __FBSDID("$FreeBSD$");
+  *      trig(NaN)    is that NaN;
+  *
+  * Accuracy:
+  *	TRIG(x) returns trig(x) nearly rounded
   */
  
  #include <float.h>
  
 -#include "math.h"
+ #define INLINE_REM_PIO2
  #include "math_private.h"
+ #include "e_rem_pio2.c"
  
- static const double
- two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
- twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
- huge   = 1.0e+300,
- tiny   = 1.0e-300;
+ double
+ sin(double x)
+ {
+ 	double y[2],z=0.0;
+diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
+--- a/modules/fdlibm/src/s_tan.cpp
++++ b/modules/fdlibm/src/s_tan.cpp
+@@ -40,17 +40,16 @@ __FBSDID("$FreeBSD$");
+  *      trig(NaN)    is that NaN;
+  *
+  * Accuracy:
+  *	TRIG(x) returns trig(x) nearly rounded
+  */
  
+ #include <float.h>
+ 
+-#include "math.h"
+ #define INLINE_REM_PIO2
+ #include "math_private.h"
+ #include "e_rem_pio2.c"
+ 
+ double
+ tan(double x)
+ {
+ 	double y[2],z=0.0;
 diff --git a/modules/fdlibm/src/s_tanh.cpp b/modules/fdlibm/src/s_tanh.cpp
 --- a/modules/fdlibm/src/s_tanh.cpp
 +++ b/modules/fdlibm/src/s_tanh.cpp
-@@ -34,17 +34,16 @@
+@@ -34,17 +34,16 @@ __FBSDID("$FreeBSD$");
   *
   * Special cases:
   *	tanh(NaN) is NaN;
   *	only tanh(0)=0 is exact for finite argument.
   */
  
  #include <float.h>
  
@@ -649,17 +822,17 @@ diff --git a/modules/fdlibm/src/s_tanh.c
  static const double one = 1.0, two = 2.0, huge = 1.0e300;
  
  double
  tanh(double x)
  {
 diff --git a/modules/fdlibm/src/s_trunc.cpp b/modules/fdlibm/src/s_trunc.cpp
 --- a/modules/fdlibm/src/s_trunc.cpp
 +++ b/modules/fdlibm/src/s_trunc.cpp
-@@ -19,17 +19,16 @@
+@@ -19,17 +19,16 @@ __FBSDID("$FreeBSD$");
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to trunc(x).
   */
  
  #include <float.h>
  
@@ -670,17 +843,17 @@ diff --git a/modules/fdlibm/src/s_trunc.
  
  double
  trunc(double x)
  {
  	int32_t i0,i1,j0;
 diff --git a/modules/fdlibm/src/s_truncf.cpp b/modules/fdlibm/src/s_truncf.cpp
 --- a/modules/fdlibm/src/s_truncf.cpp
 +++ b/modules/fdlibm/src/s_truncf.cpp
-@@ -17,17 +17,16 @@
+@@ -17,17 +17,16 @@ __FBSDID("$FreeBSD$");
   * truncf(x)
   * Return x rounded toward 0 to integral value
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to truncf(x).
   */
  
@@ -688,177 +861,8 @@ diff --git a/modules/fdlibm/src/s_truncf
  #include "math_private.h"
  
  static const float huge = 1.0e30F;
  
  float
  truncf(float x)
  {
  	int32_t i0,j0;
-diff --git a/modules/fdlibm/src/e_rem_pio2.cpp b/modules/fdlibm/src/e_rem_pio2.cpp
---- a/modules/fdlibm/src/e_rem_pio2.cpp
-+++ b/modules/fdlibm/src/e_rem_pio2.cpp
-@@ -19,17 +19,16 @@
- /* __ieee754_rem_pio2(x,y)
-  * 
-  * return the remainder of x rem pi/2 in y[0]+y[1] 
-  * use __kernel_rem_pio2()
-  */
- 
- #include <float.h>
- 
--#include "math.h"
- #include "math_private.h"
- 
- /*
-  * invpio2:  53 bits of 2/pi
-  * pio2_1:   first  33 bit of pi/2
-  * pio2_1t:  pi/2 - pio2_1
-  * pio2_2:   second 33 bit of pi/2
-  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
-
-diff --git a/modules/fdlibm/src/k_cos.cpp b/modules/fdlibm/src/k_cos.cpp
---- a/modules/fdlibm/src/k_cos.cpp
-+++ b/modules/fdlibm/src/k_cos.cpp
-@@ -48,17 +48,16 @@
-  *	   and tmp having the same precision as x.  If they have extra
-  *	   precision due to compiler bugs, then the extra precision is
-  *	   only good provided it is retained in all terms of the final
-  *	   expression for cos().  Retention happens in all cases tested
-  *	   under FreeBSD, so don't pessimize things by forcibly clipping
-  *	   any extra precision in w.
-  */
- 
--#include "math.h"
- #include "math_private.h"
- 
- static const double
- one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
- C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
- C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
- C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
- C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
-diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
---- a/modules/fdlibm/src/k_rem_pio2.cpp
-+++ b/modules/fdlibm/src/k_rem_pio2.cpp
-@@ -126,17 +126,16 @@
-  * The hexadecimal values are the intended ones for the following 
-  * constants. The decimal values may be used, provided that the 
-  * compiler will convert from decimal to binary accurately enough 
-  * to produce the hexadecimal values shown.
-  */
- 
- #include <float.h>
- 
--#include "math.h"
- #include "math_private.h"
- 
- static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
- 
- /*
-  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
-  *
-  *		integer array, contains the (24*i)-th to (24*i+23)-th 
-diff --git a/modules/fdlibm/src/k_sin.cpp b/modules/fdlibm/src/k_sin.cpp
---- a/modules/fdlibm/src/k_sin.cpp
-+++ b/modules/fdlibm/src/k_sin.cpp
-@@ -39,17 +39,16 @@
-  *		    ~ sin(x) + (1-x*x/2)*y
-  *	   For better accuracy, let 
-  *		     3      2      2      2      2
-  *		r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
-  *	   then                   3    2
-  *		sin(x) = x + (S1*x + (x *(r-y/2)+y))
-  */
- 
--#include "math.h"
- #include "math_private.h"
- 
- static const double
- half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
- S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
- S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
- S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
- S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
-diff --git a/modules/fdlibm/src/k_tan.cpp b/modules/fdlibm/src/k_tan.cpp
---- a/modules/fdlibm/src/k_tan.cpp
-+++ b/modules/fdlibm/src/k_tan.cpp
-@@ -44,17 +44,16 @@
-  *		 		    3    2
-  *		tan(x+y) = x + (T1*x + (x *(r+y)+y))
-  *
-  *      4. For x in [0.67434,pi/4],  let y = pi/4 - x, then
-  *		tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
-  *		       = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
-  */
- 
--#include "math.h"
- #include "math_private.h"
- static const double xxx[] = {
- 		 3.33333333333334091986e-01,	/* 3FD55555, 55555563 */
- 		 1.33333333333201242699e-01,	/* 3FC11111, 1110FE7A */
- 		 5.39682539762260521377e-02,	/* 3FABA1BA, 1BB341FE */
- 		 2.18694882948595424599e-02,	/* 3F9664F4, 8406D637 */
- 		 8.86323982359930005737e-03,	/* 3F8226E3, E96E8493 */
- 		 3.59207910759131235356e-03,	/* 3F6D6D22, C9560328 */
-diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
---- a/modules/fdlibm/src/s_cos.cpp
-+++ b/modules/fdlibm/src/s_cos.cpp
-@@ -41,17 +41,16 @@
-  *      trig(NaN)    is that NaN;
-  *
-  * Accuracy:
-  *	TRIG(x) returns trig(x) nearly rounded
-  */
- 
- #include <float.h>
- 
--#include "math.h"
- #define INLINE_REM_PIO2
- #include "math_private.h"
- #include "e_rem_pio2.c"
- 
- double
- cos(double x)
- {
- 	double y[2],z=0.0;
-diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
---- a/modules/fdlibm/src/s_sin.cpp
-+++ b/modules/fdlibm/src/s_sin.cpp
-@@ -41,17 +41,16 @@
-  *      trig(NaN)    is that NaN;
-  *
-  * Accuracy:
-  *	TRIG(x) returns trig(x) nearly rounded
-  */
- 
- #include <float.h>
- 
--#include "math.h"
- #define INLINE_REM_PIO2
- #include "math_private.h"
- #include "e_rem_pio2.c"
- 
- double
- sin(double x)
- {
- 	double y[2],z=0.0;
-diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
---- a/modules/fdlibm/src/s_tan.cpp
-+++ b/modules/fdlibm/src/s_tan.cpp
-@@ -40,17 +40,16 @@
-  *      trig(NaN)    is that NaN;
-  *
-  * Accuracy:
-  *	TRIG(x) returns trig(x) nearly rounded
-  */
- 
- #include <float.h>
- 
--#include "math.h"
- #define INLINE_REM_PIO2
- #include "math_private.h"
- #include "e_rem_pio2.c"
- 
- double
- tan(double x)
- {
- 	double y[2],z=0.0;
\ No newline at end of file
--- a/modules/fdlibm/patches/06_use_mfbt_endian_h_in_math_private_h.patch
+++ b/modules/fdlibm/patches/06_use_mfbt_endian_h_in_math_private_h.patch
@@ -6,21 +6,21 @@ diff --git a/modules/fdlibm/src/math_pri
   */
  
  #ifndef _MATH_PRIVATE_H_
  #define	_MATH_PRIVATE_H_
  
  #include <stdint.h>
  #include <sys/types.h>
 -#include <machine/endian.h>
++
++#include "mozilla/EndianUtils.h"
  
  #include "fdlibm.h"
  
-+#include "mozilla/EndianUtils.h"
-+
  /*
   * The original fdlibm code used statements like:
   *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
   *	ix0 = *(n0+(int*)&x);			* high word of x *
   *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
   * to dig two 32 bit words out of the 64 bit IEEE floating point
   * value.  That is non-ANSI, and, moreover, the gcc instruction
   * scheduler gets it wrong.  We instead use the following macros.
@@ -71,41 +71,36 @@ diff --git a/modules/fdlibm/src/math_pri
  
  typedef union
  {
    long double value;
    struct {
      u_int32_t lswlo;
      u_int32_t lswhi;
      u_int32_t mswlo;
-@@ -87,17 +73,22 @@ typedef union
+@@ -87,17 +73,17 @@ typedef union
    struct {
      u_int64_t lsw;
      u_int64_t msw;
    } parts64;
  } ieee_quad_shape_type;
  
  #endif
  
 -#if IEEE_WORD_ORDER == BIG_ENDIAN
-+/*
-+ * A union which permits us to convert between a double and two 32 bit
-+ * ints.
-+ */
-+
 +#if MOZ_BIG_ENDIAN()
  
  typedef union
  {
    double value;
    struct
    {
      u_int32_t msw;
      u_int32_t lsw;
-@@ -105,17 +96,17 @@ typedef union
+@@ -105,17 +91,17 @@ typedef union
    struct
    {
      u_int64_t w;
    } xparts;
  } ieee_double_shape_type;
  
  #endif
  
--- a/modules/fdlibm/patches/07_add_fdlibm_namespace_to_functions_defined_and_used_in_fdlibm.patch
+++ b/modules/fdlibm/patches/07_add_fdlibm_namespace_to_functions_defined_and_used_in_fdlibm.patch
@@ -1,24 +1,27 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -872,16 +872,50 @@ irintl(long double x)
+@@ -867,16 +867,53 @@ irintl(long double x)
  #define	__ieee754_j1f	j1f
  #define	__ieee754_y0f	y0f
  #define	__ieee754_y1f	y1f
  #define	__ieee754_jnf	jnf
  #define	__ieee754_ynf	ynf
  #define	__ieee754_remainderf remainderf
  #define	__ieee754_scalbf scalbf
  
 +#define acos fdlibm::acos
 +#define asin fdlibm::asin
 +#define atan fdlibm::atan
 +#define atan2 fdlibm::atan2
++#define cos fdlibm::cos
++#define sin fdlibm::sin
++#define tan fdlibm::tan
 +#define cosh fdlibm::cosh
 +#define sinh fdlibm::sinh
 +#define tanh fdlibm::tanh
 +#define exp fdlibm::exp
 +#define log fdlibm::log
 +#define log10 fdlibm::log10
 +#define pow fdlibm::pow
 +#define ceil fdlibm::ceil
--- a/modules/fdlibm/patches/08_remove_weak_reference_macro.patch
+++ b/modules/fdlibm/patches/08_remove_weak_reference_macro.patch
@@ -1,204 +1,204 @@
 diff --git a/modules/fdlibm/src/e_acos.cpp b/modules/fdlibm/src/e_acos.cpp
 --- a/modules/fdlibm/src/e_acos.cpp
 +++ b/modules/fdlibm/src/e_acos.cpp
-@@ -99,12 +99,8 @@ double
+@@ -99,12 +99,8 @@ __ieee754_acos(double x)
  	    c  = (z-df*df)/(s+df);
  	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
  	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
  	    r = p/q;
  	    w = r*s+c;
  	    return 2.0*(df+w);
  	}
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(acos, acosl);
 -#endif
 diff --git a/modules/fdlibm/src/e_acosh.cpp b/modules/fdlibm/src/e_acosh.cpp
 --- a/modules/fdlibm/src/e_acosh.cpp
 +++ b/modules/fdlibm/src/e_acosh.cpp
-@@ -56,12 +56,8 @@ double
+@@ -56,12 +56,8 @@ __ieee754_acosh(double x)
  	} else if (hx > 0x40000000) {	/* 2**28 > x > 2 */
  	    t=x*x;
  	    return __ieee754_log(2.0*x-one/(x+sqrt(t-one)));
  	} else {			/* 1<x<2 */
  	    t = x-one;
  	    return log1p(t+sqrt(2.0*t+t*t));
  	}
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(acosh, acoshl);
 -#endif
 diff --git a/modules/fdlibm/src/e_asin.cpp b/modules/fdlibm/src/e_asin.cpp
 --- a/modules/fdlibm/src/e_asin.cpp
 +++ b/modules/fdlibm/src/e_asin.cpp
-@@ -105,12 +105,8 @@ double
+@@ -105,12 +105,8 @@ __ieee754_asin(double x)
  	    c  = (t-w*w)/(s+w);
  	    r  = p/q;
  	    p  = 2.0*s*r-(pio2_lo-2.0*c);
  	    q  = pio4_hi-2.0*w;
  	    t  = pio4_hi-(p-q);
  	}    
  	if(hx>0) return t; else return -t;    
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(asin, asinl);
 -#endif
 diff --git a/modules/fdlibm/src/e_atan2.cpp b/modules/fdlibm/src/e_atan2.cpp
 --- a/modules/fdlibm/src/e_atan2.cpp
 +++ b/modules/fdlibm/src/e_atan2.cpp
-@@ -117,12 +117,8 @@ double
+@@ -117,12 +117,8 @@ __ieee754_atan2(double y, double x)
  	switch (m) {
  	    case 0: return       z  ;	/* atan(+,+) */
  	    case 1: return      -z  ;	/* atan(-,+) */
  	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
  	    default: /* case 3 */
  	    	    return  (z-pi_lo)-pi;/* atan(-,-) */
  	}
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(atan2, atan2l);
 -#endif
 diff --git a/modules/fdlibm/src/e_atanh.cpp b/modules/fdlibm/src/e_atanh.cpp
 --- a/modules/fdlibm/src/e_atanh.cpp
 +++ b/modules/fdlibm/src/e_atanh.cpp
-@@ -56,12 +56,8 @@ double
+@@ -56,12 +56,8 @@ __ieee754_atanh(double x)
  	SET_HIGH_WORD(x,ix);
  	if(ix<0x3fe00000) {		/* x < 0.5 */
  	    t = x+x;
  	    t = 0.5*log1p(t+t*x/(one-x));
  	} else 
  	    t = 0.5*log1p((x+x)/(one-x));
  	if(hx>=0) return t; else return -t;
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(atanh, atanhl);
 -#endif
 diff --git a/modules/fdlibm/src/e_cosh.cpp b/modules/fdlibm/src/e_cosh.cpp
 --- a/modules/fdlibm/src/e_cosh.cpp
 +++ b/modules/fdlibm/src/e_cosh.cpp
-@@ -73,12 +73,8 @@ double
+@@ -73,12 +73,8 @@ __ieee754_cosh(double x)
  
      /* |x| in [log(maxdouble), overflowthresold] */
  	if (ix<=0x408633CE)
  	    return __ldexp_exp(fabs(x), -1);
  
      /* |x| > overflowthresold, cosh(x) overflow */
  	return huge*huge;
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(cosh, coshl);
 -#endif
 diff --git a/modules/fdlibm/src/e_exp.cpp b/modules/fdlibm/src/e_exp.cpp
 --- a/modules/fdlibm/src/e_exp.cpp
 +++ b/modules/fdlibm/src/e_exp.cpp
-@@ -152,12 +152,8 @@ double
+@@ -152,12 +152,8 @@ __ieee754_exp(double x)	/* default IEEE double exp */
  	else 		y = one-((lo-(x*c)/(2.0-c))-hi);
  	if(k >= -1021) {
  	    if (k==1024) return y*2.0*0x1p1023;
  	    return y*twopk;
  	} else {
  	    return y*twopk*twom1000;
  	}
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(exp, expl);
 -#endif
 diff --git a/modules/fdlibm/src/e_hypot.cpp b/modules/fdlibm/src/e_hypot.cpp
 --- a/modules/fdlibm/src/e_hypot.cpp
 +++ b/modules/fdlibm/src/e_hypot.cpp
-@@ -119,12 +119,8 @@ double
+@@ -117,12 +117,8 @@ __ieee754_hypot(double x, double y)
+ 	    w  = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+ 	}
  	if(k!=0) {
- 	    u_int32_t high;
- 	    t1 = 1.0;
- 	    GET_HIGH_WORD(high,t1);
- 	    SET_HIGH_WORD(t1,high+(k<<20));
+ 	    t1 = 0.0;
+ 	    SET_HIGH_WORD(t1,(1023+k)<<20);
  	    return t1*w;
  	} else return w;
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(hypot, hypotl);
 -#endif
 diff --git a/modules/fdlibm/src/e_log.cpp b/modules/fdlibm/src/e_log.cpp
 --- a/modules/fdlibm/src/e_log.cpp
 +++ b/modules/fdlibm/src/e_log.cpp
-@@ -135,12 +135,8 @@ double
+@@ -135,12 +135,8 @@ __ieee754_log(double x)
  	    hfsq=0.5*f*f;
  	    if(k==0) return f-(hfsq-s*(hfsq+R)); else
  		     return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
  	} else {
  	    if(k==0) return f-s*(f-R); else
  		     return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
  	}
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(log, logl);
 -#endif
 diff --git a/modules/fdlibm/src/e_log10.cpp b/modules/fdlibm/src/e_log10.cpp
 --- a/modules/fdlibm/src/e_log10.cpp
 +++ b/modules/fdlibm/src/e_log10.cpp
-@@ -82,12 +82,8 @@ double
+@@ -82,12 +82,8 @@ __ieee754_log10(double x)
  	 * with some parallelism and it reduces the error for many args.
  	 */
  	w = y2 + val_hi;
  	val_lo += (y2 - w) + val_hi;
  	val_hi = w;
  
  	return val_lo + val_hi;
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(log10, log10l);
 -#endif
 diff --git a/modules/fdlibm/src/e_log2.cpp b/modules/fdlibm/src/e_log2.cpp
 --- a/modules/fdlibm/src/e_log2.cpp
 +++ b/modules/fdlibm/src/e_log2.cpp
-@@ -105,12 +105,8 @@ double
+@@ -105,12 +105,8 @@ __ieee754_log2(double x)
  
  	/* spadd(val_hi, val_lo, y), except for not using double_t: */
  	w = y + val_hi;
  	val_lo += (y - w) + val_hi;
  	val_hi = w;
  
  	return val_lo + val_hi;
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(log2, log2l);
 -#endif
 diff --git a/modules/fdlibm/src/e_pow.cpp b/modules/fdlibm/src/e_pow.cpp
 --- a/modules/fdlibm/src/e_pow.cpp
 +++ b/modules/fdlibm/src/e_pow.cpp
-@@ -302,12 +302,8 @@ double
+@@ -302,12 +302,8 @@ __ieee754_pow(double x, double y)
  	r  = (z*t1)/(t1-two)-(w+z*w);
  	z  = one-(r-z);
  	GET_HIGH_WORD(j,z);
  	j += (n<<20);
  	if((j>>20)<=0) z = scalbn(z,n);	/* subnormal output */
  	else SET_HIGH_WORD(z,j);
  	return s*z;
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(pow, powl);
 -#endif
 diff --git a/modules/fdlibm/src/e_sinh.cpp b/modules/fdlibm/src/e_sinh.cpp
 --- a/modules/fdlibm/src/e_sinh.cpp
 +++ b/modules/fdlibm/src/e_sinh.cpp
-@@ -67,12 +67,8 @@ double
+@@ -67,12 +67,8 @@ __ieee754_sinh(double x)
  
      /* |x| in [log(maxdouble), overflowthresold] */
  	if (ix<=0x408633CE)
  	    return h*2.0*__ldexp_exp(fabs(x), -1);
  
      /* |x| > overflowthresold, sinh(x) overflow */
  	return x*shuge;
  }
@@ -241,17 +241,17 @@ diff --git a/modules/fdlibm/src/s_atan.c
 diff --git a/modules/fdlibm/src/s_cbrt.cpp b/modules/fdlibm/src/s_cbrt.cpp
 --- a/modules/fdlibm/src/s_cbrt.cpp
 +++ b/modules/fdlibm/src/s_cbrt.cpp
 @@ -106,12 +106,8 @@ cbrt(double x)
  	s=t*t;				/* t*t is exact */
  	r=x/s;				/* error <= 0.5 ulps; |r| < |t| */
  	w=t+t;				/* t+t is exact */
  	r=(r-t)/(w+r);			/* r-t is exact; w+r ~= 3*t */
- 	t=t+t*r;			/* error <= 0.5 + 0.5/3 + epsilon */
+ 	t=t+t*r;			/* error <= (0.5 + 0.5/3) * ulp */
  
  	return(t);
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(cbrt, cbrtl);
 -#endif
 diff --git a/modules/fdlibm/src/s_ceil.cpp b/modules/fdlibm/src/s_ceil.cpp
@@ -265,16 +265,32 @@ diff --git a/modules/fdlibm/src/s_ceil.c
  	}
  	INSERT_WORDS(x,i0,i1);
  	return x;
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(ceil, ceill);
 -#endif
+diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
+--- a/modules/fdlibm/src/s_cos.cpp
++++ b/modules/fdlibm/src/s_cos.cpp
+@@ -77,12 +77,8 @@ cos(double x)
+ 		case 0: return  __kernel_cos(y[0],y[1]);
+ 		case 1: return -__kernel_sin(y[0],y[1],1);
+ 		case 2: return -__kernel_cos(y[0],y[1]);
+ 		default:
+ 		        return  __kernel_sin(y[0],y[1],1);
+ 	    }
+ 	}
+ }
+-
+-#if (LDBL_MANT_DIG == 53)
+-__weak_reference(cos, cosl);
+-#endif
 diff --git a/modules/fdlibm/src/s_expm1.cpp b/modules/fdlibm/src/s_expm1.cpp
 --- a/modules/fdlibm/src/s_expm1.cpp
 +++ b/modules/fdlibm/src/s_expm1.cpp
 @@ -210,12 +210,8 @@ expm1(double x)
  		SET_HIGH_WORD(t,((0x3ff-k)<<20));	/* 2^-k */
  	       	y = x-(e+t);
  	       	y += one;
  		y = y*twopk;
@@ -332,29 +348,61 @@ diff --git a/modules/fdlibm/src/s_rint.c
  }
 -
 -#if (LDBL_MANT_DIG == 53)
 -__weak_reference(rint, rintl);
 -#endif
 diff --git a/modules/fdlibm/src/s_scalbn.cpp b/modules/fdlibm/src/s_scalbn.cpp
 --- a/modules/fdlibm/src/s_scalbn.cpp
 +++ b/modules/fdlibm/src/s_scalbn.cpp
-@@ -53,13 +53,8 @@ scalbn (double x, int n)
- 		return huge*copysign(huge,x);	/*overflow*/
- 	    else
- 		return tiny*copysign(tiny,x); 	/*underflow*/
+@@ -36,13 +36,8 @@ double scalbn(double x, int n)
+ 			if (n < -1022)
+ 				n = -1022;
+ 		}
  	}
-         k += 54;				/* subnormal result */
- 	SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
-         return x*twom54;
+ 	u.i = (uint64_t)(0x3ff+n)<<52;
+ 	x = y * u.f;
+ 	return x;
+ }
+-
+-#if (LDBL_MANT_DIG == 53) && !defined(scalbn)
+-__weak_reference(scalbn, ldexpl);
+-__weak_reference(scalbn, scalbnl);
+-#endif
+diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
+--- a/modules/fdlibm/src/s_sin.cpp
++++ b/modules/fdlibm/src/s_sin.cpp
+@@ -77,12 +77,8 @@ sin(double x)
+ 		case 0: return  __kernel_sin(y[0],y[1],1);
+ 		case 1: return  __kernel_cos(y[0],y[1]);
+ 		case 2: return -__kernel_sin(y[0],y[1],1);
+ 		default:
+ 			return -__kernel_cos(y[0],y[1]);
+ 	    }
+ 	}
  }
 -
 -#if (LDBL_MANT_DIG == 53)
--__weak_reference(scalbn, ldexpl);
--__weak_reference(scalbn, scalbnl);
+-__weak_reference(sin, sinl);
+-#endif
+diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
+--- a/modules/fdlibm/src/s_tan.cpp
++++ b/modules/fdlibm/src/s_tan.cpp
+@@ -71,12 +71,8 @@ tan(double x)
+ 
+     /* argument reduction needed */
+ 	else {
+ 	    n = __ieee754_rem_pio2(x,y);
+ 	    return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
+ 							-1 -- n odd */
+ 	}
+ }
+-
+-#if (LDBL_MANT_DIG == 53)
+-__weak_reference(tan, tanl);
 -#endif
 diff --git a/modules/fdlibm/src/s_tanh.cpp b/modules/fdlibm/src/s_tanh.cpp
 --- a/modules/fdlibm/src/s_tanh.cpp
 +++ b/modules/fdlibm/src/s_tanh.cpp
 @@ -72,12 +72,8 @@ tanh(double x)
  	        z= -t/(t+two);
  	    }
      /* |x| >= 22, return +-1 */
@@ -378,56 +426,8 @@ diff --git a/modules/fdlibm/src/s_trunc.
  	}
  	INSERT_WORDS(x,i0,i1);
  	return x;
  }
 -
 -#if LDBL_MANT_DIG == 53
 -__weak_reference(trunc, truncl);
 -#endif
-diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
---- a/modules/fdlibm/src/s_cos.cpp
-+++ b/modules/fdlibm/src/s_cos.cpp
-@@ -78,12 +78,8 @@ cos(double x)
- 		case 0: return  __kernel_cos(y[0],y[1]);
- 		case 1: return -__kernel_sin(y[0],y[1],1);
- 		case 2: return -__kernel_cos(y[0],y[1]);
- 		default:
- 		        return  __kernel_sin(y[0],y[1],1);
- 	    }
- 	}
- }
--
--#if (LDBL_MANT_DIG == 53)
--__weak_reference(cos, cosl);
--#endif
-diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
---- a/modules/fdlibm/src/s_sin.cpp
-+++ b/modules/fdlibm/src/s_sin.cpp
-@@ -78,12 +78,8 @@ sin(double x)
- 		case 0: return  __kernel_sin(y[0],y[1],1);
- 		case 1: return  __kernel_cos(y[0],y[1]);
- 		case 2: return -__kernel_sin(y[0],y[1],1);
- 		default:
- 			return -__kernel_cos(y[0],y[1]);
- 	    }
- 	}
- }
--
--#if (LDBL_MANT_DIG == 53)
--__weak_reference(sin, sinl);
--#endif
-diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
---- a/modules/fdlibm/src/s_tan.cpp
-+++ b/modules/fdlibm/src/s_tan.cpp
-@@ -72,12 +72,8 @@ tan(double x)
- 
-     /* argument reduction needed */
- 	else {
- 	    n = __ieee754_rem_pio2(x,y);
- 	    return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /*   1 -- n even
- 							-1 -- n odd */
- 	}
- }
--
--#if (LDBL_MANT_DIG == 53)
--__weak_reference(tan, tanl);
--#endif
--- a/modules/fdlibm/patches/09_comment_out_rcsid_variable.patch
+++ b/modules/fdlibm/patches/09_comment_out_rcsid_variable.patch
@@ -296,16 +296,40 @@ diff --git a/modules/fdlibm/src/e_pow.cp
  
  /* __ieee754_pow(x,y) return x**y
   *
   *		      n
   * Method:  Let x =  2   * (1+f)
   *	1. Compute and return log2(x) in two pieces:
   *		log2(x) = w1 + w2,
   *	   where w1 has 53-24 = 29 bit trailing zeros.
+diff --git a/modules/fdlibm/src/e_rem_pio2.cpp b/modules/fdlibm/src/e_rem_pio2.cpp
+--- a/modules/fdlibm/src/e_rem_pio2.cpp
++++ b/modules/fdlibm/src/e_rem_pio2.cpp
+@@ -8,18 +8,18 @@
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice 
+  * is preserved.
+  * ====================================================
+  *
+  * Optimized by Bruce D. Evans.
+  */
+ 
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /* __ieee754_rem_pio2(x,y)
+  * 
+  * return the remainder of x rem pi/2 in y[0]+y[1] 
+  * use __kernel_rem_pio2()
+  */
+ 
+ #include <float.h>
 diff --git a/modules/fdlibm/src/e_sinh.cpp b/modules/fdlibm/src/e_sinh.cpp
 --- a/modules/fdlibm/src/e_sinh.cpp
 +++ b/modules/fdlibm/src/e_sinh.cpp
 @@ -6,18 +6,18 @@
   *
   * Developed at SunSoft, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice 
@@ -320,16 +344,40 @@ diff --git a/modules/fdlibm/src/e_sinh.c
  
  /* __ieee754_sinh(x)
   * Method : 
   * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
   *	1. Replace x by |x| (sinh(-x) = -sinh(x)). 
   *	2. 
   *		                                    E + E/(E+1)
   *	    0        <= x <= 22     :  sinh(x) := --------------, E=expm1(x)
+diff --git a/modules/fdlibm/src/k_cos.cpp b/modules/fdlibm/src/k_cos.cpp
+--- a/modules/fdlibm/src/k_cos.cpp
++++ b/modules/fdlibm/src/k_cos.cpp
+@@ -6,18 +6,18 @@
+  *
+  * Developed at SunSoft, a Sun Microsystems, Inc. business.
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice 
+  * is preserved.
+  * ====================================================
+  */
+ 
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /*
+  * __kernel_cos( x,  y )
+  * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+  * Input x is assumed to be bounded by ~pi/4 in magnitude.
+  * Input y is the tail of x. 
+  *
+  * Algorithm
 diff --git a/modules/fdlibm/src/k_exp.cpp b/modules/fdlibm/src/k_exp.cpp
 --- a/modules/fdlibm/src/k_exp.cpp
 +++ b/modules/fdlibm/src/k_exp.cpp
 @@ -21,22 +21,22 @@
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
@@ -373,16 +421,88 @@ diff --git a/modules/fdlibm/src/k_log.h 
  
  /*
   * k_log1p(f):
   * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)].
   *
   * The following describes the overall strategy for computing
   * logarithms in base e.  The argument reduction and adding the final
   * term of the polynomial are done by the caller for increased accuracy
+diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
+--- a/modules/fdlibm/src/k_rem_pio2.cpp
++++ b/modules/fdlibm/src/k_rem_pio2.cpp
+@@ -6,18 +6,18 @@
+  *
+  * Developed at SunSoft, a Sun Microsystems, Inc. business.
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice 
+  * is preserved.
+  * ====================================================
+  */
+ 
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /*
+  * __kernel_rem_pio2(x,y,e0,nx,prec)
+  * double x[],y[]; int e0,nx,prec;
+  * 
+  * __kernel_rem_pio2 return the last three digits of N with 
+  *		y = x - N*pi/2
+  * so that |y| < pi/2.
+diff --git a/modules/fdlibm/src/k_sin.cpp b/modules/fdlibm/src/k_sin.cpp
+--- a/modules/fdlibm/src/k_sin.cpp
++++ b/modules/fdlibm/src/k_sin.cpp
+@@ -6,18 +6,18 @@
+  *
+  * Developed at SunSoft, a Sun Microsystems, Inc. business.
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice 
+  * is preserved.
+  * ====================================================
+  */
+ 
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /* __kernel_sin( x, y, iy)
+  * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+  * Input x is assumed to be bounded by ~pi/4 in magnitude.
+  * Input y is the tail of x.
+  * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). 
+  *
+  * Algorithm
+diff --git a/modules/fdlibm/src/k_tan.cpp b/modules/fdlibm/src/k_tan.cpp
+--- a/modules/fdlibm/src/k_tan.cpp
++++ b/modules/fdlibm/src/k_tan.cpp
+@@ -6,18 +6,18 @@
+  *
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice
+  * is preserved.
+  * ====================================================
+  */
+ 
+ /* INDENT OFF */
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /* __kernel_tan( x, y, k )
+  * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
+  * Input x is assumed to be bounded by ~pi/4 in magnitude.
+  * Input y is the tail of x.
+  * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
+  *
+  * Algorithm
 diff --git a/modules/fdlibm/src/s_asinh.cpp b/modules/fdlibm/src/s_asinh.cpp
 --- a/modules/fdlibm/src/s_asinh.cpp
 +++ b/modules/fdlibm/src/s_asinh.cpp
 @@ -5,18 +5,18 @@
   *
   * Developed at SunPro, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice
@@ -517,16 +637,40 @@ diff --git a/modules/fdlibm/src/s_copysi
  
  /*
   * copysign(double x, double y)
   * copysign(x,y) returns a value with the magnitude of x and
   * with the sign bit of y.
   */
  
  #include "math_private.h"
+diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
+--- a/modules/fdlibm/src/s_cos.cpp
++++ b/modules/fdlibm/src/s_cos.cpp
+@@ -5,18 +5,18 @@
+  *
+  * Developed at SunPro, a Sun Microsystems, Inc. business.
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice
+  * is preserved.
+  * ====================================================
+  */
+ 
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /* cos(x)
+  * Return cosine function of x.
+  *
+  * kernel function:
+  *	__kernel_sin		... sine function on [-pi/4,pi/4]
+  *	__kernel_cos		... cosine function on [-pi/4,pi/4]
+  *	__ieee754_rem_pio2	... argument reduction routine
 diff --git a/modules/fdlibm/src/s_expm1.cpp b/modules/fdlibm/src/s_expm1.cpp
 --- a/modules/fdlibm/src/s_expm1.cpp
 +++ b/modules/fdlibm/src/s_expm1.cpp
 @@ -5,18 +5,18 @@
   *
   * Developed at SunPro, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice
@@ -655,22 +799,22 @@ diff --git a/modules/fdlibm/src/s_nearby
   */
  
 -#include <sys/cdefs.h>
 -__FBSDID("$FreeBSD$");
 +//#include <sys/cdefs.h>
 +//__FBSDID("$FreeBSD$");
  
  #include <fenv.h>
+ 
  #include "math_private.h"
  
  /*
   * We save and restore the floating-point environment to avoid raising
   * an inexact exception.  We can get away with using fesetenv()
-  * instead of feclearexcept()/feupdateenv() to restore the environment
 diff --git a/modules/fdlibm/src/s_rint.cpp b/modules/fdlibm/src/s_rint.cpp
 --- a/modules/fdlibm/src/s_rint.cpp
 +++ b/modules/fdlibm/src/s_rint.cpp
 @@ -5,18 +5,18 @@
   *
   * Developed at SunPro, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice
@@ -709,40 +853,64 @@ diff --git a/modules/fdlibm/src/s_rintf.
  
  #include <float.h>
  #include <stdint.h>
  
  #include "math_private.h"
  
  static const float
  TWO23[2]={
-diff --git a/modules/fdlibm/src/s_scalbn.cpp b/modules/fdlibm/src/s_scalbn.cpp
---- a/modules/fdlibm/src/s_scalbn.cpp
-+++ b/modules/fdlibm/src/s_scalbn.cpp
+diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
+--- a/modules/fdlibm/src/s_sin.cpp
++++ b/modules/fdlibm/src/s_sin.cpp
 @@ -5,18 +5,18 @@
   *
   * Developed at SunPro, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice
   * is preserved.
   * ====================================================
   */
  
 -#include <sys/cdefs.h>
 -__FBSDID("$FreeBSD$");
 +//#include <sys/cdefs.h>
 +//__FBSDID("$FreeBSD$");
  
- /*
-  * scalbn (double x, int n)
-  * scalbn(x,n) returns x* 2**n  computed by  exponent
-  * manipulation rather than by actually performing an
-  * exponentiation or a multiplication.
+ /* sin(x)
+  * Return sine function of x.
+  *
+  * kernel function:
+  *	__kernel_sin		... sine function on [-pi/4,pi/4]
+  *	__kernel_cos		... cose function on [-pi/4,pi/4]
+  *	__ieee754_rem_pio2	... argument reduction routine
+diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
+--- a/modules/fdlibm/src/s_tan.cpp
++++ b/modules/fdlibm/src/s_tan.cpp
+@@ -5,18 +5,18 @@
+  *
+  * Developed at SunPro, a Sun Microsystems, Inc. business.
+  * Permission to use, copy, modify, and distribute this
+  * software is freely granted, provided that this notice
+  * is preserved.
+  * ====================================================
   */
  
+-#include <sys/cdefs.h>
+-__FBSDID("$FreeBSD$");
++//#include <sys/cdefs.h>
++//__FBSDID("$FreeBSD$");
+ 
+ /* tan(x)
+  * Return tangent function of x.
+  *
+  * kernel function:
+  *	__kernel_tan		... tangent function on [-pi/4,pi/4]
+  *	__ieee754_rem_pio2	... argument reduction routine
+  *
 diff --git a/modules/fdlibm/src/s_tanh.cpp b/modules/fdlibm/src/s_tanh.cpp
 --- a/modules/fdlibm/src/s_tanh.cpp
 +++ b/modules/fdlibm/src/s_tanh.cpp
 @@ -5,18 +5,18 @@
   *
   * Developed at SunPro, a Sun Microsystems, Inc. business.
   * Permission to use, copy, modify, and distribute this
   * software is freely granted, provided that this notice
@@ -805,201 +973,8 @@ diff --git a/modules/fdlibm/src/s_truncf
  
  /*
   * truncf(x)
   * Return x rounded toward 0 to integral value
   * Method:
   *	Bit twiddling.
   * Exception:
   *	Inexact flag raised if x not equal to truncf(x).
-diff --git a/modules/fdlibm/src/e_rem_pio2.cpp b/modules/fdlibm/src/e_rem_pio2.cpp
---- a/modules/fdlibm/src/e_rem_pio2.cpp
-+++ b/modules/fdlibm/src/e_rem_pio2.cpp
-@@ -8,18 +8,18 @@
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice 
-  * is preserved.
-  * ====================================================
-  *
-  * Optimized by Bruce D. Evans.
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* __ieee754_rem_pio2(x,y)
-  * 
-  * return the remainder of x rem pi/2 in y[0]+y[1] 
-  * use __kernel_rem_pio2()
-  */
- 
- #include <float.h>
-
-diff --git a/modules/fdlibm/src/k_cos.cpp b/modules/fdlibm/src/k_cos.cpp
---- a/modules/fdlibm/src/k_cos.cpp
-+++ b/modules/fdlibm/src/k_cos.cpp
-@@ -6,18 +6,18 @@
-  *
-  * Developed at SunSoft, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice 
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /*
-  * __kernel_cos( x,  y )
-  * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
-  * Input x is assumed to be bounded by ~pi/4 in magnitude.
-  * Input y is the tail of x. 
-  *
-  * Algorithm
-diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
---- a/modules/fdlibm/src/k_rem_pio2.cpp
-+++ b/modules/fdlibm/src/k_rem_pio2.cpp
-@@ -6,18 +6,18 @@
-  *
-  * Developed at SunSoft, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice 
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /*
-  * __kernel_rem_pio2(x,y,e0,nx,prec)
-  * double x[],y[]; int e0,nx,prec;
-  * 
-  * __kernel_rem_pio2 return the last three digits of N with 
-  *		y = x - N*pi/2
-  * so that |y| < pi/2.
-diff --git a/modules/fdlibm/src/k_sin.cpp b/modules/fdlibm/src/k_sin.cpp
---- a/modules/fdlibm/src/k_sin.cpp
-+++ b/modules/fdlibm/src/k_sin.cpp
-@@ -6,18 +6,18 @@
-  *
-  * Developed at SunSoft, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice 
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* __kernel_sin( x, y, iy)
-  * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
-  * Input x is assumed to be bounded by ~pi/4 in magnitude.
-  * Input y is the tail of x.
-  * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). 
-  *
-  * Algorithm
-diff --git a/modules/fdlibm/src/k_tan.cpp b/modules/fdlibm/src/k_tan.cpp
---- a/modules/fdlibm/src/k_tan.cpp
-+++ b/modules/fdlibm/src/k_tan.cpp
-@@ -6,18 +6,18 @@
-  *
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
- /* INDENT OFF */
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* __kernel_tan( x, y, k )
-  * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854
-  * Input x is assumed to be bounded by ~pi/4 in magnitude.
-  * Input y is the tail of x.
-  * Input k indicates whether tan (if k = 1) or -1/tan (if k = -1) is returned.
-  *
-  * Algorithm
-diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
---- a/modules/fdlibm/src/s_cos.cpp
-+++ b/modules/fdlibm/src/s_cos.cpp
-@@ -5,18 +5,18 @@
-  *
-  * Developed at SunPro, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* cos(x)
-  * Return cosine function of x.
-  *
-  * kernel function:
-  *	__kernel_sin		... sine function on [-pi/4,pi/4]
-  *	__kernel_cos		... cosine function on [-pi/4,pi/4]
-  *	__ieee754_rem_pio2	... argument reduction routine
-diff --git a/modules/fdlibm/src/s_sin.cpp b/modules/fdlibm/src/s_sin.cpp
---- a/modules/fdlibm/src/s_sin.cpp
-+++ b/modules/fdlibm/src/s_sin.cpp
-@@ -5,18 +5,18 @@
-  *
-  * Developed at SunPro, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* sin(x)
-  * Return sine function of x.
-  *
-  * kernel function:
-  *	__kernel_sin		... sine function on [-pi/4,pi/4]
-  *	__kernel_cos		... cose function on [-pi/4,pi/4]
-  *	__ieee754_rem_pio2	... argument reduction routine
-diff --git a/modules/fdlibm/src/s_tan.cpp b/modules/fdlibm/src/s_tan.cpp
---- a/modules/fdlibm/src/s_tan.cpp
-+++ b/modules/fdlibm/src/s_tan.cpp
-@@ -5,18 +5,18 @@
-  *
-  * Developed at SunPro, a Sun Microsystems, Inc. business.
-  * Permission to use, copy, modify, and distribute this
-  * software is freely granted, provided that this notice
-  * is preserved.
-  * ====================================================
-  */
- 
--#include <sys/cdefs.h>
--__FBSDID("$FreeBSD$");
-+//#include <sys/cdefs.h>
-+//__FBSDID("$FreeBSD$");
- 
- /* tan(x)
-  * Return tangent function of x.
-  *
-  * kernel function:
-  *	__kernel_tan		... tangent function on [-pi/4,pi/4]
-  *	__ieee754_rem_pio2	... argument reduction routine
-  *
\ No newline at end of file
--- a/modules/fdlibm/patches/10_remove_unused_function_from_k_exp_cpp.patch
+++ b/modules/fdlibm/patches/10_remove_unused_function_from_k_exp_cpp.patch
@@ -15,41 +15,42 @@ diff --git a/modules/fdlibm/src/k_exp.cp
   #include "math_private.h"
  
  static const uint32_t k = 1799;		/* constant for reduction */
  static const double kln2 =  1246.97177782734161156;	/* k * ln2 */
  
  /*
   * Compute exp(x), scaled to avoid spurious overflow.  An exponent is
   * returned separately in 'expt'.
-@@ -78,32 +76,8 @@ double
+@@ -78,33 +76,8 @@ __ldexp_exp(double x, int expt)
  	double exp_x, scale;
  	int ex_expt;
  
  	exp_x = __frexp_exp(x, &ex_expt);
  	expt += ex_expt;
  	INSERT_WORDS(scale, (0x3ff + expt) << 20, 0);
  	return (exp_x * scale);
  }
 -
 -double complex
 -__ldexp_cexp(double complex z, int expt)
 -{
--	double x, y, exp_x, scale1, scale2;
+-	double c, exp_x, s, scale1, scale2, x, y;
 -	int ex_expt, half_expt;
 -
 -	x = creal(z);
 -	y = cimag(z);
 -	exp_x = __frexp_exp(x, &ex_expt);
 -	expt += ex_expt;
 -
 -	/*
 -	 * Arrange so that scale1 * scale2 == 2**expt.  We use this to
 -	 * compensate for scalbn being horrendously slow.
 -	 */
 -	half_expt = expt / 2;
 -	INSERT_WORDS(scale1, (0x3ff + half_expt) << 20, 0);
 -	half_expt = expt - half_expt;
 -	INSERT_WORDS(scale2, (0x3ff + half_expt) << 20, 0);
 -
--	return (CMPLX(cos(y) * exp_x * scale1 * scale2,
--	    sin(y) * exp_x * scale1 * scale2));
+-	sincos(y, &s, &c);
+-	return (CMPLX(c * exp_x * scale1 * scale2,
+-	    s * exp_x * scale1 * scale2));
 -}
--- a/modules/fdlibm/patches/11_include_cfloat_to_use_flt_eval_method.patch
+++ b/modules/fdlibm/patches/11_include_cfloat_to_use_flt_eval_method.patch
@@ -9,13 +9,13 @@ diff --git a/modules/fdlibm/src/math_pri
  
  #ifndef _MATH_PRIVATE_H_
  #define	_MATH_PRIVATE_H_
  
 +#include <cfloat>
  #include <stdint.h>
  #include <sys/types.h>
  
+ #include "mozilla/EndianUtils.h"
+ 
  #include "fdlibm.h"
  
- #include "mozilla/EndianUtils.h"
- 
  /*
--- a/modules/fdlibm/patches/13_define_strict_assign_even_if_flt_eval_method_is_not_defined.patch
+++ b/modules/fdlibm/patches/13_define_strict_assign_even_if_flt_eval_method_is_not_defined.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -328,16 +328,27 @@ do {								\
+@@ -323,16 +323,27 @@ do {								\
  	if (sizeof(type) >= sizeof(long double))	\
  		(lval) = (rval);		\
  	else {					\
  		__lval = (rval);		\
  		(lval) = __lval;		\
  	}					\
  } while (0)
  #endif
--- a/modules/fdlibm/patches/14_do_not_use_hexadecimal_floating_point_number.patch
+++ b/modules/fdlibm/patches/14_do_not_use_hexadecimal_floating_point_number.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/e_exp.cpp b/modules/fdlibm/src/e_exp.cpp
 --- a/modules/fdlibm/src/e_exp.cpp
 +++ b/modules/fdlibm/src/e_exp.cpp
-@@ -146,14 +146,17 @@ double
+@@ -146,14 +146,17 @@ __ieee754_exp(double x)	/* default IEEE double exp */
  	if(k >= -1021)
  	    INSERT_WORDS(twopk,((u_int32_t)(0x3ff+k))<<20, 0);
  	else
  	    INSERT_WORDS(twopk,((u_int32_t)(0x3ff+(k+1000)))<<20, 0);
  	c  = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
  	if(k==0) 	return one-((x*c)/(c-2.0)-x); 
  	else 		y = one-((lo-(x*c)/(2.0-c))-hi);
  	if(k >= -1021) {
--- a/modules/fdlibm/patches/15_remove_unused_rintl_function_from_s_nearbyint_cpp.patch
+++ b/modules/fdlibm/patches/15_remove_unused_rintl_function_from_s_nearbyint_cpp.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/s_nearbyint.cpp b/modules/fdlibm/src/s_nearbyint.cpp
 --- a/modules/fdlibm/src/s_nearbyint.cpp
 +++ b/modules/fdlibm/src/s_nearbyint.cpp
-@@ -53,9 +53,8 @@ fn(type x)			\
+@@ -54,9 +54,8 @@ fn(type x)			\
  	fegetenv(&env);		\
  	ret = rint(x);		\
  	fesetenv(&env);		\
  	return (ret);		\
  }
  
  DECL(double, nearbyint, rint)
  DECL(float, nearbyintf, rintf)
--- a/modules/fdlibm/patches/16_use_safer_strict_assign_on_visual_studio.patch
+++ b/modules/fdlibm/patches/16_use_safer_strict_assign_on_visual_studio.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -314,17 +314,17 @@ do {								\
+@@ -309,17 +309,17 @@ do {								\
  /* The above works on non-i386 too, but we use this to check v. */
  #define	LD80C(m, ex, v)	{ .e = (v), }
  #endif
  
  #ifdef FLT_EVAL_METHOD
  /*
   * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
   */
--- a/modules/fdlibm/patches/17_exp_exact_result_for_positive_one.patch
+++ b/modules/fdlibm/patches/17_exp_exact_result_for_positive_one.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/e_exp.cpp b/modules/fdlibm/src/e_exp.cpp
 --- a/modules/fdlibm/src/e_exp.cpp
 +++ b/modules/fdlibm/src/e_exp.cpp
-@@ -91,16 +91,18 @@ ln2LO[2]   ={ 1.90821492927058770002e-10
+@@ -91,16 +91,18 @@ ln2LO[2]   ={ 1.90821492927058770002e-10,  /* 0x3dea39ef, 0x35793c76 */
  	     -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */
  invln2 =  1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
  P1   =  1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
  P2   = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
  P3   =  6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
  P4   = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
  P5   =  4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
  
@@ -15,17 +15,17 @@ diff --git a/modules/fdlibm/src/e_exp.cp
  static volatile double
  huge	= 1.0e+300,
  twom1000= 9.33263618503218878990e-302;     /* 2**-1000=0x01700000,0*/
  
  double
  __ieee754_exp(double x)	/* default IEEE double exp */
  {
  	double y,hi=0.0,lo=0.0,c,t,twopk;
-@@ -122,16 +124,17 @@ double
+@@ -122,16 +124,17 @@ __ieee754_exp(double x)	/* default IEEE double exp */
  	    }
  	    if(x > o_threshold) return huge*huge; /* overflow */
  	    if(x < u_threshold) return twom1000*twom1000; /* underflow */
  	}
  
      /* argument reduction */
  	if(hx > 0x3fd62e42) {		/* if  |x| > 0.5 ln2 */ 
  	    if(hx < 0x3FF0A2B2) {	/* and |x| < 1.5 ln2 */
--- a/modules/fdlibm/patches/18_use_stdlib_sqrt.patch
+++ b/modules/fdlibm/patches/18_use_stdlib_sqrt.patch
@@ -14,17 +14,17 @@ diff --git a/modules/fdlibm/src/e_acos.c
  #include <float.h>
  
  #include "math_private.h"
  
  static const double
  one=  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
  pi =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
  pio2_hi =  1.57079632679489655800e+00; /* 0x3FF921FB, 0x54442D18 */
-@@ -82,23 +83,23 @@ double
+@@ -82,23 +83,23 @@ __ieee754_acos(double x)
  	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
  	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
  	    r = p/q;
  	    return pio2_hi - (x - (pio2_lo-x*r));
  	} else  if (hx<0) {		/* x < -0.5 */
  	    z = (one+x)*0.5;
  	    p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
  	    q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
@@ -61,17 +61,17 @@ diff --git a/modules/fdlibm/src/e_acosh.
  #include <float.h>
  
  #include "math_private.h"
  
  static const double
  one	= 1.0,
  ln2	= 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
  
-@@ -50,14 +51,14 @@ double
+@@ -50,14 +51,14 @@ __ieee754_acosh(double x)
  	    if(hx >=0x7ff00000) {	/* x is inf of NaN */
  	        return x+x;
  	    } else 
  		return __ieee754_log(x)+ln2;	/* acosh(huge)=log(2x) */
  	} else if(((hx-0x3ff00000)|lx)==0) {
  	    return 0.0;			/* acosh(1) = 0 */
  	} else if (hx > 0x40000000) {	/* 2**28 > x > 2 */
  	    t=x*x;
@@ -99,17 +99,17 @@ diff --git a/modules/fdlibm/src/e_asin.c
  #include <float.h>
  
  #include "math_private.h"
  
  static const double
  one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
  huge =  1.000e+300,
  pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
-@@ -90,17 +91,17 @@ double
+@@ -90,17 +91,17 @@ __ieee754_asin(double x)
  	    w = p/q;
  	    return x+x*w;
  	}
  	/* 1> |x|>= 0.5 */
  	w = one-fabs(x);
  	t = w*0.5;
  	p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
  	q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
@@ -139,17 +139,17 @@ diff --git a/modules/fdlibm/src/e_hypot.
  #include <float.h>
  
  #include "math_private.h"
  
  double
  __ieee754_hypot(double x, double y)
  {
  	double a,b,t1,t2,y1,y2,w;
-@@ -100,26 +101,26 @@ double
+@@ -100,25 +101,25 @@ __ieee754_hypot(double x, double y)
  	    }
  	}
      /* medium size a and b */
  	w = a-b;
  	if (w>b) {
  	    t1 = 0;
  	    SET_HIGH_WORD(t1,ha);
  	    t2 = a-t1;
@@ -162,45 +162,43 @@ diff --git a/modules/fdlibm/src/e_hypot.
  	    y2 = b - y1;
  	    t1 = 0;
  	    SET_HIGH_WORD(t1,ha+0x00100000);
  	    t2 = a - t1;
 -	    w  = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
 +	    w  = std::sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
  	}
  	if(k!=0) {
- 	    u_int32_t high;
- 	    t1 = 1.0;
- 	    GET_HIGH_WORD(high,t1);
- 	    SET_HIGH_WORD(t1,high+(k<<20));
+ 	    t1 = 0.0;
+ 	    SET_HIGH_WORD(t1,(1023+k)<<20);
  	    return t1*w;
  	} else return w;
+ }
 diff --git a/modules/fdlibm/src/e_pow.cpp b/modules/fdlibm/src/e_pow.cpp
 --- a/modules/fdlibm/src/e_pow.cpp
 +++ b/modules/fdlibm/src/e_pow.cpp
-@@ -52,16 +52,18 @@
+@@ -52,16 +52,17 @@
   *
   * Constants :
   * The hexadecimal values are the intended ones for the following
   * constants. The decimal values may be used, provided that the
   * compiler will convert from decimal to binary accurately enough
   * to produce the hexadecimal values shown.
   */
  
 +#include <cmath>
-+
  #include <float.h>
  #include "math_private.h"
  
  static const double
  bp[] = {1.0, 1.5,},
  dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
  dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
  zero    =  0.0,
-@@ -151,17 +153,17 @@ double
+@@ -151,17 +152,17 @@ __ieee754_pow(double x, double y)
  		    return (hy<0)?-y: zero;
  	    }
  	    if(iy==0x3ff00000) {	/* y is  +-1 */
  		if(hy<0) return one/x; else return x;
  	    }
  	    if(hy==0x40000000) return x*x; /* y is  2 */
  	    if(hy==0x3fe00000) {	/* y is  0.5 */
  		if(hx>=0)	/* x >= +0 */
--- a/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch
+++ b/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -617,95 +617,32 @@ rnint(double x)
+@@ -612,46 +612,16 @@ rnint(__double_t x)
  	 * magic number would need to be variable.  Assuming that the
  	 * rounding precision is always the default is too fragile.  This
  	 * and many other complications will move when the default is
  	 * changed to FP_PE.
  	 */
  	return ((double)(x + 0x1.8p52) - 0x1.8p52);
  }
  
@@ -40,60 +40,11 @@ diff --git a/modules/fdlibm/src/math_pri
 -}
 -#endif /* LDBL_MANT_DIG */
 -
  /*
   * irint() and i64rint() give the same result as casting to their integer
   * return type provided their arg is a floating point integer.  They can
   * sometimes be more efficient because no rounding is required.
   */
- #if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+ #if defined(amd64) || defined(__i386__)
  #define	irint(x)						\
      (sizeof(x) == sizeof(float) &&				\
-     sizeof(__float_t) == sizeof(long double) ? irintf(x) :	\
-     sizeof(x) == sizeof(double) &&				\
-     sizeof(__double_t) == sizeof(long double) ? irintd(x) :	\
-     sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
- #else
- #define	irint(x)	((int)(x))
- #endif
- 
--#define	i64rint(x)	((int64_t)(x))	/* only needed for ld128 so not opt. */
--
--#if defined(__i386__) && defined(__GNUCLIKE_ASM)
--static __inline int
--irintf(float x)
--{
--	int n;
--
--	__asm("fistl %0" : "=m" (n) : "t" (x));
--	return (n);
--}
--
--static __inline int
--irintd(double x)
--{
--	int n;
--
--	__asm("fistl %0" : "=m" (n) : "t" (x));
--	return (n);
--}
--#endif
--
--#if (defined(__amd64__) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
--static __inline int
--irintl(long double x)
--{
--	int n;
--
--	__asm("fistl %0" : "=m" (n) : "t" (x));
--	return (n);
--}
--#endif
--
- #ifdef DEBUG
- #if defined(__amd64__) || defined(__i386__)
- #define	breakpoint()	asm("int $3")
- #else
- #include <signal.h>
- 
- #define	breakpoint()	raise(SIGTRAP)
- #endif
--- a/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch
+++ b/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch
@@ -1,28 +1,28 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -21,16 +21,24 @@
+@@ -20,16 +20,24 @@
+ #include <cfloat>
  #include <stdint.h>
  #include <sys/types.h>
  
+ #include "mozilla/EndianUtils.h"
+ 
  #include "fdlibm.h"
  
- #include "mozilla/EndianUtils.h"
- 
- /*
++/*
 + * Emulate FreeBSD internal double types.
 + * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
 + */
 +
 +typedef double      __double_t;
 +typedef __double_t  double_t;
 +
-+/*
+ /*
   * The original fdlibm code used statements like:
   *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
   *	ix0 = *(n0+(int*)&x);			* high word of x *
   *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
   * to dig two 32 bit words out of the 64 bit IEEE floating point
   * value.  That is non-ANSI, and, moreover, the gcc instruction
   * scheduler gets it wrong.  We instead use the following macros.
-  * Unlike the original code, we determine the endianness at compile
--- a/modules/fdlibm/patches/21_rem_pio_fixups.patch
+++ b/modules/fdlibm/patches/21_rem_pio_fixups.patch
@@ -1,12 +1,12 @@
 diff --git a/modules/fdlibm/src/e_rem_pio2.cpp b/modules/fdlibm/src/e_rem_pio2.cpp
 --- a/modules/fdlibm/src/e_rem_pio2.cpp
 +++ b/modules/fdlibm/src/e_rem_pio2.cpp
-@@ -43,17 +43,17 @@ invpio2 =  6.36619772367581382433e-01, /
+@@ -43,17 +43,17 @@ invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
  pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
  pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
  pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
  pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
  pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
  pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
  
  #ifdef INLINE_REM_PIO2
@@ -15,16 +15,39 @@ diff --git a/modules/fdlibm/src/e_rem_pi
  #endif
  int
  __ieee754_rem_pio2(double x, double *y)
  {
  	double z,w,t,r,fn;
  	double tx[3],ty[2];
  	int32_t e0,i,j,nx,n,ix,hx;
  	u_int32_t low;
+diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
+--- a/modules/fdlibm/src/k_rem_pio2.cpp
++++ b/modules/fdlibm/src/k_rem_pio2.cpp
+@@ -305,17 +305,18 @@ __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec)
+ 	q0 =  e0-24*(jv+1);
+ 
+     /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+ 	j = jv-jx; m = jx+jk;
+ 	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
+ 
+     /* compute q[0],q[1],...q[jk] */
+ 	for (i=0;i<=jk;i++) {
+-	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
++	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
++	    q[i] = fw;
+ 	}
+ 
+ 	jz = jk;
+ recompute:
+     /* distill q[] into iq[] reversingly */
+ 	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ 	    fw    =  (double)((int32_t)(twon24* z));
+ 	    iq[i] =  (int32_t)(z-two24*fw);
 diff --git a/modules/fdlibm/src/s_cos.cpp b/modules/fdlibm/src/s_cos.cpp
 --- a/modules/fdlibm/src/s_cos.cpp
 +++ b/modules/fdlibm/src/s_cos.cpp
 @@ -43,17 +43,17 @@
   * Accuracy:
   *	TRIG(x) returns trig(x) nearly rounded
   */
  
@@ -81,31 +104,8 @@ diff --git a/modules/fdlibm/src/s_tan.cp
  
  double
  tan(double x)
  {
  	double y[2],z=0.0;
  	int32_t n, ix;
  
      /* High word of x. */
-diff --git a/modules/fdlibm/src/k_rem_pio2.cpp b/modules/fdlibm/src/k_rem_pio2.cpp
---- a/modules/fdlibm/src/k_rem_pio2.cpp
-+++ b/modules/fdlibm/src/k_rem_pio2.cpp
-@@ -305,17 +305,18 @@ __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec)
- 	q0 =  e0-24*(jv+1);
- 
-     /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
- 	j = jv-jx; m = jx+jk;
- 	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
- 
-     /* compute q[0],q[1],...q[jk] */
- 	for (i=0;i<=jk;i++) {
--	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
-+	    for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
-+	    q[i] = fw;
- 	}
- 
- 	jz = jk;
- recompute:
-     /* distill q[] into iq[] reversingly */
- 	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
- 	    fw    =  (double)((int32_t)(twon24* z));
- 	    iq[i] =  (int32_t)(z-two24*fw);
copy from modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch
copy to modules/fdlibm/patches/22_add_float_types.patch
--- a/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch
+++ b/modules/fdlibm/patches/22_add_float_types.patch
@@ -1,28 +1,22 @@
 diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
 --- a/modules/fdlibm/src/math_private.h
 +++ b/modules/fdlibm/src/math_private.h
-@@ -21,16 +21,24 @@
- #include <stdint.h>
- #include <sys/types.h>
- 
- #include "fdlibm.h"
- 
- #include "mozilla/EndianUtils.h"
+@@ -27,16 +27,18 @@
  
  /*
-+ * Emulate FreeBSD internal double types.
-+ * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
-+ */
-+
-+typedef double      __double_t;
-+typedef __double_t  double_t;
-+
-+/*
+  * Emulate FreeBSD internal double types.
+  * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
+  */
+ 
+ typedef double      __double_t;
+ typedef __double_t  double_t;
++typedef float       __float_t;
++typedef __float_t   float_t;
+ 
+ /*
   * The original fdlibm code used statements like:
   *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
   *	ix0 = *(n0+(int*)&x);			* high word of x *
   *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
   * to dig two 32 bit words out of the 64 bit IEEE floating point
   * value.  That is non-ANSI, and, moreover, the gcc instruction
-  * scheduler gets it wrong.  We instead use the following macros.
-  * Unlike the original code, we determine the endianness at compile
deleted file mode 100644
--- a/modules/fdlibm/patches/22_build_and_export_sin_cos_and_tan.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-diff --git a/modules/fdlibm/src/fdlibm.h b/modules/fdlibm/src/fdlibm.h
---- a/modules/fdlibm/src/fdlibm.h
-+++ b/modules/fdlibm/src/fdlibm.h
-@@ -19,16 +19,20 @@
- 
- namespace fdlibm {
- 
- double	acos(double);
- double	asin(double);
- double	atan(double);
- double	atan2(double, double);
- 
-+double	cos(double);
-+double	sin(double);
-+double	tan(double);
-+
- double	cosh(double);
- double	sinh(double);
- double	tanh(double);
- 
- double	exp(double);
- double	log(double);
- double	log10(double);
- 
-diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
---- a/modules/fdlibm/src/math_private.h
-+++ b/modules/fdlibm/src/math_private.h
-@@ -832,16 +832,19 @@ rnint(double_t x)
- #define	__ieee754_ynf	ynf
- #define	__ieee754_remainderf remainderf
- #define	__ieee754_scalbf scalbf
- 
- #define acos fdlibm::acos
- #define asin fdlibm::asin
- #define atan fdlibm::atan
- #define atan2 fdlibm::atan2
-+#define cos fdlibm::cos
-+#define sin fdlibm::sin
-+#define tan fdlibm::tan
- #define cosh fdlibm::cosh
- #define sinh fdlibm::sinh
- #define tanh fdlibm::tanh
- #define exp fdlibm::exp
- #define log fdlibm::log
- #define log10 fdlibm::log10
- #define pow fdlibm::pow
- #define ceil fdlibm::ceil
--- a/modules/fdlibm/src/e_hypot.cpp
+++ b/modules/fdlibm/src/e_hypot.cpp
@@ -113,15 +113,13 @@ double
 	    SET_HIGH_WORD(y1,hb);
 	    y2 = b - y1;
 	    t1 = 0;
 	    SET_HIGH_WORD(t1,ha+0x00100000);
 	    t2 = a - t1;
 	    w  = std::sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
 	}
 	if(k!=0) {
-	    u_int32_t high;
-	    t1 = 1.0;
-	    GET_HIGH_WORD(high,t1);
-	    SET_HIGH_WORD(t1,high+(k<<20));
+	    t1 = 0.0;
+	    SET_HIGH_WORD(t1,(1023+k)<<20);
 	    return t1*w;
 	} else return w;
 }
--- a/modules/fdlibm/src/e_pow.cpp
+++ b/modules/fdlibm/src/e_pow.cpp
@@ -53,17 +53,16 @@
  * Constants :
  * The hexadecimal values are the intended ones for the following
  * constants. The decimal values may be used, provided that the
  * compiler will convert from decimal to binary accurately enough
  * to produce the hexadecimal values shown.
  */
 
 #include <cmath>
-
 #include <float.h>
 #include "math_private.h"
 
 static const double
 bp[] = {1.0, 1.5,},
 dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
 dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
 zero    =  0.0,
--- a/modules/fdlibm/src/fdlibm.h
+++ b/modules/fdlibm/src/fdlibm.h
@@ -18,51 +18,49 @@
 #define mozilla_imported_fdlibm_h
 
 namespace fdlibm {
 
 double	acos(double);
 double	asin(double);
 double	atan(double);
 double	atan2(double, double);
-
 double	cos(double);
 double	sin(double);
 double	tan(double);
 
 double	cosh(double);
 double	sinh(double);
 double	tanh(double);
 
 double	exp(double);
 double	log(double);
 double	log10(double);
 
 double	pow(double, double);
+
+double	ceil(double);
 double	fabs(double);
-
 double	floor(double);
-double	trunc(double);
-double	ceil(double);
 
 double	acosh(double);
 double	asinh(double);
 double	atanh(double);
 double	cbrt(double);
 double	expm1(double);
 double	hypot(double, double);
 double	log1p(double);
 double	log2(double);
 double	rint(double);
 double	copysign(double, double);
 double	nearbyint(double);
 double	scalbn(double, int);
+double	trunc(double);
 
 float	ceilf(float);
 float	floorf(float);
-
 float	nearbyintf(float);
 float	rintf(float);
 float	truncf(float);
 
 } /* namespace fdlibm */
 
 #endif /* mozilla_imported_fdlibm_h */
--- a/modules/fdlibm/src/math_private.h
+++ b/modules/fdlibm/src/math_private.h
@@ -16,27 +16,29 @@
 
 #ifndef _MATH_PRIVATE_H_
 #define	_MATH_PRIVATE_H_
 
 #include <cfloat>
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "fdlibm.h"
+#include "mozilla/EndianUtils.h"
 
-#include "mozilla/EndianUtils.h"
+#include "fdlibm.h"
 
 /*
  * Emulate FreeBSD internal double types.
  * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
  */
 
 typedef double      __double_t;
 typedef __double_t  double_t;
+typedef float       __float_t;
+typedef __float_t   float_t;
 
 /*
  * The original fdlibm code used statements like:
  *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
  *	ix0 = *(n0+(int*)&x);			* high word of x *
  *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
  * to dig two 32 bit words out of the 64 bit IEEE floating point
  * value.  That is non-ANSI, and, moreover, the gcc instruction
@@ -89,21 +91,16 @@ typedef union
   struct {
     u_int64_t lsw;
     u_int64_t msw;
   } parts64;
 } ieee_quad_shape_type;
 
 #endif
 
-/*
- * A union which permits us to convert between a double and two 32 bit
- * ints.
- */
-
 #if MOZ_BIG_ENDIAN()
 
 typedef union
 {
   double value;
   struct
   {
     u_int32_t msw;
@@ -476,17 +473,17 @@ do {								\
  * That is usually enough, and adding c (which by normalization is about
  * 2**53 times smaller than a) cannot change b significantly.  However,
  * cancellation of 'a' with c in normalization of (a, c) may reduce 'a'
  * significantly relative to b.  The caller must ensure that significant
  * cancellation doesn't occur, either by having c of the same sign as 'a',
  * or by having |c| a few percent smaller than |a|.  Pre-normalization of
  * (a, b) may help.
  *
- * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
+ * This is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
  * exercise 19).  We gain considerable efficiency by requiring the terms to
  * be sufficiently normalized and sufficiently increasing.
  */
 #define	_3sumF(a, b, c) do {	\
 	__typeof(a) __tmp;	\
 				\
 	__tmp = (c);		\
 	_2sumF(__tmp, (a));	\
@@ -630,27 +627,60 @@ rnint(__double_t x)
 	return ((double)(x + 0x1.8p52) - 0x1.8p52);
 }
 
 /*
  * irint() and i64rint() give the same result as casting to their integer
  * return type provided their arg is a floating point integer.  They can
  * sometimes be more efficient because no rounding is required.
  */
-#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+#if defined(amd64) || defined(__i386__)
 #define	irint(x)						\
     (sizeof(x) == sizeof(float) &&				\
     sizeof(__float_t) == sizeof(long double) ? irintf(x) :	\
     sizeof(x) == sizeof(double) &&				\
     sizeof(__double_t) == sizeof(long double) ? irintd(x) :	\
     sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
 #else
 #define	irint(x)	((int)(x))
 #endif
 
+#define	i64rint(x)	((int64_t)(x))	/* only needed for ld128 so not opt. */
+
+#if defined(__i386__)
+static __inline int
+irintf(float x)
+{
+	int n;
+
+	__asm("fistl %0" : "=m" (n) : "t" (x));
+	return (n);
+}
+
+static __inline int
+irintd(double x)
+{
+	int n;
+
+	__asm("fistl %0" : "=m" (n) : "t" (x));
+	return (n);
+}
+#endif
+
+#if defined(__amd64__) || defined(__i386__)
+static __inline int
+irintl(long double x)
+{
+	int n;
+
+	__asm("fistl %0" : "=m" (n) : "t" (x));
+	return (n);
+}
+#endif
+
 #ifdef DEBUG
 #if defined(__amd64__) || defined(__i386__)
 #define	breakpoint()	asm("int $3")
 #else
 #include <signal.h>
 
 #define	breakpoint()	raise(SIGTRAP)
 #endif
--- a/modules/fdlibm/src/s_cbrt.cpp
+++ b/modules/fdlibm/src/s_cbrt.cpp
@@ -102,12 +102,12 @@ cbrt(double x)
 	u.bits=(u.bits+0x80000000)&0xffffffffc0000000ULL;
 	t=u.value;
 
     /* one step Newton iteration to 53 bits with error < 0.667 ulps */
 	s=t*t;				/* t*t is exact */
 	r=x/s;				/* error <= 0.5 ulps; |r| < |t| */
 	w=t+t;				/* t+t is exact */
 	r=(r-t)/(w+r);			/* r-t is exact; w+r ~= 3*t */
-	t=t+t*r;			/* error <= 0.5 + 0.5/3 + epsilon */
+	t=t+t*r;			/* error <= (0.5 + 0.5/3) * ulp */
 
 	return(t);
 }
--- a/modules/fdlibm/src/s_nearbyint.cpp
+++ b/modules/fdlibm/src/s_nearbyint.cpp
@@ -25,16 +25,17 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 //#include <sys/cdefs.h>
 //__FBSDID("$FreeBSD$");
 
 #include <fenv.h>
+
 #include "math_private.h"
 
 /*
  * We save and restore the floating-point environment to avoid raising
  * an inexact exception.  We can get away with using fesetenv()
  * instead of feclearexcept()/feupdateenv() to restore the environment
  * because the only exception defined for rint() is overflow, and
  * rounding can't overflow as long as emax >= p.
--- a/modules/fdlibm/src/s_scalbn.cpp
+++ b/modules/fdlibm/src/s_scalbn.cpp
@@ -1,60 +1,43 @@
-/* @(#)s_scalbn.c 5.1 93/09/24 */
 /*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005-2020 Rich Felker, et al.
  *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
+ * SPDX-License-Identifier: MIT
+ *
+ * Please see https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+ * for all contributors to musl.
  */
-
-//#include <sys/cdefs.h>
-//__FBSDID("$FreeBSD$");
-
-/*
- * scalbn (double x, int n)
- * scalbn(x,n) returns x* 2**n  computed by  exponent
- * manipulation rather than by actually performing an
- * exponentiation or a multiplication.
- */
-
 #include <float.h>
+#include <stdint.h>
 
 #include "math_private.h"
 
-static const double
-two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
-twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
-huge   = 1.0e+300,
-tiny   = 1.0e-300;
-
-double
-scalbn (double x, int n)
+double scalbn(double x, int n)
 {
-	int32_t k,hx,lx;
-	EXTRACT_WORDS(hx,lx,x);
-        k = (hx&0x7ff00000)>>20;		/* extract exponent */
-        if (k==0) {				/* 0 or subnormal x */
-            if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
-	    x *= two54;
-	    GET_HIGH_WORD(hx,x);
-	    k = ((hx&0x7ff00000)>>20) - 54;
-            if (n< -50000) return tiny*x; 	/*underflow*/
-	    }
-        if (k==0x7ff) return x+x;		/* NaN or Inf */
-        k = k+n;
-        if (k >  0x7fe) return huge*copysign(huge,x); /* overflow  */
-        if (k > 0) 				/* normal result */
-	    {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
-        if (k <= -54) {
-            if (n > 50000) 	/* in case integer overflow in n+k */
-		return huge*copysign(huge,x);	/*overflow*/
-	    else
-		return tiny*copysign(tiny,x); 	/*underflow*/
+	union {double f; uint64_t i;} u;
+	double_t y = x;
+
+	if (n > 1023) {
+		y *= 0x1p1023;
+		n -= 1023;
+		if (n > 1023) {
+			y *= 0x1p1023;
+			n -= 1023;
+			if (n > 1023)
+				n = 1023;
+		}
+	} else if (n < -1022) {
+		/* make sure final n < -53 to avoid double
+		   rounding in the subnormal range */
+		y *= 0x1p-1022 * 0x1p53;
+		n += 1022 - 53;
+		if (n < -1022) {
+			y *= 0x1p-1022 * 0x1p53;
+			n += 1022 - 53;
+			if (n < -1022)
+				n = -1022;
+		}
 	}
-        k += 54;				/* subnormal result */
-	SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
-        return x*twom54;
+	u.i = (uint64_t)(0x3ff+n)<<52;
+	x = y * u.f;
+	return x;
 }
--- a/modules/fdlibm/update.sh
+++ b/modules/fdlibm/update.sh
@@ -4,21 +4,21 @@
 # Run this within the /modules/fdlibm directory of the source tree.
 
 set -e
 
 API_BASE_URL=https://api.github.com/repos/freebsd/freebsd-src
 
 get_commit() {
     curl -s "${API_BASE_URL}/commits?path=lib/msun/src&per_page=1" \
-        | python -c 'import json, sys; print(json.loads(sys.stdin.read())[0]["sha"])'
+        | python3 -c 'import json, sys; print(json.loads(sys.stdin.read())[0]["sha"])'
 }
 get_date() {
     curl -s "${API_BASE_URL}/commits/${COMMIT}" \
-        | python -c 'import json, sys; print(json.loads(sys.stdin.read())["commit"]["committer"]["date"])'
+        | python3 -c 'import json, sys; print(json.loads(sys.stdin.read())["commit"]["committer"]["date"])'
 }
 
 mv ./src/moz.build ./src_moz.build
 rm -rf src
 if [ "$#" -eq 0 ]; then
     COMMIT=$(get_commit)
 else
     COMMIT="$1"
--- a/testing/web-platform/meta/css/CSS2/stacking-context/opacity-affects-block-in-inline.html.ini
+++ b/testing/web-platform/meta/css/CSS2/stacking-context/opacity-affects-block-in-inline.html.ini
@@ -1,4 +1,4 @@
 [opacity-affects-block-in-inline.html]
   expected:
     if (os == "win") and (processor == "x86_64") and not swgl: FAIL
-    if os == "mac": FAIL
+    if (os == "mac") and (not nightly_build or not swgl): FAIL
--- a/testing/web-platform/meta/css/css-masking/mask-image/mask-opacity-1c.html.ini
+++ b/testing/web-platform/meta/css/css-masking/mask-image/mask-opacity-1c.html.ini
@@ -1,4 +1,4 @@
 [mask-opacity-1c.html]
   expected:
     if (os == "win") and (processor == "x86_64") and not swgl: FAIL
-    if os == "mac": FAIL
+    if (os == "mac") and (not nightly_build or not swgl): FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-bottom-002.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-bottom-002.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-bottom-002.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-bottom-003.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-bottom-003.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-bottom-003.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-left-002.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-left-002.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-left-002.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-left-003.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-left-003.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-left-003.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-right-002.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-right-002.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-right-002.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-right-003.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-right-003.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-right-003.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-002.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-002.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-top-002.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-003.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-003.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-top-003.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-and-bottom-003.html.ini
+++ b/testing/web-platform/meta/css/css-position/sticky/position-sticky-top-and-bottom-003.html.ini
@@ -1,3 +1,5 @@
 [position-sticky-top-and-bottom-003.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-3
   expected:
     if os == "win": FAIL
--- a/testing/web-platform/meta/css/printing/input-file-print.html.ini
+++ b/testing/web-platform/meta/css/printing/input-file-print.html.ini
@@ -1,3 +1,3 @@
 [input-file-print.html]
   fuzzy:
-    maxDifference=0-1;totalPixels=0-2
+    maxDifference=0-22;totalPixels=0-518
--- a/testing/web-platform/meta/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html.ini
+++ b/testing/web-platform/meta/web-animations/animation-model/keyframe-effects/transform-and-opacity-on-inline-001.html.ini
@@ -1,3 +1,5 @@
 [transform-and-opacity-on-inline-001.html]
+  fuzzy:
+    if (os == "mac"): maxDifference=0-1;totalPixels=0-1
   expected:
     if os == "win": FAIL