From c2b5f396eb4ed1bd9be5a6625bd823d7a3e63678 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Thu, 23 May 2019 02:48:13 +0000
Subject: Remove UnboxedArray code part 1

---
 js/src/builtin/ModuleObject.cpp     |   2 +-
 js/src/jit/AliasAnalysisShared.cpp  |   4 -
 js/src/jit/BaselineCacheIR.cpp      |  16 --
 js/src/jit/BaselineIC.cpp           | 146 +--------------
 js/src/jit/CacheIR.cpp              |   9 +-
 js/src/jit/CacheIR.h                |   5 -
 js/src/jit/CodeGenerator.cpp        | 341 ++++++++----------------------------
 js/src/jit/CodeGenerator.h          |   4 -
 js/src/jit/IonBuilder.cpp           | 199 +++++++--------------
 js/src/jit/IonBuilder.h             |  12 +-
 js/src/jit/IonCaches.cpp            | 135 ++------------
 js/src/jit/Lowering.cpp             |  30 ----
 js/src/jit/Lowering.h               |   4 -
 js/src/jit/MCallOptimize.cpp        |  71 ++------
 js/src/jit/MIR.cpp                  |  45 -----
 js/src/jit/MIR.h                    | 176 ++-----------------
 js/src/jit/MOpcodes.h               |   4 -
 js/src/jit/MacroAssembler.cpp       |  35 ----
 js/src/jit/MacroAssembler.h         |   5 +-
 js/src/jit/ScalarReplacement.cpp    |   5 -
 js/src/jit/SharedIC.cpp             |   9 -
 js/src/jit/VMFunctions.cpp          |  12 +-
 js/src/jit/shared/LIR-shared.h      |  66 -------
 js/src/jit/shared/LOpcodes-shared.h |   4 -
 js/src/jsarray.cpp                  | 141 ++++++---------
 js/src/jsfriendapi.cpp              |   2 +-
 26 files changed, 251 insertions(+), 1231 deletions(-)

(limited to 'js/src')

diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 710c7a76c..c6bd2d300 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -947,7 +947,7 @@ ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValu
 ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObject exports)
 {
     MOZ_ASSERT(!self->namespace_());
-    MOZ_ASSERT(exports->is<ArrayObject>() || exports->is<UnboxedArrayObject>());
+    MOZ_ASSERT(exports->is<ArrayObject>());
 
     RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
     if (!ns)
diff --git a/js/src/jit/AliasAnalysisShared.cpp b/js/src/jit/AliasAnalysisShared.cpp
index 3b83df74e..0f0d4a66a 100644
--- a/js/src/jit/AliasAnalysisShared.cpp
+++ b/js/src/jit/AliasAnalysisShared.cpp
@@ -93,10 +93,6 @@ GetObject(const MDefinition* ins)
       case MDefinition::Op_Elements:
       case MDefinition::Op_MaybeCopyElementsForWrite:
       case MDefinition::Op_MaybeToDoubleElement:
-      case MDefinition::Op_UnboxedArrayLength:
-      case MDefinition::Op_UnboxedArrayInitializedLength:
-      case MDefinition::Op_IncrementUnboxedArrayInitializedLength:
-      case MDefinition::Op_SetUnboxedArrayInitializedLength:
       case MDefinition::Op_TypedArrayLength:
       case MDefinition::Op_SetTypedObjectOffset:
       case MDefinition::Op_SetDisjointTypedElements:
diff --git a/js/src/jit/BaselineCacheIR.cpp b/js/src/jit/BaselineCacheIR.cpp
index bf96932d1..7fb586811 100644
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -787,9 +787,6 @@ BaselineCacheIRCompiler::emitGuardClass()
       case GuardClassKind::Array:
         clasp = &ArrayObject::class_;
         break;
-      case GuardClassKind::UnboxedArray:
-        clasp = &UnboxedArrayObject::class_;
-        break;
       case GuardClassKind::MappedArguments:
         clasp = &MappedArgumentsObject::class_;
         break;
@@ -1003,19 +1000,6 @@ BaselineCacheIRCompiler::emitLoadInt32ArrayLengthResult()
     return true;
 }
 
-bool
-BaselineCacheIRCompiler::emitLoadUnboxedArrayLengthResult()
-{
-    Register obj = allocator.useRegister(masm, reader.objOperandId());
-    masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), R0.scratchReg());
-    masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0);
-
-    // The int32 type was monitored when attaching the stub, so we can
-    // just return.
-    emitReturnFromIC();
-    return true;
-}
-
 bool
 BaselineCacheIRCompiler::emitLoadArgumentsObjectLengthResult()
 {
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 863c61161..f43fc5bf9 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -280,12 +280,6 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
     RootedId id(cx);
 
     switch(stub->kind()) {
-      case ICStub::SetElem_DenseOrUnboxedArray:
-      case ICStub::SetElem_DenseOrUnboxedArrayAdd: {
-        id = JSID_VOID;
-        AddTypePropertyId(cx, obj, id, value);
-        break;
-      }
       case ICStub::SetProp_Native:
       case ICStub::SetProp_NativeAdd:
       case ICStub::SetProp_Unboxed: {
@@ -1366,7 +1360,7 @@ IsNativeDenseElementAccess(HandleObject obj, HandleValue key)
 static bool
 IsNativeOrUnboxedDenseElementAccess(HandleObject obj, HandleValue key)
 {
-    if (!obj->isNative() && !obj->is<UnboxedArrayObject>())
+    if (!obj->isNative())
         return false;
     if (key.isInt32() && key.toInt32() >= 0 && !obj->is<TypedArrayObject>())
         return true;
@@ -1470,20 +1464,6 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
         script = rootedScript;
     }
 
-    // Check for UnboxedArray[int] accesses.
-    if (obj->is<UnboxedArrayObject>() && rhs.isInt32() && rhs.toInt32() >= 0) {
-        JitSpew(JitSpew_BaselineIC, "  Generating GetElem(UnboxedArray[Int32]) stub");
-        ICGetElem_UnboxedArray::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
-                                                  obj->group());
-        ICStub* unboxedStub = compiler.getStub(compiler.getStubSpace(script));
-        if (!unboxedStub)
-            return false;
-
-        stub->addNewStub(unboxedStub);
-        *attached = true;
-        return true;
-    }
-
     // Check for TypedArray[int] => Number and TypedObject[int] => Number accesses.
     if ((obj->is<TypedArrayObject>() || IsPrimitiveArrayTypedObject(obj)) &&
         rhs.isNumber() &&
@@ -2089,56 +2069,6 @@ ICGetElem_Dense::Compiler::generateStubCode(MacroAssembler& masm)
     return true;
 }
 
-//
-// GetElem_UnboxedArray
-//
-
-bool
-ICGetElem_UnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
-    Label failure;
-    masm.branchTestObject(Assembler::NotEqual, R0, &failure);
-    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
-    Register scratchReg = regs.takeAny();
-
-    // Unbox R0 and group guard.
-    Register obj = masm.extractObject(R0, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICGetElem_UnboxedArray::offsetOfGroup()), scratchReg);
-    masm.branchTestObjGroup(Assembler::NotEqual, obj, scratchReg, &failure);
-
-    // Unbox key.
-    Register key = masm.extractInt32(R1, ExtractTemp1);
-
-    // Bounds check.
-    masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()),
-                scratchReg);
-    masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
-    masm.branch32(Assembler::BelowOrEqual, scratchReg, key, &failure);
-
-    // Load obj->elements.
-    masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
-    // Load value.
-    size_t width = UnboxedTypeSize(elementType_);
-    BaseIndex addr(scratchReg, key, ScaleFromElemWidth(width));
-    masm.loadUnboxedProperty(addr, elementType_, R0);
-
-    // Only monitor the result if its type might change.
-    if (elementType_ == JSVAL_TYPE_OBJECT)
-        EmitEnterTypeMonitorIC(masm);
-    else
-        EmitReturnFromIC(masm);
-
-    // Failure case - jump to next stub
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
 //
 // GetElem_TypedArray
 //
@@ -2447,10 +2377,6 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index,
     if (initLength < oldInitLength || capacity < oldCapacity)
         return false;
 
-    // Unboxed arrays need to be able to emit floating point code.
-    if (obj->is<UnboxedArrayObject>() && !obj->runtimeFromMainThread()->jitSupportsFloatingPoint)
-        return false;
-
     Shape* shape = obj->maybeShape();
 
     // Cannot optimize if the shape changed.
@@ -2871,29 +2797,6 @@ ICSetElem_DenseOrUnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
         masm.loadValue(valueAddr, tmpVal);
         EmitPreBarrier(masm, element, MIRType::Value);
         masm.storeValue(tmpVal, element);
-    } else {
-        // Set element on an unboxed array.
-
-        // Bounds check.
-        Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-        masm.load32(initLength, scratchReg);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
-        masm.branch32(Assembler::BelowOrEqual, scratchReg, key, &failure);
-
-        // Load obj->elements.
-        masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
-        // Compute the address being written to.
-        BaseIndex address(scratchReg, key, ScaleFromElemWidth(UnboxedTypeSize(unboxedType_)));
-
-        EmitUnboxedPreBarrierForBaseline(masm, address, unboxedType_);
-
-        Address valueAddr(masm.getStackPointer(), ICStackValueOffset + sizeof(Value));
-        masm.Push(R0);
-        masm.loadValue(valueAddr, R0);
-        masm.storeUnboxedProperty(address, unboxedType_,
-                                  ConstantOrRegister(TypedOrValueRegister(R0)), &failurePopR0);
-        masm.Pop(R0);
     }
 
     EmitReturnFromIC(masm);
@@ -3087,40 +2990,6 @@ ICSetElemDenseOrUnboxedArrayAddCompiler::generateStubCode(MacroAssembler& masm)
         BaseIndex element(scratchReg, key, TimesEight);
         masm.loadValue(valueAddr, tmpVal);
         masm.storeValue(tmpVal, element);
-    } else {
-        // Adding element to an unboxed array.
-
-        // Bounds check (key == initLength)
-        Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-        masm.load32(initLengthAddr, scratchReg);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), scratchReg);
-        masm.branch32(Assembler::NotEqual, scratchReg, key, &failure);
-
-        // Capacity check.
-        masm.checkUnboxedArrayCapacity(obj, RegisterOrInt32Constant(key), scratchReg, &failure);
-
-        // Load obj->elements.
-        masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), scratchReg);
-
-        // Write the value first, since this can fail. No need for pre-barrier
-        // since we're not overwriting an old value.
-        masm.Push(R0);
-        Address valueAddr(masm.getStackPointer(), ICStackValueOffset + sizeof(Value));
-        masm.loadValue(valueAddr, R0);
-        BaseIndex address(scratchReg, key, ScaleFromElemWidth(UnboxedTypeSize(unboxedType_)));
-        masm.storeUnboxedProperty(address, unboxedType_,
-                                  ConstantOrRegister(TypedOrValueRegister(R0)), &failurePopR0);
-        masm.Pop(R0);
-
-        // Increment initialized length.
-        masm.add32(Imm32(1), initLengthAddr);
-
-        // If length is now <= key, increment length.
-        Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
-        Label skipIncrementLength;
-        masm.branch32(Assembler::Above, lengthAddr, key, &skipIncrementLength);
-        masm.add32(Imm32(1), lengthAddr);
-        masm.bind(&skipIncrementLength);
     }
 
     EmitReturnFromIC(masm);
@@ -8301,19 +8170,6 @@ ICGetElem_Dense::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorSt
     return New<ICGetElem_Dense>(cx, space, other.jitCode(), firstMonitorStub, other.shape_);
 }
 
-ICGetElem_UnboxedArray::ICGetElem_UnboxedArray(JitCode* stubCode, ICStub* firstMonitorStub,
-                                               ObjectGroup *group)
-  : ICMonitoredStub(GetElem_UnboxedArray, stubCode, firstMonitorStub),
-    group_(group)
-{ }
-
-/* static */ ICGetElem_UnboxedArray*
-ICGetElem_UnboxedArray::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
-                              ICGetElem_UnboxedArray& other)
-{
-    return New<ICGetElem_UnboxedArray>(cx, space, other.jitCode(), firstMonitorStub, other.group_);
-}
-
 ICGetElem_TypedArray::ICGetElem_TypedArray(JitCode* stubCode, Shape* shape, Scalar::Type type)
   : ICStub(GetElem_TypedArray, stubCode),
     shape_(shape)
diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
index f1061af70..6822a70af 100644
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -175,7 +175,7 @@ TestMatchingReceiver(CacheIRWriter& writer, JSObject* obj, Shape* shape, ObjOper
         } else {
             writer.guardNoUnboxedExpando(objId);
         }
-    } else if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
+    } else if (obj->is<TypedObject>()) {
         writer.guardGroup(objId, obj->group());
     } else {
         Shape* shape = obj->maybeShape();
@@ -368,13 +368,6 @@ GetPropIRGenerator::tryAttachObjectLength(CacheIRWriter& writer, HandleObject ob
         return true;
     }
 
-    if (obj->is<UnboxedArrayObject>()) {
-        writer.guardClass(objId, GuardClassKind::UnboxedArray);
-        writer.loadUnboxedArrayLengthResult(objId);
-        emitted_ = true;
-        return true;
-    }
-
     if (obj->is<ArgumentsObject>() && !obj->as<ArgumentsObject>().hasOverriddenLength()) {
         if (obj->is<MappedArgumentsObject>()) {
             writer.guardClass(objId, GuardClassKind::MappedArguments);
diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h
index 51e55f48b..4fd8575f0 100644
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -96,7 +96,6 @@ class ObjOperandId : public OperandId
     _(LoadUnboxedPropertyResult)          \
     _(LoadTypedObjectResult)              \
     _(LoadInt32ArrayLengthResult)         \
-    _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadUndefinedResult)
 
@@ -128,7 +127,6 @@ struct StubField {
 enum class GuardClassKind
 {
     Array,
-    UnboxedArray,
     MappedArguments,
     UnmappedArguments,
 };
@@ -327,9 +325,6 @@ class MOZ_RAII CacheIRWriter
     void loadInt32ArrayLengthResult(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj);
     }
-    void loadUnboxedArrayLengthResult(ObjOperandId obj) {
-        writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
-    }
     void loadArgumentsObjectLengthResult(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
     }
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 6d1fb6b9b..bd275a2c1 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3183,9 +3183,7 @@ CodeGenerator::visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT* ins)
 void
 CodeGenerator::visitElements(LElements* lir)
 {
-    Address elements(ToRegister(lir->object()),
-                     lir->mir()->unboxed() ? UnboxedArrayObject::offsetOfElements()
-                                           : NativeObject::offsetOfElements());
+    Address elements(ToRegister(lir->object()), NativeObject::offsetOfElements());
     masm.loadPtr(elements, ToRegister(lir->output()));
 }
 
@@ -5341,21 +5339,11 @@ CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength* lir)
 
     bool canInline = true;
     size_t inlineLength = 0;
-    if (templateObject->is<ArrayObject>()) {
-        if (templateObject->as<ArrayObject>().hasFixedElements()) {
-            size_t numSlots = gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
-            inlineLength = numSlots - ObjectElements::VALUES_PER_HEADER;
-        } else {
-            canInline = false;
-        }
+    if (templateObject->as<ArrayObject>().hasFixedElements()) {
+        size_t numSlots = gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
+        inlineLength = numSlots - ObjectElements::VALUES_PER_HEADER;
     } else {
-        if (templateObject->as<UnboxedArrayObject>().hasInlineElements()) {
-            size_t nbytes =
-                templateObject->tenuredSizeOfThis() - UnboxedArrayObject::offsetOfInlineElements();
-            inlineLength = nbytes / templateObject->as<UnboxedArrayObject>().elementSize();
-        } else {
-            canInline = false;
-        }
+        canInline = false;
     }
 
     if (canInline) {
@@ -7811,49 +7799,6 @@ CodeGenerator::visitSetInitializedLength(LSetInitializedLength* lir)
     masm.dec32(&index);
 }
 
-void
-CodeGenerator::visitUnboxedArrayLength(LUnboxedArrayLength* lir)
-{
-    Register obj = ToRegister(lir->object());
-    Register result = ToRegister(lir->output());
-    masm.load32(Address(obj, UnboxedArrayObject::offsetOfLength()), result);
-}
-
-void
-CodeGenerator::visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir)
-{
-    Register obj = ToRegister(lir->object());
-    Register result = ToRegister(lir->output());
-    masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), result);
-    masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), result);
-}
-
-void
-CodeGenerator::visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir)
-{
-    Register obj = ToRegister(lir->object());
-    masm.add32(Imm32(1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
-}
-
-void
-CodeGenerator::visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir)
-{
-    Register obj = ToRegister(lir->object());
-    RegisterOrInt32Constant key = ToRegisterOrInt32Constant(lir->length());
-    Register temp = ToRegister(lir->temp());
-
-    Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-    masm.load32(initLengthAddr, temp);
-    masm.and32(Imm32(UnboxedArrayObject::CapacityMask), temp);
-
-    if (key.isRegister())
-        masm.or32(key.reg(), temp);
-    else
-        masm.or32(Imm32(key.constant()), temp);
-
-    masm.store32(temp, initLengthAddr);
-}
-
 void
 CodeGenerator::visitNotO(LNotO* lir)
 {
@@ -8150,46 +8095,19 @@ CodeGenerator::emitStoreElementHoleT(T* lir)
     OutOfLineStoreElementHole* ool = new(alloc()) OutOfLineStoreElementHole(lir);
     addOutOfLineCode(ool, lir->mir());
 
-    Register obj = ToRegister(lir->object());
     Register elements = ToRegister(lir->elements());
     const LAllocation* index = lir->index();
     RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
 
-    JSValueType unboxedType = lir->mir()->unboxedType();
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        Address initLength(elements, ObjectElements::offsetOfInitializedLength());
-        masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
-
-        if (lir->mir()->needsBarrier())
-            emitPreBarrier(elements, index, 0);
+    Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
 
-        masm.bind(ool->rejoinStore());
-        emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
-                              elements, index, 0);
-    } else {
-        Register temp = ToRegister(lir->getTemp(0));
-        Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-        masm.load32(initLength, temp);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp);
-        masm.branch32(Assembler::BelowOrEqual, temp, key, ool->entry());
-
-        ConstantOrRegister v = ToConstantOrRegister(lir->value(), lir->mir()->value()->type());
-
-        if (index->isConstant()) {
-            Address address(elements, ToInt32(index) * UnboxedTypeSize(unboxedType));
-            EmitUnboxedPreBarrier(masm, address, unboxedType);
-
-            masm.bind(ool->rejoinStore());
-            masm.storeUnboxedProperty(address, unboxedType, v, nullptr);
-        } else {
-            BaseIndex address(elements, ToRegister(index),
-                              ScaleFromElemWidth(UnboxedTypeSize(unboxedType)));
-            EmitUnboxedPreBarrier(masm, address, unboxedType);
+    if (lir->mir()->needsBarrier())
+        emitPreBarrier(elements, index, 0);
 
-            masm.bind(ool->rejoinStore());
-            masm.storeUnboxedProperty(address, unboxedType, v, nullptr);
-        }
-    }
+    masm.bind(ool->rejoinStore());
+    emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
+                          elements, index, 0);
 
     masm.bind(ool->rejoin());
 }
@@ -8209,47 +8127,22 @@ CodeGenerator::emitStoreElementHoleV(T* lir)
     OutOfLineStoreElementHole* ool = new(alloc()) OutOfLineStoreElementHole(lir);
     addOutOfLineCode(ool, lir->mir());
 
-    Register obj = ToRegister(lir->object());
     Register elements = ToRegister(lir->elements());
     const LAllocation* index = lir->index();
     const ValueOperand value = ToValue(lir, T::Value);
     RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
 
-    JSValueType unboxedType = lir->mir()->unboxedType();
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        Address initLength(elements, ObjectElements::offsetOfInitializedLength());
-        masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
-
-        if (lir->mir()->needsBarrier())
-            emitPreBarrier(elements, index, 0);
+    Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
 
-        masm.bind(ool->rejoinStore());
-        if (index->isConstant())
-            masm.storeValue(value, Address(elements, ToInt32(index) * sizeof(js::Value)));
-        else
-            masm.storeValue(value, BaseIndex(elements, ToRegister(index), TimesEight));
-    } else {
-        Register temp = ToRegister(lir->getTemp(0));
-        Address initLength(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-        masm.load32(initLength, temp);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), temp);
-        masm.branch32(Assembler::BelowOrEqual, temp, key, ool->entry());
-
-        if (index->isConstant()) {
-            Address address(elements, ToInt32(index) * UnboxedTypeSize(unboxedType));
-            EmitUnboxedPreBarrier(masm, address, unboxedType);
-
-            masm.bind(ool->rejoinStore());
-            masm.storeUnboxedProperty(address, unboxedType, ConstantOrRegister(value), nullptr);
-        } else {
-            BaseIndex address(elements, ToRegister(index),
-                              ScaleFromElemWidth(UnboxedTypeSize(unboxedType)));
-            EmitUnboxedPreBarrier(masm, address, unboxedType);
+    if (lir->mir()->needsBarrier())
+        emitPreBarrier(elements, index, 0);
 
-            masm.bind(ool->rejoinStore());
-            masm.storeUnboxedProperty(address, unboxedType, ConstantOrRegister(value), nullptr);
-        }
-    }
+    masm.bind(ool->rejoinStore());
+    if (index->isConstant())
+        masm.storeValue(value, Address(elements, ToInt32(index) * sizeof(js::Value)));
+    else
+        masm.storeValue(value, BaseIndex(elements, ToRegister(index), TimesEight));
 
     masm.bind(ool->rejoin());
 }
@@ -8334,8 +8227,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
     const LAllocation* index;
     MIRType valueType;
     ConstantOrRegister value;
-    JSValueType unboxedType;
-    LDefinition *temp = nullptr;
 
     if (ins->isStoreElementHoleV()) {
         LStoreElementHoleV* store = ins->toStoreElementHoleV();
@@ -8344,8 +8235,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
         index = store->index();
         valueType = store->mir()->value()->type();
         value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
-        unboxedType = store->mir()->unboxedType();
-        temp = store->getTemp(0);
     } else if (ins->isFallibleStoreElementV()) {
         LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
         object = ToRegister(store->object());
@@ -8353,8 +8242,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
         index = store->index();
         valueType = store->mir()->value()->type();
         value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
-        unboxedType = store->mir()->unboxedType();
-        temp = store->getTemp(0);
     } else if (ins->isStoreElementHoleT()) {
         LStoreElementHoleT* store = ins->toStoreElementHoleT();
         object = ToRegister(store->object());
@@ -8365,8 +8252,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
             value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
         else
             value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
-        unboxedType = store->mir()->unboxedType();
-        temp = store->getTemp(0);
     } else { // ins->isFallibleStoreElementT()
         LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
         object = ToRegister(store->object());
@@ -8377,8 +8262,6 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
             value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
         else
             value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
-        unboxedType = store->mir()->unboxedType();
-        temp = store->getTemp(0);
     }
 
     RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
@@ -8389,54 +8272,32 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
     Label callStub;
 #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     // Had to reimplement for MIPS because there are no flags.
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        Address initLength(elements, ObjectElements::offsetOfInitializedLength());
-        masm.branch32(Assembler::NotEqual, initLength, key, &callStub);
-    } else {
-        Address initLength(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-        masm.load32(initLength, ToRegister(temp));
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), ToRegister(temp));
-        masm.branch32(Assembler::NotEqual, ToRegister(temp), key, &callStub);
-    }
+    Address initLength(elements, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::NotEqual, initLength, key, &callStub);
 #else
     masm.j(Assembler::NotEqual, &callStub);
 #endif
 
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        // Check array capacity.
-        masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
-                      key, &callStub);
-
-        // Update initialized length. The capacity guard above ensures this won't overflow,
-        // due to MAX_DENSE_ELEMENTS_COUNT.
-        masm.inc32(&key);
-        masm.store32(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
-
-        // Update length if length < initializedLength.
-        Label dontUpdate;
-        masm.branch32(Assembler::AboveOrEqual, Address(elements, ObjectElements::offsetOfLength()),
-                      key, &dontUpdate);
-        masm.store32(key, Address(elements, ObjectElements::offsetOfLength()));
-        masm.bind(&dontUpdate);
+    // Check array capacity.
+    masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
+                  key, &callStub);
 
-        masm.dec32(&key);
-    } else {
-        // Check array capacity.
-        masm.checkUnboxedArrayCapacity(object, key, ToRegister(temp), &callStub);
+    // Update initialized length. The capacity guard above ensures this won't overflow,
+    // due to MAX_DENSE_ELEMENTS_COUNT.
+    masm.inc32(&key);
+    masm.store32(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
 
-        // Update initialized length.
-        masm.add32(Imm32(1), Address(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
+    // Update length if length < initializedLength.
+    Label dontUpdate;
+    masm.branch32(Assembler::AboveOrEqual, Address(elements, ObjectElements::offsetOfLength()),
+                  key, &dontUpdate);
+    masm.store32(key, Address(elements, ObjectElements::offsetOfLength()));
+    masm.bind(&dontUpdate);
 
-        // Update length if length < initializedLength.
-        Address lengthAddr(object, UnboxedArrayObject::offsetOfLength());
-        Label dontUpdate;
-        masm.branch32(Assembler::Above, lengthAddr, key, &dontUpdate);
-        masm.add32(Imm32(1), lengthAddr);
-        masm.bind(&dontUpdate);
-    }
+    masm.dec32(&key);
 
     if ((ins->isStoreElementHoleT() || ins->isFallibleStoreElementT()) &&
-        unboxedType == JSVAL_TYPE_MAGIC && valueType != MIRType::Double)
+        valueType != MIRType::Double)
     {
         // The inline path for StoreElementHoleT and FallibleStoreElementT does not always store
         // the type tag, so we do the store on the OOL path. We use MIRType::None for the element
@@ -8526,9 +8387,6 @@ typedef bool (*ConvertUnboxedObjectToNativeFn)(JSContext*, JSObject*);
 static const VMFunction ConvertUnboxedPlainObjectToNativeInfo =
     FunctionInfo<ConvertUnboxedObjectToNativeFn>(UnboxedPlainObject::convertToNative,
                                                  "UnboxedPlainObject::convertToNative");
-static const VMFunction ConvertUnboxedArrayObjectToNativeInfo =
-    FunctionInfo<ConvertUnboxedObjectToNativeFn>(UnboxedArrayObject::convertToNative,
-                                                 "UnboxedArrayObject::convertToNative");
 
 typedef bool (*ArrayPopShiftFn)(JSContext*, HandleObject, MutableHandleValue);
 static const VMFunction ArrayPopDenseInfo =
@@ -8554,20 +8412,11 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
 
     // Load elements and length, and VM call if length != initializedLength.
     RegisterOrInt32Constant key = RegisterOrInt32Constant(lengthTemp);
-    if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-        masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
-        masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
+    masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
+    masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
 
-        Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
-        masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
-    } else {
-        masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), elementsTemp);
-        masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), lengthTemp);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), lengthTemp);
-
-        Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
-        masm.branch32(Assembler::NotEqual, lengthAddr, key, ool->entry());
-    }
+    Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
 
     // Test for length != 0. On zero length either take a VM call or generate
     // an undefined value, depending on whether the call is known to produce
@@ -8579,13 +8428,10 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
 
         // According to the spec we need to set the length 0 (which is already 0).
         // This is observable when the array length is made non-writable.
-        // Handle this case in the OOL. When freezing an unboxed array it is converted
-        // to an normal array.
-        if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-            Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
-            Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
-            masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
-        }
+        // Handle this case in the OOL.
+        Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
+        Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
+        masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
 
         masm.moveValue(UndefinedValue(), out.valueReg());
         masm.jump(&done);
@@ -8597,41 +8443,25 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
     masm.dec32(&key);
 
     if (mir->mode() == MArrayPopShift::Pop) {
-        if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-            BaseIndex addr(elementsTemp, lengthTemp, TimesEight);
-            masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
-        } else {
-            size_t elemSize = UnboxedTypeSize(mir->unboxedType());
-            BaseIndex addr(elementsTemp, lengthTemp, ScaleFromElemWidth(elemSize));
-            masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
-        }
+        BaseIndex addr(elementsTemp, lengthTemp, TimesEight);
+        masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
     } else {
         MOZ_ASSERT(mir->mode() == MArrayPopShift::Shift);
         Address addr(elementsTemp, 0);
-        if (mir->unboxedType() == JSVAL_TYPE_MAGIC)
-            masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
-        else
-            masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
+        masm.loadElementTypedOrValue(addr, out, mir->needsHoleCheck(), ool->entry());
     }
 
-    if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-        // Handle the failure case when the array length is non-writable in the
-        // OOL path.  (Unlike in the adding-an-element cases, we can't rely on the
-        // capacity <= length invariant for such arrays to avoid an explicit
-        // check.)
-        Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
-        Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
-        masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
+    // Handle the failure case when the array length is non-writable in the
+    // OOL path.  (Unlike in the adding-an-element cases, we can't rely on the
+    // capacity <= length invariant for such arrays to avoid an explicit
+    // check.)
+    Address elementFlags(elementsTemp, ObjectElements::offsetOfFlags());
+    Imm32 bit(ObjectElements::NONWRITABLE_ARRAY_LENGTH);
+    masm.branchTest32(Assembler::NonZero, elementFlags, bit, ool->entry());
 
-        // Now adjust length and initializedLength.
-        masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfLength()));
-        masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
-    } else {
-        // Unboxed arrays always have writable lengths. Adjust length and
-        // initializedLength.
-        masm.store32(lengthTemp, Address(obj, UnboxedArrayObject::offsetOfLength()));
-        masm.add32(Imm32(-1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
-    }
+    // Now adjust length and initializedLength.
+    masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfLength()));
+    masm.store32(lengthTemp, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
 
     if (mir->mode() == MArrayPopShift::Shift) {
         // Don't save the temp registers.
@@ -8681,50 +8511,27 @@ CodeGenerator::emitArrayPush(LInstruction* lir, const MArrayPush* mir, Register
     OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value), StoreRegisterTo(length));
 
     RegisterOrInt32Constant key = RegisterOrInt32Constant(length);
-    if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-        // Load elements and length.
-        masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
-        masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
-
-        // Guard length == initializedLength.
-        Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
-        masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
 
-        // Guard length < capacity.
-        Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
-        masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
+    // Load elements and length.
+    masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
+    masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
 
-        // Do the store.
-        masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
-    } else {
-        // Load initialized length.
-        masm.load32(Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), length);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), length);
-
-        // Guard length == initializedLength.
-        Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
-        masm.branch32(Assembler::NotEqual, lengthAddr, key, ool->entry());
+    // Guard length == initializedLength.
+    Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
 
-        // Guard length < capacity.
-        masm.checkUnboxedArrayCapacity(obj, key, elementsTemp, ool->entry());
+    // Guard length < capacity.
+    Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
+    masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
 
-        // Load elements and do the store.
-        masm.loadPtr(Address(obj, UnboxedArrayObject::offsetOfElements()), elementsTemp);
-        size_t elemSize = UnboxedTypeSize(mir->unboxedType());
-        BaseIndex addr(elementsTemp, length, ScaleFromElemWidth(elemSize));
-        masm.storeUnboxedProperty(addr, mir->unboxedType(), value, nullptr);
-    }
+    // Do the store.
+    masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
 
     masm.inc32(&key);
 
     // Update length and initialized length.
-    if (mir->unboxedType() == JSVAL_TYPE_MAGIC) {
-        masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
-        masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
-    } else {
-        masm.store32(length, Address(obj, UnboxedArrayObject::offsetOfLength()));
-        masm.add32(Imm32(1), Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
-    }
+    masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
+    masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfInitializedLength()));
 
     masm.bind(ool->rejoin());
 }
@@ -10922,7 +10729,7 @@ CodeGenerator::visitInArray(LInArray* lir)
         }
 
         masm.branch32(Assembler::BelowOrEqual, initLength, Imm32(index), failedInitLength);
-        if (mir->needsHoleCheck() && mir->unboxedType() == JSVAL_TYPE_MAGIC) {
+        if (mir->needsHoleCheck()) {
             NativeObject::elementsSizeMustNotOverflow();
             Address address = Address(elements, index * sizeof(Value));
             masm.branchTestMagic(Assembler::Equal, address, &falseBranch);
@@ -10935,7 +10742,7 @@ CodeGenerator::visitInArray(LInArray* lir)
             failedInitLength = &negativeIntCheck;
 
         masm.branch32(Assembler::BelowOrEqual, initLength, index, failedInitLength);
-        if (mir->needsHoleCheck() && mir->unboxedType() == JSVAL_TYPE_MAGIC) {
+        if (mir->needsHoleCheck()) {
             BaseIndex address = BaseIndex(elements, ToRegister(lir->index()), TimesEight);
             masm.branchTestMagic(Assembler::Equal, address, &falseBranch);
         }
diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
index 292f163b5..b5f170d84 100644
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -234,10 +234,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
     void visitSubstr(LSubstr* lir);
     void visitInitializedLength(LInitializedLength* lir);
     void visitSetInitializedLength(LSetInitializedLength* lir);
-    void visitUnboxedArrayLength(LUnboxedArrayLength* lir);
-    void visitUnboxedArrayInitializedLength(LUnboxedArrayInitializedLength* lir);
-    void visitIncrementUnboxedArrayInitializedLength(LIncrementUnboxedArrayInitializedLength* lir);
-    void visitSetUnboxedArrayInitializedLength(LSetUnboxedArrayInitializedLength* lir);
     void visitNotO(LNotO* ins);
     void visitNotV(LNotV* ins);
     void visitBoundsCheck(LBoundsCheck* lir);
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index af85011be..3d964d1c6 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7336,12 +7336,6 @@ IonBuilder::newArrayTryTemplateObject(bool* emitted, JSObject* templateObject, u
     if (!templateObject)
         return true;
 
-    if (templateObject->is<UnboxedArrayObject>()) {
-        MOZ_ASSERT(templateObject->as<UnboxedArrayObject>().capacity() >= length);
-        if (!templateObject->as<UnboxedArrayObject>().hasInlineElements())
-            return true;
-    }
-
     MOZ_ASSERT(length <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);
 
     size_t arraySlots =
@@ -7597,7 +7591,6 @@ IonBuilder::jsop_initelem_array()
     // intializer, and that arrays are marked as non-packed when writing holes
     // to them during initialization.
     bool needStub = false;
-    JSValueType unboxedType = JSVAL_TYPE_MAGIC;
     if (shouldAbortOnPreliminaryGroups(obj)) {
         needStub = true;
     } else if (!obj->resultTypeSet() ||
@@ -7608,12 +7601,6 @@ IonBuilder::jsop_initelem_array()
     } else {
         MOZ_ASSERT(obj->resultTypeSet()->getObjectCount() == 1);
         TypeSet::ObjectKey* initializer = obj->resultTypeSet()->getObject(0);
-        if (initializer->clasp() == &UnboxedArrayObject::class_) {
-            if (initializer->group()->unboxedLayout().nativeGroup())
-                needStub = true;
-            else
-                unboxedType = initializer->group()->unboxedLayout().elementType();
-        }
         if (value->type() == MIRType::MagicHole) {
             if (!initializer->hasFlags(constraints(), OBJECT_FLAG_NON_PACKED))
                 needStub = true;
@@ -7633,60 +7620,46 @@ IonBuilder::jsop_initelem_array()
         return resumeAfter(store);
     }
 
-    return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true);
+    return initializeArrayElement(obj, index, value, /* addResumePoint = */ true);
 }
 
 bool
 IonBuilder::initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
-                                   JSValueType unboxedType,
                                    bool addResumePointAndIncrementInitializedLength)
 {
     MConstant* id = MConstant::New(alloc(), Int32Value(index));
     current->add(id);
 
     // Get the elements vector.
-    MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+    MElements* elements = MElements::New(alloc(), obj);
     current->add(elements);
 
-    if (unboxedType != JSVAL_TYPE_MAGIC) {
-        // Note: storeUnboxedValue takes care of any post barriers on the value.
-        storeUnboxedValue(obj, elements, 0, id, unboxedType, value, /* preBarrier = */ false);
-
-        if (addResumePointAndIncrementInitializedLength) {
-            MInstruction* increment = MIncrementUnboxedArrayInitializedLength::New(alloc(), obj);
-            current->add(increment);
-
-            if (!resumeAfter(increment))
-                return false;
-        }
-    } else {
-        if (NeedsPostBarrier(value))
-            current->add(MPostWriteBarrier::New(alloc(), obj, value));
+    if (NeedsPostBarrier(value))
+        current->add(MPostWriteBarrier::New(alloc(), obj, value));
 
-        if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) ||
-            (obj->isNullarySharedStub() &&
-            obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles))
-        {
-            MInstruction* valueDouble = MToDouble::New(alloc(), value);
-            current->add(valueDouble);
-            value = valueDouble;
-        }
+    if ((obj->isNewArray() && obj->toNewArray()->convertDoubleElements()) ||
+        (obj->isNullarySharedStub() &&
+        obj->resultTypeSet()->convertDoubleElements(constraints()) == TemporaryTypeSet::AlwaysConvertToDoubles))
+    {
+        MInstruction* valueDouble = MToDouble::New(alloc(), value);
+        current->add(valueDouble);
+        value = valueDouble;
+    }
 
-        // Store the value.
-        MStoreElement* store = MStoreElement::New(alloc(), elements, id, value,
+    // Store the value.
+    MStoreElement* store = MStoreElement::New(alloc(), elements, id, value,
                                                   /* needsHoleCheck = */ false);
-        current->add(store);
+    current->add(store);
 
-        if (addResumePointAndIncrementInitializedLength) {
-            // Update the initialized length. (The template object for this
-            // array has the array's ultimate length, so the length field is
-            // already correct: no updating needed.)
-            MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id);
-            current->add(initLength);
+    if (addResumePointAndIncrementInitializedLength) {
+        // Update the initialized length. (The template object for this
+        // array has the array's ultimate length, so the length field is
+        // already correct: no updating needed.)
+        MSetInitializedLength* initLength = MSetInitializedLength::New(alloc(), elements, id);
+        current->add(initLength);
 
-            if (!resumeAfter(initLength))
-                return false;
-        }
+        if (!resumeAfter(initLength))
+            return false;
     }
 
     return true;
@@ -8175,8 +8148,7 @@ IonBuilder::maybeMarkEmpty(MDefinition* ins)
 static bool
 ClassHasEffectlessLookup(const Class* clasp)
 {
-    return (clasp == &UnboxedArrayObject::class_) ||
-           IsTypedObjectClass(clasp) ||
+    return IsTypedObjectClass(clasp) ||
            (clasp->isNative() && !clasp->getOpsLookupProperty());
 }
 
@@ -9452,12 +9424,9 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
 {
     MOZ_ASSERT(*emitted == false);
 
-    JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, index);
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        if (!ElementAccessIsDenseNative(constraints(), obj, index)) {
-            trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
-            return true;
-        }
+    if (!ElementAccessIsDenseNative(constraints(), obj, index)) {
+        trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
+        return true;
     }
 
     // Don't generate a fast path if there have been bounds check failures
@@ -9474,7 +9443,7 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
         return true;
     }
 
-    if (!jsop_getelem_dense(obj, index, unboxedType))
+    if (!jsop_getelem_dense(obj, index))
         return false;
 
     trackOptimizationSuccess();
@@ -9826,7 +9795,7 @@ IonBuilder::computeHeapType(const TemporaryTypeSet* objTypes, const jsid id)
 }
 
 bool
-IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType unboxedType)
+IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index)
 {
     TemporaryTypeSet* types = bytecodeTypes(pc);
 
@@ -9850,7 +9819,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
         !ElementAccessHasExtraIndexedProperty(this, obj);
 
     MIRType knownType = MIRType::Value;
-    if (unboxedType == JSVAL_TYPE_MAGIC && barrier == BarrierKind::NoBarrier)
+    if (barrier == BarrierKind::NoBarrier)
         knownType = GetElemKnownType(needsHoleCheck, types);
 
     // Ensure index is an integer.
@@ -9859,13 +9828,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
     index = idInt32;
 
     // Get the elements vector.
-    MInstruction* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+    MInstruction* elements = MElements::New(alloc(), obj);
     current->add(elements);
 
     // Note: to help GVN, use the original MElements instruction and not
     // MConvertElementsToDoubles as operand. This is fine because converting
     // elements to double does not change the initialized length.
-    MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+    MInstruction* initLength = initializedLength(obj, elements);
 
     // If we can load the element as a definite double, make sure to check that
     // the array has been converted to homogenous doubles first.
@@ -9881,7 +9850,6 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
     }
 
     bool loadDouble =
-        unboxedType == JSVAL_TYPE_MAGIC &&
         barrier == BarrierKind::NoBarrier &&
         loopDepth_ &&
         inBounds &&
@@ -9900,18 +9868,13 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
         // hoisting.
         index = addBoundsCheck(index, initLength);
 
-        if (unboxedType != JSVAL_TYPE_MAGIC) {
-            load = loadUnboxedValue(elements, 0, index, unboxedType, barrier, types);
-        } else {
-            load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
-            current->add(load);
-        }
+        load = MLoadElement::New(alloc(), elements, index, needsHoleCheck, loadDouble);
+        current->add(load);
     } else {
         // This load may return undefined, so assume that we *can* read holes,
         // or that we can read out-of-bounds accesses. In this case, the bounds
         // check is part of the opcode.
-        load = MLoadElementHole::New(alloc(), elements, index, initLength,
-                                     unboxedType, needsHoleCheck);
+        load = MLoadElementHole::New(alloc(), elements, index, initLength, needsHoleCheck);
         current->add(load);
 
         // If maybeUndefined was true, the typeset must have undefined, and
@@ -9921,8 +9884,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType
     }
 
     if (knownType != MIRType::Value) {
-        if (unboxedType == JSVAL_TYPE_MAGIC)
-            load->setResultType(knownType);
+        load->setResultType(knownType);
         load->setResultTypeSet(types);
     }
 
@@ -10369,12 +10331,9 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object,
 {
     MOZ_ASSERT(*emitted == false);
 
-    JSValueType unboxedType = UnboxedArrayElementType(constraints(), object, index);
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        if (!ElementAccessIsDenseNative(constraints(), object, index)) {
-            trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
-            return true;
-        }
+    if (!ElementAccessIsDenseNative(constraints(), object, index)) {
+        trackOptimizationOutcome(TrackedOutcome::AccessNotDense);
+        return true;
     }
 
     if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
@@ -10408,7 +10367,7 @@ IonBuilder::setElemTryDense(bool* emitted, MDefinition* object,
     }
 
     // Emit dense setelem variant.
-    if (!jsop_setelem_dense(conversion, object, index, value, unboxedType, writeHole, emitted))
+    if (!jsop_setelem_dense(conversion, object, index, value, writeHole, emitted))
         return false;
 
     if (!*emitted) {
@@ -10498,13 +10457,11 @@ IonBuilder::setElemTryCache(bool* emitted, MDefinition* object,
 bool
 IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
                                MDefinition* obj, MDefinition* id, MDefinition* value,
-                               JSValueType unboxedType, bool writeHole, bool* emitted)
+                               bool writeHole, bool* emitted)
 {
     MOZ_ASSERT(*emitted == false);
 
-    MIRType elementType = MIRType::None;
-    if (unboxedType == JSVAL_TYPE_MAGIC)
-        elementType = DenseNativeElementType(constraints(), obj);
+    MIRType elementType = DenseNativeElementType(constraints(), obj);
     bool packed = ElementAccessIsPacked(constraints(), obj);
 
     // Writes which are on holes in the object do not have to bail out if they
@@ -10534,7 +10491,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
     obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
 
     // Get the elements vector.
-    MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+    MElements* elements = MElements::New(alloc(), obj);
     current->add(elements);
 
     // Ensure the value is a double, if double conversion might be needed.
@@ -10571,7 +10528,7 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
     MInstruction* store;
     MStoreElementCommon* common = nullptr;
     if (writeHole && hasNoExtraIndexedProperty && !mayBeFrozen) {
-        MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue, unboxedType);
+        MStoreElementHole* ins = MStoreElementHole::New(alloc(), obj, elements, id, newValue);
         store = ins;
         common = ins;
 
@@ -10583,27 +10540,23 @@ IonBuilder::jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
 
         bool strict = IsStrictSetPC(pc);
         MFallibleStoreElement* ins = MFallibleStoreElement::New(alloc(), obj, elements, id,
-                                                                newValue, unboxedType, strict);
+                                                                newValue, strict);
         store = ins;
         common = ins;
 
         current->add(ins);
         current->push(value);
     } else {
-        MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+        MInstruction* initLength = initializedLength(obj, elements);
 
         id = addBoundsCheck(id, initLength);
         bool needsHoleCheck = !packed && !hasNoExtraIndexedProperty;
 
-        if (unboxedType != JSVAL_TYPE_MAGIC) {
-            store = storeUnboxedValue(obj, elements, 0, id, unboxedType, newValue);
-        } else {
-            MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
-            store = ins;
-            common = ins;
+        MStoreElement* ins = MStoreElement::New(alloc(), elements, id, newValue, needsHoleCheck);
+        store = ins;
+        common = ins;
 
-            current->add(store);
-        }
+        current->add(store);
 
         current->push(value);
     }
@@ -10721,18 +10674,6 @@ IonBuilder::jsop_length_fastPath()
             return true;
         }
 
-        // Compute the length for unboxed array objects.
-        if (UnboxedArrayElementType(constraints(), obj, nullptr) != JSVAL_TYPE_MAGIC &&
-            !objTypes->hasObjectFlags(constraints(), OBJECT_FLAG_LENGTH_OVERFLOW))
-        {
-            current->pop();
-
-            MUnboxedArrayLength* length = MUnboxedArrayLength::New(alloc(), obj);
-            current->add(length);
-            current->push(length);
-            return true;
-        }
-
         // Compute the length for array typed objects.
         TypedObjectPrediction prediction = typedObjectPrediction(obj);
         if (!prediction.isUseless()) {
@@ -13687,11 +13628,8 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
     if (shouldAbortOnPreliminaryGroups(obj))
         return true;
 
-    JSValueType unboxedType = UnboxedArrayElementType(constraints(), obj, id);
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        if (!ElementAccessIsDenseNative(constraints(), obj, id))
-            return true;
-    }
+    if (!ElementAccessIsDenseNative(constraints(), obj, id))
+        return true;
 
     if (ElementAccessHasExtraIndexedProperty(this, obj))
         return true;
@@ -13706,10 +13644,10 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
     id = idInt32;
 
     // Get the elements vector.
-    MElements* elements = MElements::New(alloc(), obj, unboxedType != JSVAL_TYPE_MAGIC);
+    MElements* elements = MElements::New(alloc(), obj);
     current->add(elements);
 
-    MInstruction* initLength = initializedLength(obj, elements, unboxedType);
+    MInstruction* initLength = initializedLength(obj, elements);
 
     // If there are no holes, speculate the InArray check will not fail.
     if (!needsHoleCheck && !failedBoundsCheck_) {
@@ -13719,8 +13657,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
     }
 
     // Check if id < initLength and elem[id] not a hole.
-    MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck,
-                                  unboxedType);
+    MInArray* ins = MInArray::New(alloc(), elements, id, initLength, obj, needsHoleCheck);
 
     current->add(ins);
     current->push(ins);
@@ -14398,32 +14335,24 @@ IonBuilder::constantInt(int32_t i)
 }
 
 MInstruction*
-IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements, JSValueType unboxedType)
+IonBuilder::initializedLength(MDefinition* obj, MDefinition* elements)
 {
-    MInstruction* res;
-    if (unboxedType != JSVAL_TYPE_MAGIC)
-        res = MUnboxedArrayInitializedLength::New(alloc(), obj);
-    else
-        res = MInitializedLength::New(alloc(), elements);
+    MInstruction* res = MInitializedLength::New(alloc(), elements);
     current->add(res);
     return res;
 }
 
 MInstruction*
-IonBuilder::setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count)
+IonBuilder::setInitializedLength(MDefinition* obj, size_t count)
 {
     MOZ_ASSERT(count);
 
-    MInstruction* res;
-    if (unboxedType != JSVAL_TYPE_MAGIC) {
-        res = MSetUnboxedArrayInitializedLength::New(alloc(), obj, constant(Int32Value(count)));
-    } else {
-        // MSetInitializedLength takes the index of the last element, rather
-        // than the count itself.
-        MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false);
-        current->add(elements);
-        res = MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1)));
-    }
+    // MSetInitializedLength takes the index of the last element, rather
+    // than the count itself.
+    MInstruction* elements = MElements::New(alloc(), obj, /* unboxed = */ false);
+    current->add(elements);
+    MInstruction* res = 
+	    MSetInitializedLength::New(alloc(), elements, constant(Int32Value(count - 1)));
     current->add(res);
     return res;
 }
diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h
index 77528ad37..1b97c4743 100644
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -346,9 +346,8 @@ class IonBuilder
 
     MConstant* constant(const Value& v);
     MConstant* constantInt(int32_t i);
-    MInstruction* initializedLength(MDefinition* obj, MDefinition* elements,
-                                    JSValueType unboxedType);
-    MInstruction* setInitializedLength(MDefinition* obj, JSValueType unboxedType, size_t count);
+    MInstruction* initializedLength(MDefinition* obj, MDefinition* elements);
+    MInstruction* setInitializedLength(MDefinition* obj, size_t count);
 
     // Improve the type information at tests
     MOZ_MUST_USE bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
@@ -611,7 +610,6 @@ class IonBuilder
                                                         TypedObjectPrediction elemTypeReprs,
                                                         uint32_t elemSize);
     MOZ_MUST_USE bool initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value,
-                                             JSValueType unboxedType,
                                              bool addResumePointAndIncrementInitializedLength);
 
     // jsop_getelem() helpers.
@@ -723,15 +721,13 @@ class IonBuilder
     MOZ_MUST_USE bool jsop_bindname(PropertyName* name);
     MOZ_MUST_USE bool jsop_bindvar();
     MOZ_MUST_USE bool jsop_getelem();
-    MOZ_MUST_USE bool jsop_getelem_dense(MDefinition* obj, MDefinition* index,
-                                         JSValueType unboxedType);
+    MOZ_MUST_USE bool jsop_getelem_dense(MDefinition* obj, MDefinition* index);
     MOZ_MUST_USE bool jsop_getelem_typed(MDefinition* obj, MDefinition* index,
                                          ScalarTypeDescr::Type arrayType);
     MOZ_MUST_USE bool jsop_setelem();
     MOZ_MUST_USE bool jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
                                          MDefinition* object, MDefinition* index,
-                                         MDefinition* value, JSValueType unboxedType,
-                                         bool writeHole, bool* emitted);
+                                         MDefinition* value, bool writeHole, bool* emitted);
     MOZ_MUST_USE bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
                                          MDefinition* object, MDefinition* index,
                                          MDefinition* value);
diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp
index 96e488ea8..0a53f178f 100644
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -638,9 +638,6 @@ TestMatchingReceiver(MacroAssembler& masm, IonCache::StubAttacher& attacher,
         } else {
             masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), failure);
         }
-    } else if (obj->is<UnboxedArrayObject>()) {
-        MOZ_ASSERT(failure);
-        masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
     } else if (obj->is<TypedObject>()) {
         attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
                                        Address(object, JSObject::offsetOfGroup()),
@@ -1187,39 +1184,6 @@ GenerateArrayLength(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher&
     return true;
 }
 
-static void
-GenerateUnboxedArrayLength(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
-                           JSObject* array, Register object, TypedOrValueRegister output,
-                           Label* failures)
-{
-    Register outReg;
-    if (output.hasValue()) {
-        outReg = output.valueReg().scratchReg();
-    } else {
-        MOZ_ASSERT(output.type() == MIRType::Int32);
-        outReg = output.typedReg().gpr();
-    }
-    MOZ_ASSERT(object != outReg);
-
-    TestMatchingReceiver(masm, attacher, object, array, failures);
-
-    // Load length.
-    masm.load32(Address(object, UnboxedArrayObject::offsetOfLength()), outReg);
-
-    // Check for a length that fits in an int32.
-    masm.branchTest32(Assembler::Signed, outReg, outReg, failures);
-
-    if (output.hasValue())
-        masm.tagValue(JSVAL_TYPE_INT32, outReg, output.valueReg());
-
-    // Success.
-    attacher.jumpRejoin(masm);
-
-    // Failure.
-    masm.bind(failures);
-    attacher.jumpNextStub(masm);
-}
-
 // In this case, the code for TypedArray and SharedTypedArray is not the same,
 // because the code embeds pointers to the respective class arrays.  Code that
 // caches the stub code must distinguish between the two cases.
@@ -1593,40 +1557,6 @@ GetPropertyIC::tryAttachUnboxedExpando(JSContext* cx, HandleScript outerScript,
                              JS::TrackedOutcome::ICGetPropStub_UnboxedReadExpando);
 }
 
-bool
-GetPropertyIC::tryAttachUnboxedArrayLength(JSContext* cx, HandleScript outerScript, IonScript* ion,
-                                           HandleObject obj, HandleId id, void* returnAddr,
-                                           bool* emitted)
-{
-    MOZ_ASSERT(canAttachStub());
-    MOZ_ASSERT(!*emitted);
-    MOZ_ASSERT(outerScript->ionScript() == ion);
-
-    if (!obj->is<UnboxedArrayObject>())
-        return true;
-
-    if (!JSID_IS_ATOM(id, cx->names().length))
-        return true;
-
-    if (obj->as<UnboxedArrayObject>().length() > INT32_MAX)
-        return true;
-
-    if (!allowArrayLength(cx))
-        return true;
-
-    *emitted = true;
-
-    MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
-
-    Label failures;
-    emitIdGuard(masm, id, &failures);
-
-    StubAttacher attacher(*this);
-    GenerateUnboxedArrayLength(cx, masm, attacher, obj, object(), output(), &failures);
-    return linkAndAttachStub(cx, masm, attacher, ion, "unboxed array length",
-                             JS::TrackedOutcome::ICGetPropStub_UnboxedArrayLength);
-}
-
 bool
 GetPropertyIC::tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript, IonScript* ion,
                                          HandleObject obj, HandleId id, bool* emitted)
@@ -2202,9 +2132,6 @@ GetPropertyIC::tryAttachStub(JSContext* cx, HandleScript outerScript, IonScript*
         if (!*emitted && !tryAttachUnboxedExpando(cx, outerScript, ion, obj, id, returnAddr, emitted))
             return false;
 
-        if (!*emitted && !tryAttachUnboxedArrayLength(cx, outerScript, ion, obj, id, returnAddr, emitted))
-            return false;
-
         if (!*emitted && !tryAttachTypedArrayLength(cx, outerScript, ion, obj, id, emitted))
             return false;
     }
@@ -4025,7 +3952,7 @@ GetPropertyIC::tryAttachDenseElementHole(JSContext* cx, HandleScript outerScript
 GetPropertyIC::canAttachTypedOrUnboxedArrayElement(JSObject* obj, const Value& idval,
                                                    TypedOrValueRegister output)
 {
-    if (!obj->is<TypedArrayObject>() && !obj->is<UnboxedArrayObject>())
+    if (!obj->is<TypedArrayObject>())
         return false;
 
     MOZ_ASSERT(idval.isInt32() || idval.isString());
@@ -4056,13 +3983,6 @@ GetPropertyIC::canAttachTypedOrUnboxedArrayElement(JSObject* obj, const Value& i
         return output.hasValue() || !output.typedReg().isFloat();
     }
 
-    if (index >= obj->as<UnboxedArrayObject>().initializedLength())
-        return false;
-
-    JSValueType elementType = obj->as<UnboxedArrayObject>().elementType();
-    if (elementType == JSVAL_TYPE_DOUBLE)
-        return output.hasValue();
-
     return output.hasValue() || !output.typedReg().isFloat();
 }
 
@@ -4139,46 +4059,27 @@ GenerateGetTypedOrUnboxedArrayElement(JSContext* cx, MacroAssembler& masm,
 
     Label popObjectAndFail;
 
-    if (array->is<TypedArrayObject>()) {
-        // Guard on the initialized length.
-        Address length(object, TypedArrayObject::lengthOffset());
-        masm.branch32(Assembler::BelowOrEqual, length, indexReg, &failures);
+    // Guard on the initialized length.
+    Address length(object, TypedArrayObject::lengthOffset());
+    masm.branch32(Assembler::BelowOrEqual, length, indexReg, &failures);
 
-        // Save the object register on the stack in case of failure.
-        Register elementReg = object;
-        masm.push(object);
+    // Save the object register on the stack in case of failure.
+    Register elementReg = object;
+    masm.push(object);
 
-        // Load elements vector.
-        masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), elementReg);
+    // Load elements vector.
+    masm.loadPtr(Address(object, TypedArrayObject::dataOffset()), elementReg);
 
-        // Load the value. We use an invalid register because the destination
-        // register is necessary a non double register.
-        Scalar::Type arrayType = array->as<TypedArrayObject>().type();
-        int width = Scalar::byteSize(arrayType);
-        BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(width));
-        if (output.hasValue()) {
-            masm.loadFromTypedArray(arrayType, source, output.valueReg(), allowDoubleResult,
-                                    elementReg, &popObjectAndFail);
-        } else {
-            masm.loadFromTypedArray(arrayType, source, output.typedReg(), elementReg, &popObjectAndFail);
-        }
+    // Load the value. We use an invalid register because the destination
+    // register is necessary a non double register.
+    Scalar::Type arrayType = array->as<TypedArrayObject>().type();
+    int width = Scalar::byteSize(arrayType);
+    BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(width));
+    if (output.hasValue()) {
+        masm.loadFromTypedArray(arrayType, source, output.valueReg(), allowDoubleResult,
+                                elementReg, &popObjectAndFail);
     } else {
-        // Save the object register on the stack in case of failure.
-        masm.push(object);
-
-        // Guard on the initialized length.
-        masm.load32(Address(object, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()), object);
-        masm.and32(Imm32(UnboxedArrayObject::InitializedLengthMask), object);
-        masm.branch32(Assembler::BelowOrEqual, object, indexReg, &popObjectAndFail);
-
-        // Load elements vector.
-        Register elementReg = object;
-        masm.loadPtr(Address(masm.getStackPointer(), 0), object);
-        masm.loadPtr(Address(object, UnboxedArrayObject::offsetOfElements()), elementReg);
-
-        JSValueType elementType = array->as<UnboxedArrayObject>().elementType();
-        BaseIndex source(elementReg, indexReg, ScaleFromElemWidth(UnboxedTypeSize(elementType)));
-        masm.loadUnboxedProperty(source, elementType, output);
+        masm.loadFromTypedArray(arrayType, source, output.typedReg(), elementReg, &popObjectAndFail);
     }
 
     masm.pop(object);
diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index aafa57c09..e185b5746 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2888,32 +2888,6 @@ LIRGenerator::visitSetInitializedLength(MSetInitializedLength* ins)
                                            useRegisterOrConstant(ins->index())), ins);
 }
 
-void
-LIRGenerator::visitUnboxedArrayLength(MUnboxedArrayLength* ins)
-{
-    define(new(alloc()) LUnboxedArrayLength(useRegisterAtStart(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitUnboxedArrayInitializedLength(MUnboxedArrayInitializedLength* ins)
-{
-    define(new(alloc()) LUnboxedArrayInitializedLength(useRegisterAtStart(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitIncrementUnboxedArrayInitializedLength(MIncrementUnboxedArrayInitializedLength* ins)
-{
-    add(new(alloc()) LIncrementUnboxedArrayInitializedLength(useRegister(ins->object())), ins);
-}
-
-void
-LIRGenerator::visitSetUnboxedArrayInitializedLength(MSetUnboxedArrayInitializedLength* ins)
-{
-    add(new(alloc()) LSetUnboxedArrayInitializedLength(useRegister(ins->object()),
-                                                       useRegisterOrConstant(ins->length()),
-                                                       temp()), ins);
-}
-
 void
 LIRGenerator::visitNot(MNot* ins)
 {
@@ -3165,8 +3139,6 @@ LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
 
     // Use a temp register when adding new elements to unboxed arrays.
     LDefinition tempDef = LDefinition::BogusTemp();
-    if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
-        tempDef = temp();
 
     LInstruction* lir;
     switch (ins->value()->type()) {
@@ -3199,8 +3171,6 @@ LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
 
     // Use a temp register when adding new elements to unboxed arrays.
     LDefinition tempDef = LDefinition::BogusTemp();
-    if (ins->unboxedType() != JSVAL_TYPE_MAGIC)
-        tempDef = temp();
 
     LInstruction* lir;
     switch (ins->value()->type()) {
diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
index e36620bce..b096bb143 100644
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -216,10 +216,6 @@ class LIRGenerator : public LIRGeneratorSpecific
     void visitTypedObjectDescr(MTypedObjectDescr* ins);
     void visitInitializedLength(MInitializedLength* ins);
     void visitSetInitializedLength(MSetInitializedLength* ins);
-    void visitUnboxedArrayLength(MUnboxedArrayLength* ins);
-    void visitUnboxedArrayInitializedLength(MUnboxedArrayInitializedLength* ins);
-    void visitIncrementUnboxedArrayInitializedLength(MIncrementUnboxedArrayInitializedLength* ins);
-    void visitSetUnboxedArrayInitializedLength(MSetUnboxedArrayInitializedLength* ins);
     void visitNot(MNot* ins);
     void visitBoundsCheck(MBoundsCheck* ins);
     void visitBoundsCheckLower(MBoundsCheckLower* ins);
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 41ccd0ca7..7283497ea 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -475,11 +475,6 @@ IonBuilder::inlineArray(CallInfo& callInfo)
         return InliningStatus_NotInlined;
     }
 
-    if (templateObject->is<UnboxedArrayObject>()) {
-        if (templateObject->group()->unboxedLayout().nativeGroup())
-            return InliningStatus_NotInlined;
-    }
-
     // Multiple arguments imply array initialization, not just construction.
     if (callInfo.argc() >= 2) {
         initLength = callInfo.argc();
@@ -542,16 +537,15 @@ IonBuilder::inlineArray(CallInfo& callInfo)
 
     MDefinition* array = current->peek(-1);
     if (callInfo.argc() >= 2) {
-        JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
         for (uint32_t i = 0; i < initLength; i++) {
             if (!alloc().ensureBallast())
                 return InliningStatus_Error;
             MDefinition* value = callInfo.getArg(i);
-            if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
+            if (!initializeArrayElement(array, i, /* addResumePoint = */ false))
                 return InliningStatus_Error;
         }
 
-        MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
+        MInstruction* setLength = setInitializedLength(array, initLength);
         if (!resumeAfter(setLength))
             return InliningStatus_Error;
     }
@@ -620,7 +614,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
     if (!thisTypes)
         return InliningStatus_NotInlined;
     const Class* clasp = thisTypes->getKnownClass(constraints());
-    if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+    if (clasp != &ArrayObject::class_)
         return InliningStatus_NotInlined;
     if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
         trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
@@ -632,17 +626,9 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
         return InliningStatus_NotInlined;
     }
 
-    JSValueType unboxedType = JSVAL_TYPE_MAGIC;
-    if (clasp == &UnboxedArrayObject::class_) {
-        unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
-        if (unboxedType == JSVAL_TYPE_MAGIC)
-            return InliningStatus_NotInlined;
-    }
-
     callInfo.setImplicitlyUsedUnchecked();
 
-    if (clasp == &ArrayObject::class_)
-        obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+    obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
 
     TemporaryTypeSet* returnTypes = getInlineReturnTypeSet();
     bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_NON_PACKED);
@@ -653,8 +639,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
     if (barrier != BarrierKind::NoBarrier)
         returnType = MIRType::Value;
 
-    MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode,
-                                              unboxedType, needsHoleCheck, maybeUndefined);
+    MArrayPopShift* ins = MArrayPopShift::New(alloc(), obj, mode, needsHoleCheck, maybeUndefined);
     current->add(ins);
     current->push(ins);
     ins->setResultType(returnType);
@@ -761,7 +746,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
     if (!thisTypes)
         return InliningStatus_NotInlined;
     const Class* clasp = thisTypes->getKnownClass(constraints());
-    if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+    if (clasp != &ArrayObject::class_)
         return InliningStatus_NotInlined;
     if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
                                   OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -782,13 +767,6 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
         return InliningStatus_NotInlined;
     }
 
-    JSValueType unboxedType = JSVAL_TYPE_MAGIC;
-    if (clasp == &UnboxedArrayObject::class_) {
-        unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
-        if (unboxedType == JSVAL_TYPE_MAGIC)
-            return InliningStatus_NotInlined;
-    }
-
     callInfo.setImplicitlyUsedUnchecked();
 
     if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles ||
@@ -799,13 +777,12 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
         value = valueDouble;
     }
 
-    if (unboxedType == JSVAL_TYPE_MAGIC)
-        obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
+    obj = addMaybeCopyElementsForWrite(obj, /* checkNative = */ false);
 
     if (NeedsPostBarrier(value))
         current->add(MPostWriteBarrier::New(alloc(), obj, value));
 
-    MArrayPush* ins = MArrayPush::New(alloc(), obj, value, unboxedType);
+    MArrayPush* ins = MArrayPush::New(alloc(), obj, value);
     current->add(ins);
     current->push(ins);
 
@@ -846,7 +823,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
         return InliningStatus_NotInlined;
 
     const Class* clasp = thisTypes->getKnownClass(constraints());
-    if (clasp != &ArrayObject::class_ && clasp != &UnboxedArrayObject::class_)
+    if (clasp != &ArrayObject::class_)
         return InliningStatus_NotInlined;
     if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
                                   OBJECT_FLAG_LENGTH_OVERFLOW))
@@ -855,13 +832,6 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
         return InliningStatus_NotInlined;
     }
 
-    JSValueType unboxedType = JSVAL_TYPE_MAGIC;
-    if (clasp == &UnboxedArrayObject::class_) {
-        unboxedType = UnboxedArrayElementType(constraints(), obj, nullptr);
-        if (unboxedType == JSVAL_TYPE_MAGIC)
-            return InliningStatus_NotInlined;
-    }
-
     // Watch out for indexed properties on the prototype.
     if (ArrayPrototypeHasIndexedProperty(this, script())) {
         trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
@@ -882,15 +852,8 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
     if (!templateObj)
         return InliningStatus_NotInlined;
 
-    if (unboxedType == JSVAL_TYPE_MAGIC) {
-        if (!templateObj->is<ArrayObject>())
-            return InliningStatus_NotInlined;
-    } else {
-        if (!templateObj->is<UnboxedArrayObject>())
-            return InliningStatus_NotInlined;
-        if (templateObj->as<UnboxedArrayObject>().elementType() != unboxedType)
-            return InliningStatus_NotInlined;
-    }
+    if (!templateObj->is<ArrayObject>())
+        return InliningStatus_NotInlined;
 
     callInfo.setImplicitlyUsedUnchecked();
 
@@ -909,16 +872,12 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
 
         end = MArrayLength::New(alloc(), elements);
         current->add(end->toInstruction());
-    } else {
-        end = MUnboxedArrayLength::New(alloc(), obj);
-        current->add(end->toInstruction());
     }
 
     MArraySlice* ins = MArraySlice::New(alloc(), constraints(),
                                         obj, begin, end,
                                         templateObj,
-                                        templateObj->group()->initialHeap(constraints()),
-                                        unboxedType);
+                                        templateObj->group()->initialHeap(constraints()));
     current->add(ins);
     current->push(ins);
 
@@ -1500,8 +1459,6 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
         return InliningStatus_Inlined;
     }
 
-    JSValueType unboxedType = GetBoxedOrUnboxedType(templateObject);
-
     // Store all values, no need to initialize the length after each as
     // jsop_initelem_array is doing because we do not expect to bailout
     // because the memory is supposed to be allocated by now.
@@ -1512,11 +1469,11 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
         MConstant* value = arrayValues[i];
         current->add(value);
 
-        if (!initializeArrayElement(array, i, value, unboxedType, /* addResumePoint = */ false))
+        if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
             return InliningStatus_Error;
     }
 
-    MInstruction* setLength = setInitializedLength(array, unboxedType, initLength);
+    MInstruction* setLength = setInitializedLength(array, initLength);
     if (!resumeAfter(setLength))
         return InliningStatus_Error;
 
diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp
index 1f33b2174..6aa46be4b 100644
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -5823,46 +5823,6 @@ jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
     return clasp && clasp->isNative() && !IsTypedArrayClass(clasp);
 }
 
-JSValueType
-jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj,
-                             MDefinition* id)
-{
-    if (obj->mightBeType(MIRType::String))
-        return JSVAL_TYPE_MAGIC;
-
-    if (id && id->type() != MIRType::Int32 && id->type() != MIRType::Double)
-        return JSVAL_TYPE_MAGIC;
-
-    TemporaryTypeSet* types = obj->resultTypeSet();
-    if (!types || types->unknownObject())
-        return JSVAL_TYPE_MAGIC;
-
-    JSValueType elementType = JSVAL_TYPE_MAGIC;
-    for (unsigned i = 0; i < types->getObjectCount(); i++) {
-        TypeSet::ObjectKey* key = types->getObject(i);
-        if (!key)
-            continue;
-
-        if (key->unknownProperties() || !key->isGroup())
-            return JSVAL_TYPE_MAGIC;
-
-        if (key->clasp() != &UnboxedArrayObject::class_)
-            return JSVAL_TYPE_MAGIC;
-
-        const UnboxedLayout &layout = key->group()->unboxedLayout();
-
-        if (layout.nativeGroup())
-            return JSVAL_TYPE_MAGIC;
-
-        if (elementType == layout.elementType() || elementType == JSVAL_TYPE_MAGIC)
-            elementType = layout.elementType();
-        else
-            return JSVAL_TYPE_MAGIC;
-    }
-
-    return elementType;
-}
-
 bool
 jit::ElementAccessIsTypedArray(CompilerConstraintList* constraints,
                                MDefinition* obj, MDefinition* id,
@@ -6022,11 +5982,6 @@ ObjectSubsumes(TypeSet::ObjectKey* first, TypeSet::ObjectKey* second)
                firstElements.maybeTypes()->equals(secondElements.maybeTypes());
     }
 
-    if (first->clasp() == &UnboxedArrayObject::class_) {
-        return first->group()->unboxedLayout().elementType() ==
-               second->group()->unboxedLayout().elementType();
-    }
-
     return false;
 }
 
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 3e0421789..cdd737b56 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -375,8 +375,7 @@ class AliasSet {
         Element           = 1 << 1, // A Value member of obj->elements or
                                     // a typed object.
         UnboxedElement    = 1 << 2, // An unboxed scalar or reference member of
-                                    // a typed array, typed object, or unboxed
-                                    // object.
+                                    // typed object or unboxed object.
         DynamicSlot       = 1 << 3, // A Value member of obj->slots.
         FixedSlot         = 1 << 4, // A Value member of obj->fixedSlots().
         DOMProperty       = 1 << 5, // A DOM property
@@ -433,9 +432,6 @@ class AliasSet {
         MOZ_ASSERT(flags && !(flags & Store_));
         return AliasSet(flags | Store_);
     }
-    static uint32_t BoxedOrUnboxedElements(JSValueType type) {
-        return (type == JSVAL_TYPE_MAGIC) ? Element : UnboxedElement;
-    }
 };
 
 typedef Vector<MDefinition*, 6, JitAllocPolicy> MDefinitionVector;
@@ -8745,102 +8741,6 @@ class MSetInitializedLength
     ALLOW_CLONE(MSetInitializedLength)
 };
 
-// Load the length from an unboxed array.
-class MUnboxedArrayLength
-  : public MUnaryInstruction,
-    public SingleObjectPolicy::Data
-{
-    explicit MUnboxedArrayLength(MDefinition* object)
-      : MUnaryInstruction(object)
-    {
-        setResultType(MIRType::Int32);
-        setMovable();
-    }
-
-  public:
-    INSTRUCTION_HEADER(UnboxedArrayLength)
-    TRIVIAL_NEW_WRAPPERS
-    NAMED_OPERANDS((0, object))
-
-    bool congruentTo(const MDefinition* ins) const override {
-        return congruentIfOperandsEqual(ins);
-    }
-    AliasSet getAliasSet() const override {
-        return AliasSet::Load(AliasSet::ObjectFields);
-    }
-
-    ALLOW_CLONE(MUnboxedArrayLength)
-};
-
-// Load the initialized length from an unboxed array.
-class MUnboxedArrayInitializedLength
-  : public MUnaryInstruction,
-    public SingleObjectPolicy::Data
-{
-    explicit MUnboxedArrayInitializedLength(MDefinition* object)
-      : MUnaryInstruction(object)
-    {
-        setResultType(MIRType::Int32);
-        setMovable();
-    }
-
-  public:
-    INSTRUCTION_HEADER(UnboxedArrayInitializedLength)
-    TRIVIAL_NEW_WRAPPERS
-    NAMED_OPERANDS((0, object))
-
-    bool congruentTo(const MDefinition* ins) const override {
-        return congruentIfOperandsEqual(ins);
-    }
-    AliasSet getAliasSet() const override {
-        return AliasSet::Load(AliasSet::ObjectFields);
-    }
-
-    ALLOW_CLONE(MUnboxedArrayInitializedLength)
-};
-
-// Increment the initialized length of an unboxed array object.
-class MIncrementUnboxedArrayInitializedLength
-  : public MUnaryInstruction,
-    public SingleObjectPolicy::Data
-{
-    explicit MIncrementUnboxedArrayInitializedLength(MDefinition* obj)
-      : MUnaryInstruction(obj)
-    {}
-
-  public:
-    INSTRUCTION_HEADER(IncrementUnboxedArrayInitializedLength)
-    TRIVIAL_NEW_WRAPPERS
-    NAMED_OPERANDS((0, object))
-
-    AliasSet getAliasSet() const override {
-        return AliasSet::Store(AliasSet::ObjectFields);
-    }
-
-    ALLOW_CLONE(MIncrementUnboxedArrayInitializedLength)
-};
-
-// Set the initialized length of an unboxed array object.
-class MSetUnboxedArrayInitializedLength
-  : public MBinaryInstruction,
-    public SingleObjectPolicy::Data
-{
-    explicit MSetUnboxedArrayInitializedLength(MDefinition* obj, MDefinition* length)
-      : MBinaryInstruction(obj, length)
-    {}
-
-  public:
-    INSTRUCTION_HEADER(SetUnboxedArrayInitializedLength)
-    TRIVIAL_NEW_WRAPPERS
-    NAMED_OPERANDS((0, object), (1, length))
-
-    AliasSet getAliasSet() const override {
-        return AliasSet::Store(AliasSet::ObjectFields);
-    }
-
-    ALLOW_CLONE(MSetUnboxedArrayInitializedLength)
-};
-
 // Load the array length from an elements header.
 class MArrayLength
   : public MUnaryInstruction,
@@ -9341,16 +9241,12 @@ class MLoadElementHole
   : public MTernaryInstruction,
     public SingleObjectPolicy::Data
 {
-    // Unboxed element type, JSVAL_TYPE_MAGIC for dense native elements.
-    JSValueType unboxedType_;
-
     bool needsNegativeIntCheck_;
     bool needsHoleCheck_;
 
     MLoadElementHole(MDefinition* elements, MDefinition* index, MDefinition* initLength,
                      JSValueType unboxedType, bool needsHoleCheck)
       : MTernaryInstruction(elements, index, initLength),
-        unboxedType_(unboxedType),
         needsNegativeIntCheck_(true),
         needsHoleCheck_(needsHoleCheck)
     {
@@ -9372,9 +9268,6 @@ class MLoadElementHole
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, elements), (1, index), (2, initLength))
 
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     bool needsNegativeIntCheck() const {
         return needsNegativeIntCheck_;
     }
@@ -9385,8 +9278,6 @@ class MLoadElementHole
         if (!ins->isLoadElementHole())
             return false;
         const MLoadElementHole* other = ins->toLoadElementHole();
-        if (unboxedType() != other->unboxedType())
-            return false;
         if (needsHoleCheck() != other->needsHoleCheck())
             return false;
         if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
@@ -9394,7 +9285,7 @@ class MLoadElementHole
         return congruentIfOperandsEqual(other);
     }
     AliasSet getAliasSet() const override {
-        return AliasSet::Load(AliasSet::BoxedOrUnboxedElements(unboxedType()));
+        return AliasSet::Load(AliasSet::Element);
     }
     void collectRangeInfoPreTrunc() override;
 
