merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 10 Oct 2017 23:56:11 +0200
changeset 438630 e897e367d3bd489422d86fbdfac54925c18329d2
parent 438608 f1ecd5c26948c4f62149565efbfcc28abb656fa4 (current diff)
parent 438629 fd1fe0931730ae57be8aee0969183be0121e2857 (diff)
child 438631 7f17361b36179c99a5d499a08310f98e2b057968
child 438652 b880d53a30c74f8999c2c215e9555490f8768a99
child 438749 95824b886c451ae21fa14c3add27c5479bc7381b
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
e897e367d3bd / 58.0a1 / 20171010220102 / files
nightly linux64
e897e367d3bd / 58.0a1 / 20171010220102 / files
nightly mac
e897e367d3bd / 58.0a1 / 20171010220102 / files
nightly win32
e897e367d3bd / 58.0a1 / 20171010220102 / files
nightly win64
e897e367d3bd / 58.0a1 / 20171010220102 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: GbmY183Epi2
gfx/layers/D3D11YCbCrImage.cpp
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -1198,17 +1198,17 @@ def developer_options(value):
 add_old_configure_assignment('DEVELOPER_OPTIONS', developer_options)
 set_config('DEVELOPER_OPTIONS', developer_options)
 
 # Linker detection
 # ==============================================================
 
 @depends(target)
 def build_not_win_mac(target):
-    if target.kernel not in ('Darwin', 'WINNT'):
+    if target.kernel not in ('Darwin', 'WINNT', 'SunOS'):
         return True
 
 
 option('--enable-gold',
        env='MOZ_FORCE_GOLD',
        help='Enable GNU Gold Linker when it is not already the default',
        when=build_not_win_mac)
 
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -434,16 +434,18 @@ nsRange::RegisterCommonAncestor(nsINode*
   mRegisteredCommonAncestor = aNode;
 
   MarkDescendants(aNode);
 
   UniquePtr<LinkedList<nsRange>>& ranges = aNode->GetCommonAncestorRangesPtr();
   if (!ranges) {
     ranges = MakeUnique<LinkedList<nsRange>>();
   }
+
+  MOZ_DIAGNOSTIC_ASSERT(!isInList());
   ranges->insertBack(this);
   aNode->SetCommonAncestorForRangeInSelection();
 }
 
 void
 nsRange::UnregisterCommonAncestor(nsINode* aNode, bool aIsUnlinking)
 {
   NS_PRECONDITION(aNode, "bad arg");
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -369,27 +369,31 @@ SVGContentUtils::EstablishesViewport(nsI
   // Although SVG 1.1 states that <image> is an element that establishes a
   // viewport, this is really only for the document it references, not
   // for any child content, which is what this function is used for.
   return aContent && aContent->IsAnyOfSVGElements(nsGkAtoms::svg,
                                                   nsGkAtoms::foreignObject,
                                                   nsGkAtoms::symbol);
 }
 
-nsSVGElement*
-SVGContentUtils::GetNearestViewportElement(nsIContent *aContent)
+SVGViewportElement*
+SVGContentUtils::GetNearestViewportElement(const nsIContent *aContent)
 {
   nsIContent *element = aContent->GetFlattenedTreeParent();
 
   while (element && element->IsSVGElement()) {
     if (EstablishesViewport(element)) {
       if (element->IsSVGElement(nsGkAtoms::foreignObject)) {
         return nullptr;
       }
-      return static_cast<nsSVGElement*>(element);
+      MOZ_ASSERT(element->IsAnyOfSVGElements(nsGkAtoms::svg,
+                                             nsGkAtoms::symbol),
+                 "upcoming static_cast is only valid for "
+                 "SVGViewportElement subclasses");
+      return static_cast<SVGViewportElement*>(element);
     }
     element = element->GetFlattenedTreeParent();
   }
   return nullptr;
 }
 
 static gfx::Matrix
 GetCTMInternal(nsSVGElement *aElement, bool aScreenCTM, bool aHaveRecursed)
@@ -823,17 +827,17 @@ SVGContentUtils::CoordToFloat(nsSVGEleme
   case eStyleUnit_Factor:
     // user units
     return aCoord.GetFactorValue();
 
   case eStyleUnit_Coord:
     return nsPresContext::AppUnitsToFloatCSSPixels(aCoord.GetCoordValue());
 
   case eStyleUnit_Percent: {
-    SVGSVGElement* ctx = aContent->GetCtx();
+    SVGViewportElement* ctx = aContent->GetCtx();
     return ctx ? aCoord.GetPercentValue() * ctx->GetLength(SVGContentUtils::XY) : 0.0f;
   }
   default:
     return 0.0f;
   }
 }
 
 already_AddRefed<gfx::Path>
--- a/dom/svg/SVGContentUtils.h
+++ b/dom/svg/SVGContentUtils.h
@@ -27,16 +27,17 @@ class nsSVGElement;
 namespace mozilla {
 class nsSVGAnimatedTransformList;
 class SVGAnimatedPreserveAspectRatio;
 class SVGContextPaint;
 class SVGPreserveAspectRatio;
 namespace dom {
 class Element;
 class SVGSVGElement;
+class SVGViewportElement;
 } // namespace dom
 
 } // namespace mozilla
 
 #define SVG_ZERO_LENGTH_PATH_FIX_FACTOR 512
 
 /**
  * SVGTransformTypes controls the transforms that PrependLocalTransformsTo
@@ -233,18 +234,18 @@ public:
                              Rect* aBounds);
 
   /**
    * Check if this is one of the SVG elements that SVG 1.1 Full says
    * establishes a viewport: svg, symbol, image or foreignObject.
    */
   static bool EstablishesViewport(nsIContent *aContent);
 
-  static nsSVGElement*
-  GetNearestViewportElement(nsIContent *aContent);
+  static mozilla::dom::SVGViewportElement*
+  GetNearestViewportElement(const nsIContent *aContent);
 
   /* enum for specifying coordinate direction for ObjectSpace/UserSpace */
   enum ctxDirection { X, Y, XY };
 
   /**
    * Computes sqrt((aWidth^2 + aHeight^2)/2);
    */
   static double ComputeNormalizedHypotenuse(double aWidth, double aHeight);
--- a/dom/svg/SVGLength.cpp
+++ b/dom/svg/SVGLength.cpp
@@ -168,17 +168,17 @@ SVGLength::GetUserUnitsPerUnit(const nsS
       return std::numeric_limits<float>::quiet_NaN();
   }
 }
 
 /* static */ float
 SVGLength::GetUserUnitsPerPercent(const nsSVGElement *aElement, uint8_t aAxis)
 {
   if (aElement) {
-    dom::SVGSVGElement *viewportElement = aElement->GetCtx();
+    dom::SVGViewportElement *viewportElement = aElement->GetCtx();
     if (viewportElement) {
       return std::max(viewportElement->GetLength(aAxis) / 100.0f, 0.0f);
     }
   }
   return std::numeric_limits<float>::quiet_NaN();
 }
 
 // Helpers:
--- a/dom/svg/SVGMarkerElement.cpp
+++ b/dom/svg/SVGMarkerElement.cpp
@@ -245,17 +245,17 @@ SVGMarkerElement::UnsetAttr(int32_t aNam
 
   return nsSVGElement::UnsetAttr(aNamespaceID, aName, aNotify);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 void
-SVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext)
+SVGMarkerElement::SetParentCoordCtxProvider(SVGViewportElement *aContext)
 {
   mCoordCtx = aContext;
   mViewBoxToViewportTransform = nullptr;
 }
 
 /* virtual */ bool
 SVGMarkerElement::HasValidDimensions() const
 {
--- a/dom/svg/SVGMarkerElement.h
+++ b/dom/svg/SVGMarkerElement.h
@@ -148,17 +148,17 @@ public:
   void SetOrientToAngle(SVGAngle& angle, ErrorResult& rv);
 
 protected:
 
   virtual bool ParseAttribute(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
 
-  void SetParentCoordCtxProvider(SVGSVGElement *aContext);
+  void SetParentCoordCtxProvider(SVGViewportElement *aContext);
 
   virtual LengthAttributesInfo GetLengthInfo() override;
   virtual AngleAttributesInfo GetAngleInfo() override;
   virtual EnumAttributesInfo GetEnumInfo() override;
   virtual nsSVGViewBox *GetViewBox() override;
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
 
   enum { REFX, REFY, MARKERWIDTH, MARKERHEIGHT };
@@ -175,16 +175,16 @@ protected:
   static AngleInfo sAngleInfo[1];
 
   nsSVGViewBox             mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 
   // derived properties (from 'orient') handled separately
   nsSVGOrientType                        mOrientType;
 
-  SVGSVGElement                         *mCoordCtx;
+  SVGViewportElement*                    mCoordCtx;
   nsAutoPtr<gfx::Matrix>                 mViewBoxToViewportTransform;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGMarkerElement_h
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -177,25 +177,16 @@ public:
   int32_t GetIntrinsicWidth();
   int32_t GetIntrinsicHeight();
 
   // This services any pending notifications for the transform on on this root
   // <svg> node needing to be recalculated.  (Only applicable in
   // SVG-as-an-image documents.)
   virtual void FlushImageTransformInvalidation();
 
-  svgFloatSize GetViewportSize() const {
-    return svgFloatSize(mViewportWidth, mViewportHeight);
-  }
-
-  void SetViewportSize(const svgFloatSize& aSize) {
-    mViewportWidth  = aSize.width;
-    mViewportHeight = aSize.height;
-  }
-
 private:
   // SVGViewportElement methods:
 
   virtual SVGViewElement* GetCurrentViewElement() const;
   virtual SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const override;
 
   // implementation helpers:
 
--- a/dom/svg/SVGViewportElement.h
+++ b/dom/svg/SVGViewportElement.h
@@ -122,16 +122,25 @@ public:
    * The reason we have this method instead of overriding
    * GetAttributeChangeHint is because we need to act on non-attribute (e.g.
    * currentScale) changes in addition to attribute (e.g. viewBox) changes.
    */
   void ChildrenOnlyTransformChanged(uint32_t aFlags = 0);
 
   gfx::Matrix GetViewBoxTransform() const;
 
+  svgFloatSize GetViewportSize() const {
+    return svgFloatSize(mViewportWidth, mViewportHeight);
+  }
+
+  void SetViewportSize(const svgFloatSize& aSize) {
+    mViewportWidth  = aSize.width;
+    mViewportHeight = aSize.height;
+  }
+
   // WebIDL
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
   virtual nsSVGViewBox* GetViewBox() override;
 
 protected:
 
   // implementation helpers:
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -1104,17 +1104,30 @@ nsSVGElement::GetOwnerSVGElement(nsIDOMS
 {
   NS_IF_ADDREF(*aOwnerSVGElement = GetOwnerSVGElement());
   return NS_OK;
 }
 
 SVGSVGElement*
 nsSVGElement::GetOwnerSVGElement()
 {
-  return GetCtx(); // this may return nullptr
+  nsIContent* ancestor = GetFlattenedTreeParent();
+
+  while (ancestor && ancestor->IsSVGElement()) {
+    if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
+      return nullptr;
+    }
+    if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
+      return static_cast<SVGSVGElement*>(ancestor);
+    }
+    ancestor = ancestor->GetFlattenedTreeParent();
+  }
+
+  // we don't have an ancestor <svg> element...
+  return nullptr;
 }
 
 NS_IMETHODIMP
 nsSVGElement::GetViewportElement(nsIDOMSVGElement * *aViewportElement)
 {
   nsSVGElement* elem = GetViewportElement();
   NS_ADDREF(*aViewportElement = elem);
   return NS_OK;
@@ -1540,33 +1553,20 @@ nsAtom* nsSVGElement::GetEventNameForAtt
   if (aAttr == nsGkAtoms::onrepeat)
     return nsGkAtoms::onrepeatEvent;
   if (aAttr == nsGkAtoms::onend)
     return nsGkAtoms::onendEvent;
 
   return aAttr;
 }
 
-SVGSVGElement *
+SVGViewportElement *
 nsSVGElement::GetCtx() const
 {
-  nsIContent* ancestor = GetFlattenedTreeParent();
-
-  while (ancestor && ancestor->IsSVGElement()) {
-    if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) {
-      return nullptr;
-    }
-    if (ancestor->IsSVGElement(nsGkAtoms::svg)) {
-      return static_cast<SVGSVGElement*>(ancestor);
-    }
-    ancestor = ancestor->GetFlattenedTreeParent();
-  }
-
-  // we don't have an ancestor <svg> element...
-  return nullptr;
+  return SVGContentUtils::GetNearestViewportElement(this);
 }
 
 /* virtual */ gfxMatrix
 nsSVGElement::PrependLocalTransformsTo(
   const gfxMatrix &aMatrix, SVGTransformTypes aWhich) const
 {
   return aMatrix;
 }
