Browse Source

more wip js

Frank-Rainer Grahl 9 months ago
parent
commit
218ccb26ed

+ 12 - 12
mozilla-release/patches/1429206-3no2-60a1.patch

@@ -2,7 +2,7 @@
 # User Jason Orendorff <jorendorff@mozilla.com>
 # Date 1518458617 21600
 # Node ID eabb74b1c3bd181ff74c9d41003bc2b9aee6fe68
-# Parent  08ba879bf6c3b06c917658816360662293aaaaf8
+# Parent  030a3083b39c6cac4ffe641b9bafee7549676662
 Bug 1429206 - Part 3: Rename jsobj* -> vm/JSObject*. r=jandem.
 
 diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py
@@ -3130,14 +3130,14 @@ rename to js/src/vm/JSObject.h
 +#ifndef vm_JSObject_h
 +#define vm_JSObject_h
  
- /*
-  * JS object definitions.
-  *
-  * A JS object consists of a possibly-shared object descriptor containing
-  * ordered property names, called the map; and a dense vector of property
-  * values, called slots.  The map/slot pointer pair is GC'ed, while the map
-  * is reference counted and the slot vector is malloc'ed.
-@@ -1329,9 +1329,9 @@ IsObjectValueInCompartment(const Value& 
+ #include "mozilla/MemoryReporting.h"
+ 
+ #include "gc/Barrier.h"
+ #include "js/Conversions.h"
+ #include "js/GCVector.h"
+ #include "js/HeapAPI.h"
+ #include "vm/Printer.h"
+@@ -1350,9 +1350,9 @@ IsObjectValueInCompartment(const Value& 
      if (!v.isObject())
          return true;
      return v.toObject().compartment() == comp;
@@ -3651,10 +3651,10 @@ diff --git a/js/src/vm/ShapedObject.h b/js/src/vm/ShapedObject.h
  namespace js {
  
  /*
-  * Shaped objects extend the base implementation of an object with a shape
-  * field.  Subclasses of ShapedObject ascribe meaning to this field.
+  * Shaped objects are a variant of JSObject that use a GCPtrShape for their
+  * |shapeOrExpando_| field. All objects that point to a js::Shape as their
+  * |shapeOrExpando_| field should use this as their subclass.
   *
-  * ShapedObject is only created as the base class of some other class.  It's
 diff --git a/js/src/vm/SharedArrayObject.cpp b/js/src/vm/SharedArrayObject.cpp
 --- a/js/src/vm/SharedArrayObject.cpp
 +++ b/js/src/vm/SharedArrayObject.cpp

+ 695 - 0
mozilla-release/patches/1433837-5-60a1.patch

@@ -0,0 +1,695 @@
+# HG changeset patch
+# User Ted Campbell <tcampbell@mozilla.com>
+# Date 1517224740 -7200
+#      Mon Jan 29 13:19:00 2018 +0200
+# Node ID 8009cda1a18e5e2f7bcb5b970ecab9637d124dd9
+# Parent  ee2d404c4a84b0438f1cf1711d1c096e1e72f6f3
+Bug 1433837 - Use accessors for ShapedObject::shape_ field. r=jandem
+MozReview-Commit-ID: 4Kw6iAudVyH
+
+diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
+--- a/js/src/builtin/TypedObject.cpp
++++ b/js/src/builtin/TypedObject.cpp
+@@ -1598,17 +1598,17 @@ ReportTypedObjTypeError(JSContext* cx,
+     return false;
+ }
+ 
+ /* static */ void
+ OutlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
+ {
+     OutlineTypedObject& typedObj = object->as<OutlineTypedObject>();
+ 
+-    TraceEdge(trc, &typedObj.shape_, "OutlineTypedObject_shape");
++    TraceEdge(trc, typedObj.shapePtr(), "OutlineTypedObject_shape");
+ 
+     if (!typedObj.owner_)
+         return;
+ 
+     TypeDescr& descr = typedObj.typeDescr();
+ 
+     // Mark the owner, watching in case it is moved by the tracer.
+     JSObject* oldOwner = typedObj.owner_;
+@@ -2110,17 +2110,17 @@ InlineTypedObject::createCopy(JSContext*
+     return res;
+ }
+ 
+ /* static */ void
+ InlineTypedObject::obj_trace(JSTracer* trc, JSObject* object)
+ {
+     InlineTypedObject& typedObj = object->as<InlineTypedObject>();
+ 
+-    TraceEdge(trc, &typedObj.shape_, "InlineTypedObject_shape");
++    TraceEdge(trc, typedObj.shapePtr(), "InlineTypedObject_shape");
+ 
+     // Inline transparent objects do not have references and do not need more
+     // tracing. If there is an entry in the compartment's LazyArrayBufferTable,
+     // tracing that reference will be taken care of by the table itself.
+     if (typedObj.is<InlineTransparentTypedObject>())
+         return;
+ 
+     typedObj.typeDescr().traceInstances(trc, typedObj.inlineTypedMem(), 1);
+diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h
+--- a/js/src/builtin/TypedObject.h
++++ b/js/src/builtin/TypedObject.h
+@@ -587,17 +587,19 @@ class TypedObject : public ShapedObject
+     // User-accessible constructor (`new TypeDescriptor(...)`). Note that the
+     // callee here is the type descriptor.
+     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
+ 
+     /* Accessors for self hosted code. */
+     static MOZ_MUST_USE bool GetBuffer(JSContext* cx, unsigned argc, Value* vp);
+     static MOZ_MUST_USE bool GetByteOffset(JSContext* cx, unsigned argc, Value* vp);
+ 
+-    Shape** addressOfShapeFromGC() { return shape_.unsafeUnbarrieredForTracing(); }
++    Shape** addressOfShapeFromGC() {
++        return shapeRef().unsafeUnbarrieredForTracing();
++    }
+ };
+ 
+ typedef Handle<TypedObject*> HandleTypedObject;
+ 
+ class OutlineTypedObject : public TypedObject
+ {
+     // The object which owns the data this object points to. Because this
+     // pointer is managed in tandem with |data|, this is not a GCPtr and
+diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
+--- a/js/src/jsobj.cpp
++++ b/js/src/jsobj.cpp
+@@ -1526,20 +1526,20 @@ NativeObject::fillInAfterSwap(JSContext*
+ {
+     // This object has just been swapped with some other object, and its shape
+     // no longer reflects its allocated size. Correct this information and
+     // fill the slots in with the specified values.
+     MOZ_ASSERT(obj->slotSpan() == values.length());
+ 
+     // Make sure the shape's numFixedSlots() is correct.
+     size_t nfixed = gc::GetGCKindSlots(obj->asTenured().getAllocKind(), obj->getClass());
+-    if (nfixed != obj->shape_->numFixedSlots()) {
++    if (nfixed != obj->shape()->numFixedSlots()) {
+         if (!NativeObject::generateOwnShape(cx, obj))
+             return false;
+-        obj->shape_->setNumFixedSlots(nfixed);
++        obj->shape()->setNumFixedSlots(nfixed);
+     }
+ 
+     if (obj->hasPrivate())
+         obj->setPrivate(priv);
+     else
+         MOZ_ASSERT(!priv);
+ 
+     if (obj->slots_) {
+@@ -1559,17 +1559,17 @@ NativeObject::fillInAfterSwap(JSContext*
+ }
+ 
+ void
+ JSObject::fixDictionaryShapeAfterSwap()
+ {
+     // Dictionary shapes can point back to their containing objects, so after
+     // swapping the guts of those objects fix the pointers up.
+     if (isNative() && as<NativeObject>().inDictionaryMode())
+-        as<NativeObject>().shape_->listp = &as<NativeObject>().shape_;
++        as<NativeObject>().shape()->listp = as<NativeObject>().shapePtr();
+ }
+ 
+ static MOZ_MUST_USE bool
+ CopyProxyValuesBeforeSwap(ProxyObject* proxy, Vector<Value>& values)
+ {
+     MOZ_ASSERT(values.empty());
+ 
+     // Remove the GCPtrValues we're about to swap from the store buffer, to
+diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
+--- a/js/src/jsobjinlines.h
++++ b/js/src/jsobjinlines.h
+@@ -134,29 +134,29 @@ JSObject::finalize(js::FreeOp* fop)
+ 
+ MOZ_ALWAYS_INLINE void
+ js::NativeObject::sweepDictionaryListPointer()
+ {
+     // For dictionary objects (which must be native), it's possible that
+     // unreachable shapes may be marked whose listp points into this object.  In
+     // case this happens, null out the shape's pointer so that a moving GC will
+     // not try to access the dead object.
+-    if (shape_->listp == &shape_)
+-        shape_->listp = nullptr;
++    if (shape()->listp == shapePtr())
++        shape()->listp = nullptr;
+ }
+ 
+ MOZ_ALWAYS_INLINE void
+ js::NativeObject::updateDictionaryListPointerAfterMinorGC(NativeObject* old)
+ {
+     MOZ_ASSERT(this == Forwarded(old));
+ 
+     // Dictionary objects can be allocated in the nursery and when they are
+     // tenured the shape's pointer into the object needs to be updated.
+-    if (shape_->listp == &old->shape_)
+-        shape_->listp = &shape_;
++    if (shape()->listp == old->shapePtr())
++        shape()->listp = shapePtr();
+ }
+ 
+ inline void
+ js::gc::MakeAccessibleAfterMovingGC(JSObject* obj)
+ {
+     if (obj->isNative())
+         obj->as<NativeObject>().updateShapeAfterMovingGC();
+ }
+diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp
+--- a/js/src/proxy/Proxy.cpp
++++ b/js/src/proxy/Proxy.cpp
+@@ -680,17 +680,17 @@ ProxyObject::traceEdgeToTarget(JSTracer*
+     TraceCrossCompartmentEdge(trc, obj, obj->slotOfPrivate(), "proxy target");
+ }
+ 
+ /* static */ void
+ ProxyObject::trace(JSTracer* trc, JSObject* obj)
+ {
+     ProxyObject* proxy = &obj->as<ProxyObject>();
+ 
+-    TraceEdge(trc, &proxy->shape_, "ProxyObject_shape");
++    TraceEdge(trc, proxy->shapePtr(), "ProxyObject_shape");
+ 
+ #ifdef DEBUG
+     if (TlsContext.get()->isStrictProxyCheckingEnabled() && proxy->is<WrapperObject>()) {
+         JSObject* referent = MaybeForwarded(proxy->target());
+         if (referent->compartment() != proxy->compartment()) {
+             /*
+              * Assert that this proxy is tracked in the wrapper map. We maintain
+              * the invariant that the wrapped object is the key in the wrapper map.
+diff --git a/js/src/vm/Caches.h b/js/src/vm/Caches.h
+--- a/js/src/vm/Caches.h
++++ b/js/src/vm/Caches.h
+@@ -208,18 +208,20 @@ class NewObjectCache
+         entry->kind = kind;
+ 
+         entry->nbytes = gc::Arena::thingSize(kind);
+         js_memcpy(&entry->templateObject, obj, entry->nbytes);
+     }
+ 
+     static void copyCachedToObject(NativeObject* dst, NativeObject* src, gc::AllocKind kind) {
+         js_memcpy(dst, src, gc::Arena::thingSize(kind));
+-        Shape::writeBarrierPost(&dst->shape_, nullptr, dst->shape_);
+-        ObjectGroup::writeBarrierPost(&dst->group_, nullptr, dst->group_);
++
++        // Initialize with barriers
++        dst->initGroup(src->group());
++        dst->initShape(src->shape());
+     }
+ };
+ 
+ class RuntimeCaches
+ {
+     UniquePtr<js::MathCache> mathCache_;
+ 
+     js::MathCache* createMathCache(JSContext* cx);
+diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h
+--- a/js/src/vm/NativeObject-inl.h
++++ b/js/src/vm/NativeObject-inl.h
+@@ -651,24 +651,24 @@ NativeObject::setLastProperty(JSContext*
+     MOZ_ASSERT(shape->zone() == zone());
+     MOZ_ASSERT(shape->numFixedSlots() == numFixedSlots());
+     MOZ_ASSERT(shape->getObjectClass() == getClass());
+ 
+     size_t oldSpan = lastProperty()->slotSpan();
+     size_t newSpan = shape->slotSpan();
+ 
+     if (oldSpan == newSpan) {
+-        shape_ = shape;
++        setShape(shape);
+         return true;
+     }
+ 
+     if (MOZ_UNLIKELY(!updateSlotsForSpan(cx, oldSpan, newSpan)))
+         return false;
+ 
+-    shape_ = shape;
++    setShape(shape);
+     return true;
+ }
+ 
+ inline js::gc::AllocKind
+ NativeObject::allocKindForTenure() const
+ {
+     using namespace js::gc;
+     AllocKind kind = GetGCObjectFixedSlotsKind(numFixedSlots());
+diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
+--- a/js/src/vm/NativeObject.cpp
++++ b/js/src/vm/NativeObject.cpp
+@@ -165,17 +165,17 @@ js::NativeObject::checkShapeConsistency(
+         }
+ 
+         shape = lastProperty();
+         while (shape) {
+             MOZ_ASSERT_IF(!shape->isEmptyShape() && shape->isDataProperty(),
+                           shape->slot() < slotSpan());
+             if (!prev) {
+                 MOZ_ASSERT(lastProperty() == shape);
+-                MOZ_ASSERT(shape->listp == &shape_);
++                MOZ_ASSERT(shape->listp == &shapeRef());
+             } else {
+                 MOZ_ASSERT(shape->listp == &prev->parent);
+             }
+             prev = shape;
+             shape = shape->parent;
+         }
+     } else {
+         while (shape->parent) {
+@@ -196,19 +196,19 @@ js::NativeObject::checkShapeConsistency(
+         }
+     }
+ }
+ #endif
+ 
+ void
+ NativeObject::updateShapeAfterMovingGC()
+ {
+-    Shape* shape = shape_;
++    Shape* shape = this->shape();
+     if (IsForwarded(shape))
+-        shape_.unsafeSet(Forwarded(shape));
++        shapeRef().unsafeSet(Forwarded(shape));
+ }
+ 
+ void
+ js::NativeObject::initializeSlotRange(uint32_t start, uint32_t length)
+ {
+     /*
+      * No bounds check, as this is used when the object's shape does not
+      * reflect its allocated slots (updateSlotsForSpan).
+@@ -309,17 +309,17 @@ NativeObject::setLastPropertyShrinkFixed
+     DebugOnly<size_t> oldFixed = numFixedSlots();
+     DebugOnly<size_t> newFixed = shape->numFixedSlots();
+     MOZ_ASSERT(newFixed < oldFixed);
+     MOZ_ASSERT(shape->slotSpan() <= oldFixed);
+     MOZ_ASSERT(shape->slotSpan() <= newFixed);
+     MOZ_ASSERT(dynamicSlotsCount(oldFixed, shape->slotSpan(), getClass()) == 0);
+     MOZ_ASSERT(dynamicSlotsCount(newFixed, shape->slotSpan(), getClass()) == 0);
+ 
+-    shape_ = shape;
++    setShape(shape);
+ }
+ 
+ void
+ NativeObject::setLastPropertyMakeNonNative(Shape* shape)
+ {
+     MOZ_ASSERT(!inDictionaryMode());
+     MOZ_ASSERT(!shape->getObjectClass()->isNative());
+     MOZ_ASSERT(shape->zone() == zone());
+@@ -328,30 +328,30 @@ NativeObject::setLastPropertyMakeNonNati
+ 
+     if (hasDynamicElements())
+         js_free(getUnshiftedElementsHeader());
+     if (hasDynamicSlots()) {
+         js_free(slots_);
+         slots_ = nullptr;
+     }
+ 
+-    shape_ = shape;
++    setShape(shape);
+ }
+ 
+ void
+ NativeObject::setLastPropertyMakeNative(JSContext* cx, Shape* shape)
+ {
+     MOZ_ASSERT(getClass()->isNative());
+     MOZ_ASSERT(shape->getObjectClass()->isNative());
+     MOZ_ASSERT(!shape->inDictionary());
+ 
+     // This method is used to convert unboxed objects into native objects. In
+     // this case, the shape_ field was previously used to store other data and
+     // this should be treated as an initialization.
+-    shape_.init(shape);
++    initShape(shape);
+ 
+     slots_ = nullptr;
+     elements_ = emptyObjectElements;
+ 
+     size_t oldSpan = shape->numFixedSlots();
+     size_t newSpan = shape->slotSpan();
+ 
+     initializeSlotRange(0, oldSpan);
+diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
+--- a/js/src/vm/NativeObject.h
++++ b/js/src/vm/NativeObject.h
+@@ -408,17 +408,17 @@ enum class DenseElementResult {
+ enum class ShouldUpdateTypes {
+     Update,
+     DontUpdate
+ };
+ 
+ /*
+  * NativeObject specifies the internal implementation of a native object.
+  *
+- * Native objects use ShapedObject::shape_ to record property information.  Two
++ * Native objects use ShapedObject::shape to record property information. Two
+  * native objects with the same shape are guaranteed to have the same number of
+  * fixed slots.
+  *
+  * Native objects extend the base implementation of an object with storage for
+  * the object's named properties and indexed elements.
+  *
+  * These are stored separately from one another. Objects are followed by a
+  * variable-sized array of values for inline storage, which may be used by
+@@ -471,18 +471,18 @@ class NativeObject : public ShapedObject
+         static_assert(MAX_FIXED_SLOTS <= Shape::FIXED_SLOTS_MAX,
+                       "verify numFixedSlots() bitfield is big enough");
+         static_assert(sizeof(NativeObject) + MAX_FIXED_SLOTS * sizeof(Value) == JSObject::MAX_BYTE_SIZE,
+                       "inconsistent maximum object size");
+     }
+ 
+   public:
+     Shape* lastProperty() const {
+-        MOZ_ASSERT(shape_);
+-        return shape_;
++        MOZ_ASSERT(shape());
++        return shape();
+     }
+ 
+     uint32_t propertyCount() const {
+         return lastProperty()->entryCount();
+     }
+ 
+     bool hasShapeTable() const {
+         return lastProperty()->hasTable();
+@@ -736,17 +736,17 @@ class NativeObject : public ShapedObject
+     }
+ 
+     /*
+      * The methods below shadow methods on JSObject and are more efficient for
+      * known-native objects.
+      */
+     bool hasAllFlags(js::BaseShape::Flag flags) const {
+         MOZ_ASSERT(flags);
+-        return shape_->hasAllObjectFlags(flags);
++        return shape()->hasAllObjectFlags(flags);
+     }
+     bool nonProxyIsExtensible() const {
+         return !hasAllFlags(js::BaseShape::NOT_EXTENSIBLE);
+     }
+ 
+     /*
+      * Whether there may be indexed properties on this object, excluding any in
+      * the object's elements.
+diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp
+--- a/js/src/vm/Shape.cpp
++++ b/js/src/vm/Shape.cpp
+@@ -77,25 +77,25 @@ ShapeTable::init(JSContext* cx, Shape* l
+ 
+ void
+ Shape::removeFromDictionary(NativeObject* obj)
+ {
+     MOZ_ASSERT(inDictionary());
+     MOZ_ASSERT(obj->inDictionaryMode());
+     MOZ_ASSERT(listp);
+ 
+-    MOZ_ASSERT(obj->shape_->inDictionary());
+-    MOZ_ASSERT(obj->shape_->listp == &obj->shape_);
++    MOZ_ASSERT(obj->shape()->inDictionary());
++    MOZ_ASSERT(obj->shape()->listp == obj->shapePtr());
+ 
+     if (parent)
+         parent->listp = listp;
+     *listp = parent;
+     listp = nullptr;
+ 
+-    obj->shape_->clearCachedBigEnoughForShapeTable();
++    obj->shape()->clearCachedBigEnoughForShapeTable();
+ }
+ 
+ void
+ Shape::insertIntoDictionary(GCPtrShape* dictp)
+ {
+     // Don't assert inDictionaryMode() here because we may be called from
+     // NativeObject::toDictionaryMode via Shape::initDictionaryShape.
+     MOZ_ASSERT(inDictionary());
+@@ -335,17 +335,17 @@ NativeObject::getChildDataProperty(JSCon
+         if (!shape)
+             return nullptr;
+         if (child.slot() >= obj->lastProperty()->base()->slotSpan()) {
+             if (!obj->setSlotSpan(cx, child.slot() + 1)) {
+                 new (shape) Shape(obj->lastProperty()->base()->unowned(), 0);
+                 return nullptr;
+             }
+         }
+-        shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
++        shape->initDictionaryShape(child, obj->numFixedSlots(), obj->shapePtr());
+         return shape;
+     }
+ 
+     Shape* shape = cx->zone()->propertyTree().inlinedGetChild(cx, parent, child);
+     if (!shape)
+         return nullptr;
+ 
+     MOZ_ASSERT(shape->parent == parent);
+@@ -366,17 +366,17 @@ NativeObject::getChildAccessorProperty(J
+     // Accessor properties have no slot, but slot_ will reflect that of parent.
+     child.setSlot(parent->maybeSlot());
+ 
+     if (obj->inDictionaryMode()) {
+         MOZ_ASSERT(parent == obj->lastProperty());
+         Shape* shape = Allocate<AccessorShape>(cx);
+         if (!shape)
+             return nullptr;
+-        shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
++        shape->initDictionaryShape(child, obj->numFixedSlots(), obj->shapePtr());
+         return shape;
+     }
+ 
+     Shape* shape = cx->zone()->propertyTree().inlinedGetChild(cx, parent, child);
+     if (!shape)
+         return nullptr;
+ 
+     MOZ_ASSERT(shape->parent == parent);
+@@ -431,18 +431,18 @@ js::NativeObject::toDictionaryMode(JSCon
+     if (IsInsideNursery(obj) &&
+         !cx->nursery().queueDictionaryModeObjectToSweep(obj))
+     {
+         ReportOutOfMemory(cx);
+         return false;
+     }
+ 
+     MOZ_ASSERT(root->listp == nullptr);
+-    root->listp = &obj->shape_;
+-    obj->shape_ = root;
++    root->listp = obj->shapePtr();
++    obj->setShape(root);
+ 
+     MOZ_ASSERT(obj->inDictionaryMode());
+     root->base()->setSlotSpan(span);
+ 
+     return true;
+ }
+ 
+ static bool
+@@ -733,17 +733,17 @@ NativeObject::addEnumerableDataProperty(
+         if (!shape)
+             return nullptr;
+         if (slot >= obj->lastProperty()->base()->slotSpan()) {
+             if (MOZ_UNLIKELY(!obj->setSlotSpan(cx, slot + 1))) {
+                 new (shape) Shape(obj->lastProperty()->base()->unowned(), 0);
+                 return nullptr;
+             }
+         }
+-        shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
++        shape->initDictionaryShape(child, obj->numFixedSlots(), obj->shapePtr());
+     } else {
+         uint32_t slot = obj->slotSpan();
+         MOZ_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
+         // Objects with many properties are converted to dictionary
+         // mode, so we can't overflow SHAPE_MAXIMUM_SLOT here.
+         MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
+         MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
+ 
+@@ -1225,17 +1225,17 @@ NativeObject::clear(JSContext* cx, Handl
+ 
+     while (shape->parent) {
+         shape = shape->parent;
+         MOZ_ASSERT(obj->inDictionaryMode() == shape->inDictionary());
+     }
+     MOZ_ASSERT(shape->isEmptyShape());
+ 
+     if (obj->inDictionaryMode())
+-        shape->listp = &obj->shape_;
++        shape->listp = obj->shapePtr();
+ 
+     JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
+ 
+     obj->checkShapeConsistency();
+ }
+ 
+ /* static */ bool
+ NativeObject::rollbackProperties(JSContext* cx, HandleNativeObject obj, uint32_t slotSpan)
+@@ -1805,17 +1805,17 @@ Shape::fixupDictionaryShapeAfterMovingGC
+         // listp points to the parent field of the next shape.
+         Shape* next = reinterpret_cast<Shape*>(uintptr_t(listp) - offsetof(Shape, parent));
+         if (gc::IsForwarded(next))
+             listp = &gc::Forwarded(next)->parent;
+     } else {
+         // listp points to the shape_ field of an object.
+         JSObject* last = reinterpret_cast<JSObject*>(uintptr_t(listp) - ShapedObject::offsetOfShape());
+         if (gc::IsForwarded(last))
+-            listp = &gc::Forwarded(last)->as<NativeObject>().shape_;
++            listp = gc::Forwarded(last)->as<NativeObject>().shapePtr();
+     }
+ }
+ 
+ void
+ Shape::fixupShapeTreeAfterMovingGC()
+ {
+     if (kids.isNull())
+         return;
+diff --git a/js/src/vm/ShapedObject.h b/js/src/vm/ShapedObject.h
+--- a/js/src/vm/ShapedObject.h
++++ b/js/src/vm/ShapedObject.h
+@@ -19,33 +19,40 @@ namespace js {
+  * never created as a most-derived class.
+  */
+ class ShapedObject : public JSObject
+ {
+   protected:
+     // Property layout description and other state.
+     GCPtrShape shape_;
+ 
++    MOZ_ALWAYS_INLINE const GCPtrShape& shapeRef() const {
++        return shape_;
++    }
++    MOZ_ALWAYS_INLINE GCPtrShape& shapeRef() {
++        return shape_;
++    }
++
++    // Used for GC tracing and Shape::listp
++    MOZ_ALWAYS_INLINE GCPtrShape* shapePtr() {
++        return &shape_;
++    }
++
+   public:
+     // Set the shape of an object. This pointer is valid for native objects and
+     // some non-native objects. After creating an object, the objects for which
+     // the shape pointer is invalid need to overwrite this pointer before a GC
+     // can occur.
+-    void initShape(Shape* shape) {
+-        this->shape_.init(shape);
+-    }
++    void initShape(Shape* shape) { shapeRef().init(shape); }
+ 
+-    void setShape(Shape* shape) {
+-        this->shape_ = shape;
+-    }
+-
+-    Shape* shape() const { return this->shape_; }
++    void setShape(Shape* shape) { shapeRef() = shape; }
++    Shape* shape() const { return shapeRef(); }
+ 
+     void traceShape(JSTracer* trc) {
+-        TraceEdge(trc, &shape_, "shape");
++        TraceEdge(trc, shapePtr(), "shape");
+     }
+ 
+     static size_t offsetOfShape() { return offsetof(ShapedObject, shape_); }
+ 
+   private:
+     static void staticAsserts() {
+         static_assert(offsetof(ShapedObject, shape_) == offsetof(shadow::Object, shape),
+                       "shadow shape must match actual shape");
+diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp
+--- a/js/src/vm/UnboxedObject.cpp
++++ b/js/src/vm/UnboxedObject.cpp
+@@ -294,28 +294,27 @@ UnboxedPlainObject::getValue(const Unbox
+ {
+     uint8_t* p = &data_[property.offset];
+     return GetUnboxedValue(p, property.type, maybeUninitialized);
+ }
+ 
+ void
+ UnboxedPlainObject::trace(JSTracer* trc, JSObject* obj)
+ {
+-    if (obj->as<UnboxedPlainObject>().expando_) {
+-        TraceManuallyBarrieredEdge(trc,
+-            reinterpret_cast<NativeObject**>(&obj->as<UnboxedPlainObject>().expando_),
+-            "unboxed_expando");
+-    }
++    UnboxedPlainObject* uobj = &obj->as<UnboxedPlainObject>();
+ 
+-    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layoutDontCheckGeneration();
++    if (uobj->maybeExpando())
++        TraceManuallyBarrieredEdge(trc, uobj->addressOfExpando(), "unboxed_expando");
++
++    const UnboxedLayout& layout = uobj->layoutDontCheckGeneration();
+     const int32_t* list = layout.traceList();
+     if (!list)
+         return;
+ 
+-    uint8_t* data = obj->as<UnboxedPlainObject>().data();
++    uint8_t* data = uobj->data();
+     while (*list != -1) {
+         GCPtrString* heap = reinterpret_cast<GCPtrString*>(data + *list);
+         TraceEdge(trc, heap, "unboxed_string");
+         list++;
+     }
+     list++;
+     while (*list != -1) {
+         GCPtrObject* heap = reinterpret_cast<GCPtrObject*>(data + *list);
+@@ -325,18 +324,18 @@ UnboxedPlainObject::trace(JSTracer* trc,
+ 
+     // Unboxed objects don't have Values to trace.
+     MOZ_ASSERT(*(list + 1) == -1);
+ }
+ 
+ /* static */ UnboxedExpandoObject*
+ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj)
+ {
+-    if (obj->expando_)
+-        return obj->expando_;
++    if (obj->maybeExpando())
++        return obj->maybeExpando();
+ 
+     UnboxedExpandoObject* expando =
+         NewObjectWithGivenProto<UnboxedExpandoObject>(cx, nullptr, gc::AllocKind::OBJECT4);
+     if (!expando)
+         return nullptr;
+ 
+     // Don't track property types for expando objects. This allows Baseline
+     // and Ion AddSlot ICs to guard on the unboxed group without guarding on
+@@ -351,17 +350,17 @@ UnboxedPlainObject::ensureExpando(JSCont
+ 
+     // As with setValue(), we need to manually trigger post barriers on the
+     // whole object. If we treat the field as a GCPtrObject and later
+     // convert the object to its native representation, we will end up with a
+     // corrupted store buffer entry.
+     if (IsInsideNursery(expando) && !IsInsideNursery(obj))
+         cx->zone()->group()->storeBuffer().putWholeCell(obj);
+ 
+-    obj->expando_ = expando;
++    obj->setExpandoUnsafe(expando);
+     return expando;
+ }
+ 
+ bool
+ UnboxedPlainObject::containsUnboxedOrExpandoProperty(JSContext* cx, jsid id) const
+ {
+     if (layoutDontCheckGeneration().lookup(id))
+         return true;
+diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h
+--- a/js/src/vm/UnboxedObject.h
++++ b/js/src/vm/UnboxedObject.h
+@@ -270,16 +270,20 @@ class UnboxedPlainObject : public Unboxe
+     uint8_t* data() {
+         return &data_[0];
+     }
+ 
+     UnboxedExpandoObject* maybeExpando() const {
+         return expando_;
+     }
+ 
++    void setExpandoUnsafe(UnboxedExpandoObject* expando) {
++        expando_ = expando;
++    }
++
+     void initExpando() {
+         expando_ = nullptr;
+     }
+ 
+     // For use during GC.
+     JSObject** addressOfExpando() {
+         return reinterpret_cast<JSObject**>(&expando_);
+     }

+ 324 - 0
mozilla-release/patches/1433837-6-60a1.patch

@@ -0,0 +1,324 @@
+# HG changeset patch
+# User Ted Campbell <tcampbell@mozilla.com>
+# Date 1517316960 -7200
+#      Tue Jan 30 14:56:00 2018 +0200
+# Node ID f59e3ddbb98b5f324ccd8617c8c0edae5daea3a4
+# Parent  68d4611682d4dd2941e34f37a66f10da1d018e0e
+Bug 1433837 - Replace ShapedObject::shape_ with JSObject::shapeOrExpando_. r=jandem
+
+The shape is such a key piece of how our JITs work that we should define
+them on JSObject and be more explicit about the invariants. This patch
+adds a |void* shapeOrExpando_| field to JSObject since we allow
+JSObjects to store a non-Shape, provided they follow certain rules.
+
+MozReview-Commit-ID: 4r1mldmGh19
+
+diff --git a/js/src/jsobj.h b/js/src/jsobj.h
+--- a/js/src/jsobj.h
++++ b/js/src/jsobj.h
+@@ -2,25 +2,16 @@
+  * 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 jsobj_h
+ #define jsobj_h
+ 
+-/*
+- * JS object definitions.
+- *
+- * A JS object consists of a possibly-shared object descriptor containing
+- * ordered property names, called the map; and a dense vector of property
+- * values, called slots.  The map/slot pointer pair is GC'ed, while the map
+- * is reference counted and the slot vector is malloc'ed.
+- */
+-
+ #include "mozilla/MemoryReporting.h"
+ 
+ #include "gc/Barrier.h"
+ #include "js/Conversions.h"
+ #include "js/GCVector.h"
+ #include "js/HeapAPI.h"
+ #include "vm/Printer.h"
+ #include "vm/Shape.h"
+@@ -57,33 +48,58 @@ enum class IntegrityLevel {
+ 
+ // Forward declarations, required for later friend declarations.
+ bool PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, IntegrityLevel level = IntegrityLevel::Sealed);
+ bool SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded);
+ 
+ }  /* namespace js */
+ 
+ /*
+- * A JavaScript object. The members common to all objects are as follows:
++ * A JavaScript object.
++ *
++ * This is the base class for all objects exposed to JS script (as well as some
++ * objects that are only accessed indirectly). Subclasses add additional fields
++ * and execution semantics. The runtime class of an arbitrary JSObject is
++ * identified by JSObject::getClass().
++ *
++ * The members common to all objects are as follows:
+  *
+  * - The |group_| member stores the group of the object, which contains its
+  *   prototype object, its class and the possible types of its properties.
+  *
+- * Subclasses of JSObject --- mainly NativeObject and JSFunction --- add more
+- * members. Notable among these is the object's shape, which stores flags and
+- * some other state, and, for native objects, the layout of all its properties.
+- * The second word of a JSObject generally stores its shape; if the second word
+- * stores anything else, the value stored cannot be a valid Shape* pointer, so
+- * that shape guards can be performed on objects without regard to the specific
+- * layout in use.
++ * - The |shapeOrExpando_| member points to (an optional) guard object that JIT
++ *   may use to optimize. The pointed-to object dictates the constraints
++ *   imposed on the JSObject:
++ *      nullptr
++ *          - Safe value if this field is not needed.
++ *      js::Shape
++ *          - All objects that might point |shapeOrExpando_| to a js::Shape
++ *            must follow the rules specified on js::ShapedObject.
++ *      JSObject
++ *          - Implies nothing about the current object or target object. Either
++ *            of which may mutate in place. Store a JSObject* only to save
++ *            space, not to guard on.
++ *
++ * NOTE: The JIT may check |shapeOrExpando_| pointer value without ever
++ *       inspecting |group_| or the class.
++ *
++ * NOTE: Some operations can change the contents of an object (including class)
++ *       in-place so avoid assuming an object with same pointer has same class
++ *       as before.
++ *       - JSObject::swap()
++ *       - UnboxedPlainObject::convertToNative()
++ *
++ * NOTE: UnboxedObjects may change class without changing |group_|.
++ *       - js::TryConvertToUnboxedLayout
+  */
+ class JSObject : public js::gc::Cell
+ {
+   protected:
+     js::GCPtrObjectGroup group_;
++    void* shapeOrExpando_;
+ 
+   private:
+     friend class js::Shape;
+     friend class js::GCMarker;
+     friend class js::NewObjectCache;
+     friend class js::Nursery;
+     friend class js::gc::RelocationOverlay;
+     friend bool js::PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, js::IntegrityLevel level);
+@@ -522,17 +538,22 @@ class JSObject : public js::gc::Cell
+ 
+ #ifdef DEBUG
+     void dump(js::GenericPrinter& fp) const;
+     void dump() const;
+ #endif
+ 
+     /* JIT Accessors */
+ 
+-    static size_t offsetOfGroup() { return offsetof(JSObject, group_); }
++    static constexpr size_t offsetOfGroup() {
++        return offsetof(JSObject, group_);
++    }
++    static constexpr size_t offsetOfShapeOrExpando() {
++        return offsetof(JSObject, shapeOrExpando_);
++    }
+ 
+     // Maximum size in bytes of a JSObject.
+     static const size_t MAX_BYTE_SIZE = 4 * sizeof(void*) + 16 * sizeof(JS::Value);
+ 
+   private:
+     JSObject() = delete;
+     JSObject(const JSObject& other) = delete;
+     void operator=(const JSObject& other) = delete;
+@@ -571,22 +592,22 @@ operator==(const JSObject& lhs, const JS
+ 
+ static MOZ_ALWAYS_INLINE bool
+ operator!=(const JSObject& lhs, const JSObject& rhs)
+ {
+     return &lhs != &rhs;
+ }
+ 
+ // Size of the various GC thing allocation sizes used for objects.
+-struct JSObject_Slots0 : JSObject { void* data[3]; };
+-struct JSObject_Slots2 : JSObject { void* data[3]; js::Value fslots[2]; };
+-struct JSObject_Slots4 : JSObject { void* data[3]; js::Value fslots[4]; };
+-struct JSObject_Slots8 : JSObject { void* data[3]; js::Value fslots[8]; };
+-struct JSObject_Slots12 : JSObject { void* data[3]; js::Value fslots[12]; };
+-struct JSObject_Slots16 : JSObject { void* data[3]; js::Value fslots[16]; };
++struct JSObject_Slots0 : JSObject { void* data[2]; };
++struct JSObject_Slots2 : JSObject { void* data[2]; js::Value fslots[2]; };
++struct JSObject_Slots4 : JSObject { void* data[2]; js::Value fslots[4]; };
++struct JSObject_Slots8 : JSObject { void* data[2]; js::Value fslots[8]; };
++struct JSObject_Slots12 : JSObject { void* data[2]; js::Value fslots[12]; };
++struct JSObject_Slots16 : JSObject { void* data[2]; js::Value fslots[16]; };
+ 
+ /* static */ MOZ_ALWAYS_INLINE void
+ JSObject::readBarrier(JSObject* obj)
+ {
+     if (obj && obj->isTenured())
+         obj->asTenured().readBarrier(&obj->asTenured());
+ }
+ 
+diff --git a/js/src/vm/ShapedObject.h b/js/src/vm/ShapedObject.h
+--- a/js/src/vm/ShapedObject.h
++++ b/js/src/vm/ShapedObject.h
+@@ -7,58 +7,56 @@
+ #ifndef vm_ShapedObject_h
+ #define vm_ShapedObject_h
+ 
+ #include "jsobj.h"
+ 
+ namespace js {
+ 
+ /*
+- * Shaped objects extend the base implementation of an object with a shape
+- * field.  Subclasses of ShapedObject ascribe meaning to this field.
++ * Shaped objects are a variant of JSObject that use a GCPtrShape for their
++ * |shapeOrExpando_| field. All objects that point to a js::Shape as their
++ * |shapeOrExpando_| field should use this as their subclass.
+  *
+- * ShapedObject is only created as the base class of some other class.  It's
+- * never created as a most-derived class.
++ * NOTE: shape()->getObjectClass() must equal getClass().
+  */
+ class ShapedObject : public JSObject
+ {
+   protected:
+-    // Property layout description and other state.
+-    GCPtrShape shape_;
+-
++    // ShapedObjects treat the |shapeOrExpando_| field as a GCPtrShape to
++    // ensure barriers are called. Use these instead of accessing
++    // |shapeOrExpando_| directly.
+     MOZ_ALWAYS_INLINE const GCPtrShape& shapeRef() const {
+-        return shape_;
++        return *reinterpret_cast<const GCPtrShape*>(&(this->shapeOrExpando_));
+     }
+     MOZ_ALWAYS_INLINE GCPtrShape& shapeRef() {
+-        return shape_;
++        return *reinterpret_cast<GCPtrShape*>(&(this->shapeOrExpando_));
+     }
+ 
+     // Used for GC tracing and Shape::listp
+     MOZ_ALWAYS_INLINE GCPtrShape* shapePtr() {
+-        return &shape_;
++        return reinterpret_cast<GCPtrShape*>(&(this->shapeOrExpando_));
+     }
+ 
+   public:
+     // Set the shape of an object. This pointer is valid for native objects and
+     // some non-native objects. After creating an object, the objects for which
+     // the shape pointer is invalid need to overwrite this pointer before a GC
+     // can occur.
+     void initShape(Shape* shape) { shapeRef().init(shape); }
+ 
+     void setShape(Shape* shape) { shapeRef() = shape; }
+     Shape* shape() const { return shapeRef(); }
+ 
+     void traceShape(JSTracer* trc) {
+         TraceEdge(trc, shapePtr(), "shape");
+     }
+ 
+-    static size_t offsetOfShape() { return offsetof(ShapedObject, shape_); }
+-
+-  private:
+-    static void staticAsserts() {
+-        static_assert(offsetof(ShapedObject, shape_) == offsetof(shadow::Object, shape),
++    static constexpr size_t offsetOfShape() {
++        static_assert(offsetOfShapeOrExpando() == offsetof(shadow::Object, shape),
+                       "shadow shape must match actual shape");
++        return offsetOfShapeOrExpando();
+     }
+ };
+ 
+ } // namespace js
+ 
+ #endif /* vm_ShapedObject_h */
+diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h
+--- a/js/src/vm/UnboxedObject.h
++++ b/js/src/vm/UnboxedObject.h
+@@ -220,20 +220,23 @@ class UnboxedExpandoObject : public Nati
+ };
+ 
+ // Class for a plain object using an unboxed representation. The physical
+ // layout of these objects is identical to that of an InlineTypedObject, though
+ // these objects use an UnboxedLayout instead of a TypeDescr to keep track of
+ // how their properties are stored.
+ class UnboxedPlainObject : public UnboxedObject
+ {
+-    // Optional object which stores extra properties on this object. This is
+-    // not automatically barriered to avoid problems if the object is converted
+-    // to a native. See ensureExpando().
+-    UnboxedExpandoObject* expando_;
++    // The |JSObject::shapeOrExpando_| field can optionally refer to an object
++    // which stores extra properties on this object. This is not automatically
++    // barriered to avoid problems if the object is converted to a native. See
++    // ensureExpando(). This object must be an UnboxedExpandoObject.
++    //
++    // NOTE: The JIT should not assume that seeing the same expando pointer
++    //       means the object is even an UnboxedObject. Always check |group_|.
+ 
+     // Start of the inline data, which immediately follows the group and extra properties.
+     uint8_t data_[1];
+ 
+   public:
+     static const Class class_;
+ 
+     static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
+@@ -267,30 +270,30 @@ class UnboxedPlainObject : public Unboxe
+         return group()->unboxedLayoutDontCheckGeneration();
+     }
+ 
+     uint8_t* data() {
+         return &data_[0];
+     }
+ 
+     UnboxedExpandoObject* maybeExpando() const {
+-        return expando_;
++        return static_cast<UnboxedExpandoObject*>(shapeOrExpando_);
+     }
+ 
+     void setExpandoUnsafe(UnboxedExpandoObject* expando) {
+-        expando_ = expando;
++        shapeOrExpando_ = expando;
+     }
+ 
+     void initExpando() {
+-        expando_ = nullptr;
++        shapeOrExpando_ = nullptr;
+     }
+ 
+     // For use during GC.
+     JSObject** addressOfExpando() {
+-        return reinterpret_cast<JSObject**>(&expando_);
++        return reinterpret_cast<JSObject**>(&shapeOrExpando_);
+     }
+ 
+     bool containsUnboxedOrExpandoProperty(JSContext* cx, jsid id) const;
+ 
+     static UnboxedExpandoObject* ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj);
+ 
+     bool setValue(JSContext* cx, const UnboxedLayout::Property& property, const Value& v);
+     Value getValue(const UnboxedLayout::Property& property, bool maybeUninitialized = false);
+@@ -302,17 +305,17 @@ class UnboxedPlainObject : public Unboxe
+                                           NewObjectKind newKind, IdValuePair* properties);
+ 
+     void fillAfterConvert(JSContext* cx,
+                           Handle<GCVector<Value>> values, size_t* valueCursor);
+ 
+     static void trace(JSTracer* trc, JSObject* object);
+ 
+     static size_t offsetOfExpando() {
+-        return offsetof(UnboxedPlainObject, expando_);
++        return offsetOfShapeOrExpando();
+     }
+ 
+     static size_t offsetOfData() {
+         return offsetof(UnboxedPlainObject, data_[0]);
+     }
+ };
+ 
+ inline bool

+ 420 - 0
mozilla-release/patches/1434263-60a1.patch

@@ -0,0 +1,420 @@
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1517495369 -3600
+# Node ID a806fd1e54279d82f19462665955c830c14a3b08
+# Parent  9dbaa674b27a4c3944637ec5ecea9502aa742fa1
+Bug 1434263 - Refactor JSString to have an IsLinear flag instead of IsFlat. r=luke
+
+diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
+--- a/js/src/jit/CodeGenerator.cpp
++++ b/js/src/jit/CodeGenerator.cpp
+@@ -1614,20 +1614,19 @@ CreateDependentString::generate(MacroAss
+             masm.computeEffectiveAddress(BaseIndex(temp1, temp2, TimesTwo), temp1);
+         masm.storePtr(temp1, Address(string, JSString::offsetOfNonInlineChars()));
+         masm.storePtr(base, Address(string, JSDependentString::offsetOfBase()));
+ 
+         // Follow any base pointer if the input is itself a dependent string.
+         // Watch for undepended strings, which have a base pointer but don't
+         // actually share their characters with it.
+         Label noBase;
+-        masm.branchTest32(Assembler::Zero, Address(base, JSString::offsetOfFlags()),
+-                          Imm32(JSString::HAS_BASE_BIT), &noBase);
+-        masm.branchTest32(Assembler::NonZero, Address(base, JSString::offsetOfFlags()),
+-                          Imm32(JSString::FLAT_BIT), &noBase);
++        masm.load32(Address(base, JSString::offsetOfFlags()), temp1);
++        masm.and32(Imm32(JSString::TYPE_FLAGS_MASK), temp1);
++        masm.branch32(Assembler::NotEqual, temp1, Imm32(JSString::DEPENDENT_FLAGS), &noBase);
+         masm.loadPtr(Address(base, JSDependentString::offsetOfBase()), temp1);
+         masm.storePtr(temp1, Address(string, JSDependentString::offsetOfBase()));
+         masm.bind(&noBase);
+     }
+ 
+     masm.bind(&done);
+ }
+ 
+@@ -8028,17 +8027,17 @@ JitCompartment::generateStringConcatStub
+     masm.branch32(Assembler::Above, temp2, Imm32(JSString::MAX_LENGTH), &failure);
+ 
+     // Allocate a new rope.
+     masm.newGCString(output, temp3, &failure);
+ 
+     // Store rope length and flags. temp1 still holds the result of AND'ing the
+     // lhs and rhs flags, so we just have to clear the other flags to get our
+     // rope flags (Latin1 if both lhs and rhs are Latin1).
+-    static_assert(JSString::ROPE_FLAGS == 0, "Rope flags must be 0");
++    static_assert(JSString::INIT_ROPE_FLAGS == 0, "Rope type flags must be 0");
+     masm.and32(Imm32(JSString::LATIN1_CHARS_BIT), temp1);
+     masm.store32(temp1, Address(output, JSString::offsetOfFlags()));
+     masm.store32(temp2, Address(output, JSString::offsetOfLength()));
+ 
+     // Store left and right nodes.
+     masm.storePtr(lhs, Address(output, JSRope::offsetOfLeft()));
+     masm.storePtr(rhs, Address(output, JSRope::offsetOfRight()));
+     masm.ret();
+diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h
+--- a/js/src/jit/MacroAssembler-inl.h
++++ b/js/src/jit/MacroAssembler-inl.h
+@@ -392,39 +392,36 @@ MacroAssembler::branchIfTrueBool(Registe
+     // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
+     branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label);
+ }
+ 
+ void
+ MacroAssembler::branchIfRope(Register str, Label* label)
+ {
+     Address flags(str, JSString::offsetOfFlags());
+-    static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
+-    branchTest32(Assembler::Zero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
++    branchTest32(Assembler::Zero, flags, Imm32(JSString::LINEAR_BIT), label);
+ }
+ 
+ void
+ MacroAssembler::branchIfRopeOrExternal(Register str, Register temp, Label* label)
+ {
+     Address flags(str, JSString::offsetOfFlags());
+     move32(Imm32(JSString::TYPE_FLAGS_MASK), temp);
+     and32(flags, temp);
+ 
+-    static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
+-    branchTest32(Assembler::Zero, temp, temp, label);
++    branchTest32(Assembler::Zero, temp, Imm32(JSString::LINEAR_BIT), label);
+ 
+     branch32(Assembler::Equal, temp, Imm32(JSString::EXTERNAL_FLAGS), label);
+ }
+ 
+ void
+ MacroAssembler::branchIfNotRope(Register str, Label* label)
+ {
+     Address flags(str, JSString::offsetOfFlags());
+-    static_assert(JSString::ROPE_FLAGS == 0, "Rope type flags must be 0");
+-    branchTest32(Assembler::NonZero, flags, Imm32(JSString::TYPE_FLAGS_MASK), label);
++    branchTest32(Assembler::NonZero, flags, Imm32(JSString::LINEAR_BIT), label);
+ }
+ 
+ void
+ MacroAssembler::branchLatin1String(Register string, Label* label)
+ {
+     branchTest32(Assembler::NonZero, Address(string, JSString::offsetOfFlags()),
+                  Imm32(JSString::LATIN1_CHARS_BIT), label);
+ }
+diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h
+--- a/js/src/jsfriendapi.h
++++ b/js/src/jsfriendapi.h
+@@ -617,20 +617,20 @@ struct Function {
+     /* Used only for natives */
+     JSNative native;
+     const JSJitInfo* jitinfo;
+     void* _1;
+ };
+ 
+ struct String
+ {
++    static const uint32_t LINEAR_BIT       = JS_BIT(0);
+     static const uint32_t INLINE_CHARS_BIT = JS_BIT(2);
+     static const uint32_t LATIN1_CHARS_BIT = JS_BIT(6);
+-    static const uint32_t ROPE_FLAGS       = 0;
+-    static const uint32_t EXTERNAL_FLAGS   = JS_BIT(5);
++    static const uint32_t EXTERNAL_FLAGS   = JS_BIT(0) | JS_BIT(5);
+     static const uint32_t TYPE_FLAGS_MASK  = JS_BIT(6) - 1;
+     uint32_t flags;
+     uint32_t length;
+     union {
+         const JS::Latin1Char* nonInlineCharsLatin1;
+         const char16_t* nonInlineCharsTwoByte;
+         JS::Latin1Char inlineStorageLatin1[1];
+         char16_t inlineStorageTwoByte[1];
+@@ -909,17 +909,17 @@ IsExternalString(JSString* str, const JS
+ JS_FRIEND_API(JSLinearString*)
+ StringToLinearStringSlow(JSContext* cx, JSString* str);
+ 
+ MOZ_ALWAYS_INLINE JSLinearString*
+ StringToLinearString(JSContext* cx, JSString* str)
+ {
+     using shadow::String;
+     String* s = reinterpret_cast<String*>(str);
+-    if (MOZ_UNLIKELY((s->flags & String::TYPE_FLAGS_MASK) == String::ROPE_FLAGS))
++    if (MOZ_UNLIKELY(!(s->flags & String::LINEAR_BIT)))
+         return StringToLinearStringSlow(cx, str);
+     return reinterpret_cast<JSLinearString*>(str);
+ }
+ 
+ template<typename CharType>
+ MOZ_ALWAYS_INLINE void
+ CopyLinearStringChars(CharType* dest, JSLinearString* s, size_t len, size_t start = 0);
+ 
+diff --git a/js/src/vm/String-inl.h b/js/src/vm/String-inl.h
+--- a/js/src/vm/String-inl.h
++++ b/js/src/vm/String-inl.h
+@@ -104,17 +104,17 @@ JSString::validateLength(JSContext* mayb
+ 
+     return true;
+ }
+ 
+ MOZ_ALWAYS_INLINE void
+ JSRope::init(JSContext* cx, JSString* left, JSString* right, size_t length)
+ {
+     d.u1.length = length;
+-    d.u1.flags = ROPE_FLAGS;
++    d.u1.flags = INIT_ROPE_FLAGS;
+     if (left->hasLatin1Chars() && right->hasLatin1Chars())
+         d.u1.flags |= LATIN1_CHARS_BIT;
+     d.s.u2.left = left;
+     d.s.u3.right = right;
+     js::StringWriteBarrierPost(cx, &d.s.u2.left);
+     js::StringWriteBarrierPost(cx, &d.s.u3.right);
+ }
+ 
+@@ -201,25 +201,25 @@ JSDependentString::new_(JSContext* cx, J
+     str->init(cx, base, start, length);
+     return str;
+ }
+ 
+ MOZ_ALWAYS_INLINE void
+ JSFlatString::init(const char16_t* chars, size_t length)
+ {
+     d.u1.length = length;
+-    d.u1.flags = FLAT_BIT;
++    d.u1.flags = LINEAR_BIT;
+     d.s.u2.nonInlineCharsTwoByte = chars;
+ }
+ 
+ MOZ_ALWAYS_INLINE void
+ JSFlatString::init(const JS::Latin1Char* chars, size_t length)
+ {
+     d.u1.length = length;
+-    d.u1.flags = FLAT_BIT | LATIN1_CHARS_BIT;
++    d.u1.flags = LINEAR_BIT | LATIN1_CHARS_BIT;
+     d.s.u2.nonInlineCharsLatin1 = chars;
+ }
+ 
+ template <js::AllowGC allowGC, typename CharT>
+ MOZ_ALWAYS_INLINE JSFlatString*
+ JSFlatString::new_(JSContext* cx, const CharT* chars, size_t length)
+ {
+     MOZ_ASSERT(chars[length] == CharT(0));
+diff --git a/js/src/vm/String.cpp b/js/src/vm/String.cpp
+--- a/js/src/vm/String.cpp
++++ b/js/src/vm/String.cpp
+@@ -200,17 +200,17 @@ JSString::dumpRepresentation(js::Generic
+ 
+ void
+ JSString::dumpRepresentationHeader(js::GenericPrinter& out, int indent, const char* subclass) const
+ {
+     uint32_t flags = d.u1.flags;
+     // Print the string's address as an actual C++ expression, to facilitate
+     // copy-and-paste into a debugger.
+     out.printf("((%s*) %p) length: %zu  flags: 0x%x", subclass, this, length(), flags);
+-    if (flags & FLAT_BIT)               out.put(" FLAT");
++    if (flags & LINEAR_BIT)             out.put(" LINEAR");
+     if (flags & HAS_BASE_BIT)           out.put(" HAS_BASE");
+     if (flags & INLINE_CHARS_BIT)       out.put(" INLINE_CHARS");
+     if (flags & ATOM_BIT)               out.put(" ATOM");
+     if (isPermanentAtom())              out.put(" PERMANENT");
+     if (flags & LATIN1_CHARS_BIT)       out.put(" LATIN1");
+     if (flags & INDEX_VALUE_BIT)        out.put(" INDEX_VALUE(%u)", getIndexValue());
+     out.putChar('\n');
+ }
+@@ -492,18 +492,20 @@ JSRope::flattenInternal(JSContext* maybe
+             if (b == WithIncrementalBarrier) {
+                 JSString::writeBarrierPre(str->d.s.u2.left);
+                 JSString::writeBarrierPre(str->d.s.u3.right);
+             }
+             str->setNonInlineChars(left.nonInlineChars<CharT>(nogc));
+             wholeCapacity = capacity;
+             wholeChars = const_cast<CharT*>(left.nonInlineChars<CharT>(nogc));
+             pos = wholeChars + left.d.u1.length;
+-            JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
+-            left.d.u1.flags ^= (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
++            if (IsSame<CharT, char16_t>::value)
++                left.d.u1.flags = DEPENDENT_FLAGS;
++            else
++                left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
+             left.d.s.u3.base = (JSLinearString*)this;  /* will be true on exit */
+             StringWriteBarrierPostRemove(maybecx, &left.d.s.u2.left);
+             StringWriteBarrierPost(maybecx, (JSString**)&left.d.s.u3.base);
+             goto visit_right_child;
+         }
+     }
+ 
+     if (!AllocChars(this, wholeLength, &wholeChars, &wholeCapacity)) {
+@@ -1097,17 +1099,17 @@ JSExternalString::ensureFlat(JSContext* 
+         s[n] = '\0';
+     }
+ 
+     // Release the external chars.
+     finalize(cx->runtime()->defaultFreeOp());
+ 
+     // Transform the string into a non-external, flat string.
+     setNonInlineChars<char16_t>(s);
+-    d.u1.flags = FLAT_BIT;
++    d.u1.flags = LINEAR_BIT;
+ 
+     return &this->asFlat();
+ }
+ 
+ #ifdef DEBUG
+ void
+ JSAtom::dump(js::GenericPrinter& out)
+ {
+diff --git a/js/src/vm/String.h b/js/src/vm/String.h
+--- a/js/src/vm/String.h
++++ b/js/src/vm/String.h
+@@ -215,66 +215,66 @@ class JSString : public js::gc::TenuredC
+      * string instance of that type. Abstract types have no instances and thus
+      * have no such entry. The "subtype predicate" entry for a type specifies
+      * the predicate used to query whether a JSString instance is subtype
+      * (reflexively) of that type.
+      *
+      *   String        Instance     Subtype
+      *   type          encoding     predicate
+      *   ------------------------------------
+-     *   Rope          000000       000000
+-     *   Linear        -           !000000
++     *   Rope          000000       xxxxx0
++     *   Linear        -            xxxxx1
+      *   HasBase       -            xxxx1x
+-     *   Dependent     000010       000010
+-     *   External      100000       100000
+-     *   Flat          -            xxxxx1
+-     *   Undepended    000011       000011
++     *   Dependent     000011       000011
++     *   External      100001       100001
++     *   Flat          -            Linear && !Dependent && !External
++     *   Undepended    010011       010011
+      *   Extensible    010001       010001
+      *   Inline        000101       xxx1xx
+      *   FatInline     010101       x1x1xx
+      *   Atom          001001       xx1xxx
+      *   PermanentAtom 101001       1x1xxx
+      *   InlineAtom    -            xx11xx
+      *   FatInlineAtom -            x111xx
+      *
+      * Note that the first 4 flag bits (from right to left in the previous table)
+      * have the following meaning and can be used for some hot queries:
+      *
+-     *   Bit 0: IsFlat
++     *   Bit 0: IsLinear
+      *   Bit 1: HasBase (Dependent, Undepended)
+      *   Bit 2: IsInline (Inline, FatInline)
+      *   Bit 3: IsAtom (Atom, PermanentAtom)
+      *
+      *  "HasBase" here refers to the two string types that have a 'base' field:
+      *  JSDependentString and JSUndependedString.
+      *  A JSUndependedString is a JSDependentString which has been 'fixed' (by ensureFixed)
+      *  to be null-terminated.  In such cases, the string must keep marking its base since
+      *  there may be any number of *other* JSDependentStrings transitively depending on it.
+      *
+      * If the INDEX_VALUE_BIT is set the upper 16 bits of the flag word hold the integer
+      * index.
+      */
+ 
+-    static const uint32_t FLAT_BIT               = JS_BIT(0);
++    static const uint32_t LINEAR_BIT             = JS_BIT(0);
+     static const uint32_t HAS_BASE_BIT           = JS_BIT(1);
+     static const uint32_t INLINE_CHARS_BIT       = JS_BIT(2);
+     static const uint32_t ATOM_BIT               = JS_BIT(3);
+ 
+-    static const uint32_t ROPE_FLAGS             = 0;
+-    static const uint32_t DEPENDENT_FLAGS        = HAS_BASE_BIT;
+-    static const uint32_t UNDEPENDED_FLAGS       = FLAT_BIT | HAS_BASE_BIT;
+-    static const uint32_t EXTENSIBLE_FLAGS       = FLAT_BIT | JS_BIT(4);
+-    static const uint32_t EXTERNAL_FLAGS         = JS_BIT(5);
++    static const uint32_t DEPENDENT_FLAGS        = LINEAR_BIT | HAS_BASE_BIT;
++    static const uint32_t UNDEPENDED_FLAGS       = LINEAR_BIT | HAS_BASE_BIT | JS_BIT(4);
++    static const uint32_t EXTENSIBLE_FLAGS       = LINEAR_BIT | JS_BIT(4);
++    static const uint32_t EXTERNAL_FLAGS         = LINEAR_BIT | JS_BIT(5);
+ 
+     static const uint32_t FAT_INLINE_MASK        = INLINE_CHARS_BIT | JS_BIT(4);
+     static const uint32_t PERMANENT_ATOM_MASK    = ATOM_BIT | JS_BIT(5);
+ 
+     /* Initial flags for thin inline and fat inline strings. */
+-    static const uint32_t INIT_THIN_INLINE_FLAGS = FLAT_BIT | INLINE_CHARS_BIT;
+-    static const uint32_t INIT_FAT_INLINE_FLAGS  = FLAT_BIT | FAT_INLINE_MASK;
++    static const uint32_t INIT_THIN_INLINE_FLAGS = LINEAR_BIT | INLINE_CHARS_BIT;
++    static const uint32_t INIT_FAT_INLINE_FLAGS  = LINEAR_BIT | FAT_INLINE_MASK;
++    static const uint32_t INIT_ROPE_FLAGS        = 0;
+ 
+     static const uint32_t TYPE_FLAGS_MASK        = JS_BIT(6) - 1;
+ 
+     static const uint32_t LATIN1_CHARS_BIT       = JS_BIT(6);
+ 
+     static const uint32_t INDEX_VALUE_BIT        = JS_BIT(7);
+     static const uint32_t INDEX_VALUE_SHIFT      = 16;
+ 
+@@ -311,24 +311,24 @@ class JSString : public js::gc::TenuredC
+         static_assert(offsetof(JSString, d.s.u2.nonInlineCharsTwoByte) == offsetof(String, nonInlineCharsTwoByte),
+                       "shadow::String nonInlineChars offset must match JSString");
+         static_assert(offsetof(JSString, d.s.u3.externalFinalizer) == offsetof(String, externalFinalizer),
+                       "shadow::String externalFinalizer offset must match JSString");
+         static_assert(offsetof(JSString, d.inlineStorageLatin1) == offsetof(String, inlineStorageLatin1),
+                       "shadow::String inlineStorage offset must match JSString");
+         static_assert(offsetof(JSString, d.inlineStorageTwoByte) == offsetof(String, inlineStorageTwoByte),
+                       "shadow::String inlineStorage offset must match JSString");
++        static_assert(LINEAR_BIT == String::LINEAR_BIT,
++                      "shadow::String::LINEAR_BIT must match JSString::LINEAR_BIT");
+         static_assert(INLINE_CHARS_BIT == String::INLINE_CHARS_BIT,
+                       "shadow::String::INLINE_CHARS_BIT must match JSString::INLINE_CHARS_BIT");
+         static_assert(LATIN1_CHARS_BIT == String::LATIN1_CHARS_BIT,
+                       "shadow::String::LATIN1_CHARS_BIT must match JSString::LATIN1_CHARS_BIT");
+         static_assert(TYPE_FLAGS_MASK == String::TYPE_FLAGS_MASK,
+                       "shadow::String::TYPE_FLAGS_MASK must match JSString::TYPE_FLAGS_MASK");
+-        static_assert(ROPE_FLAGS == String::ROPE_FLAGS,
+-                      "shadow::String::ROPE_FLAGS must match JSString::ROPE_FLAGS");
+         static_assert(EXTERNAL_FLAGS == String::EXTERNAL_FLAGS,
+                       "shadow::String::EXTERNAL_FLAGS must match JSString::EXTERNAL_FLAGS");
+     }
+ 
+     /* Avoid lame compile errors in JSRope::flatten */
+     friend class JSRope;
+ 
+     friend class js::gc::RelocationOverlay;
+@@ -379,28 +379,28 @@ class JSString : public js::gc::TenuredC
+     static bool ensureLinear(JSContext* cx, JSString* str) {
+         return str->ensureLinear(cx) != nullptr;
+     }
+ 
+     /* Type query and debug-checked casts */
+ 
+     MOZ_ALWAYS_INLINE
+     bool isRope() const {
+-        return (d.u1.flags & TYPE_FLAGS_MASK) == ROPE_FLAGS;
++        return !(d.u1.flags & LINEAR_BIT);
+     }
+ 
+     MOZ_ALWAYS_INLINE
+     JSRope& asRope() const {
+         MOZ_ASSERT(isRope());
+         return *(JSRope*)this;
+     }
+ 
+     MOZ_ALWAYS_INLINE
+     bool isLinear() const {
+-        return !isRope();
++        return d.u1.flags & LINEAR_BIT;
+     }
+ 
+     MOZ_ALWAYS_INLINE
+     JSLinearString& asLinear() const {
+         MOZ_ASSERT(JSString::isLinear());
+         return *(JSLinearString*)this;
+     }
+ 
+@@ -412,17 +412,17 @@ class JSString : public js::gc::TenuredC
+     MOZ_ALWAYS_INLINE
+     JSDependentString& asDependent() const {
+         MOZ_ASSERT(isDependent());
+         return *(JSDependentString*)this;
+     }
+ 
+     MOZ_ALWAYS_INLINE
+     bool isFlat() const {
+-        return d.u1.flags & FLAT_BIT;
++        return isLinear() && !isDependent() && !isExternal();
+     }
+ 
+     MOZ_ALWAYS_INLINE
+     JSFlatString& asFlat() const {
+         MOZ_ASSERT(isFlat());
+         return *(JSFlatString*)this;
+     }
+ 

+ 4 - 4
mozilla-release/patches/1434622-60a1.patch

@@ -2,7 +2,7 @@
 # User Jon Coppeard <jcoppeard@mozilla.com>
 # Date 1517489143 0
 # Node ID 43a07eda5524f9f4405b7acffe7bb884be09c180
-# Parent  af9f1c868ad99ae5a4281a34139cb220ae29cb8d
+# Parent  e395fb8757912a78a90a17dddca26eaacc65db1c
 Bug 1434622 - Use a separate lock to protect the shared script data table r=sfink
 
 diff --git a/js/src/gc/GCMarker.h b/js/src/gc/GCMarker.h
@@ -91,7 +91,7 @@ diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h
          return runtime_->gc.atomMarking;
      }
      void markAtom(JSAtom* atom) {
-@@ -1220,16 +1221,47 @@ class MOZ_RAII AutoLockForExclusiveAcces
+@@ -1213,16 +1214,47 @@ class MOZ_RAII AutoLockForExclusiveAcces
              runtime->activeThreadHasExclusiveAccess = false;
  #endif
          }
@@ -164,7 +164,7 @@ diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
 diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
 --- a/js/src/jsscript.cpp
 +++ b/js/src/jsscript.cpp
-@@ -2520,17 +2520,17 @@ JSScript::setScriptData(js::SharedScript
+@@ -2517,17 +2517,17 @@ JSScript::setScriptData(js::SharedScript
   */
  bool
  JSScript::shareScriptData(JSContext* cx)
@@ -183,7 +183,7 @@ diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
          setScriptData(*p);
      } else {
          if (!cx->scriptDataTable(lock).add(p, ssd)) {
-@@ -2543,35 +2543,38 @@ JSScript::shareScriptData(JSContext* cx)
+@@ -2540,35 +2540,38 @@ JSScript::shareScriptData(JSContext* cx)
          scriptData()->incRefCount();
      }
  

+ 69 - 0
mozilla-release/patches/1434689-2-60a1.patch

@@ -0,0 +1,69 @@
+# HG changeset patch
+# User Eric Rahm <erahm@mozilla.com>
+# Date 1517440962 28800
+# Node ID 0894630b826962ad287686b79576893631ab159b
+# Parent  311d8fa15ac17998d953ad1e68b48afca189d44b
+Bug 1434689 - Part 2: Add MOZ_TEMPORARY_CLASS attribute. r=mystor
+
+This adds the MOZ_TEMPORARY_CLASS attribute to Attributes.h.
+
+diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h
+--- a/mfbt/Attributes.h
++++ b/mfbt/Attributes.h
+@@ -526,16 +526,20 @@
+  *   temporary object. If a member of another class uses this class, or if
+  *   another class inherits from this class, then it is considered to be a heap
+  *   class as well, although this attribute need not be provided in such cases.
+  * MOZ_NON_TEMPORARY_CLASS: Applies to all classes. Any class with this
+  *   annotation is expected not to live in a temporary. If a member of another
+  *   class uses this class or if another class inherits from this class, then it
+  *   is considered to be a non-temporary class as well, although this attribute
+  *   need not be provided in such cases.
++ * MOZ_TEMPORARY_CLASS: Applies to all classes. Any class with this annotation
++ *   is expected to only live in a temporary. If another class inherits from
++ *   this class, then it is considered to be a non-temporary class as well,
++ *   although this attribute need not be provided in such cases.
+  * MOZ_RAII: Applies to all classes. Any class with this annotation is assumed
+  *   to be a RAII guard, which is expected to live on the stack in an automatic
+  *   allocation. It is prohibited from being allocated in a temporary, static
+  *   storage, or on the heap. This is a combination of MOZ_STACK_CLASS and
+  *   MOZ_NON_TEMPORARY_CLASS.
+  * MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS: Applies to all classes that are
+  *   intended to prevent introducing static initializers.  This attribute
+  *   currently makes it a compile-time error to instantiate these classes
+@@ -661,16 +665,17 @@
+ #ifdef MOZ_CLANG_PLUGIN
+ #  define MOZ_CAN_RUN_SCRIPT __attribute__((annotate("moz_can_run_script")))
+ #  define MOZ_CAN_RUN_SCRIPT_BOUNDARY __attribute__((annotate("moz_can_run_script_boundary")))
+ #  define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
+ #  define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+ #  define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
+ #  define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
+ #  define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class")))
++#  define MOZ_TEMPORARY_CLASS __attribute__((annotate("moz_temporary_class")))
+ #  define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor")))
+ #  ifdef DEBUG
+      /* in debug builds, these classes do have non-trivial constructors. */
+ #    define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class")))
+ #  else
+ #    define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) \
+             MOZ_TRIVIAL_CTOR_DTOR
+ #  endif
+@@ -717,16 +722,17 @@
+ #else
+ #  define MOZ_CAN_RUN_SCRIPT /* nothing */
+ #  define MOZ_CAN_RUN_SCRIPT_BOUNDARY /* nothing */
+ #  define MOZ_MUST_OVERRIDE /* nothing */
+ #  define MOZ_STACK_CLASS /* nothing */
+ #  define MOZ_NONHEAP_CLASS /* nothing */
+ #  define MOZ_HEAP_CLASS /* nothing */
+ #  define MOZ_NON_TEMPORARY_CLASS /* nothing */
++#  define MOZ_TEMPORARY_CLASS /* nothing */
+ #  define MOZ_TRIVIAL_CTOR_DTOR /* nothing */
+ #  define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */
+ #  define MOZ_IMPLICIT /* nothing */
+ #  define MOZ_IS_SMARTPTR_TO_REFCOUNTED /* nothing */
+ #  define MOZ_IS_REFPTR /* nothing */
+ #  define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */
+ #  define MOZ_HEAP_ALLOCATOR /* nothing */
+ #  define MOZ_OWNING_REF /* nothing */

+ 47 - 0
mozilla-release/patches/1434689-3-60a1.patch

@@ -0,0 +1,47 @@
+# HG changeset patch
+# User Eric Rahm <erahm@mozilla.com>
+# Date 1517442304 28800
+# Node ID 11f8f004395cf383fdcead9f5faac52634541b2a
+# Parent  0894630b826962ad287686b79576893631ab159b
+Bug 1434689 - Part 3: Annotate nsTSubstringTuple as MOZ_TEMPORARY_CLASS. r=froydnj
+
+The documentation indicates nsTStringTuple is intended for internal use only
+and is designed to be only be used as a temporary. This makes that fact
+explicit by annotating the class for static analysis.
+
+diff --git a/xpcom/string/nsTSubstringTuple.h b/xpcom/string/nsTSubstringTuple.h
+--- a/xpcom/string/nsTSubstringTuple.h
++++ b/xpcom/string/nsTSubstringTuple.h
+@@ -3,29 +3,30 @@
+ /* 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/. */
+ // IWYU pragma: private, include "nsString.h"
+ 
+ #ifndef nsTSubstringTuple_h
+ #define nsTSubstringTuple_h
+ 
++#include "mozilla/Attributes.h"
+ #include "nsTStringRepr.h"
+ 
+ /**
+  * nsTSubstringTuple
+  *
+  * Represents a tuple of string fragments.  Built as a recursive binary tree.
+  * It is used to implement the concatenation of two or more string objects.
+  *
+  * NOTE: This class is a private implementation detail and should never be
+  * referenced outside the string code.
+  */
+ template <typename T>
+-class nsTSubstringTuple
++class MOZ_TEMPORARY_CLASS nsTSubstringTuple
+ {
+ public:
+ 
+   typedef T char_type;
+   typedef nsCharTraits<char_type> char_traits;
+ 
+   typedef nsTSubstringTuple<T> self_type;
+   typedef mozilla::detail::nsTStringRepr<char_type> base_string_type;
+

+ 51 - 0
mozilla-release/patches/1434689-4-60a1.patch

@@ -0,0 +1,51 @@
+# HG changeset patch
+# User Eric Rahm <erahm@mozilla.com>
+# Date 1517606511 28800
+# Node ID 38fdcb96bb9258fdd963a063273e36ab9da6e1fc
+# Parent  11f8f004395cf383fdcead9f5faac52634541b2a
+Bug 1434689 - Part 4: Annotate IgnoreErrors as MOZ_TEMPORARY_CLASS. r=bz
+
+IgnoreErrors is intended to only be used as a temporary class, this adds an
+explicit annotation.
+
+diff --git a/dom/bindings/ErrorResult.h b/dom/bindings/ErrorResult.h
+--- a/dom/bindings/ErrorResult.h
++++ b/dom/bindings/ErrorResult.h
+@@ -27,16 +27,17 @@
+ 
+ #include <stdarg.h>
+ 
+ #include "js/GCAnnotations.h"
+ #include "js/Value.h"
+ #include "nscore.h"
+ #include "nsString.h"
+ #include "mozilla/Assertions.h"
++#include "mozilla/Attributes.h"
+ #include "mozilla/Move.h"
+ #include "nsTArray.h"
+ #include "nsISupportsImpl.h"
+ 
+ namespace IPC {
+ class Message;
+ template <typename> struct ParamTraits;
+ } // namespace IPC
+@@ -602,17 +603,17 @@ class IgnoredErrorResult :
+ {
+ };
+ 
+ // A class for use when an ErrorResult should just automatically be
+ // ignored.  This is designed to be passed as a temporary only, like
+ // so:
+ //
+ //    foo->Bar(IgnoreErrors());
+-class IgnoreErrors {
++class MOZ_TEMPORARY_CLASS IgnoreErrors {
+ public:
+   operator ErrorResult&() && { return mInner; }
+ private:
+   // We don't use an ErrorResult member here so we don't make two separate calls
+   // to SuppressException (one from us, one from the ErrorResult destructor
+   // after asserting).
+   binding_danger::TErrorResult<binding_danger::JustSuppressCleanupPolicy> mInner;
+ };
+

+ 308 - 0
mozilla-release/patches/1434790-60a1.patch

@@ -0,0 +1,308 @@
+# HG changeset patch
+# User yuyin <yuyin-hf@loongson.cn>
+# Date 1517412720 -7200
+# Node ID 9add855243c1aae2681e4f21a4e38dabde8f71bd
+# Parent  fbafd7f786d229aafddecf91fc46807f6b79fd8c
+Bug 1434790 - MIPS64: Use XOR for Value unboxing on 64-bit to mitigate certain Spectre attacks. r=draganmladjenovic
+
+diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp
+--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
++++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
+@@ -1427,38 +1427,16 @@ MacroAssemblerMIPS64Compat::testObjectSe
+ void
+ MacroAssemblerMIPS64Compat::testUndefinedSet(Condition cond, const ValueOperand& value, Register dest)
+ {
+     MOZ_ASSERT(cond == Equal || cond == NotEqual);
+     splitTag(value, SecondScratchReg);
+     ma_cmp_set(dest, SecondScratchReg, ImmTag(JSVAL_TAG_UNDEFINED), cond);
+ }
+ 
+-// unboxing code
+-void
+-MacroAssemblerMIPS64Compat::unboxNonDouble(const ValueOperand& operand, Register dest)
+-{
+-    ma_dext(dest, operand.valueReg(), Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+-}
+-
+-void
+-MacroAssemblerMIPS64Compat::unboxNonDouble(const Address& src, Register dest)
+-{
+-    loadPtr(Address(src.base, src.offset), dest);
+-    ma_dext(dest, dest, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+-}
+-
+-void
+-MacroAssemblerMIPS64Compat::unboxNonDouble(const BaseIndex& src, Register dest)
+-{
+-    computeScaledAddress(src, SecondScratchReg);
+-    loadPtr(Address(SecondScratchReg, src.offset), dest);
+-    ma_dext(dest, dest, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+-}
+-
+ void
+ MacroAssemblerMIPS64Compat::unboxInt32(const ValueOperand& operand, Register dest)
+ {
+     ma_sll(dest, operand.valueReg(), Imm32(0));
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxInt32(Register src, Register dest)
+@@ -1514,74 +1492,80 @@ void
+ MacroAssemblerMIPS64Compat::unboxDouble(const Address& src, FloatRegister dest)
+ {
+     ma_ld(dest, Address(src.base, src.offset));
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxString(const ValueOperand& operand, Register dest)
+ {
+-    unboxNonDouble(operand, dest);
++    unboxNonDouble(operand, dest, JSVAL_TYPE_STRING);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxString(Register src, Register dest)
+ {
+-    ma_dext(dest, src, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
++    unboxNonDouble(src, dest, JSVAL_TYPE_STRING);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxString(const Address& src, Register dest)
+ {
+-    unboxNonDouble(src, dest);
++    unboxNonDouble(src, dest, JSVAL_TYPE_STRING);
++}
++
++void
++MacroAssemblerMIPS64Compat::unboxSymbol(const ValueOperand& operand, Register dest)
++{
++    unboxNonDouble(operand, dest, JSVAL_TYPE_SYMBOL);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxSymbol(Register src, Register dest)
+ {
+-    ma_dext(dest, src, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
++    unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxSymbol(const Address& src, Register dest)
+ {
+-    unboxNonDouble(src, dest);
++    unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxObject(const ValueOperand& src, Register dest)
+ {
+-    unboxNonDouble(src, dest);
++    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxObject(Register src, Register dest)
+ {
+-    ma_dext(dest, src, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
++    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxObject(const Address& src, Register dest)
+ {
+-    unboxNonDouble(src, dest);
++    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
+ }
+ 
+ void
+-MacroAssemblerMIPS64Compat::unboxValue(const ValueOperand& src, AnyRegister dest)
++MacroAssemblerMIPS64Compat::unboxValue(const ValueOperand& src, AnyRegister dest, JSValueType type)
+ {
+     if (dest.isFloat()) {
+         Label notInt32, end;
+         asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
+         convertInt32ToDouble(src.valueReg(), dest.fpu());
+         ma_b(&end, ShortJump);
+         bind(&notInt32);
+         unboxDouble(src, dest.fpu());
+         bind(&end);
+     } else {
+-        unboxNonDouble(src, dest.gpr());
++        unboxNonDouble(src, dest.gpr(), type);
+     }
+ }
+ 
+ void
+ MacroAssemblerMIPS64Compat::unboxPrivate(const ValueOperand& src, Register dest)
+ {
+     ma_dsrl(dest, src.valueReg(), Imm32(1));
+ }
+diff --git a/js/src/jit/mips64/MacroAssembler-mips64.h b/js/src/jit/mips64/MacroAssembler-mips64.h
+--- a/js/src/jit/mips64/MacroAssembler-mips64.h
++++ b/js/src/jit/mips64/MacroAssembler-mips64.h
+@@ -357,19 +357,54 @@ class MacroAssemblerMIPS64Compat : publi
+ 
+     // Returns the register containing the type tag.
+     Register splitTagForTest(const ValueOperand& value) {
+         splitTag(value, SecondScratchReg);
+         return SecondScratchReg;
+     }
+ 
+     // unboxing code
+-    void unboxNonDouble(const ValueOperand& operand, Register dest);
+-    void unboxNonDouble(const Address& src, Register dest);
+-    void unboxNonDouble(const BaseIndex& src, Register dest);
++    void unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType type) {
++        unboxNonDouble(operand.valueReg(), dest, type);
++    }
++
++    template <typename T>
++    void unboxNonDouble(T src, Register dest, JSValueType type) {
++        MOZ_ASSERT(type != JSVAL_TYPE_DOUBLE);
++        if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
++            load32(src, dest);
++            return;
++        }
++        loadPtr(src, dest);
++        unboxNonDouble(dest, dest, type);
++    }
++
++    void unboxNonDouble(Register src, Register dest, JSValueType type) {
++        MOZ_ASSERT(type != JSVAL_TYPE_DOUBLE);
++        if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
++            ma_sll(dest, src, Imm32(0));
++            return;
++        }
++        MOZ_ASSERT(ScratchRegister != src);
++        mov(ImmWord(JSVAL_TYPE_TO_SHIFTED_TAG(type)), ScratchRegister);
++        as_xor(dest, src, ScratchRegister);
++    }
++
++    template <typename T>
++    void unboxObjectOrNull(const T& src, Register dest) {
++        unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
++        JS_STATIC_ASSERT(JSVAL_OBJECT_OR_NULL_BIT == (uint64_t(0x8) << JSVAL_TAG_SHIFT));
++        ma_dins(dest, zero, Imm32(JSVAL_TAG_SHIFT + 3), Imm32(1));
++    }
++
++    void unboxGCThingForPreBarrierTrampoline(const Address& src, Register dest) {
++        loadPtr(src, dest);
++        ma_dext(dest, dest, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
++    }
++
+     void unboxInt32(const ValueOperand& operand, Register dest);
+     void unboxInt32(Register src, Register dest);
+     void unboxInt32(const Address& src, Register dest);
+     void unboxInt32(const BaseIndex& src, Register dest);
+     void unboxBoolean(const ValueOperand& operand, Register dest);
+     void unboxBoolean(Register src, Register dest);
+     void unboxBoolean(const Address& src, Register dest);
+     void unboxBoolean(const BaseIndex& src, Register dest);
+@@ -380,18 +415,18 @@ class MacroAssemblerMIPS64Compat : publi
+     void unboxString(Register src, Register dest);
+     void unboxString(const Address& src, Register dest);
+     void unboxSymbol(const ValueOperand& src, Register dest);
+     void unboxSymbol(Register src, Register dest);
+     void unboxSymbol(const Address& src, Register dest);
+     void unboxObject(const ValueOperand& src, Register dest);
+     void unboxObject(Register src, Register dest);
+     void unboxObject(const Address& src, Register dest);
+-    void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
+-    void unboxValue(const ValueOperand& src, AnyRegister dest);
++    void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT); }
++    void unboxValue(const ValueOperand& src, AnyRegister dest, JSValueType type);
+     void unboxPrivate(const ValueOperand& src, Register dest);
+ 
+     void notBoolean(const ValueOperand& val) {
+         as_xori(val.valueReg(), val.valueReg(), 1);
+     }
+ 
+     // boxing code
+     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister);
+@@ -400,16 +435,24 @@ class MacroAssemblerMIPS64Compat : publi
+     // Extended unboxing API. If the payload is already in a register, returns
+     // that register. Otherwise, provides a move to the given scratch register,
+     // and returns that.
+     Register extractObject(const Address& address, Register scratch);
+     Register extractObject(const ValueOperand& value, Register scratch) {
+         unboxObject(value, scratch);
+         return scratch;
+     }
++    Register extractString(const ValueOperand& value, Register scratch) {
++        unboxString(value, scratch);
++        return scratch;
++    }
++    Register extractSymbol(const ValueOperand& value, Register scratch) {
++        unboxSymbol(value, scratch);
++        return scratch;
++    }
+     Register extractInt32(const ValueOperand& value, Register scratch) {
+         unboxInt32(value, scratch);
+         return scratch;
+     }
+     Register extractBoolean(const ValueOperand& value, Register scratch) {
+         unboxBoolean(value, scratch);
+         return scratch;
+     }
+@@ -444,30 +487,50 @@ class MacroAssemblerMIPS64Compat : publi
+ 
+     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr);
+     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr);
+ 
+     template <typename T>
+     void loadUnboxedValue(const T& address, MIRType type, AnyRegister dest) {
+         if (dest.isFloat())
+             loadInt32OrDouble(address, dest.fpu());
+-        else if (type == MIRType::Int32)
+-            unboxInt32(address, dest.gpr());
+-        else if (type == MIRType::Boolean)
+-            unboxBoolean(address, dest.gpr());
++        else if (type == MIRType::ObjectOrNull)
++            unboxObjectOrNull(address, dest.gpr());
+         else
+-            unboxNonDouble(address, dest.gpr());
++            unboxNonDouble(address, dest.gpr(), ValueTypeFromMIRType(type));
+     }
+ 
+-    template <typename T>
+-    void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
++    void storeUnboxedPayload(ValueOperand value, BaseIndex address, size_t nbytes, JSValueType type) {
+         switch (nbytes) {
+           case 8:
+-            unboxNonDouble(value, ScratchRegister);
+-            storePtr(ScratchRegister, address);
++            if (type == JSVAL_TYPE_OBJECT)
++                unboxObjectOrNull(value, SecondScratchReg);
++            else
++                unboxNonDouble(value, SecondScratchReg, type);
++            computeEffectiveAddress(address, ScratchRegister);
++            as_sd(SecondScratchReg, ScratchRegister, 0);
++            return;
++          case 4:
++            store32(value.valueReg(), address);
++            return;
++          case 1:
++            store8(value.valueReg(), address);
++            return;
++          default: MOZ_CRASH("Bad payload width");
++        }
++    }
++
++    void storeUnboxedPayload(ValueOperand value, Address address, size_t nbytes, JSValueType type) {
++        switch (nbytes) {
++          case 8:
++            if (type == JSVAL_TYPE_OBJECT)
++                unboxObjectOrNull(value, SecondScratchReg);
++            else
++                unboxNonDouble(value, SecondScratchReg, type);
++            storePtr(SecondScratchReg, address);
+             return;
+           case 4:
+             store32(value.valueReg(), address);
+             return;
+           case 1:
+             store8(value.valueReg(), address);
+             return;
+           default: MOZ_CRASH("Bad payload width");
+

+ 153 - 0
mozilla-release/patches/1434835-60a1.patch

@@ -0,0 +1,153 @@
+# HG changeset patch
+# User Dragan Mladjenovic <dragan.mladjenovic>
+# Date 1517436000 -7200
+# Node ID 702baccfff306ce4b11b003de8e8e7503fe84425
+# Parent  a7215ce57dd3236e8e04684f2100e8c708091883
+Bug 1434835 : Port changes from Bug 1432479; r=nbp.
+
+diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp
+--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
++++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
+@@ -1260,30 +1260,30 @@ void
+ MacroAssemblerMIPSCompat::testUndefinedSet(Condition cond, const ValueOperand& value, Register dest)
+ {
+     MOZ_ASSERT(cond == Equal || cond == NotEqual);
+     ma_cmp_set(dest, value.typeReg(), ImmType(JSVAL_TYPE_UNDEFINED), cond);
+ }
+ 
+ // unboxing code
+ void
+-MacroAssemblerMIPSCompat::unboxNonDouble(const ValueOperand& operand, Register dest)
++MacroAssemblerMIPSCompat::unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType)
+ {
+     if (operand.payloadReg() != dest)
+         ma_move(dest, operand.payloadReg());
+ }
+ 
+ void
+-MacroAssemblerMIPSCompat::unboxNonDouble(const Address& src, Register dest)
++MacroAssemblerMIPSCompat::unboxNonDouble(const Address& src, Register dest, JSValueType)
+ {
+     ma_lw(dest, Address(src.base, src.offset + PAYLOAD_OFFSET));
+ }
+ 
+ void
+-MacroAssemblerMIPSCompat::unboxNonDouble(const BaseIndex& src, Register dest)
++MacroAssemblerMIPSCompat::unboxNonDouble(const BaseIndex& src, Register dest, JSValueType)
+ {
+     computeScaledAddress(src, SecondScratchReg);
+     ma_lw(dest, Address(SecondScratchReg, src.offset + PAYLOAD_OFFSET));
+ }
+ 
+ void
+ MacroAssemblerMIPSCompat::unboxInt32(const ValueOperand& operand, Register dest)
+ {
+@@ -1344,17 +1344,17 @@ MacroAssemblerMIPSCompat::unboxObject(co
+ 
+ void
+ MacroAssemblerMIPSCompat::unboxObject(const Address& src, Register dest)
+ {
+     ma_lw(dest, Address(src.base, src.offset + PAYLOAD_OFFSET));
+ }
+ 
+ void
+-MacroAssemblerMIPSCompat::unboxValue(const ValueOperand& src, AnyRegister dest)
++MacroAssemblerMIPSCompat::unboxValue(const ValueOperand& src, AnyRegister dest, JSValueType)
+ {
+     if (dest.isFloat()) {
+         Label notInt32, end;
+         asMasm().branchTestInt32(Assembler::NotEqual, src, &notInt32);
+         convertInt32ToDouble(src.payloadReg(), dest.fpu());
+         ma_b(&end, ShortJump);
+         bind(&notInt32);
+         unboxDouble(src, dest.fpu());
+diff --git a/js/src/jit/mips32/MacroAssembler-mips32.h b/js/src/jit/mips32/MacroAssembler-mips32.h
+--- a/js/src/jit/mips32/MacroAssembler-mips32.h
++++ b/js/src/jit/mips32/MacroAssembler-mips32.h
+@@ -330,48 +330,62 @@ class MacroAssemblerMIPSCompat : public 
+     }
+ 
+     // Returns the register containing the type tag.
+     Register splitTagForTest(const ValueOperand& value) {
+         return value.typeReg();
+     }
+ 
+     // unboxing code
+-    void unboxNonDouble(const ValueOperand& operand, Register dest);
+-    void unboxNonDouble(const Address& src, Register dest);
+-    void unboxNonDouble(const BaseIndex& src, Register dest);
++    void unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType);
++    void unboxNonDouble(const Address& src, Register dest, JSValueType);
++    void unboxNonDouble(const BaseIndex& src, Register dest, JSValueType);
+     void unboxInt32(const ValueOperand& operand, Register dest);
+     void unboxInt32(const Address& src, Register dest);
+     void unboxBoolean(const ValueOperand& operand, Register dest);
+     void unboxBoolean(const Address& src, Register dest);
+     void unboxDouble(const ValueOperand& operand, FloatRegister dest);
+     void unboxDouble(const Address& src, FloatRegister dest);
+     void unboxString(const ValueOperand& operand, Register dest);
+     void unboxString(const Address& src, Register dest);
+     void unboxObject(const ValueOperand& src, Register dest);
+     void unboxObject(const Address& src, Register dest);
+-    void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
+-    void unboxValue(const ValueOperand& src, AnyRegister dest);
++    void unboxObject(const BaseIndex& src, Register dest)
++    {
++        unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
++    }
++    void unboxValue(const ValueOperand& src, AnyRegister dest, JSValueType);
+     void unboxPrivate(const ValueOperand& src, Register dest);
+ 
++    void unboxGCThingForPreBarrierTrampoline(const Address& src, Register dest)
++    {
++        unboxObject(src, dest);
++    }
++
+     void notBoolean(const ValueOperand& val) {
+         as_xori(val.payloadReg(), val.payloadReg(), 1);
+     }
+ 
+     // boxing code
+     void boxDouble(FloatRegister src, const ValueOperand& dest, FloatRegister);
+     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
+ 
+     // Extended unboxing API. If the payload is already in a register, returns
+     // that register. Otherwise, provides a move to the given scratch register,
+     // and returns that.
+     Register extractObject(const Address& address, Register scratch);
+     Register extractObject(const ValueOperand& value, Register scratch) {
+         return value.payloadReg();
+     }
++    Register extractString(const ValueOperand& value, Register scratch) {
++        return value.payloadReg();
++    }
++    Register extractSymbol(const ValueOperand& value, Register scratch) {
++        return value.payloadReg();
++    }
+     Register extractInt32(const ValueOperand& value, Register scratch) {
+         return value.payloadReg();
+     }
+     Register extractBoolean(const ValueOperand& value, Register scratch) {
+         return value.payloadReg();
+     }
+     Register extractTag(const Address& address, Register scratch);
+     Register extractTag(const BaseIndex& address, Register scratch);
+@@ -434,17 +448,17 @@ class MacroAssemblerMIPSCompat : public 
+             load32(ToPayload(address), dest.gpr());
+     }
+ 
+     template <typename T>
+     void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest,
+                            MIRType slotType);
+ 
+     template <typename T>
+-    void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
++    void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes, JSValueType) {
+         switch (nbytes) {
+           case 4:
+             store32(value.payloadReg(), address);
+             return;
+           case 1:
+             store8(value.payloadReg(), address);
+             return;
+           default: MOZ_CRASH("Bad payload width");

+ 33 - 0
mozilla-release/patches/1435219-60a1.patch

@@ -0,0 +1,33 @@
+# HG changeset patch
+# User John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+# Date 1517549280 -7200
+# Node ID 6123659a067649fb4cdedb4f328b2bb950102f0c
+# Parent  466f3ab8d3227f072f13b514eef72da315740f73
+Bug 1435219 - Add missing WasmSignalHandler platform definitions on Linux sparc64 r=bbouvier
+Signed-off-by: John Paul Adrian Glaubitz <glaubitz@suse.com>
+
+diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
+--- a/js/src/wasm/WasmSignalHandlers.cpp
++++ b/js/src/wasm/WasmSignalHandlers.cpp
+@@ -171,16 +171,21 @@ struct AutoSignalHandler
+ #  define R31_sig(p) ((p)->uc_mcontext.regs[31])
+ # endif
+ # if defined(__linux__) && defined(__mips__)
+ #  define EPC_sig(p) ((p)->uc_mcontext.pc)
+ #  define RFP_sig(p) ((p)->uc_mcontext.gregs[30])
+ #  define RSP_sig(p) ((p)->uc_mcontext.gregs[29])
+ #  define R31_sig(p) ((p)->uc_mcontext.gregs[31])
+ # endif
++# if defined(__linux__) && (defined(__sparc__) && defined(__arch64__))
++#  define PC_sig(p) ((p)->uc_mcontext.mc_gregs[MC_PC])
++#  define FP_sig(p) ((p)->uc_mcontext.mc_fp)
++#  define SP_sig(p) ((p)->uc_mcontext.mc_i7)
++# endif
+ #elif defined(__NetBSD__)
+ # define XMM_sig(p,i) (((struct fxsave64*)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
+ # define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
+ # define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
+ # define ESP_sig(p) ((p)->uc_mcontext.__gregs[_REG_ESP])
+ # define RIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RIP])
+ # define RAX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RAX])
+ # define RCX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RCX])

+ 30 - 0
mozilla-release/patches/1435228-60a1.patch

@@ -0,0 +1,30 @@
+# HG changeset patch
+# User John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+# Date 1517550000 -7200
+# Node ID 997c15a7ba086970bb77af8dcf0b214cf3db409b
+# Parent  3c823d5256cdecaf52ef8a64e8f7654ca42cc5e4
+Bug 1435228 - Fix bogus preprocessor macro for defining KNOWS_MACHINE_STATE r=bbouvier
+Signed-off-by: John Paul Adrian Glaubitz <glaubitz@suse.com>
+
+diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
+--- a/js/src/wasm/WasmSignalHandlers.cpp
++++ b/js/src/wasm/WasmSignalHandlers.cpp
+@@ -418,17 +418,17 @@ struct macos_arm_context {
+ # define LR_sig(p) RLR_sig(p)
+ #elif defined(__mips__)
+ # define PC_sig(p) EPC_sig(p)
+ # define FP_sig(p) RFP_sig(p)
+ # define SP_sig(p) RSP_sig(p)
+ # define LR_sig(p) R31_sig(p)
+ #endif
+ 
+-#if defined(FP_sig) && defined(SP_sig) && defined(SP_sig)
++#if defined(PC_sig) && defined(FP_sig) && defined(SP_sig)
+ # define KNOWS_MACHINE_STATE
+ #endif
+ 
+ static uint8_t**
+ ContextToPC(CONTEXT* context)
+ {
+ #ifdef KNOWS_MACHINE_STATE
+     return reinterpret_cast<uint8_t**>(&PC_sig(context));

+ 10 - 0
mozilla-release/patches/series

@@ -961,7 +961,12 @@ servo-19918-60a1.patch
 1386404-6-60a1.patch
 1386404-7-60a1.patch
 1417388-60a1.patch
+1434835-60a1.patch
 1434622-60a1.patch
+1434790-60a1.patch
+1433837-5-60a1.patch
+1433837-6-60a1.patch
+1434263-60a1.patch
 1423582-60a1.patch
 servo-19923-60a1.patch
 servo-19924-60a1.patch
@@ -1011,6 +1016,11 @@ servo-19927-60a1.patch
 1435187-60a1.patch
 1435262-60a1.patch
 1435015-60a1.patch
+1435228-60a1.patch
+1434689-2-60a1.patch
+1434689-3-60a1.patch
+1434689-4-60a1.patch
+1435219-60a1.patch
 1435200-60a1.patch
 servo-19935-60a1.patch
 servo-19938-60a1.patch