@@ -9583,11 +9474,8 @@ class MStoreElementHole
     public MStoreElementCommon,
     public MixPolicy<SingleObjectPolicy, NoFloatPolicy<3> >::Data
 {
-    JSValueType unboxedType_;
-
     MStoreElementHole(MDefinition* object, MDefinition* elements,
-                      MDefinition* index, MDefinition* value, JSValueType unboxedType)
-      : unboxedType_(unboxedType)
+                      MDefinition* index, MDefinition* value)
     {
         initOperand(0, object);
         initOperand(1, elements);
@@ -9602,14 +9490,10 @@ class MStoreElementHole
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
 
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     AliasSet getAliasSet() const override {
         // StoreElementHole can update the initialized length, the array length
         // or reallocate obj->elements.
-        return AliasSet::Store(AliasSet::ObjectFields |
-                               AliasSet::BoxedOrUnboxedElements(unboxedType()));
+        return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
     }
 
     ALLOW_CLONE(MStoreElementHole)
@@ -9622,13 +9506,11 @@ class MFallibleStoreElement
     public MStoreElementCommon,
     public MixPolicy<SingleObjectPolicy, NoFloatPolicy<3> >::Data
 {
-    JSValueType unboxedType_;
     bool strict_;
 
     MFallibleStoreElement(MDefinition* object, MDefinition* elements,
                           MDefinition* index, MDefinition* value,
-                          JSValueType unboxedType, bool strict)
-      : unboxedType_(unboxedType)
+                          bool strict)
     {
         initOperand(0, object);
         initOperand(1, elements);
@@ -9644,12 +9526,8 @@ class MFallibleStoreElement
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))
 
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     AliasSet getAliasSet() const override {
-        return AliasSet::Store(AliasSet::ObjectFields |
-                               AliasSet::BoxedOrUnboxedElements(unboxedType()));
+        return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
     }
     bool strict() const {
         return strict_;
@@ -9754,13 +9632,12 @@ class MArrayPopShift
 
   private:
     Mode mode_;
-    JSValueType unboxedType_;
     bool needsHoleCheck_;
     bool maybeUndefined_;
 
-    MArrayPopShift(MDefinition* object, Mode mode, JSValueType unboxedType,
+    MArrayPopShift(MDefinition* object, Mode mode,
                    bool needsHoleCheck, bool maybeUndefined)
-      : MUnaryInstruction(object), mode_(mode), unboxedType_(unboxedType),
+      : MUnaryInstruction(object), mode_(mode),
         needsHoleCheck_(needsHoleCheck), maybeUndefined_(maybeUndefined)
     { }
 
@@ -9778,12 +9655,8 @@ class MArrayPopShift
     bool mode() const {
         return mode_;
     }
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     AliasSet getAliasSet() const override {
-        return AliasSet::Store(AliasSet::ObjectFields |
-                               AliasSet::BoxedOrUnboxedElements(unboxedType()));
+        return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
     }
 
     ALLOW_CLONE(MArrayPopShift)
@@ -9794,10 +9667,8 @@ class MArrayPush
   : public MBinaryInstruction,
     public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1> >::Data
 {
-    JSValueType unboxedType_;
-
-    MArrayPush(MDefinition* object, MDefinition* value, JSValueType unboxedType)
-      : MBinaryInstruction(object, value), unboxedType_(unboxedType)
+    MArrayPush(MDefinition* object, MDefinition* value)
+      : MBinaryInstruction(object, value)
     {
         setResultType(MIRType::Int32);
     }
@@ -9807,12 +9678,8 @@ class MArrayPush
     TRIVIAL_NEW_WRAPPERS
     NAMED_OPERANDS((0, object), (1, value))
 
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     AliasSet getAliasSet() const override {
-        return AliasSet::Store(AliasSet::ObjectFields |
-                               AliasSet::BoxedOrUnboxedElements(unboxedType()));
+        return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
     }
     void computeRange(TempAllocator& alloc) override;
 
@@ -9826,15 +9693,13 @@ class MArraySlice
 {
     CompilerObject templateObj_;
     gc::InitialHeap initialHeap_;
-    JSValueType unboxedType_;
 
     MArraySlice(CompilerConstraintList* constraints, MDefinition* obj,
                 MDefinition* begin, MDefinition* end,
-                JSObject* templateObj, gc::InitialHeap initialHeap, JSValueType unboxedType)
+                JSObject* templateObj, gc::InitialHeap initialHeap)
       : MTernaryInstruction(obj, begin, end),
         templateObj_(templateObj),
-        initialHeap_(initialHeap),
-        unboxedType_(unboxedType)
+        initialHeap_(initialHeap)
     {
         setResultType(MIRType::Object);
     }
@@ -12224,15 +12089,13 @@ class MInArray
 {
     bool needsHoleCheck_;
     bool needsNegativeIntCheck_;
-    JSValueType unboxedType_;
 
     MInArray(MDefinition* elements, MDefinition* index,
              MDefinition* initLength, MDefinition* object,
-             bool needsHoleCheck, JSValueType unboxedType)
+             bool needsHoleCheck)
       : MQuaternaryInstruction(elements, index, initLength, object),
         needsHoleCheck_(needsHoleCheck),
-        needsNegativeIntCheck_(true),
-        unboxedType_(unboxedType)
+        needsNegativeIntCheck_(true)
     {
         setResultType(MIRType::Boolean);
         setMovable();
@@ -12252,9 +12115,6 @@ class MInArray
     bool needsNegativeIntCheck() const {
         return needsNegativeIntCheck_;
     }
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
     void collectRangeInfoPreTrunc() override;
     AliasSet getAliasSet() const override {
         return AliasSet::Load(AliasSet::Element);
@@ -12267,8 +12127,6 @@ class MInArray
             return false;
         if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
             return false;
-        if (unboxedType() != other->unboxedType())
-            return false;
         return congruentIfOperandsEqual(other);
     }
 };
@@ -14169,8 +14027,6 @@ MDefinition::maybeConstantValue()
 
 bool ElementAccessIsDenseNative(CompilerConstraintList* constraints,
                                 MDefinition* obj, MDefinition* id);
-JSValueType UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj,
-                                    MDefinition* id);
 bool ElementAccessIsTypedArray(CompilerConstraintList* constraints,
                                MDefinition* obj, MDefinition* id,
                                Scalar::Type* arrayType);
diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h
index b80d1baf9..ab37604b4 100644
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -198,10 +198,6 @@ namespace jit {
     _(SetTypedObjectOffset)                                                 \
     _(InitializedLength)                                                    \
     _(SetInitializedLength)                                                 \
-    _(UnboxedArrayLength)                                                   \
-    _(UnboxedArrayInitializedLength)                                        \
-    _(IncrementUnboxedArrayInitializedLength)                               \
-    _(SetUnboxedArrayInitializedLength)                                     \
     _(Not)                                                                  \
     _(BoundsCheck)                                                          \
     _(BoundsCheckLower)                                                     \
diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
index f633b9b7b..e50f68722 100644
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -705,31 +705,6 @@ template void
 MacroAssembler::storeUnboxedProperty(BaseIndex address, JSValueType type,
                                      const ConstantOrRegister& value, Label* failure);
 
-void
-MacroAssembler::checkUnboxedArrayCapacity(Register obj, const RegisterOrInt32Constant& index,
-                                          Register temp, Label* failure)
-{
-    Address initLengthAddr(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength());
-    Address lengthAddr(obj, UnboxedArrayObject::offsetOfLength());
-
-    Label capacityIsIndex, done;
-    load32(initLengthAddr, temp);
-    branchTest32(Assembler::NonZero, temp, Imm32(UnboxedArrayObject::CapacityMask), &capacityIsIndex);
-    branch32(Assembler::BelowOrEqual, lengthAddr, index, failure);
-    jump(&done);
-    bind(&capacityIsIndex);
-
-    // Do a partial shift so that we can get an absolute offset from the base
-    // of CapacityArray to use.
-    JS_STATIC_ASSERT(sizeof(UnboxedArrayObject::CapacityArray[0]) == 4);
-    rshiftPtr(Imm32(UnboxedArrayObject::CapacityShift - 2), temp);
-    and32(Imm32(~0x3), temp);
-
-    addPtr(ImmPtr(&UnboxedArrayObject::CapacityArray), temp);
-    branch32(Assembler::BelowOrEqual, Address(temp, 0), index, failure);
-    bind(&done);
-}
-
 // Inlined version of gc::CheckAllocatorState that checks the bare essentials
 // and bails for anything that cannot be handled with our jit allocators.
 void
@@ -1281,16 +1256,6 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject* templateObj,
         storePtr(ImmWord(0), Address(obj, UnboxedPlainObject::offsetOfExpando()));
         if (initContents)
             initUnboxedObjectContents(obj, &templateObj->as<UnboxedPlainObject>());
-    } else if (templateObj->is<UnboxedArrayObject>()) {
-        MOZ_ASSERT(templateObj->as<UnboxedArrayObject>().hasInlineElements());
-        int elementsOffset = UnboxedArrayObject::offsetOfInlineElements();
-        computeEffectiveAddress(Address(obj, elementsOffset), temp);
-        storePtr(temp, Address(obj, UnboxedArrayObject::offsetOfElements()));
-        store32(Imm32(templateObj->as<UnboxedArrayObject>().length()),
-                Address(obj, UnboxedArrayObject::offsetOfLength()));
-        uint32_t capacityIndex = templateObj->as<UnboxedArrayObject>().capacityIndex();
-        store32(Imm32(capacityIndex << UnboxedArrayObject::CapacityShift),
-                Address(obj, UnboxedArrayObject::offsetOfCapacityIndexAndInitializedLength()));
     } else {
         MOZ_CRASH("Unknown object");
     }
diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
index b6616321c..6ee989463 100644
--- a/js/src/jit/MacroAssembler.h
+++ b/js/src/jit/MacroAssembler.h
@@ -1626,7 +1626,7 @@ class MacroAssembler : public MacroAssemblerSpecific
     void storeToTypedFloatArray(Scalar::Type arrayType, FloatRegister value, const Address& dest,
                                 unsigned numElems = 0);
 
-    // Load a property from an UnboxedPlainObject or UnboxedArrayObject.
+    // Load a property from an UnboxedPlainObject.
     template <typename T>
     void loadUnboxedProperty(T address, JSValueType type, TypedOrValueRegister output);
 
@@ -1637,9 +1637,6 @@ class MacroAssembler : public MacroAssemblerSpecific
     void storeUnboxedProperty(T address, JSValueType type,
                               const ConstantOrRegister& value, Label* failure);
 
-    void checkUnboxedArrayCapacity(Register obj, const RegisterOrInt32Constant& index,
-                                   Register temp, Label* failure);
-
     Register extractString(const Address& address, Register scratch) {
         return extractObject(address, scratch);
     }
diff --git a/js/src/jit/ScalarReplacement.cpp b/js/src/jit/ScalarReplacement.cpp
index 2065c0371..be9ceee2e 100644
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -795,11 +795,6 @@ IsArrayEscaped(MInstruction* ins)
         return true;
     }
 
-    if (obj->is<UnboxedArrayObject>()) {
-        JitSpew(JitSpew_Escape, "Template object is an unboxed plain object.");
-        return true;
-    }
-
     if (length >= 16) {
         JitSpew(JitSpew_Escape, "Array has too many elements");
         return true;
diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp
index 2475dfb22..313957462 100644
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -286,11 +286,6 @@ ICStub::trace(JSTracer* trc)
         TraceEdge(trc, &getElemStub->shape(), "baseline-getelem-dense-shape");
         break;
       }
-      case ICStub::GetElem_UnboxedArray: {
-        ICGetElem_UnboxedArray* getElemStub = toGetElem_UnboxedArray();
-        TraceEdge(trc, &getElemStub->group(), "baseline-getelem-unboxed-array-group");
-        break;
-      }
       case ICStub::GetElem_TypedArray: {
         ICGetElem_TypedArray* getElemStub = toGetElem_TypedArray();
         TraceEdge(trc, &getElemStub->shape(), "baseline-getelem-typedarray-shape");
@@ -2250,7 +2245,6 @@ IsCacheableProtoChain(JSObject* obj, JSObject* holder, bool isDOMProxy)
         if (obj == holder)
             return false;
         if (!obj->is<UnboxedPlainObject>() &&
-            !obj->is<UnboxedArrayObject>() &&
             !obj->is<TypedObject>())
         {
             return false;
@@ -2582,9 +2576,6 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
         } else if (curObj->is<UnboxedPlainObject>()) {
             if (curObj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, NameToId(name)))
                 return false;
-        } else if (curObj->is<UnboxedArrayObject>()) {
-            if (name == cx->names().length)
-                return false;
         } else if (curObj->is<TypedObject>()) {
             if (curObj->as<TypedObject>().typeDescr().hasProperty(cx->names(), NameToId(name)))
                 return false;
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 77b9e3647..0717bb86d 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -318,7 +318,7 @@ ArraySpliceDense(JSContext* cx, HandleObject obj, uint32_t start, uint32_t delet
 bool
 ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
-    MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(obj->is<ArrayObject>());
 
     AutoDetectInvalidation adi(cx, rval);
 
@@ -341,8 +341,8 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
 {
     *length = GetAnyBoxedOrUnboxedArrayLength(obj);
     DenseElementResult result =
-        SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
-                                                  ShouldUpdateTypes::DontUpdate);
+        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
+                                               ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete) {
         (*length)++;
         return result == DenseElementResult::Success;
@@ -362,7 +362,7 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
 bool
 ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
-    MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(obj->is<ArrayObject>());
 
     AutoDetectInvalidation adi(cx, rval);
 
@@ -1151,8 +1151,8 @@ SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
     // no type changes are needed.
 
     DenseElementResult result =
-        SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, index, value.address(), 1,
-                                                  ShouldUpdateTypes::DontUpdate);
+        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, index, value.address(), 1,
+                                               ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete)
         return result == DenseElementResult::Success;
 
diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h
index f386d5256..35c7e7442 100644
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -5165,72 +5165,6 @@ class LSetInitializedLength : public LInstructionHelper<0, 2, 0>
     }
 };
 
-class LUnboxedArrayLength : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(UnboxedArrayLength)
-
-    explicit LUnboxedArrayLength(const LAllocation& object) {
-        setOperand(0, object);
-    }
-
-    const LAllocation* object() {
-        return getOperand(0);
-    }
-};
-
-class LUnboxedArrayInitializedLength : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(UnboxedArrayInitializedLength)
-
-    explicit LUnboxedArrayInitializedLength(const LAllocation& object) {
-        setOperand(0, object);
-    }
-
-    const LAllocation* object() {
-        return getOperand(0);
-    }
-};
-
-class LIncrementUnboxedArrayInitializedLength : public LInstructionHelper<0, 1, 0>
-{
-  public:
-    LIR_HEADER(IncrementUnboxedArrayInitializedLength)
-
-    explicit LIncrementUnboxedArrayInitializedLength(const LAllocation& object) {
-        setOperand(0, object);
-    }
-
-    const LAllocation* object() {
-        return getOperand(0);
-    }
-};
-
-class LSetUnboxedArrayInitializedLength : public LInstructionHelper<0, 2, 1>
-{
-  public:
-    LIR_HEADER(SetUnboxedArrayInitializedLength)
-
-    explicit LSetUnboxedArrayInitializedLength(const LAllocation& object,
-                                               const LAllocation& length,
-                                               const LDefinition& temp) {
-        setOperand(0, object);
-        setOperand(1, length);
-        setTemp(0, temp);
-    }
-
-    const LAllocation* object() {
-        return getOperand(0);
-    }
-    const LAllocation* length() {
-        return getOperand(1);
-    }
-    const LDefinition* temp() {
-        return getTemp(0);
-    }
-};
-
 // Load the length from an elements header.
 class LArrayLength : public LInstructionHelper<1, 1, 0>
 {
diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h
index 6912e8904..deae92839 100644
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -267,10 +267,6 @@
     _(PostWriteElementBarrierV)     \
     _(InitializedLength)            \
     _(SetInitializedLength)         \
-    _(UnboxedArrayLength)           \
-    _(UnboxedArrayInitializedLength) \
-    _(IncrementUnboxedArrayInitializedLength) \
-    _(SetUnboxedArrayInitializedLength) \
     _(BoundsCheck)                  \
     _(BoundsCheckRange)             \
     _(BoundsCheckLower)             \
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 7a67c0095..190439d4b 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -64,7 +64,7 @@ using JS::ToUint32;
 bool
 JS::IsArray(JSContext* cx, HandleObject obj, IsArrayAnswer* answer)
 {
-    if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
+    if (obj->is<ArrayObject>()) {
         *answer = IsArrayAnswer::Array;
         return true;
     }
@@ -100,11 +100,6 @@ js::GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp)
         return true;
     }
 
-    if (obj->is<UnboxedArrayObject>()) {
-        *lengthp = obj->as<UnboxedArrayObject>().length();
-        return true;
-    }
-
     if (obj->is<ArgumentsObject>()) {
         ArgumentsObject& argsobj = obj->as<ArgumentsObject>();
         if (!argsobj.hasOverriddenLength()) {
@@ -284,7 +279,7 @@ ElementAdder::append(JSContext* cx, HandleValue v)
     MOZ_ASSERT(index_ < length_);
     if (resObj_) {
         DenseElementResult result =
-            SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
+            SetOrExtendBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
         if (result == DenseElementResult::Failure)
             return false;
         if (result == DenseElementResult::Incomplete) {
@@ -342,11 +337,11 @@ GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp)
 {
     MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj));
 
-    if (length > GetBoxedOrUnboxedInitializedLength<Type>(aobj))
+    if (length > GetBoxedOrUnboxedInitializedLength(aobj))
         return DenseElementResult::Incomplete;
 
     for (size_t i = 0; i < length; i++) {
-        vp[i] = GetBoxedOrUnboxedDenseElement<Type>(aobj, i);
+        vp[i] = GetBoxedOrUnboxedDenseElement(aobj, i);
 
         // No other indexed properties so hole => undefined.
         if (vp[i].isMagic(JS_ELEMENTS_HOLE))
@@ -398,7 +393,7 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
 {
     MOZ_ASSERT(index >= 0);
 
-    if ((obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) && !obj->isIndexed() && index <= UINT32_MAX) {
+    if (obj->is<ArrayObject>() && !obj->isIndexed() && index <= UINT32_MAX) {
         DenseElementResult result =
             SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, uint32_t(index), v.address(), 1);
         if (result != DenseElementResult::Incomplete)
@@ -823,7 +818,7 @@ array_addProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
 static inline bool
 ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj)
 {
-    return (!obj->isNative() && !obj->is<UnboxedArrayObject>()) ||
+    return !obj->isNative() ||
            obj->isIndexed() ||
            obj->is<TypedArrayObject>() ||
            ClassMayResolveId(*obj->runtimeFromAnyThread()->commonNames,
@@ -1288,10 +1283,6 @@ array_toLocaleString(JSContext* cx, unsigned argc, Value* vp)
         args.rval().setString(cx->names().empty);
         return true;
     }
-    if (obj->is<UnboxedArrayObject>() && obj->as<UnboxedArrayObject>().length() == 0) {
-        args.rval().setString(cx->names().empty);
-        return true;
-    }
 
     AutoCycleDetector detector(cx, obj);
     if (!detector.init())
@@ -1371,46 +1362,38 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
     if (length == 0 || GetBoxedOrUnboxedInitializedLength<Type>(obj) == 0)
         return DenseElementResult::Success;
 
-    if (Type == JSVAL_TYPE_MAGIC) {
-        if (obj->as<NativeObject>().denseElementsAreFrozen())
-            return DenseElementResult::Incomplete;
+    if (obj->as<NativeObject>().denseElementsAreFrozen())
+        return DenseElementResult::Incomplete;
 
-        /*
-         * It's actually surprisingly complicated to reverse an array due to the
-         * orthogonality of array length and array capacity while handling
-         * leading and trailing holes correctly.  Reversing seems less likely to
-         * be a common operation than other array mass-mutation methods, so for
-         * now just take a probably-small memory hit (in the absence of too many
-         * holes in the array at its start) and ensure that the capacity is
-         * sufficient to hold all the elements in the array if it were full.
-         */
-        DenseElementResult result = obj->as<NativeObject>().ensureDenseElements(cx, length, 0);
-        if (result != DenseElementResult::Success)
-            return result;
+    /*
+     * It's actually surprisingly complicated to reverse an array due to the
+     * orthogonality of array length and array capacity while handling
+     * leading and trailing holes correctly.  Reversing seems less likely to
+     * be a common operation than other array mass-mutation methods, so for
+     * now just take a probably-small memory hit (in the absence of too many
+     * holes in the array at its start) and ensure that the capacity is
+     * sufficient to hold all the elements in the array if it were full.
+     */
+    DenseElementResult result = obj->as<NativeObject>().ensureDenseElements(cx, length, 0);
+    if (result != DenseElementResult::Success)
+        return result;
 
-        /* Fill out the array's initialized length to its proper length. */
-        obj->as<NativeObject>().ensureDenseInitializedLength(cx, length, 0);
-    } else {
-        // Unboxed arrays can only be reversed here if their initialized length
-        // matches their actual length. Otherwise the reversal will place holes
-        // at the beginning of the array, which we don't support.
-        if (length != obj->as<UnboxedArrayObject>().initializedLength())
-            return DenseElementResult::Incomplete;
-    }
+    /* Fill out the array's initialized length to its proper length. */
+    obj->as<NativeObject>().ensureDenseInitializedLength(cx, length, 0);
 
     RootedValue origlo(cx), orighi(cx);
 
     uint32_t lo = 0, hi = length - 1;
     for (; lo < hi; lo++, hi--) {
-        origlo = GetBoxedOrUnboxedDenseElement<Type>(obj, lo);
-        orighi = GetBoxedOrUnboxedDenseElement<Type>(obj, hi);
-        SetBoxedOrUnboxedDenseElementNoTypeChange<Type>(obj, lo, orighi);
+        origlo = GetBoxedOrUnboxedDenseElement(obj, lo);
+        orighi = GetBoxedOrUnboxedDenseElement(obj, hi);
+        SetBoxedOrUnboxedDenseElementNoTypeChange(obj, lo, orighi);
         if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
         {
             return DenseElementResult::Failure;
         }
-        SetBoxedOrUnboxedDenseElementNoTypeChange<Type>(obj, hi, origlo);
+        SetBoxedOrUnboxedDenseElementNoTypeChange(obj, hi, origlo);
         if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
         {
@@ -2082,8 +2065,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         DenseElementResult result =
-            SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, length,
-                                                      args.array(), args.length());
+            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, length,
+                                                   args.array(), args.length());
         if (result != DenseElementResult::Incomplete) {
             if (result == DenseElementResult::Failure)
                 return false;
@@ -2158,21 +2141,15 @@ template <JSValueType Type>
 static inline DenseElementResult
 ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj));
+    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj));
 
     /*
      * At this point the length and initialized length have already been
      * decremented and the result fetched, so just shift the array elements
      * themselves.
      */
-    size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
-    if (Type == JSVAL_TYPE_MAGIC) {
-        obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
-    } else {
-        uint8_t* data = obj->as<UnboxedArrayObject>().elements();
-        size_t elementSize = UnboxedTypeSize(Type);
-        memmove(data, data + elementSize, initlen * elementSize);
-    }
+    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
+    obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
 
     return DenseElementResult::Success;
 }
@@ -2202,19 +2179,19 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED)))
         return DenseElementResult::Incomplete;
 
-    size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
+    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
     if (initlen == 0)
         return DenseElementResult::Incomplete;
 
-    rval.set(GetBoxedOrUnboxedDenseElement<Type>(obj, 0));
+    rval.set(GetBoxedOrUnboxedDenseElement(obj, 0));
     if (rval.isMagic(JS_ELEMENTS_HOLE))
         rval.setUndefined();
 
-    DenseElementResult result = MoveBoxedOrUnboxedDenseElements<Type>(cx, obj, 0, 1, initlen - 1);
+    DenseElementResult result = MoveBoxedOrUnboxedDenseElements(cx, obj, 0, 1, initlen - 1);
     if (result != DenseElementResult::Success)
         return result;
 
-    SetBoxedOrUnboxedInitializedLength<Type>(cx, obj, initlen - 1);
+    SetBoxedOrUnboxedInitializedLength(cx, obj, initlen - 1);
     return DenseElementResult::Success;
 }
 
@@ -2520,7 +2497,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
 
                 /* Steps 10-11. */
                 DebugOnly<DenseElementResult> result =
-                    CopyAnyBoxedOrUnboxedDenseElements(cx, arr, obj, 0, actualStart, actualDeleteCount);
+                    CopyBoxedOrUnboxedDenseElements(cx, arr, obj, 0, actualStart, actualDeleteCount);
                 MOZ_ASSERT(result.value == DenseElementResult::Success);
 
                 /* Step 12 (implicit). */
@@ -2557,14 +2534,14 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
         if (CanOptimizeForDenseStorage(obj, 0, len, cx)) {
             /* Steps 15.a-b. */
             DenseElementResult result =
-                MoveAnyBoxedOrUnboxedDenseElements(cx, obj, targetIndex, sourceIndex,
-                                                   len - sourceIndex);
+                MoveBoxedOrUnboxedDenseElements(cx, obj, targetIndex, sourceIndex,
+                                                len - sourceIndex);
             MOZ_ASSERT(result != DenseElementResult::Incomplete);
             if (result == DenseElementResult::Failure)
                 return false;
 
             /* Steps 15.c-d. */
-            SetAnyBoxedOrUnboxedInitializedLength(cx, obj, finalLength);
+            SetBoxedOrUnboxedInitializedLength(cx, obj, finalLength);
         } else {
             /*
              * This is all very slow if the length is very large. We don't yet
@@ -2644,15 +2621,15 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
 
         if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
             DenseElementResult result =
-                MoveAnyBoxedOrUnboxedDenseElements(cx, obj, actualStart + itemCount,
-                                                   actualStart + actualDeleteCount,
-                                                   len - (actualStart + actualDeleteCount));
+                MoveBoxedOrUnboxedDenseElements(cx, obj, actualStart + itemCount,
+                                                actualStart + actualDeleteCount,
+                                                len - (actualStart + actualDeleteCount));
             MOZ_ASSERT(result != DenseElementResult::Incomplete);
             if (result == DenseElementResult::Failure)
                 return false;
 
             /* Steps 16.a-b. */
-            SetAnyBoxedOrUnboxedInitializedLength(cx, obj, len + itemCount - actualDeleteCount);
+            SetBoxedOrUnboxedInitializedLength(cx, obj, len + itemCount - actualDeleteCount);
         } else {
             RootedValue fromValue(cx);
             for (double k = len - actualDeleteCount; k > actualStart; k--) {
@@ -3022,14 +2999,14 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
     if (begin > end)
         begin = end;
 
-    size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
+    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
     if (initlen > begin) {
         size_t count = Min<size_t>(initlen - begin, end - begin);
         if (count) {
-            DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements<Type>(cx, result, count);
+            DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements(cx, result, count);
             if (rv != DenseElementResult::Success)
                 return rv;
-            CopyBoxedOrUnboxedDenseElements<Type, Type>(cx, result, obj, 0, begin, count);
+            CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count);
         }
     }
 
@@ -3589,12 +3566,6 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
         newKind = TenuredObject;
 
     RootedObject proto(cx, group->proto().toObject());
-    if (group->maybeUnboxedLayout()) {
-        if (length > UnboxedArrayObject::MaximumCapacity)
-            return NewArray<maxLength>(cx, length, proto, newKind);
-        return UnboxedArrayObject::create(cx, group, length, newKind, maxLength);
-    }
-
     ArrayObject* res = NewArray<maxLength>(cx, length, proto, newKind);
     if (!res)
         return nullptr;
@@ -3701,8 +3672,8 @@ js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup
                 if (!obj)
                     return false;
                 DebugOnly<DenseElementResult> result =
-                    SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength,
-                                                              ShouldUpdateTypes::Update);
+                    SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength,
+                                                           ShouldUpdateTypes::Update);
                 MOZ_ASSERT(result.value == DenseElementResult::Success);
             }
             objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true);
@@ -3724,22 +3695,10 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
         return nullptr;
 
     DenseElementResult result =
-        SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, 0, vp, length, updateTypes);
+        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, length, updateTypes);
     if (result == DenseElementResult::Failure)
         return nullptr;
-    if (result == DenseElementResult::Success)
-        return obj;
-
-    MOZ_ASSERT(obj->is<UnboxedArrayObject>());
-    if (!UnboxedArrayObject::convertToNative(cx->asJSContext(), obj))
-        return nullptr;
-
-    result = SetOrExtendBoxedOrUnboxedDenseElements<JSVAL_TYPE_MAGIC>(cx, obj, 0, vp, length,
-                                                                      updateTypes);
-    MOZ_ASSERT(result != DenseElementResult::Incomplete);
-    if (result == DenseElementResult::Failure)
-        return nullptr;
-
+    MOZ_ASSERT(result == DenseElementResult::Success);
     return obj;
 }
 
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index f5cd56a9b..1fd9d1d28 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -271,7 +271,7 @@ js::GetBuiltinClass(JSContext* cx, HandleObject obj, ESClass* cls)
 
     if (obj->is<PlainObject>() || obj->is<UnboxedPlainObject>())
         *cls = ESClass::Object;
-    else if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>())
+    else if (obj->is<ArrayObject>())
         *cls = ESClass::Array;
     else if (obj->is<NumberObject>())
         *cls = ESClass::Number;
-- 
cgit v1.2.3


From c8300fbd6ae08925736c32f8b02c980ce1531f3f Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Thu, 23 May 2019 10:51:09 +0000
Subject: Remove UnboxedArray code part 2

---
 js/src/gc/Marking.cpp         |   2 -
 js/src/jit/BaselineIC.cpp     |   8 +-
 js/src/jit/BaselineIC.h       |  56 +--
 js/src/jit/CodeGenerator.cpp  |  19 +-
 js/src/jit/MCallOptimize.cpp  |   4 +-
 js/src/jit/MIR.h              |   6 +-
 js/src/jsarray.cpp            |  18 +-
 js/src/jsobj.cpp              |  27 +-
 js/src/jsobjinlines.h         |   2 -
 js/src/vm/Interpreter-inl.h   |   2 +-
 js/src/vm/Interpreter.cpp     |   9 -
 js/src/vm/ObjectGroup.cpp     |  73 +---
 js/src/vm/ReceiverGuard.cpp   |   8 +-
 js/src/vm/TypeInference.cpp   |   2 +-
 js/src/vm/UnboxedObject-inl.h | 466 +++---------------------
 js/src/vm/UnboxedObject.cpp   | 826 +-----------------------------------------
 js/src/vm/UnboxedObject.h     | 207 +----------
 17 files changed, 124 insertions(+), 1611 deletions(-)

(limited to 'js/src')

diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index 47d2314c1..da3ef7d0d 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2504,8 +2504,6 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
         InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
     } else if (src->is<TypedArrayObject>()) {
         tenuredSize += TypedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
-    } else if (src->is<UnboxedArrayObject>()) {
-        tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
     } else if (src->is<ArgumentsObject>()) {
         tenuredSize += ArgumentsObject::objectMovedDuringMinorGC(this, dst, src);
     } else if (src->is<ProxyObject>()) {
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index f43fc5bf9..1d230e083 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -280,6 +280,12 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
     RootedId id(cx);
 
     switch(stub->kind()) {
+      case ICStub::SetElem_DenseOrUnboxedArray:
+      case ICStub::SetElem_DenseOrUnboxedArrayAdd: {
+        id = JSID_VOID;
+        AddTypePropertyId(cx, obj, id, value);
+        break;
+      }
       case ICStub::SetProp_Native:
       case ICStub::SetProp_NativeAdd:
       case ICStub::SetProp_Unboxed: {
@@ -5763,7 +5769,7 @@ CopyArray(JSContext* cx, HandleObject obj, MutableHandleValue result)
     if (!nobj)
         return false;
     EnsureArrayGroupAnalyzed(cx, nobj);
-    CopyAnyBoxedOrUnboxedDenseElements(cx, nobj, obj, 0, 0, length);
+    CopyBoxedOrUnboxedDenseElements(cx, nobj, obj, 0, 0, length);
 
     result.setObject(*nobj);
     return true;
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index a57556d99..afbea3b69 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -892,54 +892,6 @@ class ICGetElem_Dense : public ICMonitoredStub
     };
 };
 
-class ICGetElem_UnboxedArray : public ICMonitoredStub
-{
-    friend class ICStubSpace;
-
-    GCPtrObjectGroup group_;
-
-    ICGetElem_UnboxedArray(JitCode* stubCode, ICStub* firstMonitorStub, ObjectGroup* group);
-
-  public:
-    static ICGetElem_UnboxedArray* Clone(JSContext* cx, ICStubSpace* space,
-                                         ICStub* firstMonitorStub, ICGetElem_UnboxedArray& other);
-
-    static size_t offsetOfGroup() {
-        return offsetof(ICGetElem_UnboxedArray, group_);
-    }
-
-    GCPtrObjectGroup& group() {
-        return group_;
-    }
-
-    class Compiler : public ICStubCompiler {
-      ICStub* firstMonitorStub_;
-      RootedObjectGroup group_;
-      JSValueType elementType_;
-
-      protected:
-        MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
-        virtual int32_t getKey() const {
-            return static_cast<int32_t>(engine_) |
-                  (static_cast<int32_t>(kind) << 1) |
-                  (static_cast<int32_t>(elementType_) << 17);
-        }
-
-      public:
-        Compiler(JSContext* cx, ICStub* firstMonitorStub, ObjectGroup* group)
-          : ICStubCompiler(cx, ICStub::GetElem_UnboxedArray, Engine::Baseline),
-            firstMonitorStub_(firstMonitorStub),
-            group_(cx, group),
-            elementType_(group->unboxedLayoutDontCheckGeneration().elementType())
-        {}
-
-        ICStub* getStub(ICStubSpace* space) {
-            return newStub<ICGetElem_UnboxedArray>(space, getStubCode(), firstMonitorStub_, group_);
-        }
-    };
-};
-
 // Accesses scalar elements of a typed array or typed object.
 class ICGetElem_TypedArray : public ICStub
 {
@@ -1115,9 +1067,7 @@ class ICSetElem_DenseOrUnboxedArray : public ICUpdatedStub
           : ICStubCompiler(cx, ICStub::SetElem_DenseOrUnboxedArray, Engine::Baseline),
             shape_(cx, shape),
             group_(cx, group),
-            unboxedType_(shape
-                         ? JSVAL_TYPE_MAGIC
-                         : group->unboxedLayoutDontCheckGeneration().elementType())
+            unboxedType_(JSVAL_TYPE_MAGIC)
         {}
 
         ICUpdatedStub* getStub(ICStubSpace* space) {
@@ -1225,9 +1175,7 @@ class ICSetElemDenseOrUnboxedArrayAddCompiler : public ICStubCompiler {
         : ICStubCompiler(cx, ICStub::SetElem_DenseOrUnboxedArrayAdd, Engine::Baseline),
           obj_(cx, obj),
           protoChainDepth_(protoChainDepth),
-          unboxedType_(obj->is<UnboxedArrayObject>()
-                       ? obj->as<UnboxedArrayObject>().elementType()
-                       : JSVAL_TYPE_MAGIC)
+          unboxedType_(JSVAL_TYPE_MAGIC)
     {}
 
     template <size_t ProtoChainDepth>
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index bd275a2c1..485e881fe 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -10336,22 +10336,11 @@ CodeGenerator::visitLoadElementHole(LLoadElementHole* lir)
     else
         masm.branch32(Assembler::BelowOrEqual, initLength, ToRegister(lir->index()), &undefined);
 
-    if (mir->unboxedType() != JSVAL_TYPE_MAGIC) {
-        size_t width = UnboxedTypeSize(mir->unboxedType());
-        if (lir->index()->isConstant()) {
-            Address addr(elements, ToInt32(lir->index()) * width);
-            masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
-        } else {
-            BaseIndex addr(elements, ToRegister(lir->index()), ScaleFromElemWidth(width));
-            masm.loadUnboxedProperty(addr, mir->unboxedType(), out);
-        }
+    if (lir->index()->isConstant()) {
+        NativeObject::elementsSizeMustNotOverflow();
+        masm.loadValue(Address(elements, ToInt32(lir->index()) * sizeof(Value)), out);
     } else {
-        if (lir->index()->isConstant()) {
-            NativeObject::elementsSizeMustNotOverflow();
-            masm.loadValue(Address(elements, ToInt32(lir->index()) * sizeof(Value)), out);
-        } else {
-            masm.loadValue(BaseObjectElementIndex(elements, ToRegister(lir->index())), out);
-        }
+        masm.loadValue(BaseObjectElementIndex(elements, ToRegister(lir->index())), out);
     }
 
     // If a hole check is needed, and the value wasn't a hole, we're done.
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 7283497ea..748a70973 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -541,7 +541,7 @@ IonBuilder::inlineArray(CallInfo& callInfo)
             if (!alloc().ensureBallast())
                 return InliningStatus_Error;
             MDefinition* value = callInfo.getArg(i);
-            if (!initializeArrayElement(array, i, /* addResumePoint = */ false))
+            if (!initializeArrayElement(array, i, value, /* addResumePoint = */ false))
                 return InliningStatus_Error;
         }
 
@@ -578,7 +578,7 @@ IonBuilder::inlineArrayIsArray(CallInfo& callInfo)
         if (!clasp || clasp->isProxy())
             return InliningStatus_NotInlined;
 
-        isArray = (clasp == &ArrayObject::class_ || clasp == &UnboxedArrayObject::class_);
+        isArray = (clasp == &ArrayObject::class_);
     }
 
     pushConstant(BooleanValue(isArray));
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index cdd737b56..f316827dc 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9245,7 +9245,7 @@ class MLoadElementHole
     bool needsHoleCheck_;
 
     MLoadElementHole(MDefinition* elements, MDefinition* index, MDefinition* initLength,
-                     JSValueType unboxedType, bool needsHoleCheck)
+                     bool needsHoleCheck)
       : MTernaryInstruction(elements, index, initLength),
         needsNegativeIntCheck_(true),
         needsHoleCheck_(needsHoleCheck)
@@ -9717,10 +9717,6 @@ class MArraySlice
         return initialHeap_;
     }
 
-    JSValueType unboxedType() const {
-        return unboxedType_;
-    }
-
     bool possiblyCalls() const override {
         return true;
     }
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 190439d4b..fa5ef2ab3 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -395,7 +395,7 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
 
     if (obj->is<ArrayObject>() && !obj->isIndexed() && index <= UINT32_MAX) {
         DenseElementResult result =
-            SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, uint32_t(index), v.address(), 1);
+            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, uint32_t(index), v.address(), 1);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
     }
@@ -1068,12 +1068,12 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_
     // length > initLength we rely on the second loop to add the
     // other elements.
     MOZ_ASSERT(*numProcessed == 0);