@@ -1655,17 +1655,17 @@ nsSVGElement::GetAnimatedLength(const ns
 void
 nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...)
 {
   LengthAttributesInfo info = GetLengthInfo();
 
   NS_ASSERTION(info.mLengthCount > 0,
                "GetAnimatedLengthValues on element with no length attribs");
 
-  SVGSVGElement *ctx = nullptr;
+  SVGViewportElement *ctx = nullptr;
 
   float *f = aFirst;
   uint32_t i = 0;
 
   va_list args;
   va_start(args, aFirst);
 
   while (f && i < info.mLengthCount) {
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -39,16 +39,17 @@ class nsSVGNumberPair;
 class nsSVGString;
 class nsSVGViewBox;
 
 namespace mozilla {
 class DeclarationBlock;
 
 namespace dom {
 class SVGSVGElement;
+class SVGViewportElement;
 
 static const unsigned short SVG_UNIT_TYPE_UNKNOWN           = 0;
 static const unsigned short SVG_UNIT_TYPE_USERSPACEONUSE    = 1;
 static const unsigned short SVG_UNIT_TYPE_OBJECTBOUNDINGBOX = 2;
 
 } // namespace dom
 
 class SVGAnimatedNumberList;
@@ -140,17 +141,17 @@ public:
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
   NS_DECL_NSIDOMSVGELEMENT
 
   NS_IMPL_FROMCONTENT(nsSVGElement, kNameSpaceID_SVG)
 
   // Gets the element that establishes the rectangular viewport against which
   // we should resolve percentage lengths (our "coordinate context"). Returns
   // nullptr for outer <svg> or SVG without an <svg> parent (invalid SVG).
-  mozilla::dom::SVGSVGElement* GetCtx() const;
+  mozilla::dom::SVGViewportElement* GetCtx() const;
 
   /**
    * Returns aMatrix pre-multiplied by (explicit or implicit) transforms that
    * are introduced by attributes on this element.
    *
    * If aWhich is eAllTransforms, then all the transforms from the coordinate
    * space established by this element for its children to the coordinate
    * space established by this element's parent element for this element, are
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -3800,33 +3800,36 @@ HTMLEditRules::WillCSSIndent(Selection* 
     rv = aSelection->Collapse(theBlock, 0);
     // Don't restore the selection
     selectionRestorer.Abort();
     return rv;
   }
 
   // Ok, now go through all the nodes and put them in a blockquote,
   // or whatever is appropriate.  Wohoo!
-  nsCOMPtr<nsINode> curParent;
   nsCOMPtr<Element> curList, curQuote;
   nsCOMPtr<nsIContent> sibling;
   int32_t listCount = arrayOfNodes.Length();
   for (int32_t i = 0; i < listCount; i++) {
     // here's where we actually figure out what to do
     NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
     nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
 
     // Ignore all non-editable nodes.  Leave them be.
     NS_ENSURE_STATE(mHTMLEditor);
     if (!mHTMLEditor->IsEditable(curNode)) {
       continue;
     }
 
-    curParent = curNode->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+    int32_t offset;
+    nsCOMPtr<nsINode> curParent =
+      EditorBase::GetNodeLocation(curNode, &offset);
+    if (!curParent) {
+      continue;
+    }
 
     // some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(curParent)) {
       sibling = nullptr;
 
       // Check for whether we should join a list that follows curNode.
       // We do this if the next element is a list, and the list is of the
       // same type (li/ol) as curNode was a part it.
@@ -3987,33 +3990,35 @@ HTMLEditRules::WillHTMLIndent(Selection*
     rv = aSelection->Collapse(theBlock, 0);
     // Don't restore the selection
     selectionRestorer.Abort();
     return rv;
   }
 
   // Ok, now go through all the nodes and put them in a blockquote,
   // or whatever is appropriate.  Wohoo!
-  nsCOMPtr<nsINode> curParent;
   nsCOMPtr<nsIContent> sibling;
   nsCOMPtr<Element> curList, curQuote, indentedLI;
   int32_t listCount = arrayOfNodes.Length();
   for (int32_t i = 0; i < listCount; i++) {
     // here's where we actually figure out what to do
     NS_ENSURE_STATE(arrayOfNodes[i]->IsContent());
     nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent();
 
     // Ignore all non-editable nodes.  Leave them be.
     NS_ENSURE_STATE(mHTMLEditor);
     if (!mHTMLEditor->IsEditable(curNode)) {
       continue;
     }
 
-    curParent = curNode->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+    int32_t offset;
+    nsCOMPtr<nsINode> curParent = EditorBase::GetNodeLocation(curNode, &offset);
+    if (!curParent) {
+      continue;
+    }
 
     // some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(curParent)) {
       sibling = nullptr;
 
       // Check for whether we should join a list that follows curNode.
       // We do this if the next element is a list, and the list is of the
       // same type (li/ol) as curNode was a part it.
@@ -4793,18 +4798,21 @@ HTMLEditRules::WillAlign(Selection& aSel
     if (HTMLEditUtils::SupportsAlignAttr(*curNode)) {
       rv = AlignBlock(*curNode->AsElement(), aAlignType, ContentsOnly::no);
       NS_ENSURE_SUCCESS(rv, rv);
       // Clear out curDiv so that we don't put nodes after this one into it
       curDiv = nullptr;
       continue;
     }
 
-    nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+    int32_t offset;
+    nsCOMPtr<nsINode> curParent = EditorBase::GetNodeLocation(curNode, &offset);
+    if (!curParent) {
+      continue;
+    }
 
     // Skip insignificant formatting text nodes to prevent unnecessary
     // structure splitting!
     bool isEmptyTextNode = false;
     if (curNode->GetAsText() &&
         ((HTMLEditUtils::IsTableElement(curParent) &&
           !HTMLEditUtils::IsTableCellOrCaption(*curParent)) ||
          HTMLEditUtils::IsList(curParent) ||
@@ -8783,18 +8791,21 @@ HTMLEditRules::WillAbsolutePosition(Sele
 
     // Ignore all non-editable nodes.  Leave them be.
     if (!htmlEditor->IsEditable(curNode)) {
       continue;
     }
 
     nsCOMPtr<nsIContent> sibling;
 
-    nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
-    int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
+    int32_t offset;
+    nsCOMPtr<nsINode> curParent = EditorBase::GetNodeLocation(curNode, &offset);
+    if (!curParent) {
+      continue;
+    }
 
     // Some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(curParent)) {
       // Check to see if curList is still appropriate.  Which it is if curNode
       // is still right after it in the same list.
       if (curList) {
         sibling = htmlEditor->GetPriorHTMLSibling(curNode);
       }
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/crashtests/1402904.html
@@ -0,0 +1,31 @@
+<script>
+function jsfuzzer() {
+  var option = document.getElementById("option");
+  option.addEventListener("click", () => {
+    document.execCommand("forwardDelete", false);
+  });
+  var li2 = document.getElementById("li2");
+  li2.addEventListener("DOMNodeInserted", () => {
+    option.click();
+  });
+  var select = document.getElementById("select");
+  select.parentElement.setAttribute("onpageshow", "onPageShow()");
+}
+
+function onPageShow() {
+  var li1 = document.getElementById("li1");
+  li1.addEventListener("DOMSubtreeModified", () => {
+    document.execCommand("selectAll", false);
+    document.execCommand("indent", false);
+  });
+  li1.appendChild(document.createElement("legend"));
+}
+</script>
+<body onload=jsfuzzer()>
+<select id="select">
+<option id="option"></option>
+</select>
+<li id="li1"></li>
+<ul contenteditable="true">
+<li id="li2"></li>
+<embed>a;#2
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/crashtests/1405747.html
@@ -0,0 +1,15 @@
+<script>
+function jsfuzzer() {
+try { htmlvar00017.addEventListener("DOMSubtreeModified", eventhandler5); } catch(e) { }
+try { htmlvar00017.align = ""; } catch(e) { }
+}
+function eventhandler5() {
+try { document.execCommand("selectAll", false); } catch(e) { }
+try { document.execCommand("justifyCenter", false); } catch(e) { }
+try { document.execCommand("forwardDelete", false); } catch(e) { }
+}
+</script>
+<body onload=jsfuzzer()>
+<table contenteditable="">
+<th id="htmlvar00017"></th>
+<colgroup>
\ No newline at end of file
--- a/editor/libeditor/crashtests/crashtests.list
+++ b/editor/libeditor/crashtests/crashtests.list
@@ -76,8 +76,10 @@ needs-focus load 1343918.html
 load 1345015.html
 load 1348851.html
 load 1350772.html
 load 1366176.html
 load 1375131.html
 load 1381541.html
 load 1383755.html
 load 1402469.html
+load 1402904.html
+load 1405747.html
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -123,16 +123,17 @@ D3D11ShareHandleImage::GetAsSourceSurfac
   if (FAILED(hr)) {
     NS_WARNING("Failed to create 2D staging texture.");
     return nullptr;
   }
 
   RefPtr<ID3D11DeviceContext> context;
   device->GetImmediateContext(getter_AddRefs(context));
   if (!context) {
+    gfxCriticalError() << "Failed to get immediate context.";
     return nullptr;
   }
 
   RefPtr<IDXGIKeyedMutex> mutex;
   hr = texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
 
   if (SUCCEEDED(hr) && mutex) {
     hr = mutex->AcquireSync(0, 2000);
--- a/gfx/layers/D3D11YCbCrImage.cpp
+++ b/gfx/layers/D3D11YCbCrImage.cpp
@@ -68,16 +68,20 @@ D3D11YCbCrImage::SetData(KnowsCompositor
     gfxCriticalError() << "Device used not marked as multithread-safe.";
     return false;
   }
 
   D3D11MTAutoEnter mtAutoEnter(mt.forget());
 
   RefPtr<ID3D11DeviceContext> ctx;
   allocator->GetDevice()->GetImmediateContext(getter_AddRefs(ctx));
+  if (!ctx) {
+    gfxCriticalError() << "Failed to get immediate context.";
+    return false;
+  }
 
   AutoLockD3D11Texture lockY(textureY);
   AutoLockD3D11Texture lockCb(textureCb);
   AutoLockD3D11Texture lockCr(textureCr);
 
   ctx->UpdateSubresource(textureY,
                          0,
                          nullptr,
@@ -184,16 +188,20 @@ D3D11YCbCrImage::GetAsSourceSurface()
   desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
   desc.Usage = D3D11_USAGE_STAGING;
 
   dev->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexCb));
   dev->CreateTexture2D(&desc, nullptr, getter_AddRefs(softTexCr));
 
   RefPtr<ID3D11DeviceContext> ctx;
   dev->GetImmediateContext(getter_AddRefs(ctx));
+  if (!ctx) {
+    gfxCriticalError() << "Failed to get immediate context.";
+    return nullptr;
+  }
 
   {
     AutoLockD3D11Texture lockY(texY);
     AutoLockD3D11Texture lockCb(texCb);
     AutoLockD3D11Texture lockCr(texCr);
     ctx->CopyResource(softTexY, texY);
     ctx->CopyResource(softTexCb, texCb);
     ctx->CopyResource(softTexCr, texCr);
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -62,16 +62,17 @@ enum ThreadType {
     THREAD_TYPE_ION,            // 3
     THREAD_TYPE_PARSE,          // 4
     THREAD_TYPE_COMPRESS,       // 5
     THREAD_TYPE_GCHELPER,       // 6
     THREAD_TYPE_GCPARALLEL,     // 7
     THREAD_TYPE_PROMISE_TASK,   // 8
     THREAD_TYPE_ION_FREE,       // 9
     THREAD_TYPE_WASM_TIER2,     // 10
+    THREAD_TYPE_WORKER,         // 11
     THREAD_TYPE_MAX             // Used to check shell function arguments
 };
 
 namespace oom {
 
 /*
  * Theads are tagged only in certain debug contexts.  Notably, to make testing
  * OOM in certain helper threads more effective, we allow restricting the OOM
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1439,16 +1439,27 @@ static bool
 OOMThreadTypes(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setInt32(js::THREAD_TYPE_MAX);
     return true;
 }
 
 static bool
+CheckCanSimulateOOM(JSContext* cx)
+{
+    if (js::oom::GetThreadType() != js::THREAD_TYPE_COOPERATING) {
+        JS_ReportErrorASCII(cx, "Simulated OOM failure is only supported on the main thread");
+        return false;
+    }
+
+    return true;
+}
+
+static bool
 SetupOOMFailure(JSContext* cx, bool failAlways, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (disableOOMFunctions) {
         args.rval().setUndefined();
         return true;
     }
@@ -1476,16 +1487,19 @@ SetupOOMFailure(JSContext* cx, bool fail
     if (args.length() > 1 && !ToUint32(cx, args[1], &targetThread))
         return false;
 
     if (targetThread == js::THREAD_TYPE_NONE || targetThread >= js::THREAD_TYPE_MAX) {
         JS_ReportErrorASCII(cx, "Invalid thread type specified");
         return false;
     }
 
+    if (!CheckCanSimulateOOM(cx))
+        return false;
+
     js::oom::SimulateOOMAfter(count, targetThread, failAlways);
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 OOMAfterAllocations(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -1497,16 +1511,20 @@ OOMAtAllocation(JSContext* cx, unsigned 
 {
     return SetupOOMFailure(cx, false, argc, vp);
 }
 
 static bool
 ResetOOMFailure(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (!CheckCanSimulateOOM(cx))
+        return false;
+
     args.rval().setBoolean(js::oom::HadSimulatedOOM());
     js::oom::ResetSimulatedOOM();
     return true;
 }
 
 static size_t
 CountCompartments(JSContext* cx)
 {
@@ -1532,16 +1550,19 @@ OOMTest(JSContext* cx, unsigned argc, Va
         return false;
     }
 
     if (args.length() == 2 && !args[1].isBoolean()) {
         JS_ReportErrorASCII(cx, "The optional second argument to oomTest() must be a boolean.");
         return false;
     }
 
+    if (!CheckCanSimulateOOM(cx))
+        return false;
+
     bool expectExceptionOnFailure = true;
     if (args.length() == 2)
         expectExceptionOnFailure = args[1].toBoolean();
 
     // There are some places where we do fail without raising an exception, so
     // we can't expose this to the fuzzers by default.
     if (fuzzingSafe)
         expectExceptionOnFailure = false;
@@ -4236,20 +4257,18 @@ SetRNGState(JSContext* cx, unsigned argc
     cx->compartment()->randomNumberGenerator.ref().setState(seed0, seed1);
 
     args.rval().setUndefined();
     return true;
 }
 #endif
 
 static ModuleEnvironmentObject*
-GetModuleEnvironment(JSContext* cx, HandleValue moduleValue)
+GetModuleEnvironment(JSContext* cx, HandleModuleObject module)
 {
-    RootedModuleObject module(cx, &moduleValue.toObject().as<ModuleObject>());
-
     // Use the initial environment so that tests can check bindings exists
     // before they have been instantiated.
     RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
     MOZ_ASSERT(env);
     MOZ_ASSERT_IF(module->environment(), module->environment() == env);
 
     return env;
 }
@@ -4263,17 +4282,23 @@ GetModuleEnvironmentNames(JSContext* cx,
         return false;
     }
 
     if (!args[0].isObject() || !args[0].toObject().is<ModuleObject>()) {
         JS_ReportErrorASCII(cx, "First argument should be a ModuleObject");
         return false;
     }
 
-    RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
+    RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
+    if (module->status() == MODULE_STATUS_ERRORED) {
+        JS_ReportErrorASCII(cx, "Module environment unavailable");
+        return false;
+    }
+
+    RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, module));
     Rooted<IdVector> ids(cx, IdVector(cx));
     if (!JS_Enumerate(cx, env, &ids))
         return false;
 
     uint32_t length = ids.length();
     RootedArrayObject array(cx, NewDenseFullyAllocatedArray(cx, length));
     if (!array)
         return false;
@@ -4300,17 +4325,23 @@ GetModuleEnvironmentValue(JSContext* cx,
         return false;
     }
 
     if (!args[1].isString()) {
         JS_ReportErrorASCII(cx, "Second argument should be a string");
         return false;
     }
 
-    RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
+    RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
+    if (module->status() == MODULE_STATUS_ERRORED) {
+        JS_ReportErrorASCII(cx, "Module environment unavailable");
+        return false;
+    }
+
+    RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, module));
     RootedString name(cx, args[1].toString());
     RootedId id(cx);
     if (!JS_StringToId(cx, name, &id))
         return false;
 
     if (!GetProperty(cx, env, env, id, args.rval()))
         return false;
 
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -928,18 +928,19 @@ class GCRuntime
 
     ChunkPool& fullChunks(const AutoLockGC& lock) { return fullChunks_.ref(); }
     ChunkPool& availableChunks(const AutoLockGC& lock) { return availableChunks_.ref(); }
     ChunkPool& emptyChunks(const AutoLockGC& lock) { return emptyChunks_.ref(); }
     const ChunkPool& fullChunks(const AutoLockGC& lock) const { return fullChunks_.ref(); }
     const ChunkPool& availableChunks(const AutoLockGC& lock) const { return availableChunks_.ref(); }
     const ChunkPool& emptyChunks(const AutoLockGC& lock) const { return emptyChunks_.ref(); }
     typedef ChainedIter<Chunk*, ChunkPool::Iter, ChunkPool::Iter> NonEmptyChunksIter;
-    NonEmptyChunksIter allNonEmptyChunks() {
-        return NonEmptyChunksIter(ChunkPool::Iter(availableChunks_.ref()), ChunkPool::Iter(fullChunks_.ref()));
+    NonEmptyChunksIter allNonEmptyChunks(const AutoLockGC& lock) {
+        return NonEmptyChunksIter(ChunkPool::Iter(availableChunks(lock)),
+                                  ChunkPool::Iter(fullChunks(lock)));
     }
 
     Chunk* getOrAllocChunk(const AutoLockGC& lock,
                            AutoMaybeStartBackgroundAllocation& maybeStartBGAlloc);
     void recycleChunk(Chunk* chunk, const AutoLockGC& lock);
 
 #ifdef JS_GC_ZEAL
     void startVerifyPreBarriers();
@@ -1181,21 +1182,21 @@ class GCRuntime
     GCLockData<ChunkPool> emptyChunks_;
 
     // Chunks which have had some, but not all, of their arenas allocated live
     // in the available chunk lists. When all available arenas in a chunk have
     // been allocated, the chunk is removed from the available list and moved
     // to the fullChunks pool. During a GC, if all arenas are free, the chunk
     // is moved back to the emptyChunks pool and scheduled for eventual
     // release.
-    UnprotectedData<ChunkPool> availableChunks_;
+    GCLockData<ChunkPool> availableChunks_;
 
     // When all arenas in a chunk are used, it is moved to the fullChunks pool
     // so as to reduce the cost of operations on the available lists.
-    UnprotectedData<ChunkPool> fullChunks_;
+    GCLockData<ChunkPool> fullChunks_;
 
     ActiveThreadData<RootedValueMap> rootsHash;
 
     // An incrementing id used to assign unique ids to cells that require one.
     mozilla::Atomic<uint64_t, mozilla::ReleaseAcquire> nextCellUniqueId_;
 
     /*
      * Number of the committed arenas in all GC chunks including empty chunks.
--- a/js/src/gc/Iteration.cpp
+++ b/js/src/gc/Iteration.cpp
@@ -70,18 +70,19 @@ js::IterateHeapUnbarrieredForZone(JSCont
     IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
                                               compartmentCallback, arenaCallback, cellCallback);
 }
 
 void
 js::IterateChunks(JSContext* cx, void* data, IterateChunkCallback chunkCallback)
 {
     AutoPrepareForTracing prep(cx, SkipAtoms);
+    AutoLockGC lock(cx->runtime());
 
-    for (auto chunk = cx->runtime()->gc.allNonEmptyChunks(); !chunk.done(); chunk.next())
+    for (auto chunk = cx->runtime()->gc.allNonEmptyChunks(lock); !chunk.done(); chunk.next())
         chunkCallback(cx->runtime(), data, chunk);
 }
 
 void
 js::IterateScripts(JSContext* cx, JSCompartment* compartment,
                    void* data, IterateScriptCallback scriptCallback)
 {
     MOZ_ASSERT(!cx->suppressGC);
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -189,20 +189,24 @@ gc::GCRuntime::startVerifyPreBarriers()
     }
 
     number++;
 
     VerifyPreTracer* trc = js_new<VerifyPreTracer>(rt);
     if (!trc)
         return;
 
-    AutoPrepareForTracing prep(TlsContext.get(), WithAtoms);
+    JSContext* cx = TlsContext.get();
+    AutoPrepareForTracing prep(cx, WithAtoms);
 
-    for (auto chunk = allNonEmptyChunks(); !chunk.done(); chunk.next())
-        chunk->bitmap.clear();
+    {
+        AutoLockGC lock(cx->runtime());
+        for (auto chunk = allNonEmptyChunks(lock); !chunk.done(); chunk.next())
+            chunk->bitmap.clear();
+    }
 
     gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::TRACE_HEAP);
 
     const size_t size = 64 * 1024 * 1024;
     trc->root = (VerifyNode*)js_malloc(size);
     if (!trc->root)
         goto oom;
     trc->edgeptr = (char*)trc->root;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/bug-1406452.js
@@ -0,0 +1,5 @@
+// |jit-test| error: Error
+let m = parseModule(`for (var x of iterator) {}`);
+m.declarationInstantiation();
+try { m.evaluation(); } catch (e) {}
+getModuleEnvironmentValue(m, "r");
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -389,23 +389,23 @@ struct BaselineStackBuilder
 #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
       defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
       defined(JS_CODEGEN_X64)
         // On X64, ARM, ARM64, and MIPS, the frame pointer save location depends on
         // the caller of the rectifier frame.
         BufferPointer<RectifierFrameLayout> priorFrame =
             pointerAtStackOffset<RectifierFrameLayout>(priorOffset);
         FrameType priorType = priorFrame->prevType();
-        MOZ_ASSERT(priorType == JitFrame_WasmToJSJit ||
+        MOZ_ASSERT(JSJitFrameIter::isEntry(priorType) ||
                    priorType == JitFrame_IonJS ||
                    priorType == JitFrame_BaselineStub);
 
-        // If the frame preceding the rectifier is an IonJS or WasmToJSJit
-        // entry frame, then once again the frame pointer does not matter.
-        if (priorType == JitFrame_IonJS || priorType == JitFrame_WasmToJSJit)
+        // If the frame preceding the rectifier is an IonJS or entry frame,
+        // then once again the frame pointer does not matter.
+        if (priorType == JitFrame_IonJS || JSJitFrameIter::isEntry(priorType))
             return nullptr;
 
         // Otherwise, the frame preceding the rectifier is a BaselineStub frame.
         //  let X = STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
         //      X + RectifierFrameLayout::Size()
         //        + ((RectifierFrameLayout*) X)->prevFrameLocalSize()
         //        - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
         size_t extraOffset = RectifierFrameLayout::Size() + priorFrame->prevFrameLocalSize() +
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -188,19 +188,17 @@ EnterBaseline(JSContext* cx, EnterJitDat
 JitExecStatus
 jit::EnterBaselineMethod(JSContext* cx, RunState& state)
 {
     BaselineScript* baseline = state.script()->baselineScript();
 
     EnterJitData data(cx);
     data.jitcode = baseline->method()->raw();
 
-    Rooted<GCVector<Value>> vals(cx, GCVector<Value>(cx));
-    if (!SetEnterJitData(cx, data, state, &vals))
-        return JitExec_Error;
+    SetEnterJitData(cx, data, state);
 
     JitExecStatus status = EnterBaseline(cx, data);
     if (status != JitExec_Ok)
         return status;
 
     state.setReturnValue(data.result);
     return JitExec_Ok;
 }
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2801,94 +2801,63 @@ EnterIon(JSContext* cx, EnterJitData& da
 
     // Release temporary buffer used for OSR into Ion.
     cx->freeOsrTempData();
 
     MOZ_ASSERT_IF(data.result.isMagic(), data.result.isMagic(JS_ION_ERROR));
     return data.result.isMagic() ? JitExec_Error : JitExec_Ok;
 }
 
-bool
-jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state,
-                     MutableHandle<GCVector<Value>> vals)
+void
+jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state)
 {
     data.osrFrame = nullptr;
 
     // Note: keep this in sync with EnterBaselineAtBranch.
 
     if (state.isInvoke()) {
         const CallArgs& args = state.asInvoke()->args();
         unsigned numFormals = state.script()->functionNonDelazifying()->nargs();
         data.constructing = state.asInvoke()->constructing();
         data.numActualArgs = args.length();
-        data.maxArgc = Max(args.length(), numFormals) + 1;
+        data.maxArgc = args.length() + 1;
+        data.maxArgv = args.array() - 1; // -1 to include |this|
         data.envChain = nullptr;
         data.calleeToken = CalleeToToken(&args.callee().as<JSFunction>(), data.constructing);
-
-        if (data.numActualArgs >= numFormals) {
-            data.maxArgv = args.array() - 1; // -1 to include |this|
-        } else {
-            MOZ_ASSERT(vals.empty());
-            unsigned numPushedArgs = Max(args.length(), numFormals);
-            if (!vals.reserve(numPushedArgs + 1 + data.constructing))
-                return false;
-
-            // Append |this| and any provided arguments.
-            for (size_t i = 1; i < args.length() + 2; ++i)
-                vals.infallibleAppend(args.base()[i]);
-
-            // Pad missing arguments with |undefined|.
-            while (vals.length() < numFormals + 1)
-                vals.infallibleAppend(UndefinedValue());
-
-            if (data.constructing)
-                vals.infallibleAppend(args.newTarget());
-
-            MOZ_ASSERT(vals.length() >= numFormals + 1 + data.constructing);
-            data.maxArgv = vals.begin();
-        }
+        if (numFormals > data.numActualArgs)
+            data.jitcode = cx->runtime()->jitRuntime()->getArgumentsRectifier()->raw();
     } else {
         data.constructing = false;
         data.numActualArgs = 0;
-        data.maxArgc = 0;
-        data.maxArgv = nullptr;
         data.envChain = state.asExecute()->environmentChain();
-
         data.calleeToken = CalleeToToken(state.script());
 
-        if (state.script()->isForEval() && state.script()->isDirectEvalInFunction()) {
-            // Push newTarget onto the stack.
-            if (!vals.reserve(1))
-                return false;
-
-            data.maxArgc = 1;
-            data.maxArgv = vals.begin();
+        if (state.script()->isDirectEvalInFunction()) {
             if (state.asExecute()->newTarget().isNull()) {
                 ScriptFrameIter iter(cx);
-                vals.infallibleAppend(iter.newTarget());
-            } else {
-                vals.infallibleAppend(state.asExecute()->newTarget());
+                state.asExecute()->setNewTarget(iter.newTarget());
             }
+            data.maxArgc = 1;
+            data.maxArgv = state.asExecute()->addressOfNewTarget();
+        } else {
+            data.maxArgc = 0;
+            data.maxArgv = nullptr;
         }
     }
-
-    return true;
 }
 
 JitExecStatus
 jit::IonCannon(JSContext* cx, RunState& state)
 {
     IonScript* ion = state.script()->ionScript();
 
     EnterJitData data(cx);
     data.jitcode = ion->method()->raw();
 
-    Rooted<GCVector<Value>> vals(cx, GCVector<Value>(cx));
-    if (!SetEnterJitData(cx, data, state, &vals))
-        return JitExec_Error;
+    SetEnterJitData(cx, data, state);
 
     JitExecStatus status = EnterIon(cx, data);
 
     if (status == JitExec_Ok)
         state.setReturnValue(data.result);
 
     return status;
 }
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -120,18 +120,17 @@ enum JitExecStatus
 static inline bool
 IsErrorStatus(JitExecStatus status)
 {
     return status == JitExec_Error || status == JitExec_Aborted;
 }
 
 struct EnterJitData;
 
-MOZ_MUST_USE bool SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state,
-                                  MutableHandle<GCVector<Value>> vals);
+void SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state);
 
 JitExecStatus IonCannon(JSContext* cx, RunState& state);
 
 // Walk the stack and invalidate active Ion frames for the invalid scripts.
 void Invalidate(TypeZone& types, FreeOp* fop,
                 const RecompileInfoVector& invalid, bool resetUses = true,
                 bool cancelOffThread = true);
 void Invalidate(JSContext* cx, const RecompileInfoVector& invalid, bool resetUses = true,
--- a/js/src/jit/JSJitFrameIter.cpp
+++ b/js/src/jit/JSJitFrameIter.cpp
@@ -650,16 +650,26 @@ JSJitProfilingFrameIterator::moveToWasmF
     // pass a wasm iterator the correct value of FP.
     returnAddressToFp_ = nullptr;
     fp_ = GetPreviousRawFrame<uint8_t*>(frame);
     type_ = JitFrame_WasmToJSJit;
     MOZ_ASSERT(!done());
 }
 
 void
+JSJitProfilingFrameIterator::moveToCppEntryFrame()
+{
+    // No previous frame, set to nullptr to indicate that
+    // JSJitProfilingFrameIterator is done().
+    returnAddressToFp_ = nullptr;
+    fp_ = nullptr;
+    type_ = JitFrame_CppToJSJit;
+}
+
+void
 JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
 {
     /*
      * fp_ points to a Baseline or Ion frame.  The possible call-stacks
      * patterns occurring between this frame and a previous Ion or Baseline
      * frame are as follows:
      *
      * <Baseline-Or-Ion>
@@ -674,16 +684,18 @@ JSJitProfilingFrameIterator::moveToNextF
      * ^--- Argument Rectifier
      * |    ^
      * |    |
      * |    ^--- Ion
      * |    |
      * |    ^--- Baseline Stub <---- Baseline
      * |    |
      * |    ^--- WasmToJSJit <--- (other wasm frames)
+     * |    |
+     * |    ^--- CppToJSJit
      * |
      * ^--- Entry Frame (From C++)
      *      Exit Frame (From previous JitActivation)
      *      ^
      *      |
      *      ^--- Ion
      *      |
      *      ^--- Baseline
@@ -739,16 +751,21 @@ JSJitProfilingFrameIterator::moveToNextF
             return;
         }
 
         if (rectPrevType == JitFrame_WasmToJSJit) {
             moveToWasmFrame(rectFrame);
             return;
         }
 
+        if (rectPrevType == JitFrame_CppToJSJit) {
+            moveToCppEntryFrame();
+            return;
+        }
+
         MOZ_CRASH("Bad frame type prior to rectifier frame.");
     }
 
     if (prevType == JitFrame_IonICCall) {
         IonICCallFrameLayout* callFrame =
             GetPreviousRawFrame<IonICCallFrameLayout*>(frame);
 
         MOZ_ASSERT(callFrame->prevType() == JitFrame_IonJS);
@@ -760,18 +777,14 @@ JSJitProfilingFrameIterator::moveToNextF
     }
 
     if (prevType == JitFrame_WasmToJSJit) {
         moveToWasmFrame(frame);
         return;
     }
 
     if (prevType == JitFrame_CppToJSJit) {
-        // No previous frame, set to null to indicate that
-        // JSJitProfilingFrameIterator is done().
-        returnAddressToFp_ = nullptr;
-        fp_ = nullptr;
-        type_ = JitFrame_CppToJSJit;
+        moveToCppEntryFrame();
         return;
     }
 
     MOZ_CRASH("Bad frame type.");
 }
--- a/js/src/jit/JSJitFrameIter.h
+++ b/js/src/jit/JSJitFrameIter.h
@@ -292,16 +292,17 @@ class JSJitProfilingFrameIterator
 
     inline JitFrameLayout* framePtr();
     inline JSScript* frameScript();
     MOZ_MUST_USE bool tryInitWithPC(void* pc);
     MOZ_MUST_USE bool tryInitWithTable(JitcodeGlobalTable* table, void* pc, JSRuntime* rt,
                                        bool forLastCallSite);
     void fixBaselineReturnAddress();
 
+    void moveToCppEntryFrame();
     void moveToWasmFrame(CommonFrameLayout* frame);
     void moveToNextFrame(CommonFrameLayout* frame);
 
   public:
     JSJitProfilingFrameIterator(JSContext* cx,
                               const JS::ProfilingFrameIterator::RegisterState& state);
     explicit JSJitProfilingFrameIterator(void* exitFrame);
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1659,16 +1659,17 @@ MacroAssembler::assertRectifierFramePare
 {
 #ifdef DEBUG
     {
         // Check the possible previous frame types here.
         Label checkOk;
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_IonJS), &checkOk);
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_BaselineStub), &checkOk);
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_WasmToJSJit), &checkOk);
+        branch32(Assembler::Equal, frameType, Imm32(JitFrame_CppToJSJit), &checkOk);
         assumeUnreachable("Unrecognized frame type preceding RectifierFrame.");
         bind(&checkOk);
     }
 #endif
 }
 
 void
 MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, Label* failure)
--- a/js/src/jit/Registers.h
+++ b/js/src/jit/Registers.h
@@ -130,17 +130,18 @@ Register::LiveAsIndexableSet<RegTypeName
 }
 
 template <> inline Register::SetType
 Register::AllocatableAsIndexableSet<RegTypeName::GPR>(SetType set)
 {
     return set;
 }
 
-#if defined(JS_NUNBOX32)
+#if JS_BITS_PER_WORD == 32
+// Note, some platform code depends on INT64LOW_OFFSET being zero.
 static const uint32_t INT64LOW_OFFSET = 0 * sizeof(int32_t);
 static const uint32_t INT64HIGH_OFFSET = 1 * sizeof(int32_t);
 #endif
 
 struct Register64
 {
 #ifdef JS_PUNBOX64
     Register reg;
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1003,19 +1003,18 @@ class MacroAssemblerARMCompat : public M
 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
     void load64(const Address& address, Register64 dest) {
-        load32(Address(address.base, address.offset + INT64LOW_OFFSET), dest.low);
-        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
-        load32(Address(address.base, address.offset + highOffset), dest.high);
+        load32(LowWord(address), dest.low);
+        load32(HighWord(address), dest.high);
     }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(wasm::SymbolicAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
@@ -1075,23 +1074,23 @@ class MacroAssemblerARMCompat : public M
 
     void store32(Register src, AbsoluteAddress address);
     void store32(Register src, const Address& address);
     void store32(Register src, const BaseIndex& address);
     void store32(Imm32 src, const Address& address);
     void store32(Imm32 src, const BaseIndex& address);
 
     void store64(Register64 src, Address address) {
-        store32(src.low, Address(address.base, address.offset + INT64LOW_OFFSET));
-        store32(src.high, Address(address.base, address.offset + INT64HIGH_OFFSET));
+        store32(src.low, LowWord(address));
+        store32(src.high, HighWord(address));
     }
 
     void store64(Imm64 imm, Address address) {
-        store32(imm.low(), Address(address.base, address.offset + INT64LOW_OFFSET));
-        store32(imm.hi(), Address(address.base, address.offset + INT64HIGH_OFFSET));
+        store32(imm.low(), LowWord(address));
+        store32(imm.hi(), HighWord(address));
     }
 
     void storePtr(ImmWord imm, const Address& address);
     void storePtr(ImmWord imm, const BaseIndex& address);
     void storePtr(ImmPtr imm, const Address& address);
     void storePtr(ImmPtr imm, const BaseIndex& address);
     void storePtr(ImmGCPtr imm, const Address& address);
     void storePtr(ImmGCPtr imm, const BaseIndex& address);
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -1282,20 +1282,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1349,18 +1349,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.ma_add(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.ma_add(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -1074,20 +1074,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1114,17 +1114,17 @@ JitRuntime::generateProfilerExitFrameTai
     //              Descriptor      |
     //    FP -----> ReturnAddr      |
     //
     masm.bind(&handle_Rectifier);
     {
         // scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
         masm.addPtr(masm.getStackPointer(), scratch1, scratch2);
         masm.syncStackPtr();
-        masm.add32(Imm32(JitFrameLayout::Size()), scratch2);
+        masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
@@ -1142,18 +1142,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.addPtr(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.addPtr(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/mips32/MacroAssembler-mips32.h
+++ b/js/src/jit/mips32/MacroAssembler-mips32.h
@@ -853,19 +853,18 @@ class MacroAssemblerMIPSCompat : public 
     void load16ZeroExtend(const Address& address, Register dest);
     void load16ZeroExtend(const BaseIndex& src, Register dest);
 
     void load32(const Address& address, Register dest);
     void load32(const BaseIndex& address, Register dest);
     void load32(AbsoluteAddress address, Register dest);
     void load32(wasm::SymbolicAddress address, Register dest);
     void load64(const Address& address, Register64 dest) {
-        load32(Address(address.base, address.offset + INT64LOW_OFFSET), dest.low);
-        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
-        load32(Address(address.base, address.offset + highOffset), dest.high);
+        load32(LowWord(address), dest.low);
+        load32(HighWord(address), dest.high);
     }
 
     void loadPtr(const Address& address, Register dest);
     void loadPtr(const BaseIndex& src, Register dest);
     void loadPtr(AbsoluteAddress address, Register dest);
     void loadPtr(wasm::SymbolicAddress address, Register dest);
 
     void loadPrivate(const Address& address, Register dest);
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -1261,20 +1261,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1328,18 +1328,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_addu(scratch3, scratch2, scratch1);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.as_addu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -1202,20 +1202,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1269,18 +1269,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_daddu(scratch3, scratch2, scratch1);
         masm.addPtr(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.as_daddu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/shared/Assembler-shared.h
+++ b/js/src/jit/shared/Assembler-shared.h
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_shared_Assembler_shared_h
 #define jit_shared_Assembler_shared_h
 
+#include "mozilla/CheckedInt.h"
 #include "mozilla/PodOperations.h"
 
 #include <limits.h>
 
 #include "jit/AtomicOp.h"
 #include "jit/JitAllocPolicy.h"
 #include "jit/Label.h"
 #include "jit/Registers.h"
@@ -29,16 +30,18 @@
 // JS_SMALL_BRANCH means the range on a branch instruction
 // is smaller than the whole address space
 # define JS_SMALL_BRANCH
 #endif
 
 namespace js {
 namespace jit {
 
+using mozilla::CheckedInt;
+
 namespace Disassembler {
 class HeapAccess;
 } // namespace Disassembler
 
 static const uint32_t Simd128DataSize = 4 * sizeof(int32_t);
 static_assert(Simd128DataSize == 4 * sizeof(int32_t), "SIMD data should be able to contain int32x4");
 static_assert(Simd128DataSize == 4 * sizeof(float), "SIMD data should be able to contain float32x4");
 static_assert(Simd128DataSize == 2 * sizeof(double), "SIMD data should be able to contain float64x2");
@@ -293,32 +296,68 @@ struct Address
     int32_t offset;
 
     Address(Register base, int32_t offset) : base(base), offset(offset)
     { }
 
     Address() { mozilla::PodZero(this); }
 };
 
+#if JS_BITS_PER_WORD == 32
+
+static inline Address
+LowWord(const Address& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64LOW_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return Address(address.base, offset.value());
+}
+
+static inline Address
+HighWord(const Address& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64HIGH_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return Address(address.base, offset.value());
+}
+
+#endif
+
 // Specifies an address computed in the form of a register base, a register
 // index with a scale, and a constant, 32-bit offset.
 struct BaseIndex
 {
     Register base;
     Register index;
     Scale scale;
     int32_t offset;
 
     BaseIndex(Register base, Register index, Scale scale, int32_t offset = 0)
       : base(base), index(index), scale(scale), offset(offset)
     { }
 
     BaseIndex() { mozilla::PodZero(this); }
 };
 
+#if JS_BITS_PER_WORD == 32
+
+static inline BaseIndex
+LowWord(const BaseIndex& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64LOW_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return BaseIndex(address.base, address.index, address.scale, offset.value());
+}
+
+static inline BaseIndex
+HighWord(const BaseIndex& address) {
+    CheckedInt<int32_t> offset = CheckedInt<int32_t>(address.offset) + INT64HIGH_OFFSET;
+    MOZ_ALWAYS_TRUE(offset.isValid());
+    return BaseIndex(address.base, address.index, address.scale, offset.value());
+}
+
+#endif
+
 // A BaseIndex used to access Values.  Note that |offset| is *not* scaled by
 // sizeof(Value).  Use this *only* if you're indexing into a series of Values
 // that aren't object elements or object slots (for example, values on the
 // stack, values in an arguments object, &c.).  If you're indexing into an
 // object's elements or slots, don't use this directly!  Use
 // BaseObject{Element,Slot}Index instead.
 struct BaseValueIndex : BaseIndex
 {
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -1175,20 +1175,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1241,18 +1241,18 @@ JitRuntime::generateProfilerExitFrameTai
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -203,16 +203,34 @@ PatchJump(CodeLocationJump jump, CodeLoc
     X86Encoding::SetRel32(jump.raw(), label.raw());
 }
 static inline void
 PatchBackedge(CodeLocationJump& jump_, CodeLocationLabel label, JitZoneGroup::BackedgeTarget target)
 {
     PatchJump(jump_, label);
 }
 
+static inline Operand
+LowWord(const Operand& op) {
+    switch (op.kind()) {
+      case Operand::MEM_REG_DISP: return Operand(LowWord(op.toAddress()));
+      case Operand::MEM_SCALE:    return Operand(LowWord(op.toBaseIndex()));
+      default:                    MOZ_CRASH("Invalid operand type");
+    }
+}
+
+static inline Operand
+HighWord(const Operand& op) {
+    switch (op.kind()) {
+      case Operand::MEM_REG_DISP: return Operand(HighWord(op.toAddress()));
+      case Operand::MEM_SCALE:    return Operand(HighWord(op.toBaseIndex()));
+      default:                    MOZ_CRASH("Invalid operand type");
+    }
+}
+
 // Return operand from a JS -> JS call.
 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg_Type, JSReturnReg_Data);
 
 class Assembler : public AssemblerX86Shared
 {
     void writeRelocation(JmpSrc src) {
         jumpRelocations_.writeUnsigned(src.offset());
     }
@@ -763,34 +781,30 @@ class Assembler : public AssemblerX86Sha
           default:
             MOZ_CRASH("unexpected operand kind");
         }
         return CodeOffset(masm.currentOffset());
     }
     CodeOffset movlWithPatchLow(Register regLow, const Operand& dest) {
         switch (dest.kind()) {
           case Operand::MEM_REG_DISP: {
-            Address addr = dest.toAddress();
-            Operand low(addr.base, addr.offset + INT64LOW_OFFSET);
-            return movlWithPatch(regLow, low);
+            return movlWithPatch(regLow, LowWord(dest));
           }
           case Operand::MEM_ADDRESS32: {
             Operand low(PatchedAbsoluteAddress(uint32_t(dest.address()) + INT64LOW_OFFSET));
             return movlWithPatch(regLow, low);
           }
           default:
             MOZ_CRASH("unexpected operand kind");
         }
     }
     CodeOffset movlWithPatchHigh(Register regHigh, const Operand& dest) {
         switch (dest.kind()) {
           case Operand::MEM_REG_DISP: {
-            Address addr = dest.toAddress();
-            Operand high(addr.base, addr.offset + INT64HIGH_OFFSET);
-            return movlWithPatch(regHigh, high);
+            return movlWithPatch(regHigh, HighWord(dest));
           }
           case Operand::MEM_ADDRESS32: {
             Operand high(PatchedAbsoluteAddress(uint32_t(dest.address()) + INT64HIGH_OFFSET));
             return movlWithPatch(regHigh, high);
           }
           default:
             MOZ_CRASH("unexpected operand kind");
         }
--- a/js/src/jit/x86/MacroAssembler-x86-inl.h
+++ b/js/src/jit/x86/MacroAssembler-x86-inl.h
@@ -945,57 +945,57 @@ MacroAssembler::truncateFloat32ToUInt64(
 {
     Label done;
 
     loadFloat32(src, floatTemp);
 
     truncateFloat32ToInt64(src, dest, temp);
 
     // For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
 
     // Move the value inside INT64 range.
     storeFloat32(floatTemp, dest);
     loadConstantFloat32(double(int64_t(0x8000000000000000)), floatTemp);
     vaddss(Operand(dest), floatTemp, floatTemp);
     storeFloat32(floatTemp, dest);
     truncateFloat32ToInt64(dest, dest, temp);
 
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     orl(Imm32(0x80000000), temp);
-    store32(temp, Address(dest.base, dest.offset + INT64HIGH_OFFSET));
+    store32(temp, HighWord(dest));
 
     bind(&done);
 }
 
 void
 MacroAssembler::truncateDoubleToUInt64(Address src, Address dest, Register temp,
                                        FloatRegister floatTemp)
 {
     Label done;
 
     loadDouble(src, floatTemp);
 
     truncateDoubleToInt64(src, dest, temp);
 
     // For unsigned conversion the case of [INT64, UINT64] needs to get handle seperately.
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     branch32(Assembler::Condition::NotSigned, temp, Imm32(0), &done);
 
     // Move the value inside INT64 range.
     storeDouble(floatTemp, dest);
     loadConstantDouble(double(int64_t(0x8000000000000000)), floatTemp);
     vaddsd(Operand(dest), floatTemp, floatTemp);
     storeDouble(floatTemp, dest);
     truncateDoubleToInt64(dest, dest, temp);
 
-    load32(Address(dest.base, dest.offset + INT64HIGH_OFFSET), temp);
+    load32(HighWord(dest), temp);
     orl(Imm32(0x80000000), temp);
-    store32(temp, Address(dest.base, dest.offset + INT64HIGH_OFFSET));
+    store32(temp, HighWord(dest));
 
     bind(&done);
 }
 
 // ========================================================================
 // wasm support
 
 template <class L>
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -763,40 +763,28 @@ MacroAssembler::wasmLoadI64(const wasm::
         break;
       case Scalar::Uint32:
         movl(srcAddr, out.low);
         append(access, loadOffset, framePushed());
 
         xorl(out.high, out.high);
         break;
       case Scalar::Int64: {
-        Operand low(eax);
-        Operand high(eax);
-
         if (srcAddr.kind() == Operand::MEM_SCALE) {
-            BaseIndex addr = srcAddr.toBaseIndex();
-
-            MOZ_RELEASE_ASSERT(addr.base != out.low && addr.index != out.low);
+            MOZ_RELEASE_ASSERT(srcAddr.toBaseIndex().base != out.low &&
+                               srcAddr.toBaseIndex().index != out.low);
+        }
+        if (srcAddr.kind() == Operand::MEM_REG_DISP)
+            MOZ_RELEASE_ASSERT(srcAddr.toAddress().base != out.low);
 
-            low = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64LOW_OFFSET);
-            high = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64HIGH_OFFSET);
-        } else {
-            Address addr = srcAddr.toAddress();
-
-            MOZ_RELEASE_ASSERT(addr.base != out.low);
-
-            low = Operand(addr.base, addr.offset + INT64LOW_OFFSET);
-            high = Operand(addr.base, addr.offset + INT64HIGH_OFFSET);
-        }
-
-        movl(low, out.low);
+        movl(LowWord(srcAddr), out.low);
         append(access, loadOffset, framePushed());
 
         loadOffset = size();
-        movl(high, out.high);
+        movl(HighWord(srcAddr), out.high);
         append(access, loadOffset, framePushed());
 
         break;
       }
       case Scalar::Float32:
       case Scalar::Float64:
       case Scalar::Float32x4:
       case Scalar::Int8x16:
@@ -877,34 +865,22 @@ MacroAssembler::wasmStore(const wasm::Me
 
 void
 MacroAssembler::wasmStoreI64(const wasm::MemoryAccessDesc& access, Register64 value, Operand dstAddr)
 {
     MOZ_ASSERT(!access.isAtomic());
     MOZ_ASSERT(!access.isSimd());
     MOZ_ASSERT(dstAddr.kind() == Operand::MEM_REG_DISP || dstAddr.kind() == Operand::MEM_SCALE);
 
-    Operand low(eax);
-    Operand high(eax);
-    if (dstAddr.kind() == Operand::MEM_SCALE) {
-        BaseIndex addr = dstAddr.toBaseIndex();
-        low = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64LOW_OFFSET);
-        high = Operand(addr.base, addr.index, addr.scale, addr.offset + INT64HIGH_OFFSET);
-    } else {
-        Address addr = dstAddr.toAddress();
-        low = Operand(addr.base, addr.offset + INT64LOW_OFFSET);
-        high = Operand(addr.base, addr.offset + INT64HIGH_OFFSET);
-    }
-
     size_t storeOffset = size();
-    movl(value.low, low);
+    movl(value.low, LowWord(dstAddr));
     append(access, storeOffset, framePushed());
 
     storeOffset = size();
-    movl(value.high, high);
+    movl(value.high, HighWord(dstAddr));
     append(access, storeOffset, framePushed());
 }
 
 void
 MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output, Label* oolEntry)
 {
     Label done;
     vcvttsd2si(input, output);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -582,20 +582,20 @@ class MacroAssemblerX86 : public MacroAs
         movl(Operand(address), dest);
     }
     void loadPrivate(const Address& src, Register dest) {
         movl(payloadOf(src), dest);
     }
     void load32(AbsoluteAddress address, Register dest) {
         movl(Operand(address), dest);
     }
-    void load64(const Address& address, Register64 dest) {
-        movl(Operand(Address(address.base, address.offset + INT64LOW_OFFSET)), dest.low);
-        int32_t highOffset = (address.offset < 0) ? -int32_t(INT64HIGH_OFFSET) : INT64HIGH_OFFSET;
-        movl(Operand(Address(address.base, address.offset + highOffset)), dest.high);
+    template <typename T>
+    void load64(const T& address, Register64 dest) {
+        movl(Operand(LowWord(address)), dest.low);
+        movl(Operand(HighWord(address)), dest.high);
     }
     template <typename T>
     void storePtr(ImmWord imm, T address) {
         movl(Imm32(imm.value), Operand(address));
     }
     template <typename T>
     void storePtr(ImmPtr imm, T address) {
         storePtr(ImmWord(uintptr_t(imm.value)), address);
@@ -617,23 +617,24 @@ class MacroAssemblerX86 : public MacroAs
         movl(src, Operand(address));
     }
     void store32(Register src, AbsoluteAddress address) {
         movl(src, Operand(address));
     }
     void store16(Register src, AbsoluteAddress address) {
         movw(src, Operand(address));
     }
-    void store64(Register64 src, Address address) {
-        movl(src.low, Operand(Address(address.base, address.offset + INT64LOW_OFFSET)));
-        movl(src.high, Operand(Address(address.base, address.offset + INT64HIGH_OFFSET)));
+    template <typename T>
+    void store64(Register64 src, const T& address) {
+        movl(src.low, Operand(LowWord(address)));
+        movl(src.high, Operand(HighWord(address)));
     }
     void store64(Imm64 imm, Address address) {
-        movl(imm.low(), Operand(Address(address.base, address.offset + INT64LOW_OFFSET)));
-        movl(imm.hi(), Operand(Address(address.base, address.offset + INT64HIGH_OFFSET)));
+        movl(imm.low(), Operand(LowWord(address)));
+        movl(imm.hi(), Operand(HighWord(address)));
     }
 
     void setStackArg(Register reg, uint32_t arg) {
         movl(reg, Operand(esp, arg * sizeof(intptr_t)));
     }
 
     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister temp) {
         if (Assembler::HasSSE41()) {
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -1209,20 +1209,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1275,18 +1275,18 @@ JitRuntime::generateProfilerExitFrameTai
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -143,16 +143,21 @@ JSContext::init(ContextKind kind)
 
 JSContext*
 js::NewContext(uint32_t maxBytes, uint32_t maxNurseryBytes, JSRuntime* parentRuntime)
 {
     AutoNoteSingleThreadedRegion anstr;
 
     MOZ_RELEASE_ASSERT(!TlsContext.get());
 
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+    js::oom::SetThreadType(!parentRuntime ? js::THREAD_TYPE_COOPERATING
+                                          : js::THREAD_TYPE_WORKER);
+#endif
+
     JSRuntime* runtime = js_new<JSRuntime>(parentRuntime);
     if (!runtime)
         return nullptr;
 
     JSContext* cx = js_new<JSContext>(runtime, JS::ContextOptions());
     if (!cx) {
         js_delete(runtime);
         return nullptr;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4501,25 +4501,28 @@ js::gc::MarkingValidator::nonIncremental
         return;
 
     JSRuntime* runtime = gc->rt;
     GCMarker* gcmarker = &gc->marker;
 
     gc->waitBackgroundSweepEnd();
 
     /* Save existing mark bits. */
-    for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
-        ChunkBitmap* bitmap = &chunk->bitmap;
-        ChunkBitmap* entry = js_new<ChunkBitmap>();
-        if (!entry)
-            return;
-
-        memcpy((void*)entry->bitmap, (void*)bitmap->bitmap, sizeof(bitmap->bitmap));
-        if (!map.putNew(chunk, entry))
-            return;
+    {
+        AutoLockGC lock(runtime);
+        for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) {
+            ChunkBitmap* bitmap = &chunk->bitmap;
+            ChunkBitmap* entry = js_new<ChunkBitmap>();
+            if (!entry)
+                return;
+
+            memcpy((void*)entry->bitmap, (void*)bitmap->bitmap, sizeof(bitmap->bitmap));
+            if (!map.putNew(chunk, entry))
+                return;
+        }
     }
 
     /*
      * Temporarily clear the weakmaps' mark flags for the compartments we are
      * collecting.
      */
 
     WeakMapSet markedWeakMaps;
@@ -4565,17 +4568,18 @@ js::gc::MarkingValidator::nonIncremental
             gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::UNMARK);
 
             for (GCZonesIter zone(runtime); !zone.done(); zone.next())
                 WeakMapBase::unmarkZone(zone);
 
             MOZ_ASSERT(gcmarker->isDrained());
             gcmarker->reset();
 
-            for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next())
+            AutoLockGC lock(runtime);
+            for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next())
                 chunk->bitmap.clear();
         }
     }
 
     {
         gcstats::AutoPhase ap(gc->stats(), gcstats::PhaseKind::MARK);
 
         gc->traceRuntimeForMajorGC(gcmarker, lock);
@@ -4603,20 +4607,23 @@ js::gc::MarkingValidator::nonIncremental
         /* Restore zone state. */
         for (GCZonesIter zone(runtime); !zone.done(); zone.next())
             zone->changeGCState(Zone::MarkGray, Zone::Mark);
         MOZ_ASSERT(gc->marker.isDrained());
         gc->marker.setMarkColorBlack();
     }
 
     /* Take a copy of the non-incremental mark state and restore the original. */