-    uint32_t initLength = Min<uint32_t>(GetBoxedOrUnboxedInitializedLength<Type>(obj), length);
+    uint32_t initLength = Min<uint32_t>(GetBoxedOrUnboxedInitializedLength(obj), length);
     while (*numProcessed < initLength) {
         if (!CheckForInterrupt(cx))
             return DenseElementResult::Failure;
 
-        Value elem = GetBoxedOrUnboxedDenseElement<Type>(obj, *numProcessed);
+        Value elem = GetBoxedOrUnboxedDenseElement(obj, *numProcessed);
 
         if (elem.isString()) {
             if (!sb.append(elem.toString()))
@@ -1320,7 +1320,7 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         DenseElementResult result =
-            SetOrExtendAnyBoxedOrUnboxedDenseElements(cx, obj, start, vector, count, updateTypes);
+            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, start, vector, count, updateTypes);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
     }
@@ -1359,7 +1359,7 @@ DenseElementResult
 ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
 {
     /* An empty array or an array with no elements is already reversed. */
-    if (length == 0 || GetBoxedOrUnboxedInitializedLength<Type>(obj) == 0)
+    if (length == 0 || GetBoxedOrUnboxedInitializedLength(obj) == 0)
         return DenseElementResult::Success;
 
     if (obj->as<NativeObject>().denseElementsAreFrozen())
@@ -2074,7 +2074,7 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
             uint32_t newlength = length + args.length();
             args.rval().setNumber(newlength);
 
-            // SetOrExtendAnyBoxedOrUnboxedDenseElements takes care of updating the
+            // SetOrExtendBoxedOrUnboxedDenseElements takes care of updating the
             // length for boxed and unboxed arrays. Handle updates to the length of
             // non-arrays here.
             bool isArray;
@@ -2360,7 +2360,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
         return false;
 
     /* There's no optimizing possible if it's not an array. */
-    if (!arr->is<ArrayObject>() && !arr->is<UnboxedArrayObject>())
+    if (!arr->is<ArrayObject>())
         return false;
 
     /* If it's a frozen array, always pick the slow path */
@@ -2863,7 +2863,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
 
         if (count) {
             DebugOnly<DenseElementResult> result =
-                CopyAnyBoxedOrUnboxedDenseElements(cx, narr, obj, 0, begin, count);
+                CopyBoxedOrUnboxedDenseElements(cx, narr, obj, 0, begin, count);
             MOZ_ASSERT(result.value == DenseElementResult::Success);
         }
         arr.set(narr);
@@ -3608,7 +3608,7 @@ static inline JSObject*
 NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
                       NewObjectKind newKind = GenericObject)
 {
-    if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>())
+    if (!obj->is<ArrayObject>())
         return NewArray<maxLength>(cx, length, nullptr, newKind);
 
     if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype())
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index f22ecb445..c26a42f48 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1146,7 +1146,7 @@ static bool
 GetScriptArrayObjectElements(JSContext* cx, HandleObject obj, MutableHandle<GCVector<Value>> values)
 {
     MOZ_ASSERT(!obj->isSingleton());
-    MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(obj->is<ArrayObject>());
     MOZ_ASSERT(!obj->isIndexed());
 
     size_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
@@ -1207,11 +1207,10 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
     MOZ_ASSERT_IF(obj->isSingleton(),
                   cx->compartment()->behaviors().getSingletonsAsTemplates());
     MOZ_ASSERT(obj->is<PlainObject>() ||
-               obj->is<ArrayObject>() ||
-			   obj->is<UnboxedArrayObject>());
+               obj->is<ArrayObject>());
     MOZ_ASSERT(newKind != SingletonObject);
 
-    if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
+    if (obj->is<ArrayObject>()) {
         Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
         if (!GetScriptArrayObjectElements(cx, obj, &values))
             return nullptr;
@@ -1327,9 +1326,8 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
     {
         if (mode == XDR_ENCODE) {
             MOZ_ASSERT(obj->is<PlainObject>() ||
-                       obj->is<ArrayObject>() ||
-                       obj->is<UnboxedArrayObject>());
-            isArray = (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) ? 1 : 0;
+                       obj->is<ArrayObject>());
+            isArray = obj->is<ArrayObject>() ? 1 : 0;
         }
 
         if (!xdr->codeUint32(&isArray))
@@ -2312,11 +2310,6 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
         // us the resolve hook won't define a property with this id.
         if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
             return false;
-    } else if (obj->is<UnboxedArrayObject>()) {
-        if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-            MarkNonNativePropertyFound<NoGC>(propp);
-            return true;
-        }
     } else if (obj->is<TypedObject>()) {
         if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
             MarkNonNativePropertyFound<NoGC>(propp);
@@ -3680,16 +3673,6 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
     if (IsProxy(this))
         return as<ProxyObject>().allocKindForTenure();
 
-    // Unboxed arrays use inline data if their size is small enough.
-    if (is<UnboxedArrayObject>()) {
-        const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
-        size_t nbytes = UnboxedArrayObject::offsetOfInlineElements() +
-                        nobj->capacity() * nobj->elementSize();
-        if (nbytes <= JSObject::MAX_BYTE_SIZE)
-            return GetGCObjectKindForBytes(nbytes);
-        return AllocKind::OBJECT0;
-    }
-
     // Inlined typed objects are followed by their data, so make sure we copy
     // it all over to the new object.
     if (is<InlineTypedObject>()) {
diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h
index 6be4d0d28..26f9eacce 100644
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -40,8 +40,6 @@ MaybeConvertUnboxedObjectToNative(ExclusiveContext* cx, JSObject* obj)
 {
     if (obj->is<UnboxedPlainObject>())
         return UnboxedPlainObject::convertToNative(cx->asJSContext(), obj);
-    if (obj->is<UnboxedArrayObject>())
-        return UnboxedArrayObject::convertToNative(cx->asJSContext(), obj);
     return true;
 }
 
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 710f1d89b..a2c8e220a 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -593,7 +593,7 @@ InitArrayElemOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t
     JSOp op = JSOp(*pc);
     MOZ_ASSERT(op == JSOP_INITELEM_ARRAY || op == JSOP_INITELEM_INC);
 
-    MOZ_ASSERT(obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
+    MOZ_ASSERT(obj->is<ArrayObject>());
 
     if (op == JSOP_INITELEM_INC && index == INT32_MAX) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SPREAD_TOO_LARGE);
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 3cf2deb83..7d05b2d4c 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -5001,9 +5001,6 @@ js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32
 
         if (group->shouldPreTenure() || group->maybePreliminaryObjects())
             newKind = TenuredObject;
-
-        if (group->maybeUnboxedLayout())
-            return UnboxedArrayObject::create(cx, group, length, newKind);
     }
 
     ArrayObject* obj = NewDenseFullyAllocatedArray(cx, length, nullptr, newKind);
@@ -5029,12 +5026,6 @@ js::NewArrayOperationWithTemplate(JSContext* cx, HandleObject templateObject)
 
     NewObjectKind newKind = templateObject->group()->shouldPreTenure() ? TenuredObject : GenericObject;
 
-    if (templateObject->is<UnboxedArrayObject>()) {
-        uint32_t length = templateObject->as<UnboxedArrayObject>().length();
-        RootedObjectGroup group(cx, templateObject->group());
-        return UnboxedArrayObject::create(cx, group, length, newKind);
-    }
-
     ArrayObject* obj = NewDenseFullyAllocatedArray(cx, templateObject->as<ArrayObject>().length(),
                                                    nullptr, newKind);
     if (!obj)
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index 46159a972..a227b7c9c 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -861,32 +861,6 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
         return nullptr;
     if (group->maybePreliminaryObjects())
         group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
-    if (group->maybeUnboxedLayout()) {
-        switch (group->unboxedLayout().elementType()) {
-          case JSVAL_TYPE_BOOLEAN:
-            if (elementType != TypeSet::BooleanType())
-                updateTypes = ShouldUpdateTypes::Update;
-            break;
-          case JSVAL_TYPE_INT32:
-            if (elementType != TypeSet::Int32Type())
-                updateTypes = ShouldUpdateTypes::Update;
-            break;
-          case JSVAL_TYPE_DOUBLE:
-            if (elementType != TypeSet::Int32Type() && elementType != TypeSet::DoubleType())
-                updateTypes = ShouldUpdateTypes::Update;
-            break;
-          case JSVAL_TYPE_STRING:
-            if (elementType != TypeSet::StringType())
-                updateTypes = ShouldUpdateTypes::Update;
-            break;
-          case JSVAL_TYPE_OBJECT:
-            if (elementType != TypeSet::NullType() && !elementType.get().isObjectUnchecked())
-                updateTypes = ShouldUpdateTypes::Update;
-            break;
-          default:
-            MOZ_CRASH();
-        }
-    }
 
     return NewCopiedArrayTryUseGroup(cx, group, vp, length, newKind, updateTypes);
 }
@@ -897,7 +871,7 @@ GiveObjectGroup(ExclusiveContext* cx, JSObject* source, JSObject* target)
 {
     MOZ_ASSERT(source->group() != target->group());
 
-    if (!target->is<ArrayObject>() && !target->is<UnboxedArrayObject>())
+    if (!target->is<ArrayObject>())
         return true;
 
     if (target->group()->maybePreliminaryObjects()) {
@@ -905,41 +879,21 @@ GiveObjectGroup(ExclusiveContext* cx, JSObject* source, JSObject* target)
         target->group()->maybePreliminaryObjects()->maybeAnalyze(cx, target->group(), force);
     }
 
-    if (target->is<ArrayObject>()) {
-        ObjectGroup* sourceGroup = source->group();
-
-        if (source->is<UnboxedArrayObject>()) {
-            Shape* shape = target->as<ArrayObject>().lastProperty();
-            if (!UnboxedArrayObject::convertToNativeWithGroup(cx, source, target->group(), shape))
-                return false;
-        } else if (source->is<ArrayObject>()) {
-            source->setGroup(target->group());
-        } else {
-            return true;
-        }
-
-        if (sourceGroup->maybePreliminaryObjects())
-            sourceGroup->maybePreliminaryObjects()->unregisterObject(source);
-        if (target->group()->maybePreliminaryObjects())
-            target->group()->maybePreliminaryObjects()->registerNewObject(source);
-
-        for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
-            Value v = source->as<ArrayObject>().getDenseElement(i);
-            AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
-        }
+    ObjectGroup* sourceGroup = source->group();
 
+    if (source->is<ArrayObject>()) {
+        source->setGroup(target->group());
+    } else {
         return true;
     }
 
-    if (target->is<UnboxedArrayObject>()) {
-        if (!source->is<UnboxedArrayObject>())
-            return true;
-        if (source->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_INT32)
-            return true;
-        if (target->as<UnboxedArrayObject>().elementType() != JSVAL_TYPE_DOUBLE)
-            return true;
-
-        return source->as<UnboxedArrayObject>().convertInt32ToDouble(cx, target->group());
+    if (sourceGroup->maybePreliminaryObjects())
+        sourceGroup->maybePreliminaryObjects()->unregisterObject(source);
+    if (target->group()->maybePreliminaryObjects())
+        target->group()->maybePreliminaryObjects()->registerNewObject(source);
+     for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
+        Value v = source->as<ArrayObject>().getDenseElement(i);
+        AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
     }
 
     return true;
@@ -1503,7 +1457,8 @@ ObjectGroup::allocationSiteGroup(JSContext* cx, JSScript* scriptArg, jsbytecode*
         }
     }
 
-    if (kind == JSProto_Array &&
+    // FIXME: This block can probably go because of cx->options().unboxedArrays()
+	if (kind == JSProto_Array &&
         (JSOp(*pc) == JSOP_NEWARRAY || IsCallPC(pc)) &&
         cx->options().unboxedArrays())
     {
diff --git a/js/src/vm/ReceiverGuard.cpp b/js/src/vm/ReceiverGuard.cpp
index 11c2d0727..e37bf8ee5 100644
--- a/js/src/vm/ReceiverGuard.cpp
+++ b/js/src/vm/ReceiverGuard.cpp
@@ -19,7 +19,7 @@ ReceiverGuard::ReceiverGuard(JSObject* obj)
             group = obj->group();
             if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
                 shape = expando->lastProperty();
-        } else if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
+        } else if (obj->is<TypedObject>()) {
             group = obj->group();
         } else {
             shape = obj->maybeShape();
@@ -34,7 +34,7 @@ ReceiverGuard::ReceiverGuard(ObjectGroup* group, Shape* shape)
         const Class* clasp = group->clasp();
         if (clasp == &UnboxedPlainObject::class_) {
             // Keep both group and shape.
-        } else if (clasp == &UnboxedArrayObject::class_ || IsTypedObjectClass(clasp)) {
+        } else if (IsTypedObjectClass(clasp)) {
             this->shape = nullptr;
         } else {
             this->group = nullptr;
@@ -49,8 +49,8 @@ HeapReceiverGuard::keyBits(JSObject* obj)
         // Both the group and shape need to be guarded for unboxed plain objects.
         return obj->as<UnboxedPlainObject>().maybeExpando() ? 0 : 1;
     }
-    if (obj->is<UnboxedArrayObject>() || obj->is<TypedObject>()) {
-        // Only the group needs to be guarded for unboxed arrays and typed objects.
+    if (obj->is<TypedObject>()) {
+        // Only the group needs to be guarded for typed objects.
         return 2;
     }
     // Other objects only need the shape to be guarded.
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 9e0342382..2160dbc51 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -2505,7 +2505,7 @@ TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList* constraints, jsid
 bool
 js::ClassCanHaveExtraProperties(const Class* clasp)
 {
-    if (clasp == &UnboxedPlainObject::class_ || clasp == &UnboxedArrayObject::class_)
+    if (clasp == &UnboxedPlainObject::class_)
         return false;
     return clasp->getResolve()
         || clasp->getOpsLookupProperty()
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 93ad7bf28..499f3604b 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -172,123 +172,6 @@ UnboxedPlainObject::layout() const
     return group()->unboxedLayout();
 }
 
-/////////////////////////////////////////////////////////////////////
-// UnboxedArrayObject
-/////////////////////////////////////////////////////////////////////
-
-inline const UnboxedLayout&
-UnboxedArrayObject::layout() const
-{
-    return group()->unboxedLayout();
-}
-
-inline void
-UnboxedArrayObject::setLength(ExclusiveContext* cx, uint32_t length)
-{
-    if (length > INT32_MAX) {
-        // Track objects with overflowing lengths in type information.
-        MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
-    }
-
-    length_ = length;
-}
-
-inline void
-UnboxedArrayObject::setInitializedLength(uint32_t initlen)
-{
-    if (initlen < initializedLength()) {
-        switch (elementType()) {
-          case JSVAL_TYPE_STRING:
-            for (size_t i = initlen; i < initializedLength(); i++)
-                triggerPreBarrier<JSVAL_TYPE_STRING>(i);
-            break;
-          case JSVAL_TYPE_OBJECT:
-            for (size_t i = initlen; i < initializedLength(); i++)
-                triggerPreBarrier<JSVAL_TYPE_OBJECT>(i);
-            break;
-          default:
-            MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(elementType()));
-        }
-    }
-    setInitializedLengthNoBarrier(initlen);
-}
-
-template <JSValueType Type>
-inline bool
-UnboxedArrayObject::setElementSpecific(ExclusiveContext* cx, size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    MOZ_ASSERT(Type == elementType());
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-    return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ true);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::setElementNoTypeChangeSpecific(size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    MOZ_ASSERT(Type == elementType());
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-    return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ true);
-}
-
-template <JSValueType Type>
-inline bool
-UnboxedArrayObject::initElementSpecific(ExclusiveContext* cx, size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    MOZ_ASSERT(Type == elementType());
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-    return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ false);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::initElementNoTypeChangeSpecific(size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    MOZ_ASSERT(Type == elementType());
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-    return SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ false);
-}
-
-template <JSValueType Type>
-inline Value
-UnboxedArrayObject::getElementSpecific(size_t index)
-{
-    MOZ_ASSERT(index < initializedLength());
-    MOZ_ASSERT(Type == elementType());
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-    return GetUnboxedValue(p, Type, /* maybeUninitialized = */ false);
-}
-
-template <JSValueType Type>
-inline void
-UnboxedArrayObject::triggerPreBarrier(size_t index)
-{
-    MOZ_ASSERT(UnboxedTypeNeedsPreBarrier(Type));
-
-    uint8_t* p = elements() + index * UnboxedTypeSize(Type);
-
-    switch (Type) {
-      case JSVAL_TYPE_STRING: {
-        JSString** np = reinterpret_cast<JSString**>(p);
-        JSString::writeBarrierPre(*np);
-        break;
-      }
-
-      case JSVAL_TYPE_OBJECT: {
-        JSObject** np = reinterpret_cast<JSObject**>(p);
-        JSObject::writeBarrierPre(*np);
-        break;
-      }
-
-      default:
-        MOZ_CRASH("Bad type");
-    }
-}
-
 /////////////////////////////////////////////////////////////////////
 // Combined methods for NativeObject and UnboxedArrayObject accesses.
 /////////////////////////////////////////////////////////////////////
@@ -296,7 +179,7 @@ UnboxedArrayObject::triggerPreBarrier(size_t index)
 static inline bool
 HasAnyBoxedOrUnboxedDenseElements(JSObject* obj)
 {
-    return obj->isNative() || obj->is<UnboxedArrayObject>();
+    return obj->isNative();
 }
 
 static inline size_t
@@ -304,8 +187,6 @@ GetAnyBoxedOrUnboxedInitializedLength(JSObject* obj)
 {
     if (obj->isNative())
         return obj->as<NativeObject>().getDenseInitializedLength();
-    if (obj->is<UnboxedArrayObject>())
-        return obj->as<UnboxedArrayObject>().initializedLength();
     return 0;
 }
 
@@ -314,57 +195,40 @@ GetAnyBoxedOrUnboxedCapacity(JSObject* obj)
 {
     if (obj->isNative())
         return obj->as<NativeObject>().getDenseCapacity();
-    if (obj->is<UnboxedArrayObject>())
-        return obj->as<UnboxedArrayObject>().capacity();
     return 0;
 }
 
 static inline Value
 GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
 {
-    if (obj->isNative())
-        return obj->as<NativeObject>().getDenseElement(index);
-    return obj->as<UnboxedArrayObject>().getElement(index);
+    return obj->as<NativeObject>().getDenseElement(index);
 }
 
 static inline size_t
 GetAnyBoxedOrUnboxedArrayLength(JSObject* obj)
 {
-    if (obj->is<ArrayObject>())
-        return obj->as<ArrayObject>().length();
-    return obj->as<UnboxedArrayObject>().length();
+    return obj->as<ArrayObject>().length();
 }
 
 static inline void
 SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length)
 {
-    if (obj->is<ArrayObject>()) {
-        MOZ_ASSERT(length >= obj->as<ArrayObject>().length());
-        obj->as<ArrayObject>().setLength(cx, length);
-    } else {
-        MOZ_ASSERT(length >= obj->as<UnboxedArrayObject>().length());
-        obj->as<UnboxedArrayObject>().setLength(cx, length);
-    }
+    MOZ_ASSERT(length >= obj->as<ArrayObject>().length());
+    obj->as<ArrayObject>().setLength(cx, length);
 }
 
 static inline bool
 SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
 {
-    if (obj->isNative()) {
-        obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
-        return true;
-    }
-    return obj->as<UnboxedArrayObject>().setElement(cx, index, value);
+    obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
+    return true;
 }
 
 static inline bool
 InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
 {
-    if (obj->isNative()) {
-        obj->as<NativeObject>().initDenseElementWithType(cx, index, value);
-        return true;
-    }
-    return obj->as<UnboxedArrayObject>().initElement(cx, index, value);
+    obj->as<NativeObject>().initDenseElementWithType(cx, index, value);
+    return true;
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -374,273 +238,128 @@ InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, co
 static inline JSValueType
 GetBoxedOrUnboxedType(JSObject* obj)
 {
-    if (obj->isNative())
-        return JSVAL_TYPE_MAGIC;
-    return obj->as<UnboxedArrayObject>().elementType();
+    return JSVAL_TYPE_MAGIC;
 }
 
-template <JSValueType Type>
 static inline bool
 HasBoxedOrUnboxedDenseElements(JSObject* obj)
 {
-    if (Type == JSVAL_TYPE_MAGIC)
-        return obj->isNative();
-    return obj->is<UnboxedArrayObject>() && obj->as<UnboxedArrayObject>().elementType() == Type;
+    return obj->isNative();
 }
 
-template <JSValueType Type>
 static inline size_t
 GetBoxedOrUnboxedInitializedLength(JSObject* obj)
 {
-    if (Type == JSVAL_TYPE_MAGIC)
-        return obj->as<NativeObject>().getDenseInitializedLength();
-    return obj->as<UnboxedArrayObject>().initializedLength();
+    return obj->as<NativeObject>().getDenseInitializedLength();
 }
 
-template <JSValueType Type>
 static inline DenseElementResult
 SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
 {
-    size_t oldInitlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
-    if (Type == JSVAL_TYPE_MAGIC) {
-        obj->as<NativeObject>().setDenseInitializedLength(initlen);
-        if (initlen < oldInitlen)
-            obj->as<NativeObject>().shrinkElements(cx, initlen);
-    } else {
-        obj->as<UnboxedArrayObject>().setInitializedLength(initlen);
-        if (initlen < oldInitlen)
-            obj->as<UnboxedArrayObject>().shrinkElements(cx, initlen);
-    }
+	size_t oldInitlen = GetBoxedOrUnboxedInitializedLength(obj);
+    obj->as<NativeObject>().setDenseInitializedLength(initlen);
+    if (initlen < oldInitlen)
+        obj->as<NativeObject>().shrinkElements(cx, initlen);
     return DenseElementResult::Success;
 }
 
-template <JSValueType Type>
 static inline size_t
 GetBoxedOrUnboxedCapacity(JSObject* obj)
 {
-    if (Type == JSVAL_TYPE_MAGIC)
-        return obj->as<NativeObject>().getDenseCapacity();
-    return obj->as<UnboxedArrayObject>().capacity();
+    return obj->as<NativeObject>().getDenseCapacity();
 }
 
-template <JSValueType Type>
 static inline Value
 GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
 {
-    if (Type == JSVAL_TYPE_MAGIC)
-        return obj->as<NativeObject>().getDenseElement(index);
-    return obj->as<UnboxedArrayObject>().getElementSpecific<Type>(index);
+    return obj->as<NativeObject>().getDenseElement(index);
 }
 
-template <JSValueType Type>
 static inline void
 SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value)
 {
-    if (Type == JSVAL_TYPE_MAGIC)
-        obj->as<NativeObject>().setDenseElement(index, value);
-    else
-        obj->as<UnboxedArrayObject>().setElementNoTypeChangeSpecific<Type>(index, value);
+    obj->as<NativeObject>().setDenseElement(index, value);
 }
 
-template <JSValueType Type>
 static inline bool
 SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
 {
-    if (Type == JSVAL_TYPE_MAGIC) {
-        obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
-        return true;
-    }
-    return obj->as<UnboxedArrayObject>().setElementSpecific<Type>(cx, index, value);
+    obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
+    return true;
 }
 
-template <JSValueType Type>
 static inline DenseElementResult
 EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count)
 {
-    if (Type == JSVAL_TYPE_MAGIC) {
-        if (!obj->as<ArrayObject>().ensureElements(cx, count))
-            return DenseElementResult::Failure;
-    } else {
-        if (obj->as<UnboxedArrayObject>().capacity() < count) {
-            if (!obj->as<UnboxedArrayObject>().growElements(cx, count))
-                return DenseElementResult::Failure;
-        }
-    }
+    if (!obj->as<ArrayObject>().ensureElements(cx, count))
+        return DenseElementResult::Failure;
     return DenseElementResult::Success;
 }
 
-template <JSValueType Type>
 static inline DenseElementResult
 SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
                                        uint32_t start, const Value* vp, uint32_t count,
                                        ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update)
 {
-    if (Type == JSVAL_TYPE_MAGIC) {
-        NativeObject* nobj = &obj->as<NativeObject>();
-
-        if (nobj->denseElementsAreFrozen())
-            return DenseElementResult::Incomplete;
-
-        if (obj->is<ArrayObject>() &&
-            !obj->as<ArrayObject>().lengthIsWritable() &&
-            start + count >= obj->as<ArrayObject>().length())
-        {
-            return DenseElementResult::Incomplete;
-        }
-
-        DenseElementResult result = nobj->ensureDenseElements(cx, start, count);
-        if (result != DenseElementResult::Success)
-            return result;
-
-        if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length())
-            obj->as<ArrayObject>().setLengthInt32(start + count);
-
-        if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) {
-            nobj->copyDenseElements(start, vp, count);
-        } else {
-            for (size_t i = 0; i < count; i++)
-                nobj->setDenseElementWithType(cx, start + i, vp[i]);
-        }
-
-        return DenseElementResult::Success;
-    }
-
-    UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
+    NativeObject* nobj = &obj->as<NativeObject>();
 
-    if (start > nobj->initializedLength())
+    if (nobj->denseElementsAreFrozen())
         return DenseElementResult::Incomplete;
 
-    if (start + count >= UnboxedArrayObject::MaximumCapacity)
+    if (obj->is<ArrayObject>() &&
+        !obj->as<ArrayObject>().lengthIsWritable() &&
+        start + count >= obj->as<ArrayObject>().length())
+    {
         return DenseElementResult::Incomplete;
+    }
 
-    if (start + count > nobj->capacity() && !nobj->growElements(cx, start + count))
-        return DenseElementResult::Failure;
+    DenseElementResult result = nobj->ensureDenseElements(cx, start, count);
+    if (result != DenseElementResult::Success)
+        return result;
 
-    size_t oldInitlen = nobj->initializedLength();
-
-    // Overwrite any existing elements covered by the new range. If we fail
-    // after this point due to some incompatible type being written to the
-    // object's elements, afterwards the contents will be different from when
-    // we started. The caller must retry the operation using a generic path,
-    // which will overwrite the already-modified elements as well as the ones
-    // that were left alone.
-    size_t i = 0;
-    if (updateTypes == ShouldUpdateTypes::DontUpdate) {
-        for (size_t j = start; i < count && j < oldInitlen; i++, j++)
-            nobj->setElementNoTypeChangeSpecific<Type>(j, vp[i]);
-    } else {
-        for (size_t j = start; i < count && j < oldInitlen; i++, j++) {
-            if (!nobj->setElementSpecific<Type>(cx, j, vp[i]))
-                return DenseElementResult::Incomplete;
-        }
-    }
+    if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length())
+        obj->as<ArrayObject>().setLengthInt32(start + count);
 
-    if (i != count) {
-        obj->as<UnboxedArrayObject>().setInitializedLength(start + count);
-        if (updateTypes == ShouldUpdateTypes::DontUpdate) {
-            for (; i < count; i++)
-                nobj->initElementNoTypeChangeSpecific<Type>(start + i, vp[i]);
-        } else {
-            for (; i < count; i++) {
-                if (!nobj->initElementSpecific<Type>(cx, start + i, vp[i])) {
-                    nobj->setInitializedLengthNoBarrier(oldInitlen);
-                    return DenseElementResult::Incomplete;
-                }
-            }
-        }
+    if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) {
+        nobj->copyDenseElements(start, vp, count);
+    } else {
+        for (size_t i = 0; i < count; i++)
+            nobj->setDenseElementWithType(cx, start + i, vp[i]);
     }
 
-    if (start + count >= nobj->length())
-        nobj->setLength(cx, start + count);
-
     return DenseElementResult::Success;
 }
 
-template <JSValueType Type>
 static inline DenseElementResult
 MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart,
                                 uint32_t length)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<Type>(obj));
-
-    if (Type == JSVAL_TYPE_MAGIC) {
-        if (obj->as<NativeObject>().denseElementsAreFrozen())
-            return DenseElementResult::Incomplete;
+    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj));
 
-        if (!obj->as<NativeObject>().maybeCopyElementsForWrite(cx))
-            return DenseElementResult::Failure;
-        obj->as<NativeObject>().moveDenseElements(dstStart, srcStart, length);
-    } else {
-        uint8_t* data = obj->as<UnboxedArrayObject>().elements();
-        size_t elementSize = UnboxedTypeSize(Type);
-
-        if (UnboxedTypeNeedsPreBarrier(Type) &&
-            JS::shadow::Zone::asShadowZone(obj->zone())->needsIncrementalBarrier())
-        {
-            // Trigger pre barriers on any elements we are overwriting. See
-            // NativeObject::moveDenseElements. No post barrier is needed as
-            // only whole cell post barriers are used with unboxed objects.
-            for (size_t i = 0; i < length; i++)
-                obj->as<UnboxedArrayObject>().triggerPreBarrier<Type>(dstStart + i);
-        }
+    if (obj->as<NativeObject>().denseElementsAreFrozen())
+        return DenseElementResult::Incomplete;
 
-        memmove(data + dstStart * elementSize,
-                data + srcStart * elementSize,
-                length * elementSize);
-    }
+    if (!obj->as<NativeObject>().maybeCopyElementsForWrite(cx))
+        return DenseElementResult::Failure;
+    obj->as<NativeObject>().moveDenseElements(dstStart, srcStart, length);
 
     return DenseElementResult::Success;
 }
 
-template <JSValueType DstType, JSValueType SrcType>
 static inline DenseElementResult
 CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
                                 uint32_t dstStart, uint32_t srcStart, uint32_t length)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<SrcType>(src));
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements<DstType>(dst));
-    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<DstType>(dst) == dstStart);
-    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength<SrcType>(src) >= srcStart + length);
-    MOZ_ASSERT(GetBoxedOrUnboxedCapacity<DstType>(dst) >= dstStart + length);
-
-    SetBoxedOrUnboxedInitializedLength<DstType>(cx, dst, dstStart + length);
-
-    if (DstType == JSVAL_TYPE_MAGIC) {
-        if (SrcType == JSVAL_TYPE_MAGIC) {
-            const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
-            dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
-        } else {
-            for (size_t i = 0; i < length; i++) {
-                Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
-                dst->as<NativeObject>().initDenseElement(dstStart + i, v);
-            }
-        }
-    } else if (DstType == SrcType) {
-        uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
-        uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
-        size_t elementSize = UnboxedTypeSize(DstType);
-
-        memcpy(dstData + dstStart * elementSize,
-               srcData + srcStart * elementSize,
-               length * elementSize);
-
-        // Add a store buffer entry if we might have copied a nursery pointer to dst.
-        if (UnboxedTypeNeedsPostBarrier(DstType) && !IsInsideNursery(dst))
-            dst->runtimeFromMainThread()->gc.storeBuffer.putWholeCell(dst);
-    } else if (DstType == JSVAL_TYPE_DOUBLE && SrcType == JSVAL_TYPE_INT32) {
-        uint8_t* dstData = dst->as<UnboxedArrayObject>().elements();
-        uint8_t* srcData = src->as<UnboxedArrayObject>().elements();
-
-        for (size_t i = 0; i < length; i++) {
-            int32_t v = *reinterpret_cast<int32_t*>(srcData + (srcStart + i) * sizeof(int32_t));
-            *reinterpret_cast<double*>(dstData + (dstStart + i) * sizeof(double)) = v;
-        }
-    } else {
-        for (size_t i = 0; i < length; i++) {
-            Value v = GetBoxedOrUnboxedDenseElement<SrcType>(src, srcStart + i);
-            dst->as<UnboxedArrayObject>().initElementNoTypeChangeSpecific<DstType>(dstStart + i, v);
-        }
-    }
+    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(src));
+    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(dst));
+    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(dst) == dstStart);
+    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(src) >= srcStart + length);
+    MOZ_ASSERT(GetBoxedOrUnboxedCapacity(dst) >= dstStart + length);
+
+    SetBoxedOrUnboxedInitializedLength(cx, dst, dstStart + length);
+
+    const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
+    dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
 
     return DenseElementResult::Success;
 }
@@ -666,22 +385,7 @@ CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
 {
     if (!HasAnyBoxedOrUnboxedDenseElements(obj))
         return DenseElementResult::Incomplete;
-    switch (GetBoxedOrUnboxedType(obj)) {
-      case JSVAL_TYPE_MAGIC:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
-      case JSVAL_TYPE_BOOLEAN:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_BOOLEAN>();
-      case JSVAL_TYPE_INT32:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_INT32>();
-      case JSVAL_TYPE_DOUBLE:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_DOUBLE>();
-      case JSVAL_TYPE_STRING:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_STRING>();
-      case JSVAL_TYPE_OBJECT:
-        return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_OBJECT>();
-      default:
-        MOZ_CRASH();
-    }
+    return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
 }
 
 // As above, except the specialization can reflect the unboxed type of two objects.
@@ -692,42 +396,7 @@ CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2)
     if (!HasAnyBoxedOrUnboxedDenseElements(obj1) || !HasAnyBoxedOrUnboxedDenseElements(obj2))
         return DenseElementResult::Incomplete;
 
-#define SPECIALIZE_OBJ2(TYPE)                                                     \
-    switch (GetBoxedOrUnboxedType(obj2)) {                                        \
-      case JSVAL_TYPE_MAGIC:                                                      \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_MAGIC>();   \
-      case JSVAL_TYPE_BOOLEAN:                                                    \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_BOOLEAN>(); \
-      case JSVAL_TYPE_INT32:                                                      \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_INT32>();   \
-      case JSVAL_TYPE_DOUBLE:                                                     \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_DOUBLE>();  \
-      case JSVAL_TYPE_STRING:                                                     \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_STRING>();  \
-      case JSVAL_TYPE_OBJECT:                                                     \
-        return f. DEPENDENT_TEMPLATE_HINT operator()<TYPE, JSVAL_TYPE_OBJECT>();  \
-      default:                                                                    \
-        MOZ_CRASH();                                                              \
-    }
-
-    switch (GetBoxedOrUnboxedType(obj1)) {
-      case JSVAL_TYPE_MAGIC:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_MAGIC)
-      case JSVAL_TYPE_BOOLEAN:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_BOOLEAN)
-      case JSVAL_TYPE_INT32:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_INT32)
-      case JSVAL_TYPE_DOUBLE:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_DOUBLE)
-      case JSVAL_TYPE_STRING:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_STRING)
-      case JSVAL_TYPE_OBJECT:
-        SPECIALIZE_OBJ2(JSVAL_TYPE_OBJECT)
-      default:
-        MOZ_CRASH();
-    }
-
-#undef SPECIALIZE_OBJ2
+    return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC, JSVAL_TYPE_MAGIC>();
 }
 
 #undef DEPENDENT_TEMPLATE_HINT
@@ -816,25 +485,6 @@ struct Signature ## Functor {                                           \
     }                                                                   \
 }
 
-DenseElementResult
-SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
-                                          uint32_t start, const Value* vp, uint32_t count,
-                                          ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
-
-DenseElementResult
-MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
-                                   uint32_t dstStart, uint32_t srcStart, uint32_t length);
-
-DenseElementResult
-CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
-                                   uint32_t dstStart, uint32_t srcStart, uint32_t length);
-
-void
-SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen);
-
-DenseElementResult
-EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count);
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h
diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp
index d7ad91de4..806a9db81 100644
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -417,8 +417,6 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
 
     RootedObjectGroup replacementGroup(cx);
 
-    const Class* clasp = layout.isArray() ? &ArrayObject::class_ : &PlainObject::class_;
-
     // Immediately clear any new script on the group. This is done by replacing
     // the existing new script with one for a replacement default new group.
     // This is done so that the size of the replacment group's objects is the
@@ -426,8 +424,6 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
     // slot accesses later on for sites that see converted objects from this
     // group and objects that were allocated using the replacement new group.
     if (layout.newScript()) {
-        MOZ_ASSERT(!layout.isArray());
-
         replacementGroup = ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto);
         if (!replacementGroup)
             return false;
@@ -453,15 +449,14 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
         RootedScript script(cx, layout.allocationScript());
         jsbytecode* pc = layout.allocationPc();
 
-        replacementGroup = ObjectGroupCompartment::makeGroup(cx, clasp, proto);
+        replacementGroup = ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto);
         if (!replacementGroup)
             return false;
 
         PlainObject* templateObject = &script->getObject(pc)->as<PlainObject>();
         replacementGroup->addDefiniteProperties(cx, templateObject->lastProperty());
 
-        JSProtoKey key = layout.isArray() ? JSProto_Array : JSProto_Object;
-        cx->compartment()->objectGroups.replaceAllocationSiteGroup(script, pc, key,
+        cx->compartment()->objectGroups.replaceAllocationSiteGroup(script, pc, JSProto_Object,
                                                                    replacementGroup);
 
         // Clear any baseline information at this opcode which might use the old group.
@@ -477,22 +472,12 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
         }
     }
 
-    size_t nfixed = layout.isArray() ? 0 : gc::GetGCKindSlots(layout.getAllocKind());
-
-    if (layout.isArray()) {
-        // The length shape to use for arrays is cached via a modified initial
-        // shape for array objects. Create an array now to make sure this entry
-        // is instantiated.
-        if (!NewDenseEmptyArray(cx))
-            return false;
-    }
+    size_t nfixed = gc::GetGCKindSlots(layout.getAllocKind());
 
-    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, proto, nfixed, 0));
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &PlainObject::class_, proto, nfixed, 0));
     if (!shape)
         return false;
 
-    MOZ_ASSERT_IF(layout.isArray(), !shape->isEmptyShape() && shape->slotSpan() == 0);
-
     // Add shapes for each property, if this is for a plain object.
     for (size_t i = 0; i < layout.properties().length(); i++) {
         const UnboxedLayout::Property& property = layout.properties()[i];
@@ -505,7 +490,7 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
     }
 
     ObjectGroup* nativeGroup =
-        ObjectGroupCompartment::makeGroup(cx, clasp, proto,
+        ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_, proto,
                                           group->flags() & OBJECT_FLAG_DYNAMIC_MASK);
     if (!nativeGroup)
         return false;
@@ -513,24 +498,19 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
     // No sense propagating if we don't know what we started with.
     if (!group->unknownProperties()) {
         // Propagate all property types from the old group to the new group.
-        if (layout.isArray()) {
-            if (!PropagatePropertyTypes(cx, JSID_VOID, group, nativeGroup))
+        for (size_t i = 0; i < layout.properties().length(); i++) {
+            const UnboxedLayout::Property& property = layout.properties()[i];
+            jsid id = NameToId(property.name);
+            if (!PropagatePropertyTypes(cx, id, group, nativeGroup))
                 return false;
-        } else {
-            for (size_t i = 0; i < layout.properties().length(); i++) {
-                const UnboxedLayout::Property& property = layout.properties()[i];
-                jsid id = NameToId(property.name);
-                if (!PropagatePropertyTypes(cx, id, group, nativeGroup))
-                    return false;
 
-                // If we are OOM we may not be able to propagate properties.
-                if (nativeGroup->unknownProperties())
-                    break;
+            // If we are OOM we may not be able to propagate properties.
+            if (nativeGroup->unknownProperties())
+                break;
 
-                HeapTypeSet* nativeProperty = nativeGroup->maybeGetProperty(id);
-                if (nativeProperty && nativeProperty->canSetDefinite(i))
-                    nativeProperty->setDefinite(i);
-            }
+            HeapTypeSet* nativeProperty = nativeGroup->maybeGetProperty(id);
+            if (nativeProperty && nativeProperty->canSetDefinite(i))
+                nativeProperty->setDefinite(i);
         }
     } else {
         // If we skip, though, the new group had better agree.
@@ -955,702 +935,6 @@ const Class UnboxedPlainObject::class_ = {
     &UnboxedPlainObjectObjectOps
 };
 
-/////////////////////////////////////////////////////////////////////
-// UnboxedArrayObject
-/////////////////////////////////////////////////////////////////////
-
-template <JSValueType Type>
-DenseElementResult
-AppendUnboxedDenseElements(UnboxedArrayObject* obj, uint32_t initlen,
-                           MutableHandle<GCVector<Value>> values)
-{
-    for (size_t i = 0; i < initlen; i++)
-        values.infallibleAppend(obj->getElementSpecific<Type>(i));
-    return DenseElementResult::Success;
-}
-
-DefineBoxedOrUnboxedFunctor3(AppendUnboxedDenseElements,
-                             UnboxedArrayObject*, uint32_t, MutableHandle<GCVector<Value>>);
-
-/* static */ bool
-UnboxedArrayObject::convertToNativeWithGroup(ExclusiveContext* cx, JSObject* obj,
-                                             ObjectGroup* group, Shape* shape)
-{
-    size_t length = obj->as<UnboxedArrayObject>().length();
-    size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
-
-    Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
-    if (!values.reserve(initlen))
-        return false;
-
-    AppendUnboxedDenseElementsFunctor functor(&obj->as<UnboxedArrayObject>(), initlen, &values);
-    DebugOnly<DenseElementResult> result = CallBoxedOrUnboxedSpecialization(functor, obj);
-    MOZ_ASSERT(result.value == DenseElementResult::Success);
-
-    obj->setGroup(group);
-
-    ArrayObject* aobj = &obj->as<ArrayObject>();
-    aobj->setLastPropertyMakeNative(cx, shape);
-
-    // Make sure there is at least one element, so that this array does not
-    // use emptyObjectElements / emptyObjectElementsShared.
-    if (!aobj->ensureElements(cx, Max<size_t>(initlen, 1)))
-        return false;
-
-    MOZ_ASSERT(!aobj->getDenseInitializedLength());
-    aobj->setDenseInitializedLength(initlen);
-    aobj->initDenseElements(0, values.begin(), initlen);
-    aobj->setLengthInt32(length);
-
-    return true;
-}
-
-/* static */ bool
-UnboxedArrayObject::convertToNative(JSContext* cx, JSObject* obj)
-{
-    const UnboxedLayout& layout = obj->as<UnboxedArrayObject>().layout();
-
-    if (!layout.nativeGroup()) {
-        if (!UnboxedLayout::makeNativeGroup(cx, obj->group()))
-            return false;
-    }
-
-    return convertToNativeWithGroup(cx, obj, layout.nativeGroup(), layout.nativeShape());
-}
-
-bool
-UnboxedArrayObject::convertInt32ToDouble(ExclusiveContext* cx, ObjectGroup* group)
-{
-    MOZ_ASSERT(elementType() == JSVAL_TYPE_INT32);
-    MOZ_ASSERT(group->unboxedLayout().elementType() == JSVAL_TYPE_DOUBLE);
-
-    Vector<int32_t> values(cx);
-    if (!values.reserve(initializedLength()))
-        return false;
-    for (size_t i = 0; i < initializedLength(); i++)
-        values.infallibleAppend(getElementSpecific<JSVAL_TYPE_INT32>(i).toInt32());
-
-    uint8_t* newElements;
-    if (hasInlineElements()) {
-        newElements = AllocateObjectBuffer<uint8_t>(cx, this, capacity() * sizeof(double));
-    } else {
-        newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
-                                                      capacity() * sizeof(int32_t),
-                                                      capacity() * sizeof(double));
-    }
-    if (!newElements)
-        return false;
-
-    setGroup(group);
-    elements_ = newElements;
-
-    for (size_t i = 0; i < initializedLength(); i++)
-        setElementNoTypeChangeSpecific<JSVAL_TYPE_DOUBLE>(i, DoubleValue(values[i]));
-
-    return true;
-}
-
-/* static */ UnboxedArrayObject*
-UnboxedArrayObject::create(ExclusiveContext* cx, HandleObjectGroup group, uint32_t length,
-                           NewObjectKind newKind, uint32_t maxLength)
-{
-    MOZ_ASSERT(length <= MaximumCapacity);
-
-    MOZ_ASSERT(group->clasp() == &class_);
-    uint32_t elementSize = UnboxedTypeSize(group->unboxedLayout().elementType());
-    uint32_t capacity = Min(length, maxLength);
-    uint32_t nbytes = offsetOfInlineElements() + elementSize * capacity;
-
-    UnboxedArrayObject* res;
-    if (nbytes <= JSObject::MAX_BYTE_SIZE) {
-        gc::AllocKind allocKind = gc::GetGCObjectKindForBytes(nbytes);
-
-        // If there was no provided length information, pick an allocation kind
-        // to accommodate small arrays (as is done for normal native arrays).
-        if (capacity == 0)
-            allocKind = gc::AllocKind::OBJECT8;
-
-        res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, allocKind, newKind);
-        if (!res)
-            return nullptr;
-        res->setInitializedLengthNoBarrier(0);
-        res->setInlineElements();
-
-        size_t actualCapacity = (GetGCKindBytes(allocKind) - offsetOfInlineElements()) / elementSize;
-        MOZ_ASSERT(actualCapacity >= capacity);
-        res->setCapacityIndex(exactCapacityIndex(actualCapacity));
-    } else {
-        res = NewObjectWithGroup<UnboxedArrayObject>(cx, group, gc::AllocKind::OBJECT0, newKind);
-        if (!res)
-            return nullptr;
-        res->setInitializedLengthNoBarrier(0);
-
-        uint32_t capacityIndex = (capacity == length)
-                                 ? CapacityMatchesLengthIndex
-                                 : chooseCapacityIndex(capacity, length);
-        uint32_t actualCapacity = computeCapacity(capacityIndex, length);
-
-        res->elements_ = AllocateObjectBuffer<uint8_t>(cx, res, actualCapacity * elementSize);
-        if (!res->elements_) {
-            // Make the object safe for GC.
-            res->setInlineElements();
-            return nullptr;
-        }
-
-        res->setCapacityIndex(capacityIndex);
-    }
-
-    res->setLength(cx, length);
-    return res;
-}
-
-bool
-UnboxedArrayObject::setElement(ExclusiveContext* cx, size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    uint8_t* p = elements() + index * elementSize();
-    return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ true);
-}
-
-bool
-UnboxedArrayObject::initElement(ExclusiveContext* cx, size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    uint8_t* p = elements() + index * elementSize();
-    return SetUnboxedValue(cx, this, JSID_VOID, p, elementType(), v, /* preBarrier = */ false);
-}
-
-void
-UnboxedArrayObject::initElementNoTypeChange(size_t index, const Value& v)
-{
-    MOZ_ASSERT(index < initializedLength());
-    uint8_t* p = elements() + index * elementSize();
-    if (UnboxedTypeNeedsPreBarrier(elementType()))
-        *reinterpret_cast<void**>(p) = nullptr;
-    SetUnboxedValueNoTypeChange(this, p, elementType(), v, /* preBarrier = */ false);
-}
-
-Value
-UnboxedArrayObject::getElement(size_t index)
-{
-    MOZ_ASSERT(index < initializedLength());
-    uint8_t* p = elements() + index * elementSize();
-    return GetUnboxedValue(p, elementType(), /* maybeUninitialized = */ false);
-}
-
-/* static */ void
-UnboxedArrayObject::trace(JSTracer* trc, JSObject* obj)
-{
-    JSValueType type = obj->as<UnboxedArrayObject>().elementType();
-    if (!UnboxedTypeNeedsPreBarrier(type))
-        return;
-
-    MOZ_ASSERT(obj->as<UnboxedArrayObject>().elementSize() == sizeof(uintptr_t));
-    size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
-    void** elements = reinterpret_cast<void**>(obj->as<UnboxedArrayObject>().elements());
-
-    switch (type) {
-      case JSVAL_TYPE_OBJECT:
-        for (size_t i = 0; i < initlen; i++) {
-            GCPtrObject* heap = reinterpret_cast<GCPtrObject*>(elements + i);
-            TraceNullableEdge(trc, heap, "unboxed_object");
-        }
-        break;
-
-      case JSVAL_TYPE_STRING:
-        for (size_t i = 0; i < initlen; i++) {
-            GCPtrString* heap = reinterpret_cast<GCPtrString*>(elements + i);
-            TraceEdge(trc, heap, "unboxed_string");
-        }
-        break;
-
-      default:
-        MOZ_CRASH();
-    }
-}
-
-/* static */ void
-UnboxedArrayObject::objectMoved(JSObject* obj, const JSObject* old)
-{
-    UnboxedArrayObject& dst = obj->as<UnboxedArrayObject>();
-    const UnboxedArrayObject& src = old->as<UnboxedArrayObject>();
-
-    // Fix up possible inline data pointer.
-    if (src.hasInlineElements())
-        dst.setInlineElements();
-}
-
-/* static */ void
-UnboxedArrayObject::finalize(FreeOp* fop, JSObject* obj)
-{
-    MOZ_ASSERT(!IsInsideNursery(obj));
-    if (!obj->as<UnboxedArrayObject>().hasInlineElements())
-        js_free(obj->as<UnboxedArrayObject>().elements());
-}
-
-/* static */ size_t
-UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
-                                             gc::AllocKind allocKind)
-{
-    UnboxedArrayObject* ndst = &dst->as<UnboxedArrayObject>();
-    UnboxedArrayObject* nsrc = &src->as<UnboxedArrayObject>();
-    MOZ_ASSERT(ndst->elements() == nsrc->elements());
-
-    Nursery& nursery = trc->runtime()->gc.nursery;
-
-    if (!nursery.isInside(nsrc->elements())) {
-        nursery.removeMallocedBuffer(nsrc->elements());
-        return 0;
-    }
-
-    // Determine if we can use inline data for the target array. If this is
-    // possible, the nursery will have picked an allocation size that is large
-    // enough.
-    size_t nbytes = nsrc->capacity() * nsrc->elementSize();
-    if (offsetOfInlineElements() + nbytes <= GetGCKindBytes(allocKind)) {
-        ndst->setInlineElements();
-    } else {
-        MOZ_ASSERT(allocKind == gc::AllocKind::OBJECT0);
-
-        AutoEnterOOMUnsafeRegion oomUnsafe;
-        uint8_t* data = nsrc->zone()->pod_malloc<uint8_t>(nbytes);
-        if (!data)
-            oomUnsafe.crash("Failed to allocate unboxed array elements while tenuring.");
-        ndst->elements_ = data;
-    }
-
-    PodCopy(ndst->elements(), nsrc->elements(), nsrc->initializedLength() * nsrc->elementSize());
-
-    // Set a forwarding pointer for the element buffers in case they were
-    // preserved on the stack by Ion.
-    bool direct = nsrc->capacity() * nsrc->elementSize() >= sizeof(uintptr_t);
-    nursery.maybeSetForwardingPointer(trc, nsrc->elements(), ndst->elements(), direct);
-
-    return ndst->hasInlineElements() ? 0 : nbytes;
-}
-
-// Possible capacities for unboxed arrays. Some of these capacities might seem
-// a little weird, but were chosen to allow the inline data of objects of each
-// size to be fully utilized for arrays of the various types on both 32 bit and
-// 64 bit platforms.
-//
-// To find the possible inline capacities, the following script was used:
-//
-// var fixedSlotCapacities = [0, 2, 4, 8, 12, 16];
-// var dataSizes = [1, 4, 8];
-// var header32 = 4 * 2 + 4 * 2;
-// var header64 = 8 * 2 + 4 * 2;
-//
-// for (var i = 0; i < fixedSlotCapacities.length; i++) {
-//    var nfixed = fixedSlotCapacities[i];
-//    var size32 = 4 * 4 + 8 * nfixed - header32;
-//    var size64 = 8 * 4 + 8 * nfixed - header64;
-//    for (var j = 0; j < dataSizes.length; j++) {
-//        print(size32 / dataSizes[j]);
-//        print(size64 / dataSizes[j]);
-//    }
-// }
-//
-/* static */ const uint32_t
-UnboxedArrayObject::CapacityArray[] = {
-    UINT32_MAX, // For CapacityMatchesLengthIndex.
-    0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 16, 17, 18, 24, 26, 32, 34, 40, 64, 72, 96, 104, 128, 136,
-    256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288,
-    1048576, 2097152, 3145728, 4194304, 5242880, 6291456, 7340032, 8388608, 9437184, 11534336,
-    13631488, 15728640, 17825792, 20971520, 24117248, 27262976, 31457280, 35651584, 40894464,
-    46137344, 52428800, 59768832, MaximumCapacity
-};
-
-static const uint32_t
-Pow2CapacityIndexes[] = {
-    2,  // 1
-    3,  // 2
-    5,  // 4
-    8,  // 8
-    13, // 16
-    18, // 32
-    21, // 64
-    25, // 128
-    27, // 256
-    28, // 512
-    29, // 1024
-    30, // 2048
-    31, // 4096
-    32, // 8192
-    33, // 16384
-    34, // 32768
-    35, // 65536
-    36, // 131072
-    37, // 262144
-    38, // 524288
-    39  // 1048576
-};
-
-static const uint32_t MebiCapacityIndex = 39;
-
-/* static */ uint32_t
-UnboxedArrayObject::chooseCapacityIndex(uint32_t capacity, uint32_t length)
-{
-    // Note: the structure and behavior of this method follow along with
-    // NativeObject::goodAllocated. Changes to the allocation strategy in one
-    // should generally be matched by the other.
-
-    // Make sure we have enough space to store all possible values for the capacity index.
-    // This ought to be a static_assert, but MSVC doesn't like that.
-    MOZ_ASSERT(mozilla::ArrayLength(CapacityArray) - 1 <= (CapacityMask >> CapacityShift));
-
-    // The caller should have ensured the capacity is possible for an unboxed array.
-    MOZ_ASSERT(capacity <= MaximumCapacity);
-
-    static const uint32_t Mebi = 1024 * 1024;
-
-    if (capacity <= Mebi) {
-        capacity = mozilla::RoundUpPow2(capacity);
-
-        // When the required capacity is close to the array length, then round
-        // up to the array length itself, as for NativeObject.
-        if (length >= capacity && capacity > (length / 3) * 2)
-            return CapacityMatchesLengthIndex;
-
-        if (capacity < MinimumDynamicCapacity)
-            capacity = MinimumDynamicCapacity;
-
-        uint32_t bit = mozilla::FloorLog2Size(capacity);
-        MOZ_ASSERT(capacity == uint32_t(1 << bit));
-        MOZ_ASSERT(bit <= 20);
-        MOZ_ASSERT(mozilla::ArrayLength(Pow2CapacityIndexes) == 21);
-
-        uint32_t index = Pow2CapacityIndexes[bit];
-        MOZ_ASSERT(CapacityArray[index] == capacity);
-
-        return index;
-    }
-
-    MOZ_ASSERT(CapacityArray[MebiCapacityIndex] == Mebi);
-
-    for (uint32_t i = MebiCapacityIndex + 1;; i++) {
-        if (CapacityArray[i] >= capacity)
-            return i;
-    }
-
-    MOZ_CRASH("Invalid capacity");
-}
-
-/* static */ uint32_t
-UnboxedArrayObject::exactCapacityIndex(uint32_t capacity)
-{
-    for (size_t i = CapacityMatchesLengthIndex + 1; i < ArrayLength(CapacityArray); i++) {
-        if (CapacityArray[i] == capacity)
-            return i;
-    }
-    MOZ_CRASH();
-}
-
-bool
-UnboxedArrayObject::growElements(ExclusiveContext* cx, size_t cap)
-{
-    // The caller should have checked if this capacity is possible for an
-    // unboxed array, so the only way this call can fail is from OOM.
-    MOZ_ASSERT(cap <= MaximumCapacity);
-
-    uint32_t oldCapacity = capacity();
-    uint32_t newCapacityIndex = chooseCapacityIndex(cap, length());
-    uint32_t newCapacity = computeCapacity(newCapacityIndex, length());
-
-    MOZ_ASSERT(oldCapacity < cap);
-    MOZ_ASSERT(cap <= newCapacity);
-
-    // The allocation size computation below cannot have integer overflows.
-    JS_STATIC_ASSERT(MaximumCapacity < UINT32_MAX / sizeof(double));
-
-    uint8_t* newElements;
-    if (hasInlineElements()) {
-        newElements = AllocateObjectBuffer<uint8_t>(cx, this, newCapacity * elementSize());
-        if (!newElements)
-            return false;
-        js_memcpy(newElements, elements(), initializedLength() * elementSize());
-    } else {
-        newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
-                                                      oldCapacity * elementSize(),
-                                                      newCapacity * elementSize());
-        if (!newElements)
-            return false;
-    }
-
-    elements_ = newElements;
-    setCapacityIndex(newCapacityIndex);
-
-    return true;
-}
-
-void
-UnboxedArrayObject::shrinkElements(ExclusiveContext* cx, size_t cap)
-{
-    if (hasInlineElements())
-        return;
-
-    uint32_t oldCapacity = capacity();
-    uint32_t newCapacityIndex = chooseCapacityIndex(cap, 0);
-    uint32_t newCapacity = computeCapacity(newCapacityIndex, 0);
-
-    MOZ_ASSERT(cap < oldCapacity);
-    MOZ_ASSERT(cap <= newCapacity);
-
-    if (newCapacity >= oldCapacity)
-        return;
-
-    uint8_t* newElements = ReallocateObjectBuffer<uint8_t>(cx, this, elements(),
-                                                           oldCapacity * elementSize(),
-                                                           newCapacity * elementSize());
-    if (!newElements)
-        return;
-
-    elements_ = newElements;
-    setCapacityIndex(newCapacityIndex);
-}
-
-bool
-UnboxedArrayObject::containsProperty(ExclusiveContext* cx, jsid id)
-{
-    if (JSID_IS_INT(id) && uint32_t(JSID_TO_INT(id)) < initializedLength())
-        return true;
-    if (JSID_IS_ATOM(id) && JSID_TO_ATOM(id) == cx->names().length)
-        return true;
-    return false;
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
-                                       HandleId id, MutableHandleObject objp,
-                                       MutableHandleShape propp)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        MarkNonNativePropertyFound<CanGC>(propp);
-        objp.set(obj);
-        return true;
-    }
-
-    RootedObject proto(cx, obj->staticPrototype());
-    if (!proto) {
-        objp.set(nullptr);
-        propp.set(nullptr);
-        return true;
-    }
-
-    return LookupProperty(cx, proto, id, objp, propp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
-                                       Handle<PropertyDescriptor> desc,
-                                       ObjectOpResult& result)
-{
-    if (JSID_IS_INT(id) && !desc.getter() && !desc.setter() && desc.attributes() == JSPROP_ENUMERATE) {
-        UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
-
-        uint32_t index = JSID_TO_INT(id);
-        if (index < nobj->initializedLength()) {
-            if (nobj->setElement(cx, index, desc.value()))
-                return result.succeed();
-        } else if (index == nobj->initializedLength() && index < MaximumCapacity) {
-            if (nobj->initializedLength() == nobj->capacity()) {
-                if (!nobj->growElements(cx, index + 1))
-                    return false;
-            }
-            nobj->setInitializedLength(index + 1);
-            if (nobj->initElement(cx, index, desc.value())) {
-                if (nobj->length() <= index)
-                    nobj->setLengthInt32(index + 1);
-                return result.succeed();
-            }
-            nobj->setInitializedLengthNoBarrier(index);
-        }
-    }
-
-    if (!convertToNative(cx, obj))
-        return false;
-
-    return DefineProperty(cx, obj, id, desc, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        *foundp = true;
-        return true;
-    }
-
-    RootedObject proto(cx, obj->staticPrototype());
-    if (!proto) {
-        *foundp = false;
-        return true;
-    }
-
-    return HasProperty(cx, proto, id, foundp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
-                                    HandleId id, MutableHandleValue vp)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        if (JSID_IS_INT(id))
-            vp.set(obj->as<UnboxedArrayObject>().getElement(JSID_TO_INT(id)));
-        else
-            vp.set(Int32Value(obj->as<UnboxedArrayObject>().length()));
-        return true;
-    }
-
-    RootedObject proto(cx, obj->staticPrototype());
-    if (!proto) {
-        vp.setUndefined();
-        return true;
-    }
-
-    return GetProperty(cx, proto, receiver, id, vp);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
-                                    HandleValue receiver, ObjectOpResult& result)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        if (receiver.isObject() && obj == &receiver.toObject()) {
-            if (JSID_IS_INT(id)) {
-                if (obj->as<UnboxedArrayObject>().setElement(cx, JSID_TO_INT(id), v))
-                    return result.succeed();
-            } else {
-                uint32_t len;
-                if (!CanonicalizeArrayLengthValue(cx, v, &len))
-                    return false;
-                UnboxedArrayObject* nobj = &obj->as<UnboxedArrayObject>();
-                if (len < nobj->initializedLength()) {
-                    nobj->setInitializedLength(len);
-                    nobj->shrinkElements(cx, len);
-                }
-                nobj->setLength(cx, len);
-                return result.succeed();
-            }
-
-            if (!convertToNative(cx, obj))
-                return false;
-            return SetProperty(cx, obj, id, v, receiver, result);
-        }
-
-        return SetPropertyByDefining(cx, id, v, receiver, result);
-    }
-
-    return SetPropertyOnProto(cx, obj, id, v, receiver, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
-                                                 MutableHandle<PropertyDescriptor> desc)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        if (JSID_IS_INT(id)) {
-            desc.value().set(obj->as<UnboxedArrayObject>().getElement(JSID_TO_INT(id)));
-            desc.setAttributes(JSPROP_ENUMERATE);
-        } else {
-            desc.value().set(Int32Value(obj->as<UnboxedArrayObject>().length()));
-            desc.setAttributes(JSPROP_PERMANENT);
-        }
-        desc.object().set(obj);
-        return true;
-    }
-
-    desc.object().set(nullptr);
-    return true;
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
-                                       ObjectOpResult& result)
-{
-    if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
-        size_t initlen = obj->as<UnboxedArrayObject>().initializedLength();
-        if (JSID_IS_INT(id) && JSID_TO_INT(id) == int32_t(initlen - 1)) {
-            obj->as<UnboxedArrayObject>().setInitializedLength(initlen - 1);
-            obj->as<UnboxedArrayObject>().shrinkElements(cx, initlen - 1);
-            return result.succeed();
-        }
-    }
-
-    if (!convertToNative(cx, obj))
-        return false;
-    return DeleteProperty(cx, obj, id, result);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable)
-{
-    if (!convertToNative(cx, obj))
-        return false;
-    return WatchProperty(cx, obj, id, callable);
-}
-
-/* static */ bool
-UnboxedArrayObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
-                                  bool enumerableOnly)
-{
-    for (size_t i = 0; i < obj->as<UnboxedArrayObject>().initializedLength(); i++) {
-        if (!properties.append(INT_TO_JSID(i)))
-            return false;
-    }
-
-    if (!enumerableOnly && !properties.append(NameToId(cx->names().length)))
-        return false;
-
-    return true;
-}
-
-static const ClassOps UnboxedArrayObjectClassOps = {
-    nullptr,        /* addProperty */
-    nullptr,        /* delProperty */
-    nullptr,        /* getProperty */
-    nullptr,        /* setProperty */
-    nullptr,        /* enumerate   */
-    nullptr,        /* resolve     */
-    nullptr,        /* mayResolve  */
-    UnboxedArrayObject::finalize,
-    nullptr,        /* call        */
-    nullptr,        /* hasInstance */
-    nullptr,        /* construct   */
-    UnboxedArrayObject::trace,
-};
-
-static const ClassExtension UnboxedArrayObjectClassExtension = {
-    nullptr,    /* weakmapKeyDelegateOp */
-    UnboxedArrayObject::objectMoved
-};
-
-static const ObjectOps UnboxedArrayObjectObjectOps = {
-    UnboxedArrayObject::obj_lookupProperty,
-    UnboxedArrayObject::obj_defineProperty,
-    UnboxedArrayObject::obj_hasProperty,
-    UnboxedArrayObject::obj_getProperty,
-    UnboxedArrayObject::obj_setProperty,
-    UnboxedArrayObject::obj_getOwnPropertyDescriptor,
-    UnboxedArrayObject::obj_deleteProperty,
-    UnboxedArrayObject::obj_watch,
-    nullptr,   /* No unwatch needed, as watch() converts the object to native */
-    nullptr,   /* getElements */
-    UnboxedArrayObject::obj_enumerate,
-    nullptr    /* funToString */
-};
-
-const Class UnboxedArrayObject::class_ = {
-    "Array",
-    Class::NON_NATIVE |
-    JSCLASS_SKIP_NURSERY_FINALIZE |
-    JSCLASS_BACKGROUND_FINALIZE,
-    &UnboxedArrayObjectClassOps,
-    JS_NULL_CLASS_SPEC,
-    &UnboxedArrayObjectClassExtension,
-    &UnboxedArrayObjectObjectOps
-};
-
 /////////////////////////////////////////////////////////////////////
 // API
 /////////////////////////////////////////////////////////////////////
@@ -1661,31 +945,6 @@ NextValue(Handle<GCVector<Value>> values, size_t* valueCursor)
     return values[(*valueCursor)++];
 }
 
-void
-UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
-                                     Handle<GCVector<Value>> values, size_t* valueCursor)
-{
-    MOZ_ASSERT(CapacityArray[1] == 0);
-    setCapacityIndex(1);
-    setInitializedLengthNoBarrier(0);
-    setInlineElements();
-
-    setLength(cx, NextValue(values, valueCursor).toInt32());
-
-    int32_t initlen = NextValue(values, valueCursor).toInt32();
-    if (!initlen)
-        return;
-
-    AutoEnterOOMUnsafeRegion oomUnsafe;
-    if (!growElements(cx, initlen))
-        oomUnsafe.crash("UnboxedArrayObject::fillAfterConvert");
-
-    setInitializedLength(initlen);
-
-    for (size_t i = 0; i < size_t(initlen); i++)
-        JS_ALWAYS_TRUE(initElement(cx, i, NextValue(values, valueCursor)));
-}
-
 void
 UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
                                      Handle<GCVector<Value>> values, size_t* valueCursor)
@@ -1695,58 +954,3 @@ UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
     for (size_t i = 0; i < layout().properties().length(); i++)
         JS_ALWAYS_TRUE(setValue(cx, layout().properties()[i], NextValue(values, valueCursor)));
 }
-
-DefineBoxedOrUnboxedFunctor6(SetOrExtendBoxedOrUnboxedDenseElements,
-                             ExclusiveContext*, JSObject*, uint32_t, const Value*, uint32_t,
-                             ShouldUpdateTypes);
-
-DenseElementResult
-js::SetOrExtendAnyBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
-                                              uint32_t start, const Value* vp, uint32_t count,
-                                              ShouldUpdateTypes updateTypes)
-{
-    SetOrExtendBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, start, vp, count, updateTypes);
-    return CallBoxedOrUnboxedSpecialization(functor, obj);
-};
-
-DefineBoxedOrUnboxedFunctor5(MoveBoxedOrUnboxedDenseElements,
-                             JSContext*, JSObject*, uint32_t, uint32_t, uint32_t);
-
-DenseElementResult
-js::MoveAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj,
-                                       uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
-    MoveBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, dstStart, srcStart, length);
-    return CallBoxedOrUnboxedSpecialization(functor, obj);
-}
-
-DefineBoxedOrUnboxedFunctorPair6(CopyBoxedOrUnboxedDenseElements,
-                                 JSContext*, JSObject*, JSObject*, uint32_t, uint32_t, uint32_t);
-
-DenseElementResult
-js::CopyAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
-                                       uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
-    CopyBoxedOrUnboxedDenseElementsFunctor functor(cx, dst, src, dstStart, srcStart, length);
-    return CallBoxedOrUnboxedSpecialization(functor, dst, src);
-}
-
-DefineBoxedOrUnboxedFunctor3(SetBoxedOrUnboxedInitializedLength,
-                             JSContext*, JSObject*, size_t);
-
-void
-js::SetAnyBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
-{
-    SetBoxedOrUnboxedInitializedLengthFunctor functor(cx, obj, initlen);
-    JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
-}
-
-DefineBoxedOrUnboxedFunctor3(EnsureBoxedOrUnboxedDenseElements,
-                             JSContext*, JSObject*, size_t);
-
-DenseElementResult
-js::EnsureAnyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t initlen)
-{
-    EnsureBoxedOrUnboxedDenseElementsFunctor functor(cx, obj, initlen);
-    return CallBoxedOrUnboxedSpecialization(functor, obj);
-}
diff --git a/js/src/vm/UnboxedObject.h b/js/src/vm/UnboxedObject.h
index 779dd14c7..ba66434bc 100644
--- a/js/src/vm/UnboxedObject.h
+++ b/js/src/vm/UnboxedObject.h
@@ -96,17 +96,11 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
     // from an array of values.
     GCPtrJitCode constructorCode_;
 
-    // The following members are only used for unboxed arrays.
-
-    // The type of array elements.
-    JSValueType elementType_;
-
   public:
     UnboxedLayout()
       : nativeGroup_(nullptr), nativeShape_(nullptr),
         allocationScript_(nullptr), allocationPc_(nullptr), replacementGroup_(nullptr),
-        size_(0), newScript_(nullptr), traceList_(nullptr), constructorCode_(nullptr),
-        elementType_(JSVAL_TYPE_MAGIC)
+        size_(0), newScript_(nullptr), traceList_(nullptr), constructorCode_(nullptr)
     {}
 
     bool initProperties(const PropertyVector& properties, size_t size) {
@@ -114,10 +108,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
         return properties_.appendAll(properties);
     }
 
-    void initArray(JSValueType elementType) {
-        elementType_ = elementType;
-    }
-
     ~UnboxedLayout() {
         if (newScript_)
             newScript_->clear();
@@ -130,10 +120,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
         constructorCode_.init(nullptr);
     }
 
-    bool isArray() const {
-        return elementType_ != JSVAL_TYPE_MAGIC;
-    }
-
     void detachFromCompartment();
 
     const PropertyVector& properties() const {
@@ -201,10 +187,6 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
         constructorCode_ = code;
     }
 
-    JSValueType elementType() const {
-        return elementType_;
-    }
-
     inline gc::AllocKind getAllocKind() const;
 
     void trace(JSTracer* trc);
@@ -324,193 +306,6 @@ UnboxedLayout::getAllocKind() const
     return gc::GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + size());
 }
 
-// Class for an array object using an unboxed representation.
-class UnboxedArrayObject : public JSObject
-{
-    // Elements pointer for the object.
-    uint8_t* elements_;
-
-    // The nominal array length. This always fits in an int32_t.
-    uint32_t length_;
-
-    // Value indicating the allocated capacity and initialized length of the
-    // array. The top CapacityBits bits are an index into CapacityArray, which
-    // indicates the elements capacity. The low InitializedLengthBits store the
-    // initialized length of the array.
-    uint32_t capacityIndexAndInitializedLength_;
-
-    // If the elements are inline, they will point here.
-    uint8_t inlineElements_[1];
-
-  public:
-    static const uint32_t CapacityBits = 6;
-    static const uint32_t CapacityShift = 26;
-
-    static const uint32_t CapacityMask = uint32_t(-1) << CapacityShift;
-    static const uint32_t InitializedLengthMask = (1 << CapacityShift) - 1;
-
-    static const uint32_t MaximumCapacity = InitializedLengthMask;
-    static const uint32_t MinimumDynamicCapacity = 8;
-
-    static const uint32_t CapacityArray[];
-
-    // Capacity index which indicates the array's length is also its capacity.
-    static const uint32_t CapacityMatchesLengthIndex = 0;
-
-  private:
-    static inline uint32_t computeCapacity(uint32_t index, uint32_t length) {
-        if (index == CapacityMatchesLengthIndex)
-            return length;
-        return CapacityArray[index];
-    }
-
-    static uint32_t chooseCapacityIndex(uint32_t capacity, uint32_t length);
-    static uint32_t exactCapacityIndex(uint32_t capacity);
-
-  public:
-    static const Class class_;
-
-    static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
-                                   HandleId id, MutableHandleObject objp,
-                                   MutableHandleShape propp);
-
-    static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
-                                   Handle<PropertyDescriptor> desc,
-                                   ObjectOpResult& result);
-
-    static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
-
-    static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
-                                HandleId id, MutableHandleValue vp);
-
-    static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
-                                HandleValue receiver, ObjectOpResult& result);
-
-    static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
-                                             MutableHandle<PropertyDescriptor> desc);
-
-    static bool obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
-                                   ObjectOpResult& result);
-
-    static bool obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
-                              bool enumerableOnly);
-    static bool obj_watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable);
-
-    inline const UnboxedLayout& layout() const;
-
-    const UnboxedLayout& layoutDontCheckGeneration() const {
-        return group()->unboxedLayoutDontCheckGeneration();
-    }
-
-    JSValueType elementType() const {
-        return layoutDontCheckGeneration().elementType();
-    }
-
-    uint32_t elementSize() const {
-        return UnboxedTypeSize(elementType());
-    }
-
-    static bool convertToNative(JSContext* cx, JSObject* obj);
-    static UnboxedArrayObject* create(ExclusiveContext* cx, HandleObjectGroup group,
-                                      uint32_t length, NewObjectKind newKind,
-                                      uint32_t maxLength = MaximumCapacity);
-
-    static bool convertToNativeWithGroup(ExclusiveContext* cx, JSObject* obj,
-                                         ObjectGroup* group, Shape* shape);
-    bool convertInt32ToDouble(ExclusiveContext* cx, ObjectGroup* group);
-
-    void fillAfterConvert(ExclusiveContext* cx,
-                          Handle<GCVector<Value>> values, size_t* valueCursor);
-
-    static void trace(JSTracer* trc, JSObject* object);
-    static void objectMoved(JSObject* obj, const JSObject* old);
-    static void finalize(FreeOp* fop, JSObject* obj);
-
-    static size_t objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src,
-                                           gc::AllocKind allocKind);
-
-    uint8_t* elements() {
-        return elements_;
-    }
-
-    bool hasInlineElements() const {
-        return elements_ == &inlineElements_[0];
-    }
-
-    uint32_t length() const {
-        return length_;
-    }
-
-    uint32_t initializedLength() const {
-        return capacityIndexAndInitializedLength_ & InitializedLengthMask;
-    }
-
-    uint32_t capacityIndex() const {
-        return (capacityIndexAndInitializedLength_ & CapacityMask) >> CapacityShift;
-    }
-
-    uint32_t capacity() const {
-        return computeCapacity(capacityIndex(), length());
-    }
-
-    bool containsProperty(ExclusiveContext* cx, jsid id);
-
-    bool setElement(ExclusiveContext* cx, size_t index, const Value& v);
-    bool initElement(ExclusiveContext* cx, size_t index, const Value& v);
-    void initElementNoTypeChange(size_t index, const Value& v);
-    Value getElement(size_t index);
-
-    template <JSValueType Type> inline bool setElementSpecific(ExclusiveContext* cx, size_t index,
-                                                               const Value& v);
-    template <JSValueType Type> inline void setElementNoTypeChangeSpecific(size_t index, const Value& v);
-    template <JSValueType Type> inline bool initElementSpecific(ExclusiveContext* cx, size_t index,
-                                                                const Value& v);
-    template <JSValueType Type> inline void initElementNoTypeChangeSpecific(size_t index, const Value& v);
-    template <JSValueType Type> inline Value getElementSpecific(size_t index);
-    template <JSValueType Type> inline void triggerPreBarrier(size_t index);
-
-    bool growElements(ExclusiveContext* cx, size_t cap);
-    void shrinkElements(ExclusiveContext* cx, size_t cap);
-
-    static uint32_t offsetOfElements() {
-        return offsetof(UnboxedArrayObject, elements_);
-    }
-    static uint32_t offsetOfLength() {
-        return offsetof(UnboxedArrayObject, length_);
-    }
-    static uint32_t offsetOfCapacityIndexAndInitializedLength() {
-        return offsetof(UnboxedArrayObject, capacityIndexAndInitializedLength_);
-    }
-    static uint32_t offsetOfInlineElements() {
-        return offsetof(UnboxedArrayObject, inlineElements_);
-    }
-
-    void setLengthInt32(uint32_t length) {
-        MOZ_ASSERT(length <= INT32_MAX);
-        length_ = length;
-    }
-
-    inline void setLength(ExclusiveContext* cx, uint32_t len);
-    inline void setInitializedLength(uint32_t initlen);
-
-    inline void setInitializedLengthNoBarrier(uint32_t initlen) {
-        MOZ_ASSERT(initlen <= InitializedLengthMask);
-        capacityIndexAndInitializedLength_ =
-            (capacityIndexAndInitializedLength_ & CapacityMask) | initlen;
-    }
-
-  private:
-    void setInlineElements() {
-        elements_ = &inlineElements_[0];
-    }
-
-    void setCapacityIndex(uint32_t index) {
-        MOZ_ASSERT(index <= (CapacityMask >> CapacityShift));
-        capacityIndexAndInitializedLength_ =
-            (index << CapacityShift) | initializedLength();
-    }
-};
-
 } // namespace js
 
 namespace JS {
-- 
cgit v1.2.3


From e34920575d6dac353cb3d8a5d1b9c11ae05c5a8c Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Mon, 10 Jun 2019 16:49:47 +0000
Subject: Inline combined methods for NativeObject and UnboxedArrayObject
 accesses.

---
 js/src/jit/BaselineIC.cpp        |  34 +++++-----
 js/src/jit/BaselineIC.h          |  12 ++--
 js/src/jit/BaselineInspector.cpp |   2 +-
 js/src/jit/BaselineInspector.h   |   2 +-
 js/src/jit/MCallOptimize.cpp     |  10 +--
 js/src/jit/VMFunctions.cpp       |   2 +-
 js/src/jsarray.cpp               | 117 ++++++++++++++++++---------------
 js/src/jsobj.cpp                 |  22 ++++---
 js/src/vm/UnboxedObject-inl.h    | 138 +++------------------------------------
 9 files changed, 115 insertions(+), 224 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 1d230e083..28e263ac7 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -2373,8 +2373,8 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index,
                                       Shape* oldShape, uint32_t oldCapacity, uint32_t oldInitLength,
                                       bool* isAddingCaseOut, size_t* protoDepthOut)
 {
-    uint32_t initLength = GetAnyBoxedOrUnboxedInitializedLength(obj);
-    uint32_t capacity = GetAnyBoxedOrUnboxedCapacity(obj);
+    uint32_t initLength = obj->as<NativeObject>().getDenseInitializedLength();
+    uint32_t capacity = obj->as<NativeObject>().getDenseCapacity();
 
     *isAddingCaseOut = false;
     *protoDepthOut = 0;
@@ -2464,8 +2464,8 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
     uint32_t oldCapacity = 0;
     uint32_t oldInitLength = 0;
     if (index.isInt32() && index.toInt32() >= 0) {
-        oldCapacity = GetAnyBoxedOrUnboxedCapacity(obj);
-        oldInitLength = GetAnyBoxedOrUnboxedInitializedLength(obj);
+        oldCapacity = obj->as<NativeObject>().getDenseCapacity();
+        oldInitLength = obj->as<NativeObject>().getDenseInitializedLength();
     }
 
     if (op == JSOP_INITELEM || op == JSOP_INITHIDDENELEM) {
@@ -5762,14 +5762,14 @@ TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script, jsb
 }
 
 static bool
-CopyArray(JSContext* cx, HandleObject obj, MutableHandleValue result)
+CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
 {
-    uint32_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
-    JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, obj, length, TenuredObject);
+    uint32_t length = arr->length();
+    JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
     if (!nobj)
         return false;
     EnsureArrayGroupAnalyzed(cx, nobj);
-    CopyBoxedOrUnboxedDenseElements(cx, nobj, obj, 0, 0, length);
+    CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length);
 
     result.setObject(*nobj);
     return true;