-    for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
-        ChunkBitmap* bitmap = &chunk->bitmap;
-        ChunkBitmap* entry = map.lookup(chunk)->value();
-        Swap(*entry, *bitmap);
+    {
+        AutoLockGC lock(runtime);
+        for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) {
+            ChunkBitmap* bitmap = &chunk->bitmap;
+            ChunkBitmap* entry = map.lookup(chunk)->value();
+            Swap(*entry, *bitmap);
+        }
     }
 
     for (GCZonesIter zone(runtime); !zone.done(); zone.next()) {
         WeakMapBase::unmarkZone(zone);
         AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!zone->gcWeakKeys().clear())
             oomUnsafe.crash("clearing weak keys table for validator");
     }
@@ -4641,17 +4648,18 @@ js::gc::MarkingValidator::validate()
      * the mark bits to those previously recorded for a non-incremental mark.
      */
 
     if (!initialized)
         return;
 
     gc->waitBackgroundSweepEnd();
 
-    for (auto chunk = gc->allNonEmptyChunks(); !chunk.done(); chunk.next()) {
+    AutoLockGC lock(gc->rt);
+    for (auto chunk = gc->allNonEmptyChunks(lock); !chunk.done(); chunk.next()) {
         BitmapMap::Ptr ptr = map.lookup(chunk);
         if (!ptr)
             continue;  /* Allocated after we did the non-incremental mark. */
 
         ChunkBitmap* bitmap = ptr->value();
         ChunkBitmap* incBitmap = &chunk->bitmap;
 
         for (size_t i = 0; i < ArenasPerChunk; i++) {
--- a/js/src/vm/Initialization.cpp
+++ b/js/src/vm/Initialization.cpp
@@ -93,17 +93,16 @@ JS::detail::InitWithFailureDiagnostic(bo
 #ifdef DEBUG
     CheckMessageParameterCounts();
 #endif
 
     RETURN_IF_FAIL(js::TlsContext.init());
 
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     RETURN_IF_FAIL(js::oom::InitThreadType());
-    js::oom::SetThreadType(js::THREAD_TYPE_COOPERATING);
 #endif
 
     RETURN_IF_FAIL(js::Mutex::Init());
 
     RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
 
     js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works.
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -433,42 +433,32 @@ js::RunScript(JSContext* cx, RunState& s
     }
 
     return Interpret(cx, state);
 }
 #ifdef _MSC_VER
 # pragma optimize("", on)
 #endif
 
-struct AutoGCIfRequested
-{
-    JSRuntime* runtime;
-    explicit AutoGCIfRequested(JSRuntime* rt) : runtime(rt) {}
-    ~AutoGCIfRequested() { runtime->gc.gcIfRequested(); }
-};
-
 /*
  * Find a function reference and its 'this' value implicit first parameter
  * under argc arguments on cx's stack, and call the function.  Push missing
  * required arguments, allocate declared local variables, and pop everything
  * when done.  Then push the return value.
  *
  * Note: This function DOES NOT call GetThisValue to munge |args.thisv()| if
  *       necessary.  The caller (usually the interpreter) must have performed
  *       this step already!
  */
 bool
 js::InternalCallOrConstruct(JSContext* cx, const CallArgs& args, MaybeConstruct construct)
 {
     MOZ_ASSERT(args.length() <= ARGS_LENGTH_MAX);
     MOZ_ASSERT(!cx->zone()->types.activeAnalysis);
 
-    /* Perform GC if necessary on exit from the function. */
-    AutoGCIfRequested gcIfRequested(cx->runtime());
-
     unsigned skipForCallee = args.length() + 1 + (construct == CONSTRUCT);
     if (args.calleev().isPrimitive())
         return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct);
 
     /* Invoke non-functions. */
     if (MOZ_UNLIKELY(!args.callee().is<JSFunction>())) {
         MOZ_ASSERT_IF(construct, !args.callee().constructHook());
         JSNative call = args.callee().callHook();
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -256,17 +256,20 @@ class ExecuteState : public RunState
                  JSObject& envChain, AbstractFramePtr evalInFrame, Value* result)
       : RunState(cx, Execute, script),
         newTargetValue_(cx, newTargetValue),
         envChain_(cx, &envChain),
         evalInFrame_(evalInFrame),
         result_(result)
     { }
 
-    Value newTarget() { return newTargetValue_; }
+    Value newTarget() const { return newTargetValue_; }
+    void setNewTarget(const Value& v) { newTargetValue_ = v; }
+    Value* addressOfNewTarget() { return newTargetValue_.address(); }
+
     JSObject* environmentChain() const { return envChain_; }
     bool isDebuggerEval() const { return !!evalInFrame_; }
 
     virtual InterpreterFrame* pushInterpreterFrame(JSContext* cx);
 
     virtual void setReturnValue(const Value& v) {
         if (result_)
             *result_ = v;
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -2516,19 +2516,19 @@ class BaseCompiler
             ABIArg argLoc = call.abi.next(MIRType::Int64);
             if (argLoc.kind() == ABIArg::Stack) {
                 ScratchI32 scratch(*this);
 #if defined(JS_CODEGEN_X64)
                 loadI64(Register64(scratch), arg);
                 masm.movq(scratch, Operand(StackPointer, argLoc.offsetFromArgBase()));
 #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
                 loadI64Low(scratch, arg);
-                masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64LOW_OFFSET));
+                masm.store32(scratch, LowWord(Address(StackPointer, argLoc.offsetFromArgBase())));
                 loadI64High(scratch, arg);
-                masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64HIGH_OFFSET));
+                masm.store32(scratch, HighWord(Address(StackPointer, argLoc.offsetFromArgBase())));
 #else
                 MOZ_CRASH("BaseCompiler platform hook: passArg I64");
 #endif
             } else {
                 loadI64(argLoc.gpr64(), arg);
             }
             break;
           }