@@ -5801,26 +5801,22 @@ TryAttachStringSplit(JSContext* cx, ICCall_Fallback* stub, HandleScript script,
     RootedValue arr(cx);
 
     // Copy the array before storing in stub.
-    if (!CopyArray(cx, obj, &arr))
+    if (!CopyArray(cx, obj.as<ArrayObject>(), &arr))
         return false;
 
     // Atomize all elements of the array.
-    RootedObject arrObj(cx, &arr.toObject());
-    uint32_t initLength = GetAnyBoxedOrUnboxedArrayLength(arrObj);
+    RootedArrayObject arrObj(cx, &arr.toObject().as<ArrayObject>());
+    uint32_t initLength = arrObj->length();
     for (uint32_t i = 0; i < initLength; i++) {
-        JSAtom* str = js::AtomizeString(cx, GetAnyBoxedOrUnboxedDenseElement(arrObj, i).toString());
+        JSAtom* str = js::AtomizeString(cx, arrObj->getDenseElement(i).toString());
         if (!str)
             return false;
 
-        if (!SetAnyBoxedOrUnboxedDenseElement(cx, arrObj, i, StringValue(str))) {
-            // The value could not be stored to an unboxed dense element.
-            return true;
-        }
+        arrObj->setDenseElementWithType(cx, i, StringValue(str));
     }
 
     ICCall_StringSplit::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
-                                          script->pcToOffset(pc), str, sep,
-                                          arr);
+                                          script->pcToOffset(pc), str, sep, arrObj);
     ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
     if (!newStub)
         return false;
@@ -6705,7 +6701,7 @@ ICCallScriptedCompiler::generateStubCode(MacroAssembler& masm)
     return true;
 }
 
-typedef bool (*CopyArrayFn)(JSContext*, HandleObject, MutableHandleValue);
+typedef bool (*CopyArrayFn)(JSContext*, HandleArrayObject, MutableHandleValue);
 static const VMFunction CopyArrayInfo = FunctionInfo<CopyArrayFn>(CopyArray, "CopyArray");
 
 bool
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index afbea3b69..901fca9cc 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -2818,10 +2818,10 @@ class ICCall_StringSplit : public ICMonitoredStub
     uint32_t pcOffset_;
     GCPtrString expectedStr_;
     GCPtrString expectedSep_;
-    GCPtrObject templateObject_;
+    GCPtrArrayObject templateObject_;
 
     ICCall_StringSplit(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset, JSString* str,
-                       JSString* sep, JSObject* templateObject)
+                       JSString* sep, ArrayObject* templateObject)
       : ICMonitoredStub(ICStub::Call_StringSplit, stubCode, firstMonitorStub),
         pcOffset_(pcOffset), expectedStr_(str), expectedSep_(sep),
         templateObject_(templateObject)
@@ -2848,7 +2848,7 @@ class ICCall_StringSplit : public ICMonitoredStub
         return expectedSep_;
     }
 
-    GCPtrObject& templateObject() {
+    GCPtrArrayObject& templateObject() {
         return templateObject_;
     }
 
@@ -2858,7 +2858,7 @@ class ICCall_StringSplit : public ICMonitoredStub
         uint32_t pcOffset_;
         RootedString expectedStr_;
         RootedString expectedSep_;
-        RootedObject templateObject_;
+        RootedArrayObject templateObject_;
 
         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
 
@@ -2869,13 +2869,13 @@ class ICCall_StringSplit : public ICMonitoredStub
 
       public:
         Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset, HandleString str,
-                 HandleString sep, HandleValue templateObject)
+                 HandleString sep, HandleArrayObject templateObject)
           : ICCallStubCompiler(cx, ICStub::Call_StringSplit),
             firstMonitorStub_(firstMonitorStub),
             pcOffset_(pcOffset),
             expectedStr_(cx, str),
             expectedSep_(cx, sep),
-            templateObject_(cx, &templateObject.toObject())
+            templateObject_(cx, templateObject)
         { }
 
         ICStub* getStub(ICStubSpace* space) {
diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp
index 9c7b88fb2..bcb527516 100644
--- a/js/src/jit/BaselineInspector.cpp
+++ b/js/src/jit/BaselineInspector.cpp
@@ -580,7 +580,7 @@ BaselineInspector::getTemplateObjectForNative(jsbytecode* pc, Native native)
 
 bool
 BaselineInspector::isOptimizableCallStringSplit(jsbytecode* pc, JSString** strOut, JSString** sepOut,
-                                                JSObject** objOut)
+                                                ArrayObject** objOut)
 {
     if (!hasBaselineScript())
         return false;
diff --git a/js/src/jit/BaselineInspector.h b/js/src/jit/BaselineInspector.h
index 4a1791798..1ed4b5547 100644
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -113,7 +113,7 @@ class BaselineInspector
     bool hasSeenNonStringIterMore(jsbytecode* pc);
 
     MOZ_MUST_USE bool isOptimizableCallStringSplit(jsbytecode* pc, JSString** strOut,
-                                                   JSString** sepOut, JSObject** objOut);
+                                                   JSString** sepOut, ArrayObject** objOut);
     JSObject* getTemplateObject(jsbytecode* pc);
     JSObject* getTemplateObjectForNative(jsbytecode* pc, Native native);
     JSObject* getTemplateObjectForClassHook(jsbytecode* pc, const Class* clasp);
diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
index 748a70973..0d5779cee 100644
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -522,7 +522,7 @@ IonBuilder::inlineArray(CallInfo& callInfo)
         // Make sure initLength matches the template object's length. This is
         // not guaranteed to be the case, for instance if we're inlining the
         // MConstant may come from an outer script.
-        if (initLength != GetAnyBoxedOrUnboxedArrayLength(templateObject))
+        if (initLength != templateObject->as<ArrayObject>().length())
             return InliningStatus_NotInlined;
 
         // Don't inline large allocations.
@@ -1396,7 +1396,7 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
     // Check if exist a template object in stub.
     JSString* stringStr = nullptr;
     JSString* stringSep = nullptr;
-    JSObject* templateObject = nullptr;
+    ArrayObject* templateObject = nullptr;
     if (!inspector->isOptimizableCallStringSplit(pc, &stringStr, &stringSep, &templateObject))
         return InliningStatus_NotInlined;
 
@@ -1422,13 +1422,13 @@ IonBuilder::inlineConstantStringSplitString(CallInfo& callInfo)
     if (!key.maybeTypes()->hasType(TypeSet::StringType()))
         return InliningStatus_NotInlined;
 
-    uint32_t initLength = GetAnyBoxedOrUnboxedArrayLength(templateObject);
-    if (GetAnyBoxedOrUnboxedInitializedLength(templateObject) != initLength)
+    uint32_t initLength = templateObject->length();
+    if (templateObject->getDenseInitializedLength() != initLength)
         return InliningStatus_NotInlined;
 
     Vector<MConstant*, 0, SystemAllocPolicy> arrayValues;
     for (uint32_t i = 0; i < initLength; i++) {
-        Value str = GetAnyBoxedOrUnboxedDenseElement(templateObject, i);
+        Value str = templateObject->getDenseElement(i);
         MOZ_ASSERT(str.toString()->isAtom());
         MConstant* value = MConstant::New(alloc().fallible(), str, constraints());
         if (!value)
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 0717bb86d..7b1e1cad6 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -339,7 +339,7 @@ ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 bool
 ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
 {
-    *length = GetAnyBoxedOrUnboxedArrayLength(obj);
+    *length = obj->as<ArrayObject>().length();
     DenseElementResult result =
         SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
                                                ShouldUpdateTypes::DontUpdate);
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index a8bd3f028..da692c1b5 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -248,18 +248,20 @@ static bool
 GetElement(JSContext* cx, HandleObject obj, HandleObject receiver,
            uint32_t index, bool* hole, MutableHandleValue vp)
 {
-    AssertGreaterThanZero(index);
-    if (index < GetAnyBoxedOrUnboxedInitializedLength(obj)) {
-        vp.set(GetAnyBoxedOrUnboxedDenseElement(obj, uint32_t(index)));
-        if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
-            *hole = false;
-            return true;
+    if (obj->isNative()) {
+        NativeObject* nobj = &obj->as<NativeObject>();
+        if (index < nobj->getDenseInitializedLength()) {
+            vp.set(nobj->getDenseElement(size_t(index)));
+            if (!vp.isMagic(JS_ELEMENTS_HOLE)) {
+                *hole = false;
+                return true;
+            }
         }
-    }
-    if (obj->is<ArgumentsObject>()) {
-        if (obj->as<ArgumentsObject>().maybeGetElement(uint32_t(index), vp)) {
-            *hole = false;
-            return true;
+        if (nobj->is<ArgumentsObject>() && index <= UINT32_MAX) {
+            if (nobj->as<ArgumentsObject>().maybeGetElement(uint32_t(index), vp)) {
+                *hole = false;
+                return true;
+            }
         }
     }
 
@@ -337,11 +339,11 @@ GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp)
 {
     MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj));
 
-    if (length > GetBoxedOrUnboxedInitializedLength(aobj))
+    if (length > aobj->as<NativeObject>().getDenseInitializedLength())
         return DenseElementResult::Incomplete;
 
     for (size_t i = 0; i < length; i++) {
-        vp[i] = GetBoxedOrUnboxedDenseElement(aobj, i);
+        vp[i] = aobj->as<NativeObject>().getDenseElement(i);
 
         // No other indexed properties so hole => undefined.
         if (vp[i].isMagic(JS_ELEMENTS_HOLE))
@@ -849,7 +851,7 @@ js::ObjectMayHaveExtraIndexedProperties(JSObject* obj)
 
         if (ObjectMayHaveExtraIndexedOwnProperties(obj))
             return true;
-        if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0)
+        if (obj->as<NativeObject>().getDenseInitializedLength() != 0)
             return true;
     } while (true);
 }
@@ -1068,12 +1070,13 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_
     // length > initLength we rely on the second loop to add the
     // other elements.
     MOZ_ASSERT(*numProcessed == 0);
-    uint32_t initLength = Min<uint32_t>(GetBoxedOrUnboxedInitializedLength(obj), length);
+    uint32_t initLength = Min<uint32_t>(obj->as<NativeObject>().getDenseInitializedLength(),
+                                        length);
     while (*numProcessed < initLength) {
         if (!CheckForInterrupt(cx))
             return DenseElementResult::Failure;
 
-        Value elem = GetBoxedOrUnboxedDenseElement(obj, *numProcessed);
+        Value elem = obj->as<NativeObject>().getDenseElement(*numProcessed);
 
         if (elem.isString()) {
             if (!sb.append(elem.toString()))
@@ -1207,11 +1210,14 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
     // An optimized version of a special case of steps 7-11: when length==1 and
     // the 0th element is a string, ToString() of that element is a no-op and
     // so it can be immediately returned as the result.
-    if (length == 1 && GetAnyBoxedOrUnboxedInitializedLength(obj) == 1) {
-        Value elem0 = GetAnyBoxedOrUnboxedDenseElement(obj, 0);
-        if (elem0.isString()) {
-            args.rval().set(elem0);
-            return true;
+    if (length == 1 && obj->isNative()) {
+        NativeObject* nobj = &obj->as<NativeObject>();
+        if (nobj->getDenseInitializedLength() == 1) {
+            Value elem0 = nobj->getDenseElement(0);
+            if (elem0.isString()) {
+                args.rval().set(elem0);
+                return true;
+            }
         }
     }
 
@@ -1359,7 +1365,7 @@ DenseElementResult
 ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
 {
     /* An empty array or an array with no elements is already reversed. */
-    if (length == 0 || GetBoxedOrUnboxedInitializedLength(obj) == 0)
+    if (length == 0 || obj->as<NativeObject>().getDenseInitializedLength() == 0)
         return DenseElementResult::Success;
 
     if (obj->as<NativeObject>().denseElementsAreFrozen())
@@ -1385,15 +1391,15 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
 
     uint32_t lo = 0, hi = length - 1;
     for (; lo < hi; lo++, hi--) {
-        origlo = GetBoxedOrUnboxedDenseElement(obj, lo);
-        orighi = GetBoxedOrUnboxedDenseElement(obj, hi);
-        SetBoxedOrUnboxedDenseElementNoTypeChange(obj, lo, orighi);
+        origlo = obj->as<NativeObject>().getDenseElement(lo);
+        orighi = obj->as<NativeObject>().getDenseElement(hi);
+        obj->as<NativeObject>().setDenseElement(lo, orighi);
         if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
         {
             return DenseElementResult::Failure;
         }
-        SetBoxedOrUnboxedDenseElementNoTypeChange(obj, hi, origlo);
+        obj->as<NativeObject>().setDenseElement(hi, origlo);
         if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
         {
@@ -2074,14 +2080,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
             uint32_t newlength = length + args.length();
             args.rval().setNumber(newlength);
 
-            // SetOrExtendBoxedOrUnboxedDenseElements takes care of updating the
-            // length for boxed and unboxed arrays. Handle updates to the length of
-            // non-arrays here.
-            bool isArray;
-            if (!IsArray(cx, obj, &isArray))
-                return false;
-
-            if (!isArray)
+            // Handle updates to the length of non-arrays here.
+            if (!obj->is<ArrayObject>())
                 return SetLengthProperty(cx, obj, newlength);
 
             return true;
@@ -2141,14 +2141,15 @@ template <JSValueType Type>
 static inline DenseElementResult
 ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj));
+    MOZ_ASSERT(obj->isNative());
+
+    size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
 
     /*
      * At this point the length and initialized length have already been
      * decremented and the result fetched, so just shift the array elements
      * themselves.
      */
-    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
     obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
 
     return DenseElementResult::Success;
@@ -2165,6 +2166,15 @@ js::ArrayShiftMoveElements(JSObject* obj)
     JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
 }
 
+static inline void
+SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen)
+{
+    size_t oldInitlen = obj->getDenseInitializedLength();
+    obj->setDenseInitializedLength(initlen);
+    if (initlen < oldInitlen)
+        obj->shrinkElements(cx, initlen);
+}
+
 template <JSValueType Type>
 DenseElementResult
 ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
@@ -2179,11 +2189,11 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED)))
         return DenseElementResult::Incomplete;
 
-    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
+    size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
     if (initlen == 0)
         return DenseElementResult::Incomplete;
 
-    rval.set(GetBoxedOrUnboxedDenseElement(obj, 0));
+    rval.set(obj->as<NativeObject>().getDenseElement(0));
     if (rval.isMagic(JS_ELEMENTS_HOLE))
         rval.setUndefined();
 
@@ -2191,7 +2201,7 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     if (result != DenseElementResult::Success)
         return result;
 
-    SetBoxedOrUnboxedInitializedLength(cx, obj, initlen - 1);
+    SetInitializedLength(cx, obj.as<NativeObject>(), initlen - 1);
     return DenseElementResult::Success;
 }
 
@@ -2364,7 +2374,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
         return false;
 
     /* If it's a frozen array, always pick the slow path */
-    if (arr->is<ArrayObject>() && arr->as<ArrayObject>().denseElementsAreFrozen())
+    if (arr->as<ArrayObject>().denseElementsAreFrozen())
         return false;
 
     /*
@@ -2396,7 +2406,7 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
      * is subsumed by the initializedLength comparison.)
      */
     return !ObjectMayHaveExtraIndexedProperties(arr) &&
-           startingIndex + count <= GetAnyBoxedOrUnboxedInitializedLength(arr);
+           startingIndex + count <= arr->as<NativeObject>().getDenseInitializedLength();
 }
 
 /* ES 2016 draft Mar 25, 2016 22.1.3.26. */
@@ -2541,7 +2551,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
                 return false;
 
             /* Steps 15.c-d. */
-            SetBoxedOrUnboxedInitializedLength(cx, obj, finalLength);
+            SetInitializedLength(cx, obj.as<NativeObject>(), finalLength);
         } else {
             /*
              * This is all very slow if the length is very large. We don't yet
@@ -2629,7 +2639,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
                 return false;
 
             /* Steps 16.a-b. */
-            SetBoxedOrUnboxedInitializedLength(cx, obj, len + itemCount - actualDeleteCount);
+            SetInitializedLength(cx, obj.as<NativeObject>(), len + itemCount - actualDeleteCount);
         } else {
             RootedValue fromValue(cx);
             for (double k = len - actualDeleteCount; k > actualStart; k--) {
@@ -2851,7 +2861,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
         begin = end;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
-        size_t initlen = GetAnyBoxedOrUnboxedInitializedLength(obj);
+        size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
         size_t count = 0;
         if (initlen > begin)
             count = Min<size_t>(initlen - begin, end - begin);
@@ -2859,7 +2869,9 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
         RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
         if (!narr)
             return false;
-        SetAnyBoxedOrUnboxedArrayLength(cx, narr, end - begin);
+
+        MOZ_ASSERT(count >= narr->as<ArrayObject>().length());
+        narr->as<ArrayObject>().setLength(cx, count);
 
         if (count) {
             DebugOnly<DenseElementResult> result =
@@ -2991,7 +3003,7 @@ template <JSValueType Type>
 DenseElementResult
 ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result)
 {
-    int32_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
+    int32_t length = obj->as<ArrayObject>().length();
 
     uint32_t begin = NormalizeSliceTerm(beginArg, length);
     uint32_t end = NormalizeSliceTerm(endArg, length);
@@ -2999,18 +3011,19 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
     if (begin > end)
         begin = end;
 
-    size_t initlen = GetBoxedOrUnboxedInitializedLength(obj);
+    size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+    size_t count = Min<size_t>(initlen - begin, end - begin);
     if (initlen > begin) {
-        size_t count = Min<size_t>(initlen - begin, end - begin);
         if (count) {
-            DenseElementResult rv = EnsureBoxedOrUnboxedDenseElements(cx, result, count);
-            if (rv != DenseElementResult::Success)
-                return rv;
+            if (!result->as<ArrayObject>().ensureElements(cx, count))
+                return DenseElementResult::Failure;
             CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count);
         }
     }
 
-    SetAnyBoxedOrUnboxedArrayLength(cx, result, end - begin);
+    MOZ_ASSERT(count >= result->as<ArrayObject>().length());
+    result->as<ArrayObject>().setLength(cx, count);
+
     return DenseElementResult::Success;
 }
 
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index c26a42f48..deaa1d53e 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1143,19 +1143,18 @@ js::CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto)
 }
 
 static bool
-GetScriptArrayObjectElements(JSContext* cx, HandleObject obj, MutableHandle<GCVector<Value>> values)
+GetScriptArrayObjectElements(JSContext* cx, HandleArrayObject arr, MutableHandle<GCVector<Value>> values)
 {
-    MOZ_ASSERT(!obj->isSingleton());
-    MOZ_ASSERT(obj->is<ArrayObject>());
-    MOZ_ASSERT(!obj->isIndexed());
+    MOZ_ASSERT(!arr->isSingleton());
+    MOZ_ASSERT(!arr->isIndexed());
 
-    size_t length = GetAnyBoxedOrUnboxedArrayLength(obj);
+    size_t length = arr->length();
     if (!values.appendN(MagicValue(JS_ELEMENTS_HOLE), length))
         return false;
 
-    size_t initlen = GetAnyBoxedOrUnboxedInitializedLength(obj);
+    size_t initlen = arr->getDenseInitializedLength();
     for (size_t i = 0; i < initlen; i++)
-        values[i].set(GetAnyBoxedOrUnboxedDenseElement(obj, i));
+        values[i].set(arr->getDenseElement(i));
 
     return true;
 }
@@ -1212,7 +1211,7 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
 
     if (obj->is<ArrayObject>()) {
         Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
-        if (!GetScriptArrayObjectElements(cx, obj, &values))
+        if (!GetScriptArrayObjectElements(cx, obj.as<ArrayObject>(), &values))
             return nullptr;
 
         // Deep clone any elements.
@@ -1339,8 +1338,11 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
 
     if (isArray) {
         Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
-        if (mode == XDR_ENCODE && !GetScriptArrayObjectElements(cx, obj, &values))
-            return false;
+        if (mode == XDR_ENCODE) {
+            RootedArrayObject arr(cx, &obj->as<ArrayObject>());
+            if (!GetScriptArrayObjectElements(cx, arr, &values))
+                return false;
+        }
 
         uint32_t initialized;
         if (mode == XDR_ENCODE)
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 499f3604b..b308464fe 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -172,130 +172,10 @@ UnboxedPlainObject::layout() const
     return group()->unboxedLayout();
 }
 
-/////////////////////////////////////////////////////////////////////
-// Combined methods for NativeObject and UnboxedArrayObject accesses.
-/////////////////////////////////////////////////////////////////////
-
-static inline bool
-HasAnyBoxedOrUnboxedDenseElements(JSObject* obj)
-{
-    return obj->isNative();
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedInitializedLength(JSObject* obj)
-{
-    if (obj->isNative())
-        return obj->as<NativeObject>().getDenseInitializedLength();
-    return 0;
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedCapacity(JSObject* obj)
-{
-    if (obj->isNative())
-        return obj->as<NativeObject>().getDenseCapacity();
-    return 0;
-}
-
-static inline Value
-GetAnyBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
-{
-    return obj->as<NativeObject>().getDenseElement(index);
-}
-
-static inline size_t
-GetAnyBoxedOrUnboxedArrayLength(JSObject* obj)
-{
-    return obj->as<ArrayObject>().length();
-}
-
-static inline void
-SetAnyBoxedOrUnboxedArrayLength(JSContext* cx, JSObject* obj, size_t length)
-{
-    MOZ_ASSERT(length >= obj->as<ArrayObject>().length());
-    obj->as<ArrayObject>().setLength(cx, length);
-}
-
-static inline bool
-SetAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
-    obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
-    return true;
-}
-
-static inline bool
-InitAnyBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
-    obj->as<NativeObject>().initDenseElementWithType(cx, index, value);
-    return true;
-}
-
 /////////////////////////////////////////////////////////////////////
 // Template methods for NativeObject and UnboxedArrayObject accesses.
 /////////////////////////////////////////////////////////////////////
 
-static inline JSValueType
-GetBoxedOrUnboxedType(JSObject* obj)
-{
-    return JSVAL_TYPE_MAGIC;
-}
-
-static inline bool
-HasBoxedOrUnboxedDenseElements(JSObject* obj)
-{
-    return obj->isNative();
-}
-
-static inline size_t
-GetBoxedOrUnboxedInitializedLength(JSObject* obj)
-{
-    return obj->as<NativeObject>().getDenseInitializedLength();
-}
-
-static inline DenseElementResult
-SetBoxedOrUnboxedInitializedLength(JSContext* cx, JSObject* obj, size_t initlen)
-{
-	size_t oldInitlen = GetBoxedOrUnboxedInitializedLength(obj);
-    obj->as<NativeObject>().setDenseInitializedLength(initlen);
-    if (initlen < oldInitlen)
-        obj->as<NativeObject>().shrinkElements(cx, initlen);
-    return DenseElementResult::Success;
-}
-
-static inline size_t
-GetBoxedOrUnboxedCapacity(JSObject* obj)
-{
-    return obj->as<NativeObject>().getDenseCapacity();
-}
-
-static inline Value
-GetBoxedOrUnboxedDenseElement(JSObject* obj, size_t index)
-{
-    return obj->as<NativeObject>().getDenseElement(index);
-}
-
-static inline void
-SetBoxedOrUnboxedDenseElementNoTypeChange(JSObject* obj, size_t index, const Value& value)
-{
-    obj->as<NativeObject>().setDenseElement(index, value);
-}
-
-static inline bool
-SetBoxedOrUnboxedDenseElement(JSContext* cx, JSObject* obj, size_t index, const Value& value)
-{
-    obj->as<NativeObject>().setDenseElementWithType(cx, index, value);
-    return true;
-}
-
-static inline DenseElementResult
-EnsureBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, size_t count)
-{
-    if (!obj->as<ArrayObject>().ensureElements(cx, count))
-        return DenseElementResult::Failure;
-    return DenseElementResult::Success;
-}
-
 static inline DenseElementResult
 SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
                                        uint32_t start, const Value* vp, uint32_t count,
@@ -334,7 +214,7 @@ static inline DenseElementResult
 MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart,
                                 uint32_t length)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(obj));
+    MOZ_ASSERT(obj->isNative());
 
     if (obj->as<NativeObject>().denseElementsAreFrozen())
         return DenseElementResult::Incomplete;
@@ -350,13 +230,13 @@ static inline DenseElementResult
 CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
                                 uint32_t dstStart, uint32_t srcStart, uint32_t length)
 {
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(src));
-    MOZ_ASSERT(HasBoxedOrUnboxedDenseElements(dst));
-    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(dst) == dstStart);
-    MOZ_ASSERT(GetBoxedOrUnboxedInitializedLength(src) >= srcStart + length);
-    MOZ_ASSERT(GetBoxedOrUnboxedCapacity(dst) >= dstStart + length);
+    MOZ_ASSERT(src->isNative());
+    MOZ_ASSERT(dst->isNative());
+    MOZ_ASSERT(dst->as<NativeObject>().getDenseInitializedLength() == dstStart);
+    MOZ_ASSERT(src->as<NativeObject>().getDenseInitializedLength() >= srcStart + length);
+    MOZ_ASSERT(dst->as<NativeObject>().getDenseCapacity() >= dstStart + length);
 
-    SetBoxedOrUnboxedInitializedLength(cx, dst, dstStart + length);
+    dst->as<NativeObject>().setDenseInitializedLength(dstStart + length);
 
     const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
     dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
@@ -383,7 +263,7 @@ template <typename F>
 DenseElementResult
 CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
 {
-    if (!HasAnyBoxedOrUnboxedDenseElements(obj))
+    if (!obj->isNative())
         return DenseElementResult::Incomplete;
     return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
 }
@@ -393,7 +273,7 @@ template <typename F>
 DenseElementResult
 CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2)
 {
-    if (!HasAnyBoxedOrUnboxedDenseElements(obj1) || !HasAnyBoxedOrUnboxedDenseElements(obj2))
+    if (!obj1->isNative() || !obj2->isNative())
         return DenseElementResult::Incomplete;
 
     return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC, JSVAL_TYPE_MAGIC>();
-- 
cgit v1.2.3


From e95089d84ac71276bd059e52293ab42c2259d89e Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Wed, 12 Jun 2019 03:19:09 +0000
Subject: Make use of ArrayObjects in favor of generic JS objects.

ArrayObjects has been a thing for years but been under-used. About time
they are used where prudent.
---
 js/src/frontend/BytecodeEmitter.cpp |  4 +--
 js/src/jit/BaselineCompiler.cpp     |  6 ++--
 js/src/jit/BaselineIC.cpp           |  8 ++---
 js/src/jit/CodeGenerator.cpp        |  8 ++---
 js/src/jit/Recover.cpp              |  2 +-
 js/src/jsarray.cpp                  | 68 ++++++++++---------------------------
 js/src/jsarray.h                    | 24 ++++++-------
 js/src/jsstr.cpp                    |  6 ++--
 js/src/jsstr.h                      |  2 +-
 js/src/vm/JSONParser.cpp            |  4 +--
 js/src/vm/ObjectGroup.cpp           |  7 ++--
 js/src/vm/ObjectGroup.h             | 10 +++---
 js/src/vm/Stack.cpp                 |  2 +-
 js/src/vm/Stack.h                   |  2 +-
 14 files changed, 57 insertions(+), 96 deletions(-)

(limited to 'js/src')

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index c524184d6..ea6baeec7 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6281,8 +6281,8 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje
         }
         MOZ_ASSERT(idx == count);
 
-        JSObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
-                                                    newKind, arrayKind);
+        ArrayObject* obj = ObjectGroup::newArrayObject(cx, values.begin(), values.length(),
+                                                       newKind, arrayKind);
         if (!obj)
             return false;
 
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 3fa5a80ed..93e3759b9 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2055,7 +2055,7 @@ BaselineCompiler::emit_JSOP_SPREADCALLARRAY()
     return emit_JSOP_NEWARRAY();
 }
 
-typedef JSObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
+typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
 const VMFunction jit::NewArrayCopyOnWriteInfo =
     FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
 
@@ -4136,14 +4136,14 @@ BaselineCompiler::emit_JSOP_REST()
 {
     frame.syncStack(0);
 
-    JSObject* templateObject =
+    ArrayObject* templateObject =
         ObjectGroup::newArrayObject(cx, nullptr, 0, TenuredObject,
                                     ObjectGroup::NewArrayKind::UnknownIndex);
     if (!templateObject)
         return false;
 
     // Call IC.
-    ICRest_Fallback::Compiler compiler(cx, &templateObject->as<ArrayObject>());
+    ICRest_Fallback::Compiler compiler(cx, templateObject);
     if (!emitOpIC(compiler.getStub(&stubSpace_)))
         return false;
 
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 28e263ac7..2b0822655 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5765,10 +5765,10 @@ static bool
 CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
 {
     uint32_t length = arr->length();
-    JSObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
+    ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
     if (!nobj)
         return false;
-    EnsureArrayGroupAnalyzed(cx, nobj);
+    EnsureArrayGroupAnalyzed(cx, nobj); //XXX
     CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length);
 
     result.setObject(*nobj);
@@ -8547,8 +8547,8 @@ static bool DoRestFallback(JSContext* cx, BaselineFrame* frame, ICRest_Fallback*
     unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0;
     Value* rest = frame->argv() + numFormals;
 
-    JSObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
-                                                ObjectGroup::NewArrayKind::UnknownIndex);
+    ArrayObject* obj = ObjectGroup::newArrayObject(cx, rest, numRest, GenericObject,
+                                                   ObjectGroup::NewArrayKind::UnknownIndex);
     if (!obj)
         return false;
     res.setObject(*obj);
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 485e881fe..ae9c61031 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5169,11 +5169,11 @@ static JSObject*
 NewArrayWithGroup(JSContext* cx, uint32_t length, HandleObjectGroup group,
                   bool convertDoubleElements)
 {
-    JSObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
+    ArrayObject* res = NewFullyAllocatedArrayTryUseGroup(cx, group, length);
     if (!res)
         return nullptr;
     if (convertDoubleElements)
-        res->as<ArrayObject>().setShouldConvertDoubleElements();
+        res->setShouldConvertDoubleElements();
     return res;
 }
 
@@ -5319,7 +5319,7 @@ CodeGenerator::visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir)
     masm.bind(ool->rejoin());
 }
 
-typedef JSObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
+typedef ArrayObject* (*ArrayConstructorOneArgFn)(JSContext*, HandleObjectGroup, int32_t length);
 static const VMFunction ArrayConstructorOneArgInfo =
     FunctionInfo<ArrayConstructorOneArgFn>(ArrayConstructorOneArg, "ArrayConstructorOneArg");
 
@@ -7765,7 +7765,7 @@ CodeGenerator::visitSinCos(LSinCos *lir)
     masm.freeStack(sizeof(double) * 2);
 }
 
-typedef JSObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
+typedef ArrayObject* (*StringSplitFn)(JSContext*, HandleObjectGroup, HandleString, HandleString, uint32_t);
 static const VMFunction StringSplitInfo =
     FunctionInfo<StringSplitFn>(js::str_split_string, "str_split_string");
 
diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
index 6fd71f377..8fe6ee3fb 100644
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1355,7 +1355,7 @@ RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
     RootedValue result(cx);
     RootedObjectGroup group(cx, templateObject->group());
 
-    JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
+    ArrayObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
     if (!resultObject)
         return false;
 
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index da692c1b5..0d6f78fcf 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2811,7 +2811,7 @@ SliceSlowly(JSContext* cx, HandleObject obj, HandleObject receiver,
 }
 
 static bool
-SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleObject result)
+SliceSparse(JSContext* cx, HandleObject obj, uint32_t begin, uint32_t end, HandleArrayObject result)
 {
     MOZ_ASSERT(begin <= end);
 
@@ -2866,7 +2866,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
         if (initlen > begin)
             count = Min<size_t>(initlen - begin, end - begin);
 
-        RootedObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
+        RootedArrayObject narr(cx, NewFullyAllocatedArrayTryReuseGroup(cx, obj, count));
         if (!narr)
             return false;
 
@@ -2882,7 +2882,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
         return true;
     }
 
-    RootedObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
+    RootedArrayObject narr(cx, NewPartlyAllocatedArrayTryReuseGroup(cx, obj, end - begin));
     if (!narr)
         return false;
 
@@ -3069,7 +3069,7 @@ array_isArray(JSContext* cx, unsigned argc, Value* vp)
 static bool
 ArrayFromCallArgs(JSContext* cx, CallArgs& args, HandleObject proto = nullptr)
 {
-    JSObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
+    ArrayObject* obj = NewCopiedArrayForCallingAllocationSite(cx, args.array(), args.length(), proto);
     if (!obj)
         return false;
 
@@ -3234,7 +3234,7 @@ ArrayConstructorImpl(JSContext* cx, CallArgs& args, bool isConstructor)
         }
     }
 
-    JSObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
+    ArrayObject* obj = NewPartlyAllocatedArrayForCallingAllocationSite(cx, length, proto);
     if (!obj)
         return false;
 
@@ -3260,7 +3260,7 @@ js::array_construct(JSContext* cx, unsigned argc, Value* vp)
     return ArrayConstructorImpl(cx, args, /* isConstructor = */ false);
 }
 
-JSObject*
+ArrayObject*
 js::ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt)
 {
     if (lengthInt < 0) {
@@ -3555,7 +3555,7 @@ js::NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSOb
     return arr;
 }
 
-JSObject*
+ArrayObject*
 js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap)
 {
     MOZ_ASSERT(!gc::IsInsideNursery(templateObject));
@@ -3573,7 +3573,7 @@ js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc
 // specified group cannot be used, ensure that the created array at least has
 // the given [[Prototype]].
 template <uint32_t maxLength>
-static inline JSObject*
+static inline ArrayObject*
 NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
                     NewObjectKind newKind = GenericObject)
 {
@@ -3603,14 +3603,14 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
     return res;
 }
 
-JSObject*
+ArrayObject*
 js::NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
                                       NewObjectKind newKind)
 {
     return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
 }
 
-JSObject*
+ArrayObject*
 js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length)
 {
     return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
@@ -3624,7 +3624,7 @@ js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup g
 // |length| is larger than the input object's initialized length (in which case
 // UnboxedArrayObject::MaximumCapacity might be exceeded).
 template <uint32_t maxLength>
-static inline JSObject*
+static inline ArrayObject*
 NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
                       NewObjectKind newKind = GenericObject)
 {
@@ -3641,20 +3641,20 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
     return NewArrayTryUseGroup<maxLength>(cx, group, length, newKind);
 }
 
-JSObject*
+ArrayObject*
 js::NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
                                         NewObjectKind newKind)
 {
     return NewArrayTryReuseGroup<UINT32_MAX>(cx, obj, length, newKind);
 }
 
-JSObject*
+ArrayObject*
 js::NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length)
 {
     return NewArrayTryReuseGroup<ArrayObject::EagerAllocationMaxLength>(cx, obj, length);
 }
 
-JSObject*
+ArrayObject*
 js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
                                                    NewObjectKind newKind)
 {
@@ -3664,7 +3664,7 @@ js::NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
     return NewArrayTryUseGroup<UINT32_MAX>(cx, group, length, newKind);
 }
 
-JSObject*
+ArrayObject*
 js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto)
 {
     RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array, proto));
@@ -3673,44 +3673,12 @@ js::NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length
     return NewArrayTryUseGroup<ArrayObject::EagerAllocationMaxLength>(cx, group, length);
 }
 
-bool
-js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
-                                         const Value* vp, size_t length)
-{
-    static const size_t EagerPreliminaryObjectAnalysisThreshold = 800;
-
-    // Force analysis to see if an unboxed array can be used when making a
-    // sufficiently large array, to avoid excessive analysis and copying later
-    // on. If this is the first array of its group that is being created, first
-    // make a dummy array with the initial elements of the array we are about
-    // to make, so there is some basis for the unboxed array analysis.
-    if (length > EagerPreliminaryObjectAnalysisThreshold) {
-        if (PreliminaryObjectArrayWithTemplate* objects = group->maybePreliminaryObjects()) {
-            if (objects->empty()) {
-                size_t nlength = Min<size_t>(length, 100);
-                JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, nlength);
-                if (!obj)
-                    return false;
-                DebugOnly<DenseElementResult> result =
-                    SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, nlength,
-                                                           ShouldUpdateTypes::Update);
-                MOZ_ASSERT(result.value == DenseElementResult::Success);
-            }
-            objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true);
-        }
-    }
-    return true;
-}
-
-JSObject*
+ArrayObject*
 js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
                               const Value* vp, size_t length, NewObjectKind newKind,
                               ShouldUpdateTypes updateTypes)
 {
-    if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
-        return nullptr;
-
-    JSObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
+    ArrayObject* obj = NewFullyAllocatedArrayTryUseGroup(cx, group, length, newKind);
     if (!obj)
         return nullptr;
 
@@ -3722,7 +3690,7 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
     return obj;
 }
 
-JSObject*
+ArrayObject*
 js::NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
                                            HandleObject proto /* = nullptr */)
 {
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index e22cde881..ecde87c3b 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -72,30 +72,30 @@ extern ArrayObject*
 NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject* templateObject);
 
 /* Create a dense array with the same copy-on-write elements as another object. */
-extern JSObject*
+extern ArrayObject*
 NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
 
 // The methods below can create either boxed or unboxed arrays.
 
-extern JSObject*
+extern ArrayObject*
 NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
                                   NewObjectKind newKind = GenericObject);
 
-extern JSObject*
+extern ArrayObject*
 NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length);
 
-extern JSObject*
+extern ArrayObject*
 NewFullyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
                                     NewObjectKind newKind = GenericObject);
 
-extern JSObject*
+extern ArrayObject*
 NewPartlyAllocatedArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length);
 
-extern JSObject*
+extern ArrayObject*
 NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
                                                NewObjectKind newKind = GenericObject);
 
-extern JSObject*
+extern ArrayObject*
 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
 
 enum class ShouldUpdateTypes
@@ -104,17 +104,13 @@ enum class ShouldUpdateTypes
     DontUpdate
 };
 
-extern bool
-MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup group,
-                                     const Value* vp, size_t length);
-
-extern JSObject*
+extern ArrayObject*
 NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
                           const Value* vp, size_t length,
                           NewObjectKind newKind = GenericObject,
                           ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
 
-extern JSObject*
+extern ArrayObject*
 NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
                                        HandleObject proto = nullptr);
 
@@ -202,7 +198,7 @@ array_splice(JSContext* cx, unsigned argc, js::Value* vp);
 extern bool
 NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v);
 
-extern JSObject*
+extern ArrayObject*
 ArrayConstructorOneArg(JSContext* cx, HandleObjectGroup group, int32_t lengthInt);
 
 #ifdef DEBUG
diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
index 7765b1197..d7db5129d 100644
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2369,7 +2369,7 @@ js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString patt
 }
 
 // ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
-static JSObject*
+static ArrayObject*
 SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearString sep,
             HandleObjectGroup group)
 {
@@ -2466,7 +2466,7 @@ SplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleLinearS
 }
 
 // Fast-path for splitting a string into a character array via split("").
-static JSObject*
+static ArrayObject*
 CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObjectGroup group)
 {
     size_t strLength = str->length();
@@ -2491,7 +2491,7 @@ CharSplitHelper(JSContext* cx, HandleLinearString str, uint32_t limit, HandleObj
 }
 
 // ES 2016 draft Mar 25, 2016 21.1.3.17 steps 4, 8, 12-18.
-JSObject*
+ArrayObject*
 js::str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep, uint32_t limit)
 
 {
diff --git a/js/src/jsstr.h b/js/src/jsstr.h
index 38fbfa85e..68175c826 100644
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -465,7 +465,7 @@ FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote)
     return res;
 }
 
-JSObject*
+ArrayObject*
 str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep,
                  uint32_t limit);
 
diff --git a/js/src/vm/JSONParser.cpp b/js/src/vm/JSONParser.cpp
index 01883bb15..e50da3bc4 100644
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -606,8 +606,8 @@ JSONParserBase::finishArray(MutableHandleValue vp, ElementVector& elements)
 {
     MOZ_ASSERT(&elements == &stack.back().elements());
 
-    JSObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
-                                                GenericObject);
+    ArrayObject* obj = ObjectGroup::newArrayObject(cx, elements.begin(), elements.length(),
+                                                   GenericObject);
     if (!obj)
         return false;
 
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index a227b7c9c..c2866f5ae 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -774,7 +774,7 @@ GetValueTypeForTable(const Value& v)
     return type;
 }
 
-/* static */ JSObject*
+/* static */ ArrayObject*
 ObjectGroup::newArrayObject(ExclusiveContext* cx,
                             const Value* vp, size_t length,
                             NewObjectKind newKind, NewArrayKind arrayKind)
@@ -854,11 +854,8 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
     }
 
     // The type of the elements being added will already be reflected in type
-    // information, but make sure when creating an unboxed array that the
-    // common element type is suitable for the unboxed representation.
+    // information.
     ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate;
-    if (!MaybeAnalyzeBeforeCreatingLargeArray(cx, group, vp, length))
-        return nullptr;
     if (group->maybePreliminaryObjects())
         group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
 
diff --git a/js/src/vm/ObjectGroup.h b/js/src/vm/ObjectGroup.h
index 4e24de9f1..553cb8366 100644
--- a/js/src/vm/ObjectGroup.h
+++ b/js/src/vm/ObjectGroup.h
@@ -505,11 +505,11 @@ class ObjectGroup : public gc::TenuredCell
         UnknownIndex  // Make an array with an unknown element type.
     };
 
-    // Create an ArrayObject or UnboxedArrayObject with the specified elements
-    // and a group specialized for the elements.
-    static JSObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
-                                    NewObjectKind newKind,
-                                    NewArrayKind arrayKind = NewArrayKind::Normal);
+    // Create an ArrayObject with the specified elements and a group specialized
+    // for the elements.
+    static ArrayObject* newArrayObject(ExclusiveContext* cx, const Value* vp, size_t length,
+                                       NewObjectKind newKind,
+                                       NewArrayKind arrayKind = NewArrayKind::Normal);
 
     // Create a PlainObject or UnboxedPlainObject with the specified properties
     // and a group specialized for those properties.
diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp
index 87e95c893..c5f2cf5f3 100644
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -82,7 +82,7 @@ InterpreterFrame::isNonGlobalEvalFrame() const
     return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
 }
 
-JSObject*
+ArrayObject*
 InterpreterFrame::createRestParameter(JSContext* cx)
 {
     MOZ_ASSERT(script()->hasRest());
diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h
index 552738d89..dc9306c99 100644
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -523,7 +523,7 @@ class InterpreterFrame
     ArgumentsObject& argsObj() const;
     void initArgsObj(ArgumentsObject& argsobj);
 
-    JSObject* createRestParameter(JSContext* cx);
+    ArrayObject* createRestParameter(JSContext* cx);
 
     /*
      * Environment chain
-- 
cgit v1.2.3


From 93ce7c7372b20f6e6c6778f9c196b723a1df27a8 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Wed, 12 Jun 2019 09:09:53 +0000
Subject: Remove unused LIR temp register for unboxed arrays.

---
 js/src/jit/Lowering.cpp        | 16 ++++------------
 js/src/jit/shared/LIR-shared.h | 24 ++++++++----------------
 2 files changed, 12 insertions(+), 28 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp
index e185b5746..68417138b 100644
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3137,20 +3137,16 @@ LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
     const LUse elements = useRegister(ins->elements());
     const LAllocation index = useRegisterOrConstant(ins->index());
 
-    // Use a temp register when adding new elements to unboxed arrays.
-    LDefinition tempDef = LDefinition::BogusTemp();
-
     LInstruction* lir;
     switch (ins->value()->type()) {
       case MIRType::Value:
-        lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
-                                              tempDef);
+        lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()));
         break;
 
       default:
       {
         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
-        lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, tempDef);
+        lir = new(alloc()) LStoreElementHoleT(object, elements, index, value);
         break;
       }
     }
@@ -3169,18 +3165,14 @@ LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
     const LUse elements = useRegister(ins->elements());
     const LAllocation index = useRegisterOrConstant(ins->index());
 
-    // Use a temp register when adding new elements to unboxed arrays.
-    LDefinition tempDef = LDefinition::BogusTemp();
-
     LInstruction* lir;
     switch (ins->value()->type()) {
       case MIRType::Value:
-        lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()),
-                                                  tempDef);
+        lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()));
         break;
       default:
         const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
-        lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value, tempDef);
+        lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value);
         break;
     }
 
diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h
index 35c7e7442..ffa4d8367 100644
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -5669,19 +5669,17 @@ class LStoreElementT : public LInstructionHelper<0, 3, 0>
 };
 
 // Like LStoreElementV, but supports indexes >= initialized length.
-class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
+class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(StoreElementHoleV)
 
     LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
-                       const LAllocation& index, const LBoxAllocation& value,
-                       const LDefinition& temp) {
+                       const LAllocation& index, const LBoxAllocation& value) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setBoxOperand(Value, value);
-        setTemp(0, temp);
     }
 
     static const size_t Value = 3;
@@ -5701,19 +5699,17 @@ class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
 };
 
 // Like LStoreElementT, but supports indexes >= initialized length.
-class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
+class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(StoreElementHoleT)
 
     LStoreElementHoleT(const LAllocation& object, const LAllocation& elements,
-                       const LAllocation& index, const LAllocation& value,
-                       const LDefinition& temp) {
+                       const LAllocation& index, const LAllocation& value) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setOperand(3, value);
-        setTemp(0, temp);
     }
 
     const MStoreElementHole* mir() const {
@@ -5734,19 +5730,17 @@ class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
 };
 
 // Like LStoreElementV, but can just ignore assignment (for eg. frozen objects)
-class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
+class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(FallibleStoreElementV)
 
     LFallibleStoreElementV(const LAllocation& object, const LAllocation& elements,
-                           const LAllocation& index, const LBoxAllocation& value,
-                           const LDefinition& temp) {
+                           const LAllocation& index, const LBoxAllocation& value) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setBoxOperand(Value, value);
-        setTemp(0, temp);
     }
 
     static const size_t Value = 3;
@@ -5766,19 +5760,17 @@ class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
 };
 
 // Like LStoreElementT, but can just ignore assignment (for eg. frozen objects)
-class LFallibleStoreElementT : public LInstructionHelper<0, 4, 1>
+class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
 {
   public:
     LIR_HEADER(FallibleStoreElementT)
 
     LFallibleStoreElementT(const LAllocation& object, const LAllocation& elements,
-                           const LAllocation& index, const LAllocation& value,
-                           const LDefinition& temp) {
+                           const LAllocation& index, const LAllocation& value) {
         setOperand(0, object);
         setOperand(1, elements);
         setOperand(2, index);
         setOperand(3, value);
-        setTemp(0, temp);
     }
 
     const MFallibleStoreElement* mir() const {
-- 
cgit v1.2.3


From ec96ef3b7712da562d9f2f26c4099a5700c4eea4 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Wed, 12 Jun 2019 09:56:41 +0000
Subject: Remove unboxed array context option and shell flag.

---
 js/src/jsapi.h            |  8 --------
 js/src/shell/js.cpp       |  4 ----
 js/src/vm/ObjectGroup.cpp | 13 -------------
 3 files changed, 25 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 005d2278e..3f65dad34 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1093,7 +1093,6 @@ class JS_PUBLIC_API(ContextOptions) {
         wasmAlwaysBaseline_(false),
         throwOnAsmJSValidationFailure_(false),
         nativeRegExp_(true),
-        unboxedArrays_(false),
         asyncStack_(true),
         throwOnDebuggeeWouldRun_(true),
         dumpStackOnDebuggeeWouldRun_(false),
@@ -1170,12 +1169,6 @@ class JS_PUBLIC_API(ContextOptions) {
         return *this;
     }
 
-    bool unboxedArrays() const { return unboxedArrays_; }
-    ContextOptions& setUnboxedArrays(bool flag) {
-        unboxedArrays_ = flag;
-        return *this;
-    }
-
     bool asyncStack() const { return asyncStack_; }
     ContextOptions& setAsyncStack(bool flag) {
         asyncStack_ = flag;
@@ -1238,7 +1231,6 @@ class JS_PUBLIC_API(ContextOptions) {
     bool wasmAlwaysBaseline_ : 1;
     bool throwOnAsmJSValidationFailure_ : 1;
     bool nativeRegExp_ : 1;
-    bool unboxedArrays_ : 1;
     bool asyncStack_ : 1;
     bool throwOnDebuggeeWouldRun_ : 1;
     bool dumpStackOnDebuggeeWouldRun_ : 1;
diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
index 193d8d22b..29cbd9762 100644
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -320,7 +320,6 @@ static bool enableIon = false;
 static bool enableAsmJS = false;
 static bool enableWasm = false;
 static bool enableNativeRegExp = false;
-static bool enableUnboxedArrays = false;
 static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
 static bool enableWasmAlwaysBaseline = false;
 static bool enableArrayProtoValues = true;
@@ -7260,7 +7259,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
     enableAsmJS = !op.getBoolOption("no-asmjs");
     enableWasm = !op.getBoolOption("no-wasm");
     enableNativeRegExp = !op.getBoolOption("no-native-regexp");
-    enableUnboxedArrays = op.getBoolOption("unboxed-arrays");
     enableWasmAlwaysBaseline = op.getBoolOption("wasm-always-baseline");
     enableArrayProtoValues = !op.getBoolOption("no-array-proto-values");
 
@@ -7270,7 +7268,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
                              .setWasm(enableWasm)
                              .setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
                              .setNativeRegExp(enableNativeRegExp)
-                             .setUnboxedArrays(enableUnboxedArrays)
                              .setArrayProtoValues(enableArrayProtoValues);
 
     if (op.getBoolOption("wasm-check-bce"))
@@ -7710,7 +7707,6 @@ main(int argc, char** argv, char** envp)
         || !op.addBoolOption('\0', "no-wasm", "Disable WebAssembly compilation")
         || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
         || !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
-        || !op.addBoolOption('\0', "unboxed-arrays", "Allow creating unboxed arrays")
         || !op.addBoolOption('\0', "wasm-always-baseline", "Enable wasm baseline compiler when possible")
         || !op.addBoolOption('\0', "wasm-check-bce", "Always generate wasm bounds check, even redundant ones.")
         || !op.addBoolOption('\0', "no-array-proto-values", "Remove Array.prototype.values")
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index c2866f5ae..6b984a803 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1454,19 +1454,6 @@ ObjectGroup::allocationSiteGroup(JSContext* cx, JSScript* scriptArg, jsbytecode*
         }
     }
 
-    // FIXME: This block can probably go because of cx->options().unboxedArrays()
-	if (kind == JSProto_Array &&
-        (JSOp(*pc) == JSOP_NEWARRAY || IsCallPC(pc)) &&
-        cx->options().unboxedArrays())
-    {
-        PreliminaryObjectArrayWithTemplate* preliminaryObjects =
-            cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
-        if (preliminaryObjects)
-            res->setPreliminaryObjects(preliminaryObjects);
-        else
-            cx->recoverFromOutOfMemory();
-    }
-
     if (!table->add(p, key, res)) {
         ReportOutOfMemory(cx);
         return nullptr;
-- 
cgit v1.2.3


From ef8e0ce6075150ed4501edad1376e4046cd8e3cb Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Wed, 12 Jun 2019 11:03:35 +0000
Subject: Remove functors for array natives.

---
 js/src/jsarray.cpp            | 166 +++++++++++++++---------------------------
 js/src/jsarray.h              |   2 +-
 js/src/vm/UnboxedObject-inl.h | 121 ------------------------------
 3 files changed, 59 insertions(+), 230 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 0d6f78fcf..9abc99e34 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -333,37 +333,31 @@ js::GetElementsWithAdder(JSContext* cx, HandleObject obj, HandleObject receiver,
     return true;
 }
 
-template <JSValueType Type>
-DenseElementResult
-GetBoxedOrUnboxedDenseElements(JSObject* aobj, uint32_t length, Value* vp)
+static bool
+GetDenseElements(NativeObject* aobj, uint32_t length, Value* vp)
 {
     MOZ_ASSERT(!ObjectMayHaveExtraIndexedProperties(aobj));
 
-    if (length > aobj->as<NativeObject>().getDenseInitializedLength())
-        return DenseElementResult::Incomplete;
+    if (length > aobj->getDenseInitializedLength())
+        return false;
 
     for (size_t i = 0; i < length; i++) {
-        vp[i] = aobj->as<NativeObject>().getDenseElement(i);
+        vp[i] = aobj->getDenseElement(i);
 
         // No other indexed properties so hole => undefined.
         if (vp[i].isMagic(JS_ELEMENTS_HOLE))
             vp[i] = UndefinedValue();
     }
 
-    return DenseElementResult::Success;
+    return true;
 }
 
-DefineBoxedOrUnboxedFunctor3(GetBoxedOrUnboxedDenseElements,
-                             JSObject*, uint32_t, Value*);
-
 bool
 js::GetElements(JSContext* cx, HandleObject aobj, uint32_t length, Value* vp)
 {
     if (!ObjectMayHaveExtraIndexedProperties(aobj)) {
-        GetBoxedOrUnboxedDenseElementsFunctor functor(aobj, length, vp);
-        DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, aobj);
-        if (result != DenseElementResult::Incomplete)
-            return result == DenseElementResult::Success;
+        if (GetDenseElements(&aobj->as<NativeObject>(), length, vp))
+            return true;
     }
 
     if (aobj->is<ArgumentsObject>()) {
@@ -1061,32 +1055,32 @@ struct StringSeparatorOp
     }
 };
 
-template <typename SeparatorOp, JSValueType Type>
-static DenseElementResult
-ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
+template <typename SeparatorOp>
+static bool
+ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleNativeObject obj, uint64_t length,
                      StringBuffer& sb, uint32_t* numProcessed)
 {
     // This loop handles all elements up to initializedLength. If
     // length > initLength we rely on the second loop to add the
     // other elements.
     MOZ_ASSERT(*numProcessed == 0);
-    uint32_t initLength = Min<uint32_t>(obj->as<NativeObject>().getDenseInitializedLength(),
+    uint32_t initLength = Min<uint32_t>(obj->getDenseInitializedLength(),
                                         length);
     while (*numProcessed < initLength) {
         if (!CheckForInterrupt(cx))
-            return DenseElementResult::Failure;
+            return false;
 
         Value elem = obj->as<NativeObject>().getDenseElement(*numProcessed);
 
         if (elem.isString()) {
             if (!sb.append(elem.toString()))
-                return DenseElementResult::Failure;
+                return false;
         } else if (elem.isNumber()) {
             if (!NumberValueToStringBuffer(cx, elem, sb))
-                return DenseElementResult::Failure;
+                return false;
         } else if (elem.isBoolean()) {
             if (!BooleanToStringBuffer(elem.toBoolean(), sb))
-                return DenseElementResult::Failure;
+                return false;
         } else if (elem.isObject() || elem.isSymbol()) {
             /*
              * Object stringifying could modify the initialized length or make
@@ -1102,32 +1096,12 @@ ArrayJoinDenseKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_
         }
 
         if (++(*numProcessed) != length && !sepOp(cx, sb))
-            return DenseElementResult::Failure;
+            return false;
     }
 
-    return DenseElementResult::Incomplete;
+    return true;
 }
 
-template <typename SeparatorOp>
-struct ArrayJoinDenseKernelFunctor {
-    JSContext* cx;
-    SeparatorOp sepOp;
-    HandleObject obj;
-    uint32_t length;
-    StringBuffer& sb;
-    uint32_t* numProcessed;
-
-    ArrayJoinDenseKernelFunctor(JSContext* cx, SeparatorOp sepOp, HandleObject obj,
-                                uint32_t length, StringBuffer& sb, uint32_t* numProcessed)
-      : cx(cx), sepOp(sepOp), obj(obj), length(length), sb(sb), numProcessed(numProcessed)
-    {}
-
-    template <JSValueType Type>
-    DenseElementResult operator()() {
-        return ArrayJoinDenseKernel<SeparatorOp, Type>(cx, sepOp, obj, length, sb, numProcessed);
-    }
-};
-
 template <typename SeparatorOp>
 static bool
 ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t length,
@@ -1136,10 +1110,10 @@ ArrayJoinKernel(JSContext* cx, SeparatorOp sepOp, HandleObject obj, uint32_t len
     uint32_t i = 0;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
-        ArrayJoinDenseKernelFunctor<SeparatorOp> functor(cx, sepOp, obj, length, sb, &i);
-        DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
-        if (result == DenseElementResult::Failure)
+        if (!ArrayJoinDenseKernel<SeparatorOp>(cx, sepOp, obj.as<NativeObject>(), length, sb, &i))
+        {
             return false;
+        }
     }
 
     if (i != length) {
@@ -1260,7 +1234,7 @@ js::array_join(JSContext* cx, unsigned argc, Value* vp)
     }
 
     // Step 11
-    JSString *str = sb.finishString();
+    JSString* str = sb.finishString();
     if (!str)
         return false;
 
@@ -1360,15 +1334,14 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
     return true;
 }
 
-template <JSValueType Type>
-DenseElementResult
-ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
+static DenseElementResult
+ArrayReverseDenseKernel(JSContext* cx, HandleNativeObject obj, uint32_t length)
 {
     /* An empty array or an array with no elements is already reversed. */
-    if (length == 0 || obj->as<NativeObject>().getDenseInitializedLength() == 0)
+    if (length == 0 || obj->getDenseInitializedLength() == 0)
         return DenseElementResult::Success;
 
-    if (obj->as<NativeObject>().denseElementsAreFrozen())
+    if (obj->denseElementsAreFrozen())
         return DenseElementResult::Incomplete;
 
     /*
@@ -1380,26 +1353,26 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
      * holes in the array at its start) and ensure that the capacity is
      * sufficient to hold all the elements in the array if it were full.
      */
-    DenseElementResult result = obj->as<NativeObject>().ensureDenseElements(cx, length, 0);
+    DenseElementResult result = obj->ensureDenseElements(cx, length, 0);
     if (result != DenseElementResult::Success)
         return result;
 
     /* Fill out the array's initialized length to its proper length. */
-    obj->as<NativeObject>().ensureDenseInitializedLength(cx, length, 0);
+    obj->ensureDenseInitializedLength(cx, length, 0);
 
     RootedValue origlo(cx), orighi(cx);
 
     uint32_t lo = 0, hi = length - 1;
     for (; lo < hi; lo++, hi--) {
-        origlo = obj->as<NativeObject>().getDenseElement(lo);
-        orighi = obj->as<NativeObject>().getDenseElement(hi);
-        obj->as<NativeObject>().setDenseElement(lo, orighi);
+        origlo = obj->getDenseElement(lo);
+        orighi = obj->getDenseElement(hi);
+        obj->setDenseElement(lo, orighi);
         if (orighi.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(lo)))
         {
             return DenseElementResult::Failure;
         }
-        obj->as<NativeObject>().setDenseElement(hi, origlo);
+        obj->setDenseElement(hi, origlo);
         if (origlo.isMagic(JS_ELEMENTS_HOLE) &&
             !SuppressDeletedProperty(cx, obj, INT_TO_JSID(hi)))
         {
@@ -1410,9 +1383,6 @@ ArrayReverseDenseKernel(JSContext* cx, HandleObject obj, uint32_t length)
     return DenseElementResult::Success;
 }
 
-DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
-                             JSContext*, HandleObject, uint32_t);
-
 bool
 js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -1427,8 +1397,8 @@ js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
-        ArrayReverseDenseKernelFunctor functor(cx, obj, len);
-        DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+        DenseElementResult result =
+            ArrayReverseDenseKernel(cx, obj.as<NativeObject>(), uint32_t(len));
         if (result != DenseElementResult::Incomplete) {
             /*
              * Per ECMA-262, don't update the length of the array, even if the new
@@ -2137,33 +2107,20 @@ js::array_pop(JSContext* cx, unsigned argc, Value* vp)
     return SetLengthProperty(cx, obj, index);
 }
 
-template <JSValueType Type>
-static inline DenseElementResult
-ShiftMoveBoxedOrUnboxedDenseElements(JSObject* obj)
+void
+js::ArrayShiftMoveElements(NativeObject* obj)
 {
-    MOZ_ASSERT(obj->isNative());
+    MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
 
-    size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+    size_t initlen = obj->getDenseInitializedLength();
+    MOZ_ASSERT(initlen > 0);
 
     /*
      * At this point the length and initialized length have already been
      * decremented and the result fetched, so just shift the array elements
      * themselves.
      */
-    obj->as<NativeObject>().moveDenseElementsNoPreBarrier(0, 1, initlen);
-
-    return DenseElementResult::Success;
-}
-
-DefineBoxedOrUnboxedFunctor1(ShiftMoveBoxedOrUnboxedDenseElements, JSObject*);
-
-void
-js::ArrayShiftMoveElements(JSObject* obj)
-{
-    MOZ_ASSERT_IF(obj->is<ArrayObject>(), obj->as<ArrayObject>().lengthIsWritable());
-
-    ShiftMoveBoxedOrUnboxedDenseElementsFunctor functor(obj);
-    JS_ALWAYS_TRUE(CallBoxedOrUnboxedSpecialization(functor, obj) == DenseElementResult::Success);
+    obj->moveDenseElementsNoPreBarrier(0, 1, initlen - 1);
 }
 
 static inline void
@@ -2175,8 +2132,7 @@ SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen)
         obj->shrinkElements(cx, initlen);
 }
 
-template <JSValueType Type>
-DenseElementResult
+static DenseElementResult
 ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
     if (ObjectMayHaveExtraIndexedProperties(obj))
@@ -2205,9 +2161,6 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     return DenseElementResult::Success;
 }
 
-DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
-                             JSContext*, HandleObject, MutableHandleValue);
-
 /* ES5 15.4.4.9 */
 bool
 js::array_shift(JSContext* cx, unsigned argc, Value* vp)
@@ -2239,8 +2192,7 @@ js::array_shift(JSContext* cx, unsigned argc, Value* vp)
     uint32_t newlen = len - 1;
 
     /* Fast paths. */
-    ArrayShiftDenseKernelFunctor functor(cx, obj, args.rval());
-    DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
+    DenseElementResult result = ArrayShiftDenseKernel(cx, obj, args.rval());
     if (result != DenseElementResult::Incomplete) {
         if (result == DenseElementResult::Failure)
             return false;
@@ -2999,11 +2951,10 @@ js::array_slice(JSContext* cx, unsigned argc, Value* vp)
     return true;
 }
 
-template <JSValueType Type>
-DenseElementResult
-ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t endArg, JSObject* result)
+static bool
+ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, int32_t beginArg, int32_t endArg, ArrayObject* result)
 {
-    int32_t length = obj->as<ArrayObject>().length();
+    int32_t length = arr->length();
 
     uint32_t begin = NormalizeSliceTerm(beginArg, length);
     uint32_t end = NormalizeSliceTerm(endArg, length);
@@ -3011,34 +2962,33 @@ ArraySliceDenseKernel(JSContext* cx, JSObject* obj, int32_t beginArg, int32_t en
     if (begin > end)
         begin = end;
 
-    size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+    size_t initlen = arr->getDenseInitializedLength();
     size_t count = Min<size_t>(initlen - begin, end - begin);
     if (initlen > begin) {
         if (count) {
-            if (!result->as<ArrayObject>().ensureElements(cx, count))
-                return DenseElementResult::Failure;
-            CopyBoxedOrUnboxedDenseElements(cx, result, obj, 0, begin, count);
+            if (!result->ensureElements(cx, count))
+                return false;
+            CopyBoxedOrUnboxedDenseElements(cx, result, arr, 0, begin, count);
         }
     }
 
-    MOZ_ASSERT(count >= result->as<ArrayObject>().length());
-    result->as<ArrayObject>().setLength(cx, count);
+    MOZ_ASSERT(count >= result->length());
+    result->setLength(cx, count);
 
-    return DenseElementResult::Success;
+    return true;
 }
 
-DefineBoxedOrUnboxedFunctor5(ArraySliceDenseKernel,
-                             JSContext*, JSObject*, int32_t, int32_t, JSObject*);
-
 JSObject*
 js::array_slice_dense(JSContext* cx, HandleObject obj, int32_t begin, int32_t end,
                       HandleObject result)
 {
     if (result && IsArraySpecies(cx, obj)) {
-        ArraySliceDenseKernelFunctor functor(cx, obj, begin, end, result);
-        DenseElementResult rv = CallBoxedOrUnboxedSpecialization(functor, result);
-        MOZ_ASSERT(rv != DenseElementResult::Incomplete);
-        return rv == DenseElementResult::Success ? result : nullptr;
+        if (!ArraySliceDenseKernel(cx, &obj->as<ArrayObject>(), begin, end,
+                                   &result->as<ArrayObject>()))
+        {
+            return nullptr;
+        }
+        return result;
     }
 
     // Slower path if the JIT wasn't able to allocate an object inline.
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index ecde87c3b..1bee742ce 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -168,7 +168,7 @@ extern bool
 array_join(JSContext* cx, unsigned argc, js::Value* vp);
 
 extern void
-ArrayShiftMoveElements(JSObject* obj);
+ArrayShiftMoveElements(NativeObject* obj);
 
 extern bool
 array_shift(JSContext* cx, unsigned argc, js::Value* vp);
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index b308464fe..711a064f2 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -244,127 +244,6 @@ CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
     return DenseElementResult::Success;
 }
 
-/////////////////////////////////////////////////////////////////////
-// Dispatch to specialized methods based on the type of an object.
-/////////////////////////////////////////////////////////////////////
-
-// Goop to fix MSVC. See DispatchTraceKindTyped in TraceKind.h.
-// The clang-cl front end defines _MSC_VER, but still requires the explicit
-// template declaration, so we must test for __clang__ here as well.
-#if defined(_MSC_VER) && !defined(__clang__)
-# define DEPENDENT_TEMPLATE_HINT
-#else
-# define DEPENDENT_TEMPLATE_HINT template
-#endif
-
-// Function to dispatch a method specialized to whatever boxed or unboxed dense
-// elements which an input object has.
-template <typename F>
-DenseElementResult
-CallBoxedOrUnboxedSpecialization(F f, JSObject* obj)
-{
-    if (!obj->isNative())
-        return DenseElementResult::Incomplete;
-    return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC>();
-}
-
-// As above, except the specialization can reflect the unboxed type of two objects.
-template <typename F>
-DenseElementResult
-CallBoxedOrUnboxedSpecialization(F f, JSObject* obj1, JSObject* obj2)
-{
-    if (!obj1->isNative() || !obj2->isNative())
-        return DenseElementResult::Incomplete;
-
-    return f. DEPENDENT_TEMPLATE_HINT operator()<JSVAL_TYPE_MAGIC, JSVAL_TYPE_MAGIC>();
-}
-
-#undef DEPENDENT_TEMPLATE_HINT
-
-#define DefineBoxedOrUnboxedFunctor1(Signature, A)                      \
-struct Signature ## Functor {                                           \
-    A a;                                                                \
-    explicit Signature ## Functor(A a)                                  \
-      : a(a)                                                            \
-    {}                                                                  \
-    template <JSValueType Type>                                         \
-    DenseElementResult operator()() {                                   \
-        return Signature<Type>(a);                                      \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctor3(Signature, A, B, C)                \
-struct Signature ## Functor {                                           \
-    A a; B b; C c;                                                      \
-    Signature ## Functor(A a, B b, C c)                                 \
-      : a(a), b(b), c(c)                                                \
-    {}                                                                  \
-    template <JSValueType Type>                                         \
-    DenseElementResult operator()() {                                   \
-        return Signature<Type>(a, b, c);                                \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctor4(Signature, A, B, C, D)             \
-struct Signature ## Functor {                                           \
-    A a; B b; C c; D d;                                                 \
-    Signature ## Functor(A a, B b, C c, D d)                            \
-      : a(a), b(b), c(c), d(d)                                          \
-    {}                                                                  \
-    template <JSValueType Type>                                         \
-    DenseElementResult operator()() {                                   \
-        return Signature<Type>(a, b, c, d);                             \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctorPair4(Signature, A, B, C, D)         \
-struct Signature ## Functor {                                           \
-    A a; B b; C c; D d;                                                 \
-    Signature ## Functor(A a, B b, C c, D d)                            \
-      : a(a), b(b), c(c), d(d)                                          \
-    {}                                                                  \
-    template <JSValueType TypeOne, JSValueType TypeTwo>                 \
-    DenseElementResult operator()() {                                   \
-        return Signature<TypeOne, TypeTwo>(a, b, c, d);                 \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctor5(Signature, A, B, C, D, E)          \
-struct Signature ## Functor {                                           \
-    A a; B b; C c; D d; E e;                                            \
-    Signature ## Functor(A a, B b, C c, D d, E e)                       \
-      : a(a), b(b), c(c), d(d), e(e)                                    \
-    {}                                                                  \
-    template <JSValueType Type>                                         \
-    DenseElementResult operator()() {                                   \
-        return Signature<Type>(a, b, c, d, e);                          \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctor6(Signature, A, B, C, D, E, F)       \
-struct Signature ## Functor {                                           \
-    A a; B b; C c; D d; E e; F f;                                       \
-    Signature ## Functor(A a, B b, C c, D d, E e, F f)                  \
-      : a(a), b(b), c(c), d(d), e(e), f(f)                              \
-    {}                                                                  \
-    template <JSValueType Type>                                         \
-    DenseElementResult operator()() {                                   \
-        return Signature<Type>(a, b, c, d, e, f);                       \
-    }                                                                   \
-}
-
-#define DefineBoxedOrUnboxedFunctorPair6(Signature, A, B, C, D, E, F)   \
-struct Signature ## Functor {                                           \
-    A a; B b; C c; D d; E e; F f;                                       \
-    Signature ## Functor(A a, B b, C c, D d, E e, F f)                  \
-      : a(a), b(b), c(c), d(d), e(e), f(f)                              \
-    {}                                                                  \
-    template <JSValueType TypeOne, JSValueType TypeTwo>                 \
-    DenseElementResult operator()() {                                   \
-        return Signature<TypeOne, TypeTwo>(a, b, c, d, e, f);           \
-    }                                                                   \
-}
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h
-- 
cgit v1.2.3


From 9153838ea299da3bd00767394ff021318c1e0f12 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Mon, 17 Jun 2019 15:09:05 +0000
Subject: Fix typo in ArrayShiftMoveElements

---
 js/src/jsarray.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'js/src')

diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 9abc99e34..7af7c9800 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2120,7 +2120,7 @@ js::ArrayShiftMoveElements(NativeObject* obj)
      * decremented and the result fetched, so just shift the array elements
      * themselves.
      */
-    obj->moveDenseElementsNoPreBarrier(0, 1, initlen - 1);
+    obj->moveDenseElementsNoPreBarrier(0, 1, initlen);
 }
 
 static inline void
-- 
cgit v1.2.3


From 3c878b1e3bbb043b22ab032bce1fe111b8062ca9 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Mon, 17 Jun 2019 18:37:23 +0000
Subject: Convert CopyBoxedOrUnboxedDenseElements to something that doesn't
 crash.

---
 js/src/jit/BaselineIC.cpp     | 14 ++++++++++++--
 js/src/jsarray.cpp            | 24 +++++++++++++++++++++---
 js/src/vm/UnboxedObject-inl.h | 18 ------------------
 3 files changed, 33 insertions(+), 23 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 2b0822655..17fdb1807 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5769,8 +5769,18 @@ CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
     if (!nobj)
         return false;
     EnsureArrayGroupAnalyzed(cx, nobj); //XXX
-    CopyBoxedOrUnboxedDenseElements(cx, nobj, arr, 0, 0, length);
-
+	
+    MOZ_ASSERT(arr->isNative());
+    MOZ_ASSERT(nobj->isNative());
+    MOZ_ASSERT(nobj->as<NativeObject>().getDenseInitializedLength() == 0);
+    MOZ_ASSERT(arr->as<NativeObject>().getDenseInitializedLength() >= length);
+    MOZ_ASSERT(nobj->as<NativeObject>().getDenseCapacity() >= length);
+
+    nobj->as<NativeObject>().setDenseInitializedLength(length);
+
+    const Value* vp = arr->as<NativeObject>().getDenseElements();
+    nobj->as<NativeObject>().initDenseElements(0, vp, length);
+	
     result.setObject(*nobj);
     return true;
 }
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 7af7c9800..159717fea 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2361,6 +2361,22 @@ CanOptimizeForDenseStorage(HandleObject arr, uint32_t startingIndex, uint32_t co
            startingIndex + count <= arr->as<NativeObject>().getDenseInitializedLength();
 }
 
+static inline DenseElementResult
+CopyDenseElements(JSContext* cx, NativeObject* dst, NativeObject* src,
+                      uint32_t dstStart, uint32_t srcStart, uint32_t length)
+{
+    MOZ_ASSERT(dst->getDenseInitializedLength() == dstStart);
+    MOZ_ASSERT(src->getDenseInitializedLength() >= srcStart + length);
+    MOZ_ASSERT(dst->getDenseCapacity() >= dstStart + length);
+
+    dst->setDenseInitializedLength(dstStart + length);
+
+    const Value* vp = src->getDenseElements() + srcStart;
+    dst->initDenseElements(dstStart, vp, length);
+
+    return DenseElementResult::Success;
+}
+
 /* ES 2016 draft Mar 25, 2016 22.1.3.26. */
 bool
 js::array_splice(JSContext* cx, unsigned argc, Value* vp)
@@ -2459,7 +2475,9 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
 
                 /* Steps 10-11. */
                 DebugOnly<DenseElementResult> result =
-                    CopyBoxedOrUnboxedDenseElements(cx, arr, obj, 0, actualStart, actualDeleteCount);
+                    CopyDenseElements(cx, &arr->as<NativeObject>(), 
+					                  &obj->as<NativeObject>(), 0, 
+									  actualStart, actualDeleteCount);
                 MOZ_ASSERT(result.value == DenseElementResult::Success);
 
                 /* Step 12 (implicit). */
@@ -2827,7 +2845,7 @@ ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint32_t length, uint32_t be
 
         if (count) {
             DebugOnly<DenseElementResult> result =
-                CopyBoxedOrUnboxedDenseElements(cx, narr, obj, 0, begin, count);
+                CopyDenseElements(cx, &narr->as<NativeObject>(), &obj->as<NativeObject>(), 0, begin, count);
             MOZ_ASSERT(result.value == DenseElementResult::Success);
         }
         arr.set(narr);
@@ -2968,7 +2986,7 @@ ArraySliceDenseKernel(JSContext* cx, ArrayObject* arr, int32_t beginArg, int32_t
         if (count) {
             if (!result->ensureElements(cx, count))
                 return false;
-            CopyBoxedOrUnboxedDenseElements(cx, result, arr, 0, begin, count);
+            CopyDenseElements(cx, &result->as<NativeObject>(), &arr->as<NativeObject>(), 0, begin, count);
         }
     }
 
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 711a064f2..069527141 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -226,24 +226,6 @@ MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart,
     return DenseElementResult::Success;
 }
 