--- a/js/src/wasm/WasmStubs.cpp
+++ b/js/src/wasm/WasmStubs.cpp
@@ -134,20 +134,20 @@ SetupABIArguments(MacroAssembler& masm, 
             switch (type) {
               case MIRType::Int32:
                 masm.load32(src, scratch);
                 masm.storePtr(scratch, Address(masm.getStackPointer(), iter->offsetFromArgBase()));
                 break;
               case MIRType::Int64: {
                 Register sp = masm.getStackPointer();
 #if JS_BITS_PER_WORD == 32
-                masm.load32(Address(src.base, src.offset + INT64LOW_OFFSET), scratch);
-                masm.store32(scratch, Address(sp, iter->offsetFromArgBase() + INT64LOW_OFFSET));
-                masm.load32(Address(src.base, src.offset + INT64HIGH_OFFSET), scratch);
-                masm.store32(scratch, Address(sp, iter->offsetFromArgBase() + INT64HIGH_OFFSET));
+                masm.load32(LowWord(src), scratch);
+                masm.store32(scratch, LowWord(Address(sp, iter->offsetFromArgBase())));
+                masm.load32(HighWord(src), scratch);
+                masm.store32(scratch, HighWord(Address(sp, iter->offsetFromArgBase())));
 #else
                 Register64 scratch64(scratch);
                 masm.load64(src, scratch64);
                 masm.store64(scratch64, Address(sp, iter->offsetFromArgBase()));
 #endif
                 break;
               }
               case MIRType::Double:
@@ -379,20 +379,20 @@ GenerateEntry(MacroAssembler& masm, cons
 static void
 StackCopy(MacroAssembler& masm, MIRType type, Register scratch, Address src, Address dst)
 {
     if (type == MIRType::Int32) {
         masm.load32(src, scratch);
         masm.store32(scratch, dst);
     } else if (type == MIRType::Int64) {
 #if JS_BITS_PER_WORD == 32
-        masm.load32(Address(src.base, src.offset + INT64LOW_OFFSET), scratch);
-        masm.store32(scratch, Address(dst.base, dst.offset + INT64LOW_OFFSET));
-        masm.load32(Address(src.base, src.offset + INT64HIGH_OFFSET), scratch);
-        masm.store32(scratch, Address(dst.base, dst.offset + INT64HIGH_OFFSET));
+        masm.load32(LowWord(src), scratch);
+        masm.store32(scratch, LowWord(dst));
+        masm.load32(HighWord(src), scratch);
+        masm.store32(scratch, HighWord(dst));
 #else
         Register64 scratch64(scratch);
         masm.load64(src, scratch64);
         masm.store64(scratch64, dst);
 #endif
     } else if (type == MIRType::Float32) {
         masm.loadFloat32(src, ScratchFloat32Reg);
         masm.storeFloat32(ScratchFloat32Reg, dst);
@@ -785,17 +785,24 @@ GenerateImportJitExit(MacroAssembler& ma
     //   (sp + sizeof(void*)) % JitStackAlignment == 0
     // But now we possibly want to call one of several different C++ functions,
     // so subtract the sizeof(void*) so that sp is aligned for an ABI call.
     static_assert(ABIStackAlignment <= JitStackAlignment, "subsumes");
     masm.reserveStack(sizeOfRetAddr);
     unsigned nativeFramePushed = masm.framePushed();
     AssertStackAlignment(masm, ABIStackAlignment);
 
-    masm.branchTestMagic(Assembler::Equal, JSReturnOperand, throwLabel);
+#ifdef DEBUG
+    {
+        Label ok;
+        masm.branchTestMagic(Assembler::NotEqual, JSReturnOperand, &ok);
+        masm.breakpoint();
+        masm.bind(&ok);
+    }
+#endif
 
     Label oolConvert;
     switch (fi.sig().ret()) {
       case ExprType::Void:
         break;
       case ExprType::I32:
         masm.convertValueToInt32(JSReturnOperand, ReturnDoubleReg, ReturnReg, &oolConvert,
                                  /* -0 check */ false);
@@ -877,25 +884,22 @@ GenerateImportJitExit(MacroAssembler& ma
         AssertStackAlignment(masm, ABIStackAlignment);
         switch (fi.sig().ret()) {
           case ExprType::I32:
             masm.call(SymbolicAddress::CoerceInPlace_ToInt32);
             masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
             masm.unboxInt32(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnReg);
             break;
           case ExprType::F64:
-            masm.call(SymbolicAddress::CoerceInPlace_ToNumber);
-            masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
-            masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
-            break;
           case ExprType::F32:
             masm.call(SymbolicAddress::CoerceInPlace_ToNumber);
             masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
             masm.loadDouble(Address(masm.getStackPointer(), offsetToCoerceArgv), ReturnDoubleReg);
-            masm.convertDoubleToFloat32(ReturnDoubleReg, ReturnFloat32Reg);
+            if (fi.sig().ret() == ExprType::F32)
+                masm.convertDoubleToFloat32(ReturnDoubleReg, ReturnFloat32Reg);
             break;
           default:
             MOZ_CRASH("Unsupported convert type");
         }
 
         // Maintain the invariant that exitFP is either unset or not set to a
         // wasm tagged exitFP, per the jit exit contract.
         ClearExitFP(masm, scratch);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -116,17 +116,17 @@
 #include "mozilla/Telemetry.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "RegionBuilder.h"
-#include "SVGSVGElement.h"
+#include "SVGViewportElement.h"
 #include "DisplayItemClip.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "prenv.h"
 #include "TextDrawTarget.h"
 #include "nsDeckFrame.h"
 #include "nsIEffectiveTLDService.h" // for IsInStyloBlocklist
 
 #ifdef MOZ_XUL
@@ -9760,17 +9760,17 @@ ComputeSVGReferenceRect(nsIFrame* aFrame
                 nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke);
       r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
                                          nsPresContext::AppUnitsPerCSSPixel());
       break;
     }
     case StyleGeometryBox::ViewBox: {
       nsIContent* content = aFrame->GetContent();
       nsSVGElement* element = static_cast<nsSVGElement*>(content);
-      SVGSVGElement* svgElement = element->GetCtx();
+      SVGViewportElement* svgElement = element->GetCtx();
       MOZ_ASSERT(svgElement);
 
       if (svgElement && svgElement->HasViewBoxRect()) {
         // If a ‘viewBox‘ attribute is specified for the SVG viewport creating
         // element:
         // 1. The reference box is positioned at the origin of the coordinate
         //    system established by the ‘viewBox‘ attribute.
         // 2. The dimension of the reference box is set to the width and height
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -526,16 +526,17 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-
 == use-localRef-mask-01.svg use-localRef-mask-01-ref.svg
 
 == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
 
 == viewBox-and-pattern-01.svg pass.svg
 == viewBox-and-pattern-02.svg pass.svg
 == viewBox-and-pattern-03.svg pass.svg
 == viewBox-and-pattern-04.svg pass.svg
+== viewBox-and-symbol-01.svg pass.svg
 == viewBox-invalid-01.svg pass.svg
 == viewBox-invalid-02.svg pass.svg
 == viewBox-valid-01.svg pass.svg
 == viewBox-valid-02.xhtml pass.svg
 == viewport-percent-graphic-user-01.svg pass.svg
 == winding-01.svg pass.svg
 
 == zero-stroke-01.svg pass.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/viewBox-and-symbol-01.svg
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <symbol id="mySymbol" viewBox="0 0 20 20">
+      <rect fill="lime" x="50%" height="20px" width="3%"/>
+    </symbol>
+  </defs>
+  <rect width="100%" height="100%" fill="lime"/>
+  <svg viewBox="0 0 20 20">
+    <rect fill="red" x="50%" height="20px" width="2%"/>
+  </svg>
+  <svg>
+    <use href="#mySymbol"/>
+  </svg>
+</svg>
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Main header first:
 #include "nsCSSClipPathInstance.h"
 
 #include "gfx2DGlue.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
-#include "mozilla/dom/SVGSVGElement.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/ShapeUtils.h"
 #include "nsCSSRendering.h"
 #include "nsIFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsRuleNode.h"
 #include "nsSVGElement.h"
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -11,17 +11,16 @@
 #include "mozilla/gfx/2D.h"
 #include "imgIContainer.h"
 #include "nsContainerFrame.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIImageLoadingContent.h"
 #include "nsLayoutUtils.h"
 #include "imgINotificationObserver.h"
 #include "SVGObserverUtils.h"
-#include "mozilla/dom/SVGSVGElement.h"
 #include "nsSVGUtils.h"
 #include "SVGContentUtils.h"
 #include "SVGGeometryFrame.h"
 #include "SVGImageContext.h"
 #include "mozilla/dom/SVGImageElement.h"
 #include "nsContentUtils.h"
 #include "nsIReflowCallback.h"
 #include "mozilla/Unused.h"
--- a/layout/svg/nsSVGImageFrame.h
+++ b/layout/svg/nsSVGImageFrame.h
@@ -12,17 +12,16 @@
 #include "mozilla/gfx/2D.h"
 #include "imgIContainer.h"
 #include "nsContainerFrame.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsIImageLoadingContent.h"
 #include "nsLayoutUtils.h"
 #include "imgINotificationObserver.h"
 #include "SVGObserverUtils.h"
-#include "mozilla/dom/SVGSVGElement.h"
 #include "nsSVGUtils.h"
 #include "SVGContentUtils.h"
 #include "SVGGeometryFrame.h"
 #include "SVGImageContext.h"
 #include "mozilla/dom/SVGImageElement.h"
 #include "nsContentUtils.h"
 #include "nsIReflowCallback.h"
 #include "mozilla/Unused.h"
--- a/layout/svg/nsSVGMarkerFrame.cpp
+++ b/layout/svg/nsSVGMarkerFrame.cpp
@@ -189,17 +189,17 @@ nsSVGMarkerFrame::GetMarkBBoxContributio
   // We need to include zero width/height vertical/horizontal lines, so we have
   // to use UnionEdges.
   bbox.UnionEdges(child->GetBBoxContribution(tm, aFlags));
 
   return bbox;
 }
 
 void
-nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext)
+nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGViewportElement *aContext)
 {
   SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(GetContent());
   marker->SetParentCoordCtxProvider(aContext);
 }
 
 void
 nsSVGMarkerFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
 {
@@ -214,17 +214,17 @@ nsSVGMarkerFrame::AutoMarkerReferencer::
     SVGGeometryFrame *aMarkedFrame
     MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
       : mFrame(aFrame)
 {
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   mFrame->mInUse = true;
   mFrame->mMarkedFrame = aMarkedFrame;
 
-  SVGSVGElement *ctx =
+  SVGViewportElement *ctx =
     static_cast<nsSVGElement*>(aMarkedFrame->GetContent())->GetCtx();
   mFrame->SetParentCoordCtxProvider(ctx);
 }
 
 nsSVGMarkerFrame::AutoMarkerReferencer::~AutoMarkerReferencer()
 {
   mFrame->SetParentCoordCtxProvider(nullptr);
 
--- a/layout/svg/nsSVGMarkerFrame.h
+++ b/layout/svg/nsSVGMarkerFrame.h
@@ -15,17 +15,17 @@
 #include "nsSVGContainerFrame.h"
 #include "nsSVGUtils.h"
 
 class gfxContext;
 
 namespace mozilla {
 class SVGGeometryFrame;
 namespace dom {
-class SVGSVGElement;
+class SVGViewportElement;
 } // namespace dom
 } // namespace mozilla
 
 struct nsSVGMark;
 
 class nsSVGMarkerFrame final : public nsSVGContainerFrame
 {
   typedef mozilla::image::imgDrawingParams imgDrawingParams;
@@ -113,17 +113,17 @@ private:
                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
     ~AutoMarkerReferencer();
   private:
     nsSVGMarkerFrame *mFrame;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   };
 
   // nsSVGMarkerFrame methods:
-  void SetParentCoordCtxProvider(mozilla::dom::SVGSVGElement *aContext);
+  void SetParentCoordCtxProvider(mozilla::dom::SVGViewportElement *aContext);
 
   // recursion prevention flag
   bool mInUse;
 
   // second recursion prevention flag, for GetCanvasTM()
   bool mInUse2;
 };
 
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -655,17 +655,17 @@ nsSVGPatternFrame::GetPatternRect(uint16
 gfxMatrix
 nsSVGPatternFrame::ConstructCTM(const nsSVGViewBox& aViewBox,
                                 uint16_t aPatternContentUnits,
                                 uint16_t aPatternUnits,
                                 const gfxRect &callerBBox,
                                 const Matrix &callerCTM,
                                 nsIFrame *aTarget)
 {
-  SVGSVGElement *ctx = nullptr;
+  SVGViewportElement *ctx = nullptr;
   nsIContent* targetContent = aTarget->GetContent();
   gfxFloat scaleX, scaleY;
 
   // The objectBoundingBox conversion must be handled in the CTM:
   if (IncludeBBoxScale(aViewBox, aPatternContentUnits, aPatternUnits)) {
     scaleX = callerBBox.Width();
     scaleY = callerBBox.Height();
   } else {
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -44,17 +44,17 @@
 #include "nsSVGLength2.h"
 #include "nsSVGMaskFrame.h"
 #include "nsSVGOuterSVGFrame.h"
 #include "mozilla/dom/SVGClipPathElement.h"
 #include "mozilla/dom/SVGPathElement.h"
 #include "SVGGeometryElement.h"
 #include "SVGGeometryFrame.h"
 #include "nsSVGPaintServerFrame.h"
-#include "mozilla/dom/SVGSVGElement.h"
+#include "mozilla/dom/SVGViewportElement.h"
 #include "nsTextFrame.h"
 #include "SVGContentUtils.h"
 #include "SVGTextFrame.h"
 #include "mozilla/Unused.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
@@ -285,17 +285,17 @@ nsSVGUtils::NotifyAncestorsOfFilterRegio
 Size
 nsSVGUtils::GetContextSize(const nsIFrame* aFrame)
 {
   Size size;
 
   MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "bad cast");
   const nsSVGElement* element = static_cast<nsSVGElement*>(aFrame->GetContent());
 
-  SVGSVGElement* ctx = element->GetCtx();
+  SVGViewportElement* ctx = element->GetCtx();
   if (ctx) {
     size.width = ctx->GetLength(SVGContentUtils::X);
     size.height = ctx->GetLength(SVGContentUtils::Y);
   }
   return size;
 }
 
 float
@@ -318,17 +318,17 @@ nsSVGUtils::ObjectSpace(const gfxRect &a
     NS_NOTREACHED("unexpected ctx type");
     axis = 0.0f;
     break;
   }
   if (aLength->IsPercentage()) {
     // Multiply first to avoid precision errors:
     return axis * aLength->GetAnimValInSpecifiedUnits() / 100;
   }
-  return aLength->GetAnimValue(static_cast<SVGSVGElement*>(nullptr)) * axis;
+  return aLength->GetAnimValue(static_cast<SVGViewportElement*>(nullptr)) * axis;
 }
 
 float
 nsSVGUtils::UserSpace(nsSVGElement *aSVGElement, const nsSVGLength2 *aLength)
 {
   return aLength->GetAnimValue(aSVGElement);
 }
 
--- a/python/mozboot/mozboot/osx.py
+++ b/python/mozboot/mozboot/osx.py
@@ -370,17 +370,17 @@ class OSXBootstrapper(BaseBootstrapper):
         missing = [package for package in packages if package not in installed]
         if missing:
             print(PACKAGE_MANAGER_PACKAGES % ('MacPorts',))
             self.run_as_root([self.port, '-v', 'install'] + missing)
 
     def ensure_macports_system_packages(self):
         packages = [
             'python27',
-            'py27-readline',
+            'py27-gnureadline',
             'mercurial',
             'autoconf213',
             'gnutar',
             'watchman',
         ]
 
         self._ensure_macports_packages(packages)
         self.run_as_root([self.port, 'select', '--set', 'python', 'python27'])
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "sandboxBroker.h"
 
 #include <string>
+#include <vector>
 
 #include "base/win/windows_version.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Logging.h"
 #include "mozilla/NSPRLogModulesParser.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Telemetry.h"
@@ -23,20 +24,36 @@
 #include "nsIProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 #include "sandbox/win/src/sandbox.h"
 #include "sandbox/win/src/security_level.h"
 #include "WinUtils.h"
 
-// We're just blocking one DLL for the moment because of problems with the
-// Alternate Desktop. If and when we expand this we'll make this a static list
-// and add checking to see if DLL is loaded in the parent.
-#define WEBROOT_DLL L"WRusr.dll"
+// This list of DLLs have been found to cause instability in sandboxed child
+// processes and so they will be unloaded if they attempt to load.
+const std::vector<std::wstring> kDllsToUnload = {
+  // HitmanPro - SurfRight now part of Sophos (bug 1400637)
+  L"hmpalert.dll",
+
+  // K7 Computing (bug 1400637)
+  L"k7pswsen.dll",
+
+  // Symantec (bug 1400637)
+  L"prntm64.dll",
+  L"sysfer.dll",
+
+  // Avast Antivirus (bug 1400637)
+  L"snxhk64.dll",
+  L"snxhk.dll",
+
+  // Webroot SecureAnywhere (bug 1400637)
+  L"wrusr.dll",
+};
 
 namespace mozilla
 {
 
 sandbox::BrokerServices *SandboxBroker::sBrokerService = nullptr;
 
 // This is set to true in Initialize when our exe file name has a drive type of
 // DRIVE_REMOTE, so that we can tailor the sandbox policy as some settings break
@@ -211,19 +228,30 @@ SandboxBroker::LaunchApp(const wchar_t *
   }
 
   logFileName = _wgetenv(L"NSPR_LOG_FILE");
   if (logFileName) {
     mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
                      sandbox::TargetPolicy::FILES_ALLOW_ANY, logFileName);
   }
 
+  // Add DLLs to the policy that have been found to cause instability with the
+  // sandbox, so that they will be unloaded when they attempt to load.
+  sandbox::ResultCode result;
+  for (std::wstring dllToUnload : kDllsToUnload) {
+    // Similar to Chromium, we only add a DLL if it is loaded in this process.
+    if (::GetModuleHandleW(dllToUnload.c_str())) {
+      result = mPolicy->AddDllToUnload(dllToUnload.c_str());
+      MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
+                         "AddDllToUnload should never fail, what happened?");
+    }
+  }
+
   // Ceate the sandboxed process
   PROCESS_INFORMATION targetInfo = {0};
-  sandbox::ResultCode result;
   sandbox::ResultCode last_warning = sandbox::SBOX_ALL_OK;
   DWORD last_error = ERROR_SUCCESS;
   result = sBrokerService->SpawnTarget(aPath, aArguments, mPolicy,
                                        &last_warning, &last_error, &targetInfo);
   if (sandbox::SBOX_ALL_OK != result) {
     nsAutoCString key;
     key.AppendASCII(XRE_ChildProcessTypeToString(aProcessType));
     key.AppendLiteral("/0x");
@@ -440,22 +468,16 @@ SandboxBroker::SetSecurityLevelForConten
     sandbox::MITIGATION_DEP |
     sandbox::MITIGATION_EXTENSION_POINT_DISABLE;
 
   if (aSandboxLevel > 3) {
     result = mPolicy->SetAlternateDesktop(false);
     MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
                        "Failed to create alternate desktop for sandbox.");
 
-    // Webroot SecureAnywhere causes crashes when we use an Alternate Desktop,
-    // so block the DLL from loading in the child process. (bug 1400637)
-    result = mPolicy->AddDllToUnload(WEBROOT_DLL);
-    MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
-                       "AddDllToUnload should never fail, what happened?");
-
     mitigations |= sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL;
     // If we're running from a network drive then we can't block loading from
     // remote locations.
     if (!sRunningFromNetworkDrive) {
       mitigations |= sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE;
     }
   }
 
@@ -828,22 +850,16 @@ SandboxBroker::SetSecurityLevelForGMPlug
   result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, level);
   SANDBOX_ENSURE_SUCCESS(result,
                          "SetTokenLevel should never fail with these arguments, what happened?");
 
   result = mPolicy->SetAlternateDesktop(true);
   SANDBOX_ENSURE_SUCCESS(result,
                          "Failed to create alternate desktop for sandbox.");
 
-  // Webroot SecureAnywhere causes crashes when we use an Alternate Desktop,
-  // so block the DLL from loading in the child process. (bug 1400637)
-  result = mPolicy->AddDllToUnload(WEBROOT_DLL);
-  MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
-                     "AddDllToUnload should never fail, what happened?");
-
   result = mPolicy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
   MOZ_ASSERT(sandbox::SBOX_ALL_OK == result,
              "SetIntegrityLevel should never fail with these arguments, what happened?");
 
   result =
     mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
   SANDBOX_ENSURE_SUCCESS(result,
                          "SetIntegrityLevel should never fail with these arguments, what happened?");