-static inline DenseElementResult
-CopyBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* dst, JSObject* src,
-                                uint32_t dstStart, uint32_t srcStart, uint32_t length)
-{
-    MOZ_ASSERT(src->isNative());
-    MOZ_ASSERT(dst->isNative());
-    MOZ_ASSERT(dst->as<NativeObject>().getDenseInitializedLength() == dstStart);
-    MOZ_ASSERT(src->as<NativeObject>().getDenseInitializedLength() >= srcStart + length);
-    MOZ_ASSERT(dst->as<NativeObject>().getDenseCapacity() >= dstStart + length);
-
-    dst->as<NativeObject>().setDenseInitializedLength(dstStart + length);
-
-    const Value* vp = src->as<NativeObject>().getDenseElements() + srcStart;
-    dst->as<NativeObject>().initDenseElements(dstStart, vp, length);
-
-    return DenseElementResult::Success;
-}
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h
-- 
cgit v1.2.3


From 8d2929313f6f8be66770f1137fa54a0825a3c768 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Thu, 13 Jun 2019 11:42:21 +0000
Subject: Clean up and rename MoveBoxedOrUnboxedDenseElements.

---
 js/src/jsarray.cpp            | 25 +++++++++++++++++++------
 js/src/vm/UnboxedObject-inl.h | 16 ----------------
 2 files changed, 19 insertions(+), 22 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 159717fea..97f035fd9 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2132,6 +2132,20 @@ SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen)
         obj->shrinkElements(cx, initlen);
 }
 
+static DenseElementResult
+MoveDenseElements(JSContext* cx, NativeObject* obj, uint32_t dstStart, uint32_t srcStart,
+                  uint32_t length)
+{
+    if (obj->denseElementsAreFrozen())
+        return DenseElementResult::Incomplete;
+
+    if (!obj->maybeCopyElementsForWrite(cx))
+        return DenseElementResult::Failure;
+    obj->moveDenseElements(dstStart, srcStart, length);
+
+    return DenseElementResult::Success;
+}
+
 static DenseElementResult
 ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
@@ -2153,7 +2167,7 @@ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
     if (rval.isMagic(JS_ELEMENTS_HOLE))
         rval.setUndefined();
 
-    DenseElementResult result = MoveBoxedOrUnboxedDenseElements(cx, obj, 0, 1, initlen - 1);
+    DenseElementResult result = MoveDenseElements(cx, &obj->as<NativeObject>(), 0, 1, initlen - 1);
     if (result != DenseElementResult::Success)
         return result;
 
@@ -2514,8 +2528,7 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
         if (CanOptimizeForDenseStorage(obj, 0, len, cx)) {
             /* Steps 15.a-b. */
             DenseElementResult result =
-                MoveBoxedOrUnboxedDenseElements(cx, obj, targetIndex, sourceIndex,
-                                                len - sourceIndex);
+                MoveDenseElements(cx, &obj->as<NativeObject>(), targetIndex, sourceIndex, len - sourceIndex);
             MOZ_ASSERT(result != DenseElementResult::Incomplete);
             if (result == DenseElementResult::Failure)
                 return false;
@@ -2601,9 +2614,9 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
 
         if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
             DenseElementResult result =
-                MoveBoxedOrUnboxedDenseElements(cx, obj, actualStart + itemCount,
-                                                actualStart + actualDeleteCount,
-                                                len - (actualStart + actualDeleteCount));
+                MoveDenseElements(cx, &obj->as<NativeObject>(), actualStart + itemCount,
+                                  actualStart + actualDeleteCount,
+                                  len - (actualStart + actualDeleteCount));
             MOZ_ASSERT(result != DenseElementResult::Incomplete);
             if (result == DenseElementResult::Failure)
                 return false;
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 069527141..193ca75c8 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -210,22 +210,6 @@ SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
     return DenseElementResult::Success;
 }
 
-static inline DenseElementResult
-MoveBoxedOrUnboxedDenseElements(JSContext* cx, JSObject* obj, uint32_t dstStart, uint32_t srcStart,
-                                uint32_t length)
-{
-    MOZ_ASSERT(obj->isNative());
-
-    if (obj->as<NativeObject>().denseElementsAreFrozen())
-        return DenseElementResult::Incomplete;
-
-    if (!obj->as<NativeObject>().maybeCopyElementsForWrite(cx))
-        return DenseElementResult::Failure;
-    obj->as<NativeObject>().moveDenseElements(dstStart, srcStart, length);
-
-    return DenseElementResult::Success;
-}
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h
-- 
cgit v1.2.3


From 85f9a95ddbc39a1b120eeb8280685e1ae40dc5dc Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Fri, 14 Jun 2019 11:33:28 +0000
Subject: Replace SetOrExtendBoxedOrUnboxedDenseElements with direct calls.

---
 js/src/jit/CodeGenerator.cpp  | 13 ++++++-------
 js/src/jit/VMFunctions.cpp    | 23 ++++++++++-------------
 js/src/jit/VMFunctions.h      |  6 +++---
 js/src/jsarray.cpp            | 20 ++++++++++----------
 js/src/jsarray.h              |  6 ------
 js/src/vm/NativeObject-inl.h  | 32 ++++++++++++++++++++++++++++++++
 js/src/vm/NativeObject.h      |  9 +++++++++
 js/src/vm/UnboxedObject-inl.h | 38 --------------------------------------
 8 files changed, 70 insertions(+), 77 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index ae9c61031..e0b8a7f28 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8213,11 +8213,10 @@ CodeGenerator::visitFallibleStoreElementV(LFallibleStoreElementV* lir)
     masm.bind(&isFrozen);
 }
 
-typedef bool (*SetDenseOrUnboxedArrayElementFn)(JSContext*, HandleObject, int32_t,
-                                                HandleValue, bool strict);
-static const VMFunction SetDenseOrUnboxedArrayElementInfo =
-    FunctionInfo<SetDenseOrUnboxedArrayElementFn>(SetDenseOrUnboxedArrayElement,
-                                                  "SetDenseOrUnboxedArrayElement");
+typedef bool (*SetDenseElementFn)(JSContext*, HandleNativeObject, int32_t, HandleValue,
+                                  bool strict);
+static const VMFunction SetDenseElementInfo =
+    FunctionInfo<SetDenseElementFn>(jit::SetDenseElement, "SetDenseElement");
 
 void
 CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
@@ -8326,7 +8325,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
     else
         pushArg(ToRegister(index));
     pushArg(object);
-    callVM(SetDenseOrUnboxedArrayElementInfo, ins);
+    callVM(SetDenseElementInfo, ins);
 
     restoreLive(ins);
     masm.jump(ool->rejoin());
@@ -8500,7 +8499,7 @@ CodeGenerator::visitArrayPopShiftT(LArrayPopShiftT* lir)
     emitArrayPopShift(lir, lir->mir(), obj, elements, length, out);
 }
 
-typedef bool (*ArrayPushDenseFn)(JSContext*, HandleObject, HandleValue, uint32_t*);
+typedef bool (*ArrayPushDenseFn)(JSContext*, HandleArrayObject, HandleValue, uint32_t*);
 static const VMFunction ArrayPushDenseInfo =
     FunctionInfo<ArrayPushDenseFn>(jit::ArrayPushDense, "ArrayPushDense");
 
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index 7b1e1cad6..297357b1e 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -337,12 +337,11 @@ ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 }
 
 bool
-ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
+ArrayPushDense(JSContext* cx, HandleArrayObject arr, HandleValue v, uint32_t* length)
 {
-    *length = obj->as<ArrayObject>().length();
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, *length, v.address(), 1,
-                                               ShouldUpdateTypes::DontUpdate);
+    *length = arr->length();
+    DenseElementResult result = arr->setOrExtendDenseElements(cx, *length, v.address(), 1,
+                                                              ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete) {
         (*length)++;
         return result == DenseElementResult::Success;
@@ -350,7 +349,7 @@ ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length)
 
     JS::AutoValueArray<3> argv(cx);
     argv[0].setUndefined();
-    argv[1].setObject(*obj);
+    argv[1].setObject(*arr);
     argv[2].set(v);
     if (!js::array_push(cx, 1, argv.begin()))
         return false;
@@ -1143,16 +1142,14 @@ Recompile(JSContext* cx)
 }
 
 bool
-SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
-                              HandleValue value, bool strict)
+SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index, HandleValue value, bool strict)
 {
     // This function is called from Ion code for StoreElementHole's OOL path.
-    // In this case we know the object is native or an unboxed array and that
-    // no type changes are needed.
+    // In this case we know the object is native and that no type changes are
+	// needed.
 
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, index, value.address(), 1,
-                                               ShouldUpdateTypes::DontUpdate);
+    DenseElementResult result = obj->setOrExtendDenseElements(cx, index, value.address(), 1,
+                                                              ShouldUpdateTypes::DontUpdate);
     if (result != DenseElementResult::Incomplete)
         return result == DenseElementResult::Success;
 
diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h
index 572f05373..9a2edd0f3 100644
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -622,7 +622,7 @@ template<bool Equal>
 bool StringsEqual(JSContext* cx, HandleString left, HandleString right, bool* res);
 
 MOZ_MUST_USE bool ArrayPopDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
-MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleObject obj, HandleValue v, uint32_t* length);
+MOZ_MUST_USE bool ArrayPushDense(JSContext* cx, HandleArrayObject obj, HandleValue v, uint32_t* length);
 MOZ_MUST_USE bool ArrayShiftDense(JSContext* cx, HandleObject obj, MutableHandleValue rval);
 JSString* ArrayJoin(JSContext* cx, HandleObject array, HandleString sep);
 
@@ -748,8 +748,8 @@ ForcedRecompile(JSContext* cx);
 JSString* StringReplace(JSContext* cx, HandleString string, HandleString pattern,
                         HandleString repl);
 
-MOZ_MUST_USE bool SetDenseOrUnboxedArrayElement(JSContext* cx, HandleObject obj, int32_t index,
-                                                HandleValue value, bool strict);
+MOZ_MUST_USE bool SetDenseElement(JSContext* cx, HandleNativeObject obj, int32_t index,
+                                  HandleValue value, bool strict);
 
 void AssertValidObjectPtr(JSContext* cx, JSObject* obj);
 void AssertValidObjectOrNullPtr(JSContext* cx, JSObject* obj);
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 97f035fd9..b77a5bce8 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -280,8 +280,8 @@ ElementAdder::append(JSContext* cx, HandleValue v)
 {
     MOZ_ASSERT(index_ < length_);
     if (resObj_) {
-        DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, resObj_, index_, v.address(), 1);
+        NativeObject* resObj = &resObj_->as<NativeObject>();
+        DenseElementResult result = resObj->setOrExtendDenseElements(cx, index_, v.address(), 1);
         if (result == DenseElementResult::Failure)
             return false;
         if (result == DenseElementResult::Incomplete) {
@@ -390,8 +390,8 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
     MOZ_ASSERT(index >= 0);
 
     if (obj->is<ArrayObject>() && !obj->isIndexed() && index <= UINT32_MAX) {
-        DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, uint32_t(index), v.address(), 1);
+        NativeObject* nobj = &obj->as<NativeObject>();
+        DenseElementResult result = nobj->setOrExtendDenseElements(cx, uint32_t(index), v.address(), 1);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
     }
@@ -1299,8 +1299,9 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start,
         return false;
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
-        DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, start, vector, count, updateTypes);
+        NativeObject* nobj = &obj->as<NativeObject>();
+        DenseElementResult result = nobj->setOrExtendDenseElements(cx, uint32_t(start), vector,
+                                                                   count, updateTypes);
         if (result != DenseElementResult::Incomplete)
             return result == DenseElementResult::Success;
     }
@@ -2041,8 +2042,8 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp)
 
     if (!ObjectMayHaveExtraIndexedProperties(obj)) {
         DenseElementResult result =
-            SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, length,
-                                                   args.array(), args.length());
+            obj->as<NativeObject>().setOrExtendDenseElements(cx, uint32_t(length),
+                                                             args.array(), args.length());
         if (result != DenseElementResult::Incomplete) {
             if (result == DenseElementResult::Failure)
                 return false;
@@ -3663,8 +3664,7 @@ js::NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
     if (!obj)
         return nullptr;
 
-    DenseElementResult result =
-        SetOrExtendBoxedOrUnboxedDenseElements(cx, obj, 0, vp, length, updateTypes);
+    DenseElementResult result = obj->setOrExtendDenseElements(cx->asJSContext(), 0, vp, length, updateTypes);
     if (result == DenseElementResult::Failure)
         return nullptr;
     MOZ_ASSERT(result == DenseElementResult::Success);
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index 1bee742ce..36cac743d 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -98,12 +98,6 @@ NewFullyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length,
 extern ArrayObject*
 NewPartlyAllocatedArrayForCallingAllocationSite(JSContext* cx, size_t length, HandleObject proto);
 
-enum class ShouldUpdateTypes
-{
-    Update,
-    DontUpdate
-};
-
 extern ArrayObject*
 NewCopiedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group,
                           const Value* vp, size_t length,
diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h
index 48a42a8db..052a3385c 100644
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -235,6 +235,38 @@ NativeObject::ensureDenseElements(ExclusiveContext* cx, uint32_t index, uint32_t
     return DenseElementResult::Success;
 }
 
+inline DenseElementResult
+NativeObject::setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp,
+                                       uint32_t count,
+                                       ShouldUpdateTypes updateTypes)
+{
+    if (denseElementsAreFrozen())
+        return DenseElementResult::Incomplete;
+
+    if (is<ArrayObject>() &&
+        !as<ArrayObject>().lengthIsWritable() &&
+        start + count >= as<ArrayObject>().length())
+    {
+        return DenseElementResult::Incomplete;
+    }
+
+    DenseElementResult result = ensureDenseElements(cx, start, count);
+    if (result != DenseElementResult::Success)
+        return result;
+
+    if (is<ArrayObject>() && start + count >= as<ArrayObject>().length())
+        as<ArrayObject>().setLengthInt32(start + count);
+
+    if (updateTypes == ShouldUpdateTypes::DontUpdate && !shouldConvertDoubleElements()) {
+        copyDenseElements(start, vp, count);
+    } else {
+        for (size_t i = 0; i < count; i++)
+            setDenseElementWithType(cx, start + i, vp[i]);
+    }
+
+    return DenseElementResult::Success;
+}
+
 inline Value
 NativeObject::getDenseOrTypedArrayElement(uint32_t idx)
 {
diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 4dbc167ab..4957a01d2 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -349,6 +349,11 @@ enum class DenseElementResult {
     Incomplete
 };
 
+enum class ShouldUpdateTypes {
+    Update,
+    DontUpdate
+};
+
 /*
  * NativeObject specifies the internal implementation of a native object.
  *
@@ -1147,6 +1152,10 @@ class NativeObject : public ShapedObject
         elementsRangeWriteBarrierPost(dstStart, count);
     }
 
+    inline DenseElementResult
+    setOrExtendDenseElements(JSContext* cx, uint32_t start, const Value* vp, uint32_t count,
+                             ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update);
+
     bool shouldConvertDoubleElements() {
         return getElementsHeader()->shouldConvertDoubleElements();
     }
diff --git a/js/src/vm/UnboxedObject-inl.h b/js/src/vm/UnboxedObject-inl.h
index 193ca75c8..c1468a5b1 100644
--- a/js/src/vm/UnboxedObject-inl.h
+++ b/js/src/vm/UnboxedObject-inl.h
@@ -172,44 +172,6 @@ UnboxedPlainObject::layout() const
     return group()->unboxedLayout();
 }
 
-/////////////////////////////////////////////////////////////////////
-// Template methods for NativeObject and UnboxedArrayObject accesses.
-/////////////////////////////////////////////////////////////////////
-
-static inline DenseElementResult
-SetOrExtendBoxedOrUnboxedDenseElements(ExclusiveContext* cx, JSObject* obj,
-                                       uint32_t start, const Value* vp, uint32_t count,
-                                       ShouldUpdateTypes updateTypes = ShouldUpdateTypes::Update)
-{
-    NativeObject* nobj = &obj->as<NativeObject>();
-
-    if (nobj->denseElementsAreFrozen())
-        return DenseElementResult::Incomplete;
-
-    if (obj->is<ArrayObject>() &&
-        !obj->as<ArrayObject>().lengthIsWritable() &&
-        start + count >= obj->as<ArrayObject>().length())
-    {
-        return DenseElementResult::Incomplete;
-    }
-
-    DenseElementResult result = nobj->ensureDenseElements(cx, start, count);
-    if (result != DenseElementResult::Success)
-        return result;
-
-    if (obj->is<ArrayObject>() && start + count >= obj->as<ArrayObject>().length())
-        obj->as<ArrayObject>().setLengthInt32(start + count);
-
-    if (updateTypes == ShouldUpdateTypes::DontUpdate && !nobj->shouldConvertDoubleElements()) {
-        nobj->copyDenseElements(start, vp, count);
-    } else {
-        for (size_t i = 0; i < count; i++)
-            nobj->setDenseElementWithType(cx, start + i, vp[i]);
-    }
-
-    return DenseElementResult::Success;
-}
-
 } // namespace js
 
 #endif // vm_UnboxedObject_inl_h
-- 
cgit v1.2.3


From e9aac71c6d7fa67c7581e2bd75accae5a9699165 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 16 Jun 2019 19:55:05 +0000
Subject: Remove and clean up more code.

---
 js/src/jit/BaselineIC.cpp   | 23 +++--------------------
 js/src/jit/MIR.h            | 10 +++++-----
 js/src/jsarray.cpp          | 32 ++++++++++----------------------
 js/src/jsarray.h            |  2 --
 js/src/vm/Interpreter.cpp   |  5 +----
 js/src/vm/ObjectGroup.cpp   | 34 +++-------------------------------
 js/src/vm/TypeInference.cpp |  4 ++--
 js/src/vm/TypeInference.h   |  4 ++--
 8 files changed, 26 insertions(+), 88 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 17fdb1807..9151d9634 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5365,13 +5365,6 @@ GetTemplateObjectForSimd(JSContext* cx, JSFunction* target, MutableHandleObject
     return true;
 }
 
-static void
-EnsureArrayGroupAnalyzed(JSContext* cx, JSObject* obj)
-{
-    if (PreliminaryObjectArrayWithTemplate* objects = obj->group()->maybePreliminaryObjects())
-        objects->maybeAnalyze(cx, obj->group(), /* forceAnalyze = */ true);
-}
-
 static bool
 GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs& args,
                            MutableHandleObject res, bool* skipAttach)
@@ -5403,10 +5396,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
             // With this and other array templates, analyze the group so that
             // we don't end up with a template whose structure might change later.
             res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count, TenuredObject));
-            if (!res)
-                return false;
-            EnsureArrayGroupAnalyzed(cx, res);
-            return true;
+            return !!res;
         }
     }
 
@@ -5432,10 +5422,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
                 }
                 res.set(NewFullyAllocatedArrayTryReuseGroup(cx, &args.thisv().toObject(), 0,
                                                             TenuredObject));
-                if (!res)
-                    return false;
-                EnsureArrayGroupAnalyzed(cx, res);
-                return true;
+                return !!res;
             }
         }
     }
@@ -5452,10 +5439,7 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
         }
 
         res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, 0, TenuredObject));
-        if (!res)
-            return false;
-        EnsureArrayGroupAnalyzed(cx, res);
-        return true;
+        return !!res;
     }
 
     if (native == StringConstructor) {
@@ -5768,7 +5752,6 @@ CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
     ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
     if (!nobj)
         return false;
-    EnsureArrayGroupAnalyzed(cx, nobj); //XXX
 	
     MOZ_ASSERT(arr->isNative());
     MOZ_ASSERT(nobj->isNative());
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index f316827dc..4bedfb268 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -9234,7 +9234,7 @@ class MLoadElement
     ALLOW_CLONE(MLoadElement)
 };
 
-// Load a value from the elements vector for a dense native or unboxed array.
+// Load a value from the elements vector of a native object.
 // If the index is out-of-bounds, or the indexed slot has a hole, undefined is
 // returned instead.
 class MLoadElementHole
@@ -9465,10 +9465,10 @@ class MStoreElement
     ALLOW_CLONE(MStoreElement)
 };
 
-// Like MStoreElement, but supports indexes >= initialized length, and can
-// handle unboxed arrays. The downside is that we cannot hoist the elements
-// vector and bounds check, since this instruction may update the (initialized)
-// length and reallocate the elements vector.
+// Like MStoreElement, but supports indexes >= initialized length. The downside
+// is that we cannot hoist the elements vector and bounds check, since this
+// instruction may update the (initialized) length and reallocate the elements
+// vector.
 class MStoreElementHole
   : public MAryInstruction<4>,
     public MStoreElementCommon,
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index b77a5bce8..6129b2b65 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2261,9 +2261,6 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
     if (args.length() > 0) {
         /* Slide up the array to make room for all args at the bottom. */
         if (length > 0) {
-            // Only include a fast path for boxed arrays. Unboxed arrays can'nt
-            // be optimized here because unshifting temporarily places holes at
-            // the start of the array.
             bool optimized = false;
             do {
                 if (!obj->is<ArrayObject>())
@@ -2323,10 +2320,10 @@ js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
 }
 
 /*
- * Returns true if this is a dense or unboxed array whose |count| properties
- * starting from |startingIndex| may be accessed (get, set, delete) directly
- * through its contiguous vector of elements without fear of getters, setters,
- * etc. along the prototype chain, or of enumerators requiring notification of
+ * Returns true if this is a dense array whose properties ending at |endIndex|
+ * (exclusive) may be accessed (get, set, delete) directly through its
+ * contiguous vector of elements without fear of getters, setters, etc. along
+ * the prototype chain, or of enumerators requiring notification of
  * modifications.
  */
 static inline bool
@@ -3550,10 +3547,10 @@ js::NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc
     return arr;
 }
 
-// Return a new boxed or unboxed array with the specified length and allocated
-// capacity (up to maxLength), using the specified group if possible. If the
-// specified group cannot be used, ensure that the created array at least has
-// the given [[Prototype]].
+// Return a new array with the specified length and allocated capacity (up to
+// maxLength), using the specified group if possible. If the specified group
+// cannot be used, ensure that the created array at least has the given
+// [[Prototype]].
 template <uint32_t maxLength>
 static inline ArrayObject*
 NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
@@ -3561,10 +3558,7 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
 {
     MOZ_ASSERT(newKind != SingletonObject);
 
-    if (group->maybePreliminaryObjects())
-        group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
-
-    if (group->shouldPreTenure() || group->maybePreliminaryObjects())
+    if (group->shouldPreTenure())
         newKind = TenuredObject;
 
     RootedObject proto(cx, group->proto().toObject());
@@ -3579,9 +3573,6 @@ NewArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length
     if (res->length() > INT32_MAX)
         res->setLength(cx, res->length());
 
-    if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
-        preliminaryObjects->registerNewObject(res);
-
     return res;
 }
 
@@ -3601,10 +3592,7 @@ js::NewPartlyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup g
 // Return a new array with the default prototype and specified allocated
 // capacity and length. If possible, try to reuse the group of the input
 // object. The resulting array will either reuse the input object's group or
-// will have unknown property types. Additionally, the result will have the
-// same boxed/unboxed elements representation as the input object, unless
-// |length| is larger than the input object's initialized length (in which case
-// UnboxedArrayObject::MaximumCapacity might be exceeded).
+// will have unknown property types.
 template <uint32_t maxLength>
 static inline ArrayObject*
 NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index 36cac743d..f9e11149f 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -75,8 +75,6 @@ NewDenseFullyAllocatedArrayWithTemplate(JSContext* cx, uint32_t length, JSObject
 extern ArrayObject*
 NewDenseCopyOnWriteArray(JSContext* cx, HandleArrayObject templateObject, gc::InitialHeap heap);
 
-// The methods below can create either boxed or unboxed arrays.
-
 extern ArrayObject*
 NewFullyAllocatedArrayTryUseGroup(ExclusiveContext* cx, HandleObjectGroup group, size_t length,
                                   NewObjectKind newKind = GenericObject);
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 7d05b2d4c..f4f6c0da4 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4933,7 +4933,7 @@ js::NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
             newKind = TenuredObject;
     }
 
-    RootedObject obj(cx);
+    RootedPlainObject obj(cx);
 
     if (*pc == JSOP_NEWOBJECT) {
         RootedPlainObject baseObject(cx, &script->getObject(pc)->as<PlainObject>());
@@ -5011,9 +5011,6 @@ js::NewArrayOperation(JSContext* cx, HandleScript script, jsbytecode* pc, uint32
         MOZ_ASSERT(obj->isSingleton());
     } else {
         obj->setGroup(group);
-
-        if (PreliminaryObjectArray* preliminaryObjects = group->maybePreliminaryObjects())
-            preliminaryObjects->registerNewObject(obj);
     }
 
     return obj;
diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp
index 6b984a803..63ac33eea 100644
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -838,17 +838,6 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
 
         AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType);
 
-        if (elementType != TypeSet::UnknownType()) {
-            // Keep track of the initial objects we create with this type.
-            // If the initial ones have a consistent shape and property types, we
-            // will try to use an unboxed layout for the group.
-            PreliminaryObjectArrayWithTemplate* preliminaryObjects =
-                cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
-            if (!preliminaryObjects)
-                return nullptr;
-            group->setPreliminaryObjects(preliminaryObjects);
-        }
-
         if (!p.add(cx, *table, ObjectGroupCompartment::ArrayObjectKey(elementType), group))
             return nullptr;
     }
@@ -856,9 +845,6 @@ ObjectGroup::newArrayObject(ExclusiveContext* cx,
     // The type of the elements being added will already be reflected in type
     // information.
     ShouldUpdateTypes updateTypes = ShouldUpdateTypes::DontUpdate;
-    if (group->maybePreliminaryObjects())
-        group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
-
     return NewCopiedArrayTryUseGroup(cx, group, vp, length, newKind, updateTypes);
 }
 
@@ -868,27 +854,13 @@ GiveObjectGroup(ExclusiveContext* cx, JSObject* source, JSObject* target)
 {
     MOZ_ASSERT(source->group() != target->group());
 
-    if (!target->is<ArrayObject>())
+    if (!target->is<ArrayObject>() || !source->is<ArrayObject>()) {
         return true;
-
-    if (target->group()->maybePreliminaryObjects()) {
-        bool force = IsInsideNursery(source);
-        target->group()->maybePreliminaryObjects()->maybeAnalyze(cx, target->group(), force);
     }
 
-    ObjectGroup* sourceGroup = source->group();
-
-    if (source->is<ArrayObject>()) {
-        source->setGroup(target->group());
-    } else {
-        return true;
-    }
+    source->setGroup(target->group());
 
-    if (sourceGroup->maybePreliminaryObjects())
-        sourceGroup->maybePreliminaryObjects()->unregisterObject(source);
-    if (target->group()->maybePreliminaryObjects())
-        target->group()->maybePreliminaryObjects()->registerNewObject(source);
-     for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
+    for (size_t i = 0; i < source->as<ArrayObject>().getDenseInitializedLength(); i++) {
         Value v = source->as<ArrayObject>().getDenseElement(i);
         AddTypePropertyId(cx, source->group(), source, JSID_VOID, v);
     }
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 2160dbc51..0551e2c58 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -3393,7 +3393,7 @@ JSFunction::setTypeForScriptedFunction(ExclusiveContext* cx, HandleFunction fun,
 /////////////////////////////////////////////////////////////////////
 
 void
-PreliminaryObjectArray::registerNewObject(JSObject* res)
+PreliminaryObjectArray::registerNewObject(PlainObject* res)
 {
     // The preliminary object pointers are weak, and won't be swept properly
     // during nursery collections, so the preliminary objects need to be
@@ -3411,7 +3411,7 @@ PreliminaryObjectArray::registerNewObject(JSObject* res)
 }
 
 void
-PreliminaryObjectArray::unregisterObject(JSObject* obj)
+PreliminaryObjectArray::unregisterObject(PlainObject* obj)
 {
     for (size_t i = 0; i < COUNT; i++) {
         if (objects[i] == obj) {
diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
index 04fed448c..94ce7e871 100644
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -814,8 +814,8 @@ class PreliminaryObjectArray
   public:
     PreliminaryObjectArray() = default;
 
-    void registerNewObject(JSObject* res);
-    void unregisterObject(JSObject* obj);
+    void registerNewObject(PlainObject* res);
+    void unregisterObject(PlainObject* obj);
 
     JSObject* get(size_t i) const {
         MOZ_ASSERT(i < COUNT);
-- 
cgit v1.2.3


From 625366321008cc464f4295db80c48dd5a19f3ee4 Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 16 Jun 2019 20:06:39 +0000
Subject: Update comment

---
 js/src/vm/NativeObject.h | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'js/src')

diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 4957a01d2..da4f873a6 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -339,10 +339,8 @@ IsObjectValueInCompartment(const Value& v, JSCompartment* comp);
 #endif
 
 // Operations which change an object's dense elements can either succeed, fail,
-// or be unable to complete. For native objects, the latter is used when the
-// object's elements must become sparse instead. The enum below is used for
-// such operations, and for similar operations on unboxed arrays and methods
-// that work on both kinds of objects.
+// or be unable to complete. The latter is used when the object's elements must
+// become sparse instead. The enum below is used for such operations.
 enum class DenseElementResult {
     Failure,
     Success,
-- 
cgit v1.2.3


From 772cd4b188fd9f30521d4983f60363f4a830e2aa Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 16 Jun 2019 23:13:47 +0000
Subject: Remove JSOP_SPREADCALLARRAY and just use JSOP_NEWARRAY again.

---
 js/src/frontend/BytecodeEmitter.cpp |  9 ++++-----
 js/src/frontend/BytecodeEmitter.h   |  2 +-
 js/src/jit/BaselineCompiler.cpp     |  6 ------
 js/src/jit/BaselineCompiler.h       |  1 -
 js/src/jit/IonBuilder.cpp           |  2 ++
 js/src/vm/Interpreter.cpp           |  2 +-
 js/src/vm/Opcodes.h                 | 12 +-----------
 7 files changed, 9 insertions(+), 25 deletions(-)

(limited to 'js/src')

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index ea6baeec7..7f9fa8a5d 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -9192,7 +9192,7 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
                 return false;
         }
 
-        if (!emitArray(args, argc, JSOP_SPREADCALLARRAY))
+        if (!emitArray(args, argc))
             return false;
 
         if (optCodeEmitted) {
@@ -9683,11 +9683,11 @@ BytecodeEmitter::emitArrayLiteral(ParseNode* pn)
         }
     }
 
-    return emitArray(pn->pn_head, pn->pn_count, JSOP_NEWARRAY);
+    return emitArray(pn->pn_head, pn->pn_count);
 }
 
 bool
-BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
+BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count)
 {
 
     /*
@@ -9698,7 +9698,6 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
      * to avoid dup'ing and popping the array as each element is added, as
      * JSOP_SETELEM/JSOP_SETPROP would do.
      */
-    MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
 
     uint32_t nspread = 0;
     for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
@@ -9719,7 +9718,7 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
 
     // For arrays with spread, this is a very pessimistic allocation, the
     // minimum possible final size.
-    if (!emitUint32Operand(op, count - nspread))                    // ARRAY
+    if (!emitUint32Operand(JSOP_NEWARRAY, count - nspread))         // ARRAY
         return false;
 
     ParseNode* pn2 = pn;
diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h
index 814fa11d4..29050c846 100644
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -521,7 +521,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool emitAtomOp(ParseNode* pn, JSOp op);
 
     MOZ_MUST_USE bool emitArrayLiteral(ParseNode* pn);
-    MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count, JSOp op);
+    MOZ_MUST_USE bool emitArray(ParseNode* pn, uint32_t count);
     MOZ_MUST_USE bool emitArrayComp(ParseNode* pn);
 
     MOZ_MUST_USE bool emitInternedScopeOp(uint32_t index, JSOp op);
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 93e3759b9..6b64bfb44 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2049,12 +2049,6 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
     return true;
 }
 
-bool
-BaselineCompiler::emit_JSOP_SPREADCALLARRAY()
-{
-    return emit_JSOP_NEWARRAY();
-}
-
 typedef ArrayObject* (*NewArrayCopyOnWriteFn)(JSContext*, HandleArrayObject, gc::InitialHeap);
 const VMFunction jit::NewArrayCopyOnWriteInfo =
     FunctionInfo<NewArrayCopyOnWriteFn>(js::NewDenseCopyOnWriteArray, "NewDenseCopyOnWriteArray");
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 6b5bf009e..910a52980 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -100,7 +100,6 @@ namespace jit {
     _(JSOP_BITNOT)             \
     _(JSOP_NEG)                \
     _(JSOP_NEWARRAY)           \
-    _(JSOP_SPREADCALLARRAY)    \
     _(JSOP_NEWARRAY_COPYONWRITE) \
     _(JSOP_INITELEM_ARRAY)     \
     _(JSOP_NEWOBJECT)          \
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 3d964d1c6..fc864a197 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -2218,6 +2218,8 @@ IonBuilder::inspectOpcode(JSOp op)
         // update that stale value.
 #endif
       default:
+	    // Any unused opcodes and JSOP_LIMIT will end up here without having
+        // to explicitly specify
         break;
     }
 
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index f4f6c0da4..74a1ef3e9 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1916,6 +1916,7 @@ CASE(EnableInterruptsPseudoOpcode)
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_NOP_DESTRUCTURING)
+CASE(JSOP_UNUSED126)
 CASE(JSOP_UNUSED192)
 CASE(JSOP_UNUSED209)
 CASE(JSOP_UNUSED210)
@@ -3636,7 +3637,6 @@ CASE(JSOP_NEWINIT)
 END_CASE(JSOP_NEWINIT)
 
 CASE(JSOP_NEWARRAY)
-CASE(JSOP_SPREADCALLARRAY)
 {
     uint32_t length = GET_UINT32(REGS.pc);
     JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length);
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index 4b044c8d8..095ef57ae 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1281,17 +1281,7 @@
      *   Stack: receiver, obj, propval => obj[propval]
      */ \
     macro(JSOP_GETELEM_SUPER, 125, "getelem-super", NULL, 1,  3,  1, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC) \
-    /*
-     * Pushes newly created array for a spread call onto the stack. This has
-     * the same semantics as JSOP_NEWARRAY, but is distinguished to avoid
-     * using unboxed arrays in spread calls, which would make compiling spread
-     * calls in baseline more complex.
-     *   Category: Literals
-     *   Type: Array
-     *   Operands: uint32_t length
-     *   Stack: => obj
-     */ \
-    macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 5,  0,  1, JOF_UINT32) \
+    macro(JSOP_UNUSED126, 126, "unused126", NULL, 5,  0,  1, JOF_UINT32) \
     \
     /*
      * Defines the given function on the current scope.
-- 
cgit v1.2.3


From ccb3f2b730992b65ce404e8c6fbdc297485413ac Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Sun, 16 Jun 2019 23:17:34 +0000
Subject: Remove/inline CanonicalizeArrayLengthValue.

---
 js/src/jsarray.cpp | 36 ++++++++++++++----------------------
 js/src/jsarray.h   |  7 -------
 2 files changed, 14 insertions(+), 29 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 6129b2b65..a33735143 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -511,24 +511,6 @@ struct ReverseIndexComparator
     }
 };
 
-bool
-js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
-{
-    double d;
-
-    if (!ToUint32(cx, v, newLen))
-        return false;
-
-    if (!ToNumber(cx, v, &d))
-        return false;
-
-    if (d == *newLen)
-        return true;
-
-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
-    return false;
-}
-
 /* ES6 draft rev 34 (2015 Feb 20) 9.4.2.4 ArraySetLength */
 bool
 js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
@@ -550,12 +532,22 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
     } else {
         // Step 2 is irrelevant in our implementation.
 
-        // Steps 3-7.
-        MOZ_ASSERT_IF(attrs & JSPROP_IGNORE_VALUE, value.isUndefined());
-        if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
+        // Step 3.
+        if (!ToUint32(cx, value, &newLen))
+            return false;
+
+        // Step 4.
+        double d;
+        if (!ToNumber(cx, value, &d))
             return false;
 
-        // Step 8 is irrelevant in our implementation.
+        // Step 5.
+        if (d != newLen) {
+            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
+            return false;
+        }
+
+        // Steps 6-8 are irrelevant in our implementation.
     }
 
     // Steps 9-11.
diff --git a/js/src/jsarray.h b/js/src/jsarray.h
index f9e11149f..ec2e4f514 100644
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -117,13 +117,6 @@ NewValuePair(JSContext* cx, const Value& val1, const Value& val2, MutableHandleV
 extern bool
 WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
 
-/*
- * Canonicalize |vp| to a uint32_t value potentially suitable for use as an
- * array length.
- */
-extern bool
-CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* canonicalized);
-
 extern bool
 GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp);
 
-- 
cgit v1.2.3


From fcc11b2fec61c37c90ffe40e8f406eba64654a9c Mon Sep 17 00:00:00 2001
From: wolfbeast <mcwerewolf@wolfbeast.com>
Date: Tue, 18 Jun 2019 12:59:22 +0000
Subject: Tabs -> Spaces (no code change)

---
 js/src/jit/BaselineIC.cpp | 4 ++--
 js/src/jsarray.cpp        | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'js/src')

diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 9151d9634..64cdf01a6 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5752,7 +5752,7 @@ CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
     ArrayObject* nobj = NewFullyAllocatedArrayTryReuseGroup(cx, arr, length, TenuredObject);
     if (!nobj)
         return false;
-	
+    
     MOZ_ASSERT(arr->isNative());
     MOZ_ASSERT(nobj->isNative());
     MOZ_ASSERT(nobj->as<NativeObject>().getDenseInitializedLength() == 0);
@@ -5763,7 +5763,7 @@ CopyArray(JSContext* cx, HandleArrayObject arr, MutableHandleValue result)
 
     const Value* vp = arr->as<NativeObject>().getDenseElements();
     nobj->as<NativeObject>().initDenseElements(0, vp, length);
-	
+    
     result.setObject(*nobj);
     return true;
 }
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index a33735143..5854fda4c 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2480,8 +2480,8 @@ js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueI
                 /* Steps 10-11. */
                 DebugOnly<DenseElementResult> result =
                     CopyDenseElements(cx, &arr->as<NativeObject>(), 
-					                  &obj->as<NativeObject>(), 0, 
-									  actualStart, actualDeleteCount);
+                                      &obj->as<NativeObject>(), 0, 
+                                      actualStart, actualDeleteCount);
                 MOZ_ASSERT(result.value == DenseElementResult::Success);
 
                 /* Step 12 (implicit). */
-- 
cgit v1.2.3