/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "vm/UnboxedObject-inl.h"

#include "jit/BaselineIC.h"
#include "jit/JitCommon.h"
#include "jit/Linker.h"

#include "jsobjinlines.h"

#include "gc/Nursery-inl.h"
#include "jit/MacroAssembler-inl.h"
#include "vm/Shape-inl.h"

using mozilla::ArrayLength;
using mozilla::DebugOnly;
using mozilla::PodCopy;
using mozilla::UniquePtr;

using namespace js;

/////////////////////////////////////////////////////////////////////
// UnboxedLayout
/////////////////////////////////////////////////////////////////////

void
UnboxedLayout::trace(JSTracer* trc)
{
    for (size_t i = 0; i < properties_.length(); i++)
        TraceManuallyBarrieredEdge(trc, &properties_[i].name, "unboxed_layout_name");

    if (newScript())
        newScript()->trace(trc);

    if (nativeGroup_)
        TraceEdge(trc, &nativeGroup_, "unboxed_layout_nativeGroup");

    if (nativeShape_)
        TraceEdge(trc, &nativeShape_, "unboxed_layout_nativeShape");

    if (allocationScript_)
        TraceEdge(trc, &allocationScript_, "unboxed_layout_allocationScript");

    if (replacementGroup_)
        TraceEdge(trc, &replacementGroup_, "unboxed_layout_replacementGroup");

    if (constructorCode_)
        TraceEdge(trc, &constructorCode_, "unboxed_layout_constructorCode");
}

size_t
UnboxedLayout::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
{
    return mallocSizeOf(this)
         + properties_.sizeOfExcludingThis(mallocSizeOf)
         + (newScript() ? newScript()->sizeOfIncludingThis(mallocSizeOf) : 0)
         + mallocSizeOf(traceList());
}

void
UnboxedLayout::setNewScript(TypeNewScript* newScript, bool writeBarrier /* = true */)
{
    if (newScript_ && writeBarrier)
        TypeNewScript::writeBarrierPre(newScript_);
    newScript_ = newScript;
}

// Constructor code returns a 0x1 value to indicate the constructor code should
// be cleared.
static const uintptr_t CLEAR_CONSTRUCTOR_CODE_TOKEN = 0x1;

/* static */ bool
UnboxedLayout::makeConstructorCode(JSContext* cx, HandleObjectGroup group)
{
    gc::AutoSuppressGC suppress(cx);

    using namespace jit;

    if (!cx->compartment()->ensureJitCompartmentExists(cx))
        return false;

    UnboxedLayout& layout = group->unboxedLayout();
    MOZ_ASSERT(!layout.constructorCode());

    UnboxedPlainObject* templateObject = UnboxedPlainObject::create(cx, group, TenuredObject);
    if (!templateObject)
        return false;

    JitContext jitContext(cx, nullptr);

    MacroAssembler masm;

    Register propertiesReg, newKindReg;
#ifdef JS_CODEGEN_X86
    propertiesReg = eax;
    newKindReg = ecx;
    masm.loadPtr(Address(masm.getStackPointer(), sizeof(void*)), propertiesReg);
    masm.loadPtr(Address(masm.getStackPointer(), 2 * sizeof(void*)), newKindReg);
#else
    propertiesReg = IntArgReg0;
    newKindReg = IntArgReg1;
#endif

    MOZ_ASSERT(propertiesReg.volatile_());
    MOZ_ASSERT(newKindReg.volatile_());

    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
    regs.take(propertiesReg);
    regs.take(newKindReg);
    Register object = regs.takeAny(), scratch1 = regs.takeAny(), scratch2 = regs.takeAny();

    LiveGeneralRegisterSet savedNonVolatileRegisters = SavedNonVolatileRegisters(regs);
    masm.PushRegsInMask(savedNonVolatileRegisters);

    // The scratch double register might be used by MacroAssembler methods.
    if (ScratchDoubleReg.volatile_())
        masm.push(ScratchDoubleReg);

    Label failure, tenuredObject, allocated;
    masm.branch32(Assembler::NotEqual, newKindReg, Imm32(GenericObject), &tenuredObject);
    masm.branchTest32(Assembler::NonZero, AbsoluteAddress(group->addressOfFlags()),
                      Imm32(OBJECT_FLAG_PRE_TENURE), &tenuredObject);

    // Allocate an object in the nursery
    masm.createGCObject(object, scratch1, templateObject, gc::DefaultHeap, &failure,
                        /* initFixedSlots = */ false);

    masm.jump(&allocated);
    masm.bind(&tenuredObject);

    // Allocate an object in the tenured heap.
    masm.createGCObject(object, scratch1, templateObject, gc::TenuredHeap, &failure,
                        /* initFixedSlots = */ false);

    // If any of the properties being stored are in the nursery, add a store
    // buffer entry for the new object.
    Label postBarrier;
    for (size_t i = 0; i < layout.properties().length(); i++) {
        const UnboxedLayout::Property& property = layout.properties()[i];
        if (property.type == JSVAL_TYPE_OBJECT) {
            Address valueAddress(propertiesReg, i * sizeof(IdValuePair) + offsetof(IdValuePair, value));
            Label notObject;
            masm.branchTestObject(Assembler::NotEqual, valueAddress, &notObject);
            Register valueObject = masm.extractObject(valueAddress, scratch1);
            masm.branchPtrInNurseryRange(Assembler::Equal, valueObject, scratch2, &postBarrier);
            masm.bind(&notObject);
        }
    }

    masm.jump(&allocated);
    masm.bind(&postBarrier);

    LiveGeneralRegisterSet liveVolatileRegisters;
    liveVolatileRegisters.add(propertiesReg);
    if (object.volatile_())
        liveVolatileRegisters.add(object);
    masm.PushRegsInMask(liveVolatileRegisters);

    masm.mov(ImmPtr(cx->runtime()), scratch1);
    masm.setupUnalignedABICall(scratch2);
    masm.passABIArg(scratch1);
    masm.passABIArg(object);
    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, PostWriteBarrier));

    masm.PopRegsInMask(liveVolatileRegisters);

    masm.bind(&allocated);

    ValueOperand valueOperand;
#ifdef JS_NUNBOX32
    valueOperand = ValueOperand(scratch1, scratch2);
#else
    valueOperand = ValueOperand(scratch1);
#endif

    Label failureStoreOther, failureStoreObject;

    for (size_t i = 0; i < layout.properties().length(); i++) {
        const UnboxedLayout::Property& property = layout.properties()[i];
        Address valueAddress(propertiesReg, i * sizeof(IdValuePair) + offsetof(IdValuePair, value));
        Address targetAddress(object, UnboxedPlainObject::offsetOfData() + property.offset);

        masm.loadValue(valueAddress, valueOperand);

        if (property.type == JSVAL_TYPE_OBJECT) {
            HeapTypeSet* types = group->maybeGetProperty(IdToTypeId(NameToId(property.name)));

            Label notObject;
            masm.branchTestObject(Assembler::NotEqual, valueOperand,
                                  types->mightBeMIRType(MIRType_Null) ? &notObject : &failureStoreObject);

            Register payloadReg = masm.extractObject(valueOperand, scratch1);

            if (!types->hasType(TypeSet::AnyObjectType())) {
                Register scratch = (payloadReg == scratch1) ? scratch2 : scratch1;
                masm.guardObjectType(payloadReg, types, scratch, &failureStoreObject);
            }

            masm.storeUnboxedProperty(targetAddress, JSVAL_TYPE_OBJECT,
                                      TypedOrValueRegister(MIRType_Object,
                                                           AnyRegister(payloadReg)), nullptr);

            if (notObject.used()) {
                Label done;
                masm.jump(&done);
                masm.bind(&notObject);
                masm.branchTestNull(Assembler::NotEqual, valueOperand, &failureStoreOther);
                masm.storeUnboxedProperty(targetAddress, JSVAL_TYPE_OBJECT, NullValue(), nullptr);
                masm.bind(&done);
            }
        } else {
            masm.storeUnboxedProperty(targetAddress, property.type,
                                      ConstantOrRegister(valueOperand), &failureStoreOther);
        }
    }

    Label done;
    masm.bind(&done);

    if (object != ReturnReg)
        masm.movePtr(object, ReturnReg);

    // Restore non-volatile registers which were saved on entry.
    if (ScratchDoubleReg.volatile_())
        masm.pop(ScratchDoubleReg);
    masm.PopRegsInMask(savedNonVolatileRegisters);

    masm.abiret();

    masm.bind(&failureStoreOther);

    // There was a failure while storing a value which cannot be stored at all
    // in the unboxed object. Initialize the object so it is safe for GC and
    // return null.
    masm.initUnboxedObjectContents(object, templateObject);

    masm.bind(&failure);

    masm.movePtr(ImmWord(0), object);
    masm.jump(&done);

    masm.bind(&failureStoreObject);

    // There was a failure while storing a value to an object slot of the
    // unboxed object. If the value is storable, the failure occurred due to
    // incomplete type information in the object, so return a token to trigger
    // regeneration of the jitcode after a new object is created in the VM.
    {
        Label isObject;
        masm.branchTestObject(Assembler::Equal, valueOperand, &isObject);
        masm.branchTestNull(Assembler::NotEqual, valueOperand, &failureStoreOther);
        masm.bind(&isObject);
    }

    // Initialize the object so it is safe for GC.
    masm.initUnboxedObjectContents(object, templateObject);

    masm.movePtr(ImmWord(CLEAR_CONSTRUCTOR_CODE_TOKEN), object);
    masm.jump(&done);

    Linker linker(masm);
    AutoFlushICache afc("UnboxedObject");
    JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
    if (!code)
        return false;

    layout.setConstructorCode(code);
    return true;
}

void
UnboxedLayout::detachFromCompartment()
{
    if (isInList())
        remove();
}

/////////////////////////////////////////////////////////////////////
// UnboxedPlainObject
/////////////////////////////////////////////////////////////////////

bool
UnboxedPlainObject::setValue(ExclusiveContext* cx, const UnboxedLayout::Property& property,
                             const Value& v)
{
    uint8_t* p = &data_[property.offset];
    return SetUnboxedValue(cx, this, NameToId(property.name), p, property.type, v,
                           /* preBarrier = */ true);
}

Value
UnboxedPlainObject::getValue(const UnboxedLayout::Property& property,
                             bool maybeUninitialized /* = false */)
{
    uint8_t* p = &data_[property.offset];
    return GetUnboxedValue(p, property.type, maybeUninitialized);
}

void
UnboxedPlainObject::trace(JSTracer* trc, JSObject* obj)
{
    if (obj->as<UnboxedPlainObject>().expando_) {
        TraceManuallyBarrieredEdge(trc,
            reinterpret_cast<NativeObject**>(&obj->as<UnboxedPlainObject>().expando_),
            "unboxed_expando");
    }

    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layoutDontCheckGeneration();
    const int32_t* list = layout.traceList();
    if (!list)
        return;

    uint8_t* data = obj->as<UnboxedPlainObject>().data();
    while (*list != -1) {
        HeapPtrString* heap = reinterpret_cast<HeapPtrString*>(data + *list);
        TraceEdge(trc, heap, "unboxed_string");
        list++;
    }
    list++;
    while (*list != -1) {
        HeapPtrObject* heap = reinterpret_cast<HeapPtrObject*>(data + *list);
        if (*heap)
            TraceEdge(trc, heap, "unboxed_object");
        list++;
    }

    // Unboxed objects don't have Values to trace.
    MOZ_ASSERT(*(list + 1) == -1);
}

/* static */ UnboxedExpandoObject*
UnboxedPlainObject::ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj)
{
    if (obj->expando_)
        return obj->expando_;

    UnboxedExpandoObject* expando =
        NewObjectWithGivenProto<UnboxedExpandoObject>(cx, nullptr, gc::AllocKind::OBJECT4);
    if (!expando)
        return nullptr;

    // If the expando is tenured then the original object must also be tenured.
    // Otherwise barriers triggered on the original object for writes to the
    // expando (as can happen in the JIT) won't see the tenured->nursery edge.
    // See WholeCellEdges::mark.
    MOZ_ASSERT_IF(!IsInsideNursery(expando), !IsInsideNursery(obj));

    // As with setValue(), we need to manually trigger post barriers on the
    // whole object. If we treat the field as a HeapPtrObject and later convert
    // the object to its native representation, we will end up with a corrupted
    // store buffer entry.
    if (IsInsideNursery(expando) && !IsInsideNursery(obj))
        cx->runtime()->gc.storeBuffer.putWholeCell(obj);

    obj->expando_ = expando;
    return expando;
}

bool
UnboxedPlainObject::containsUnboxedOrExpandoProperty(ExclusiveContext* cx, jsid id) const
{
    if (layout().lookup(id))
        return true;

    if (maybeExpando() && maybeExpando()->containsShapeOrElement(cx, id))
        return true;

    return false;
}

static bool
PropagatePropertyTypes(JSContext* cx, jsid id, ObjectGroup* oldGroup, ObjectGroup* newGroup)
{
    HeapTypeSet* typeProperty = oldGroup->maybeGetProperty(id);
    TypeSet::TypeList types;
    if (!typeProperty->enumerateTypes(&types)) {
        ReportOutOfMemory(cx);
        return false;
    }
    for (size_t j = 0; j < types.length(); j++)
        AddTypePropertyId(cx, newGroup, nullptr, id, types[j]);
    return true;
}

static PlainObject*
MakeReplacementTemplateObject(JSContext* cx, HandleObjectGroup group, const UnboxedLayout &layout)
{
    PlainObject* obj = NewObjectWithGroup<PlainObject>(cx, group, layout.getAllocKind(),
                                                       TenuredObject);
    if (!obj)
        return nullptr;

    for (size_t i = 0; i < layout.properties().length(); i++) {
        const UnboxedLayout::Property& property = layout.properties()[i];
        if (!obj->addDataProperty(cx, NameToId(property.name), i, JSPROP_ENUMERATE))
            return nullptr;
        MOZ_ASSERT(obj->slotSpan() == i + 1);
        MOZ_ASSERT(!obj->inDictionaryMode());
    }

    return obj;
}

/* static */ bool
UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
{
    AutoEnterAnalysis enter(cx);

    UnboxedLayout& layout = group->unboxedLayout();
    Rooted<TaggedProto> proto(cx, group->proto());

    MOZ_ASSERT(!layout.nativeGroup());

    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
    // same as that for the unboxed group, so that we do not see polymorphic
    // 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;

        PlainObject* templateObject = MakeReplacementTemplateObject(cx, replacementGroup, layout);
        if (!templateObject)
            return false;

        TypeNewScript* replacementNewScript =
            TypeNewScript::makeNativeVersion(cx, layout.newScript(), templateObject);
        if (!replacementNewScript)
            return false;

        replacementGroup->setNewScript(replacementNewScript);
        gc::TraceTypeNewScript(replacementGroup);

        group->clearNewScript(cx, replacementGroup);
    }

    // Similarly, if this group is keyed to an allocation site, replace its
    // entry with a new group that has no unboxed layout.
    if (layout.allocationScript()) {
        RootedScript script(cx, layout.allocationScript());
        jsbytecode* pc = layout.allocationPc();

        replacementGroup = ObjectGroupCompartment::makeGroup(cx, clasp, 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,
                                                                   replacementGroup);

        // Clear any baseline information at this opcode which might use the old group.
        if (script->hasBaselineScript()) {
            jit::ICEntry& entry = script->baselineScript()->icEntryFromPCOffset(script->pcToOffset(pc));
            jit::ICFallbackStub* fallback = entry.fallbackStub();
            for (jit::ICStubIterator iter = fallback->beginChain(); !iter.atEnd(); iter++)
                iter.unlink(cx);
            if (fallback->isNewObject_Fallback())
                fallback->toNewObject_Fallback()->setTemplateObject(nullptr);
            else if (fallback->isNewArray_Fallback())
                fallback->toNewArray_Fallback()->setTemplateGroup(replacementGroup);
        }
    }

    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;
    }

    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, 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];

        Rooted<StackShape> child(cx, StackShape(shape->base()->unowned(), NameToId(property.name),
                                                i, JSPROP_ENUMERATE, 0));
        shape = cx->compartment()->propertyTree.getChild(cx, shape, child);
        if (!shape)
            return false;
    }

    ObjectGroup* nativeGroup =
        ObjectGroupCompartment::makeGroup(cx, clasp, proto,
                                          group->flags() & OBJECT_FLAG_DYNAMIC_MASK);
    if (!nativeGroup)
        return false;

    // Propagate all property types from the old group to the new group.
    if (layout.isArray()) {
        if (!PropagatePropertyTypes(cx, JSID_VOID, 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;

            HeapTypeSet* nativeProperty = nativeGroup->maybeGetProperty(id);
            if (nativeProperty && nativeProperty->canSetDefinite(i))
                nativeProperty->setDefinite(i);
        }
    }

    layout.nativeGroup_ = nativeGroup;
    layout.nativeShape_ = shape;
    layout.replacementGroup_ = replacementGroup;

    nativeGroup->setOriginalUnboxedGroup(group);

    group->markStateChange(cx);

    return true;
}

/* static */ bool
UnboxedPlainObject::convertToNative(JSContext* cx, JSObject* obj)
{
    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();
    UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();

    if (!layout.nativeGroup()) {
        if (!UnboxedLayout::makeNativeGroup(cx, obj->group()))
            return false;

        // makeNativeGroup can reentrantly invoke this method.
        if (obj->is<PlainObject>())
            return true;
    }

    AutoValueVector values(cx);
    for (size_t i = 0; i < layout.properties().length(); i++) {
        // We might be reading properties off the object which have not been
        // initialized yet. Make sure any double values we read here are
        // canonicalized.
        if (!values.append(obj->as<UnboxedPlainObject>().getValue(layout.properties()[i], true)))
            return false;
    }

    // We are eliminating the expando edge with the conversion, so trigger a
    // pre barrier.
    JSObject::writeBarrierPre(expando);

    // Additionally trigger a post barrier on the expando itself. Whole cell
    // store buffer entries can be added on the original unboxed object for
    // writes to the expando (see WholeCellEdges::trace), so after conversion
    // we need to make sure the expando itself will still be traced.
    if (expando && !IsInsideNursery(expando))
        cx->runtime()->gc.storeBuffer.putWholeCell(expando);

    obj->setGroup(layout.nativeGroup());
    obj->as<PlainObject>().setLastPropertyMakeNative(cx, layout.nativeShape());

    for (size_t i = 0; i < values.length(); i++)
        obj->as<PlainObject>().initSlotUnchecked(i, values[i]);

    if (expando) {
        // Add properties from the expando object to the object, in order.
        // Suppress GC here, so that callers don't need to worry about this
        // method collecting. The stuff below can only fail due to OOM, in
        // which case the object will not have been completely filled back in.
        gc::AutoSuppressGC suppress(cx);

        Vector<jsid> ids(cx);
        for (Shape::Range<NoGC> r(expando->lastProperty()); !r.empty(); r.popFront()) {
            if (!ids.append(r.front().propid()))
                return false;
        }
        for (size_t i = 0; i < expando->getDenseInitializedLength(); i++) {
            if (!expando->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE)) {
                if (!ids.append(INT_TO_JSID(i)))
                    return false;
            }
        }
        ::Reverse(ids.begin(), ids.end());

        RootedPlainObject nobj(cx, &obj->as<PlainObject>());
        Rooted<UnboxedExpandoObject*> nexpando(cx, expando);
        RootedId id(cx);
        Rooted<PropertyDescriptor> desc(cx);
        for (size_t i = 0; i < ids.length(); i++) {
            id = ids[i];
            if (!GetOwnPropertyDescriptor(cx, nexpando, id, &desc))
                return false;
            ObjectOpResult result;
            if (!DefineProperty(cx, nobj, id, desc, result))
                return false;
            MOZ_ASSERT(result.ok());
        }
    }

    return true;
}

/* static */
UnboxedPlainObject*
UnboxedPlainObject::create(ExclusiveContext* cx, HandleObjectGroup group, NewObjectKind newKind)
{
    MOZ_ASSERT(group->clasp() == &class_);
    gc::AllocKind allocKind = group->unboxedLayout().getAllocKind();

    UnboxedPlainObject* res =
        NewObjectWithGroup<UnboxedPlainObject>(cx, group, allocKind, newKind);
    if (!res)
        return nullptr;

    // Overwrite the dummy shape which was written to the object's expando field.
    res->initExpando();

    // Initialize reference fields of the object. All fields in the object will
    // be overwritten shortly, but references need to be safe for the GC.
    const int32_t* list = res->layout().traceList();
    if (list) {
        uint8_t* data = res->data();
        while (*list != -1) {
            HeapPtrString* heap = reinterpret_cast<HeapPtrString*>(data + *list);
            heap->init(cx->names().empty);
            list++;
        }
        list++;
        while (*list != -1) {
            HeapPtrObject* heap = reinterpret_cast<HeapPtrObject*>(data + *list);
            heap->init(nullptr);
            list++;
        }
        // Unboxed objects don't have Values to initialize.
        MOZ_ASSERT(*(list + 1) == -1);
    }

    return res;
}

/* static */ JSObject*
UnboxedPlainObject::createWithProperties(ExclusiveContext* cx, HandleObjectGroup group,
                                         NewObjectKind newKind, IdValuePair* properties)
{
    MOZ_ASSERT(newKind == GenericObject || newKind == TenuredObject);

    UnboxedLayout& layout = group->unboxedLayout();

    if (layout.constructorCode()) {
        MOZ_ASSERT(cx->isJSContext());

        typedef JSObject* (*ConstructorCodeSignature)(IdValuePair*, NewObjectKind);
        ConstructorCodeSignature function =
            reinterpret_cast<ConstructorCodeSignature>(layout.constructorCode()->raw());

        JSObject* obj;
        {
            JS::AutoSuppressGCAnalysis nogc;
            obj = reinterpret_cast<JSObject*>(CALL_GENERATED_2(function, properties, newKind));
        }
        if (obj > reinterpret_cast<JSObject*>(CLEAR_CONSTRUCTOR_CODE_TOKEN))
            return obj;

        if (obj == reinterpret_cast<JSObject*>(CLEAR_CONSTRUCTOR_CODE_TOKEN))
            layout.setConstructorCode(nullptr);
    }

    UnboxedPlainObject* obj = UnboxedPlainObject::create(cx, group, newKind);
    if (!obj)
        return nullptr;

    for (size_t i = 0; i < layout.properties().length(); i++) {
        if (!obj->setValue(cx, layout.properties()[i], properties[i].value))
            return NewPlainObjectWithProperties(cx, properties, layout.properties().length(), newKind);
    }

#if !defined(JS_CODEGEN_NONE) && !defined(COBALT_DISABLE_JIT)
    if (cx->isJSContext() &&
        !layout.constructorCode() &&
        cx->asJSContext()->runtime()->jitSupportsFloatingPoint)
    {
        if (!UnboxedLayout::makeConstructorCode(cx->asJSContext(), group))
            return nullptr;
    }
#endif

    return obj;
}

/* static */ bool
UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
                                       HandleId id, MutableHandleObject objp,
                                       MutableHandleShape propp)
{
    if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
        MarkNonNativePropertyFound<CanGC>(propp);
        objp.set(obj);
        return true;
    }

    RootedObject proto(cx, obj->getProto());
    if (!proto) {
        objp.set(nullptr);
        propp.set(nullptr);
        return true;
    }

    return LookupProperty(cx, proto, id, objp, propp);
}

/* static */ bool
UnboxedPlainObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
                                       Handle<JSPropertyDescriptor> desc,
                                       ObjectOpResult& result)
{
    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();

    if (const UnboxedLayout::Property* property = layout.lookup(id)) {
        if (!desc.getter() && !desc.setter() && desc.attributes() == JSPROP_ENUMERATE) {
            // This define is equivalent to setting an existing property.
            if (obj->as<UnboxedPlainObject>().setValue(cx, *property, desc.value()))
                return result.succeed();
        }

        // Trying to incompatibly redefine an existing property requires the
        // object to be converted to a native object.
        if (!convertToNative(cx, obj))
            return false;

        return DefineProperty(cx, obj, id, desc, result);
    }

    // Define the property on the expando object.
    Rooted<UnboxedExpandoObject*> expando(cx, ensureExpando(cx, obj.as<UnboxedPlainObject>()));
    if (!expando)
        return false;

    // Update property types on the unboxed object as well.
    AddTypePropertyId(cx, obj, id, desc.value());

    return DefineProperty(cx, expando, id, desc, result);
}

/* static */ bool
UnboxedPlainObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
{
    if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
        *foundp = true;
        return true;
    }

    RootedObject proto(cx, obj->getProto());
    if (!proto) {
        *foundp = false;
        return true;
    }

    return HasProperty(cx, proto, id, foundp);
}

/* static */ bool
UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
                                    HandleId id, MutableHandleValue vp)
{
    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();

    if (const UnboxedLayout::Property* property = layout.lookup(id)) {
        vp.set(obj->as<UnboxedPlainObject>().getValue(*property));
        return true;
    }

    if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
        if (expando->containsShapeOrElement(cx, id)) {
            RootedObject nexpando(cx, expando);
            return GetProperty(cx, nexpando, receiver, id, vp);
        }
    }

    RootedObject proto(cx, obj->getProto());
    if (!proto) {
        vp.setUndefined();
        return true;
    }

    return GetProperty(cx, proto, receiver, id, vp);
}

/* static */ bool
UnboxedPlainObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
                                    HandleValue receiver, ObjectOpResult& result)
{
    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();

    if (const UnboxedLayout::Property* property = layout.lookup(id)) {
        if (receiver.isObject() && obj == &receiver.toObject()) {
            if (obj->as<UnboxedPlainObject>().setValue(cx, *property, v))
                return result.succeed();

            if (!convertToNative(cx, obj))
                return false;
            return SetProperty(cx, obj, id, v, receiver, result);
        }

        return SetPropertyByDefining(cx, id, v, receiver, result);
    }

    if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
        if (expando->containsShapeOrElement(cx, id)) {
            // Update property types on the unboxed object as well.
            AddTypePropertyId(cx, obj, id, v);

            RootedObject nexpando(cx, expando);
            return SetProperty(cx, nexpando, id, v, receiver, result);
        }
    }

    return SetPropertyOnProto(cx, obj, id, v, receiver, result);
}

/* static */ bool
UnboxedPlainObject::obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
                                                 MutableHandle<JSPropertyDescriptor> desc)
{
    const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();

    if (const UnboxedLayout::Property* property = layout.lookup(id)) {
        desc.value().set(obj->as<UnboxedPlainObject>().getValue(*property));
        desc.setAttributes(JSPROP_ENUMERATE);
        desc.object().set(obj);
        return true;
    }

    if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
        if (expando->containsShapeOrElement(cx, id)) {
            RootedObject nexpando(cx, expando);
            if (!GetOwnPropertyDescriptor(cx, nexpando, id, desc))
                return false;
            if (desc.object() == nexpando)
                desc.object().set(obj);
            return true;
        }
    }

    desc.object().set(nullptr);
    return true;
}

/* static */ bool
UnboxedPlainObject::obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
                                       ObjectOpResult& result)
{
    if (!convertToNative(cx, obj))
        return false;
    return DeleteProperty(cx, obj, id, result);
}

/* static */ bool
UnboxedPlainObject::obj_watch(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable)
{
    if (!convertToNative(cx, obj))
        return false;
    return WatchProperty(cx, obj, id, callable);
}

/* static */ bool
UnboxedPlainObject::obj_enumerate(JSContext* cx, HandleObject obj, AutoIdVector& properties,
                                  bool enumerableOnly)
{
    // Ignore expando properties here, they are special-cased by the property
    // enumeration code.

    const UnboxedLayout::PropertyVector& unboxed = obj->as<UnboxedPlainObject>().layout().properties();
    for (size_t i = 0; i < unboxed.length(); i++) {
        if (!properties.append(NameToId(unboxed[i].name)))
            return false;
    }

    return true;
}

const Class UnboxedExpandoObject::class_ = {
    "UnboxedExpandoObject",
    0
};

const Class UnboxedPlainObject::class_ = {
    js_Object_str,
    Class::NON_NATIVE |
    JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
    nullptr,        /* addProperty */
    nullptr,        /* delProperty */
    nullptr,        /* getProperty */
    nullptr,        /* setProperty */
    nullptr,        /* enumerate   */
    nullptr,        /* resolve     */
    nullptr,        /* mayResolve  */
    nullptr,        /* finalize    */
    nullptr,        /* call        */
    nullptr,        /* hasInstance */
    nullptr,        /* construct   */
    UnboxedPlainObject::trace,
    JS_NULL_CLASS_SPEC,
    JS_NULL_CLASS_EXT,
    {
        UnboxedPlainObject::obj_lookupProperty,
        UnboxedPlainObject::obj_defineProperty,
        UnboxedPlainObject::obj_hasProperty,
        UnboxedPlainObject::obj_getProperty,
        UnboxedPlainObject::obj_setProperty,
        UnboxedPlainObject::obj_getOwnPropertyDescriptor,
        UnboxedPlainObject::obj_deleteProperty,
        UnboxedPlainObject::obj_watch,
        nullptr,   /* No unwatch needed, as watch() converts the object to native */
        nullptr,   /* getElements */
        UnboxedPlainObject::obj_enumerate,
    }
};

/////////////////////////////////////////////////////////////////////
// UnboxedArrayObject
/////////////////////////////////////////////////////////////////////

template <JSValueType Type>
DenseElementResult
AppendUnboxedDenseElements(UnboxedArrayObject* obj, uint32_t initlen, AutoValueVector* values)
{
    for (size_t i = 0; i < initlen; i++)
        values->infallibleAppend(obj->getElementSpecific<Type>(i));
    return DenseElementResult::Success;
}

DefineBoxedOrUnboxedFunctor3(AppendUnboxedDenseElements,
                             UnboxedArrayObject*, uint32_t, AutoValueVector*);

/* 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();

    AutoValueVector values(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++) {
            HeapPtrObject* heap = reinterpret_cast<HeapPtrObject*>(elements + i);
            if (*heap)
                TraceEdge(trc, heap, "unboxed_object");
        }
        break;

      case JSVAL_TYPE_STRING:
        for (size_t i = 0; i < initlen; i++) {
            HeapPtrString* heap = reinterpret_cast<HeapPtrString*>(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->getProto());
    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<JSPropertyDescriptor> 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->getProto());
    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->getProto());
    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<JSPropertyDescriptor> 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;
}

const Class UnboxedArrayObject::class_ = {
    "Array",
    Class::NON_NATIVE |
    JSCLASS_SKIP_NURSERY_FINALIZE |
    JSCLASS_BACKGROUND_FINALIZE,
    nullptr,        /* addProperty */
    nullptr,        /* delProperty */
    nullptr,        /* getProperty */
    nullptr,        /* setProperty */
    nullptr,        /* enumerate   */
    nullptr,        /* resolve     */
    nullptr,        /* mayResolve  */
    UnboxedArrayObject::finalize,
    nullptr,        /* call        */
    nullptr,        /* hasInstance */
    nullptr,        /* construct   */
    UnboxedArrayObject::trace,
    JS_NULL_CLASS_SPEC,
    {
        false,      /* isWrappedNative */
        nullptr,    /* weakmapKeyDelegateOp */
        UnboxedArrayObject::objectMoved
    },
    {
        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,
    }
};

/////////////////////////////////////////////////////////////////////
// API
/////////////////////////////////////////////////////////////////////

static bool
UnboxedTypeIncludes(JSValueType supertype, JSValueType subtype)
{
    if (supertype == JSVAL_TYPE_DOUBLE && subtype == JSVAL_TYPE_INT32)
        return true;
    if (supertype == JSVAL_TYPE_OBJECT && subtype == JSVAL_TYPE_NULL)
        return true;
    return false;
}

static bool
CombineUnboxedTypes(const Value& value, JSValueType* existing)
{
    JSValueType type = value.isDouble() ? JSVAL_TYPE_DOUBLE : value.extractNonDoubleType();

    if (*existing == JSVAL_TYPE_MAGIC || *existing == type || UnboxedTypeIncludes(type, *existing)) {
        *existing = type;
        return true;
    }
    if (UnboxedTypeIncludes(*existing, type))
        return true;
    return false;
}

// Return whether the property names and types in layout are a subset of the
// specified vector.
static bool
PropertiesAreSuperset(const UnboxedLayout::PropertyVector& properties, UnboxedLayout* layout)
{
    for (size_t i = 0; i < layout->properties().length(); i++) {
        const UnboxedLayout::Property& layoutProperty = layout->properties()[i];
        bool found = false;
        for (size_t j = 0; j < properties.length(); j++) {
            if (layoutProperty.name == properties[j].name) {
                found = (layoutProperty.type == properties[j].type);
                break;
            }
        }
        if (!found)
            return false;
    }
    return true;
}

static bool
CombinePlainObjectProperties(PlainObject* obj, Shape* templateShape,
                             UnboxedLayout::PropertyVector& properties)
{
    // All preliminary objects must have been created with enough space to
    // fill in their unboxed data inline. This is ensured either by using
    // the largest allocation kind (which limits the maximum size of an
    // unboxed object), or by using an allocation kind that covers all
    // properties in the template, as the space used by unboxed properties
    // is less than or equal to that used by boxed properties.
    MOZ_ASSERT(gc::GetGCKindSlots(obj->asTenured().getAllocKind()) >=
               Min(NativeObject::MAX_FIXED_SLOTS, templateShape->slotSpan()));

    if (obj->lastProperty() != templateShape || obj->hasDynamicElements()) {
        // Only use an unboxed representation if all created objects match
        // the template shape exactly.
        return false;
    }

    for (size_t i = 0; i < templateShape->slotSpan(); i++) {
        Value val = obj->getSlot(i);

        JSValueType& existing = properties[i].type;
        if (!CombineUnboxedTypes(val, &existing))
            return false;
    }

    return true;
}

static bool
CombineArrayObjectElements(ExclusiveContext* cx, ArrayObject* obj, JSValueType* elementType)
{
    if (obj->inDictionaryMode() ||
        obj->lastProperty()->propid() != AtomToId(cx->names().length) ||
        !obj->lastProperty()->previous()->isEmptyShape())
    {
        // Only use an unboxed representation if the object has no properties.
        return false;
    }

    for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
        Value val = obj->getDenseElement(i);

        // For now, unboxed arrays cannot have holes.
        if (val.isMagic(JS_ELEMENTS_HOLE))
            return false;

        if (!CombineUnboxedTypes(val, elementType))
            return false;
    }

    return true;
}

static size_t
ComputePlainObjectLayout(ExclusiveContext* cx, Shape* templateShape,
                         UnboxedLayout::PropertyVector& properties)
{
    // Fill in the names for all the object's properties.
    for (Shape::Range<NoGC> r(templateShape); !r.empty(); r.popFront()) {
        size_t slot = r.front().slot();
        MOZ_ASSERT(!properties[slot].name);
        properties[slot].name = JSID_TO_ATOM(r.front().propid())->asPropertyName();
    }

    // Fill in all the unboxed object's property offsets.
    uint32_t offset = 0;

    // Search for an existing unboxed layout which is a subset of this one.
    // If there are multiple such layouts, use the largest one. If we're able
    // to find such a layout, use the same property offsets for the shared
    // properties, which will allow us to generate better code if the objects
    // have a subtype/supertype relation and are accessed at common sites.
    UnboxedLayout* bestExisting = nullptr;
    for (UnboxedLayout* existing : cx->compartment()->unboxedLayouts) {
        if (PropertiesAreSuperset(properties, existing)) {
            if (!bestExisting ||
                existing->properties().length() > bestExisting->properties().length())
            {
                bestExisting = existing;
            }
        }
    }
    if (bestExisting) {
        for (size_t i = 0; i < bestExisting->properties().length(); i++) {
            const UnboxedLayout::Property& existingProperty = bestExisting->properties()[i];
            for (size_t j = 0; j < templateShape->slotSpan(); j++) {
                if (existingProperty.name == properties[j].name) {
                    MOZ_ASSERT(existingProperty.type == properties[j].type);
                    properties[j].offset = existingProperty.offset;
                }
            }
        }
        offset = bestExisting->size();
    }

    // Order remaining properties from the largest down for the best space
    // utilization.
    static const size_t typeSizes[] = { 8, 4, 1 };

    for (size_t i = 0; i < ArrayLength(typeSizes); i++) {
        size_t size = typeSizes[i];
        for (size_t j = 0; j < templateShape->slotSpan(); j++) {
            if (properties[j].offset != UINT32_MAX)
                continue;
            JSValueType type = properties[j].type;
            if (UnboxedTypeSize(type) == size) {
                offset = JS_ROUNDUP(offset, size);
                properties[j].offset = offset;
                offset += size;
            }
        }
    }

    // The final offset is the amount of data needed by the object.
    return offset;
}

static bool
SetLayoutTraceList(ExclusiveContext* cx, UnboxedLayout* layout)
{
    // Figure out the offsets of any objects or string properties.
    Vector<int32_t, 8, SystemAllocPolicy> objectOffsets, stringOffsets;
    for (size_t i = 0; i < layout->properties().length(); i++) {
        const UnboxedLayout::Property& property = layout->properties()[i];
        MOZ_ASSERT(property.offset != UINT32_MAX);
        if (property.type == JSVAL_TYPE_OBJECT) {
            if (!objectOffsets.append(property.offset))
                return false;
        } else if (property.type == JSVAL_TYPE_STRING) {
            if (!stringOffsets.append(property.offset))
                return false;
        }
    }

    // Construct the layout's trace list.
    if (!objectOffsets.empty() || !stringOffsets.empty()) {
        Vector<int32_t, 8, SystemAllocPolicy> entries;
        if (!entries.appendAll(stringOffsets) ||
            !entries.append(-1) ||
            !entries.appendAll(objectOffsets) ||
            !entries.append(-1) ||
            !entries.append(-1))
        {
            return false;
        }
        int32_t* traceList = cx->zone()->pod_malloc<int32_t>(entries.length());
        if (!traceList)
            return false;
        PodCopy(traceList, entries.begin(), entries.length());
        layout->setTraceList(traceList);
    }

    return true;
}

static inline Value
NextValue(const AutoValueVector& values, size_t* valueCursor)
{
    return values[(*valueCursor)++];
}

static bool
GetValuesFromPreliminaryArrayObject(ArrayObject* obj, AutoValueVector& values)
{
    if (!values.append(Int32Value(obj->length())))
        return false;
    if (!values.append(Int32Value(obj->getDenseInitializedLength())))
        return false;
    for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
        if (!values.append(obj->getDenseElement(i)))
            return false;
    }
    return true;
}

void
UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
                                     const AutoValueVector& 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)));
}

static bool
GetValuesFromPreliminaryPlainObject(PlainObject* obj, AutoValueVector& values)
{
    for (size_t i = 0; i < obj->slotSpan(); i++) {
        if (!values.append(obj->getSlot(i)))
            return false;
    }
    return true;
}

void
UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
                                     const AutoValueVector& values, size_t* valueCursor)
{
    initExpando();
    memset(data(), 0, layout().size());
    for (size_t i = 0; i < layout().properties().length(); i++)
        JS_ALWAYS_TRUE(setValue(cx, layout().properties()[i], NextValue(values, valueCursor)));
}

bool
js::TryConvertToUnboxedLayout(ExclusiveContext* cx, Shape* templateShape,
                              ObjectGroup* group, PreliminaryObjectArray* objects)
{
    bool isArray = !templateShape;

    // Unboxed arrays are nightly only for now. The js_sb_getenv() call will be
    // removed when they are on by default. See bug 1153266.
    if (isArray) {
#ifdef NIGHTLY_BUILD
        if (!js_sb_getenv("JS_OPTION_USE_UNBOXED_ARRAYS")) {
            if (!group->runtimeFromAnyThread()->options().unboxedArrays())
                return true;
        }
#else
        return true;
#endif
    } else {
        if (jit::JitOptions.disableUnboxedObjects)
            return true;
    }

    MOZ_ASSERT_IF(templateShape, !templateShape->getObjectFlags());

    if (group->runtimeFromAnyThread()->isSelfHostingGlobal(cx->global()))
        return true;

    if (!isArray && templateShape->slotSpan() == 0)
        return true;

    UnboxedLayout::PropertyVector properties;
    if (!isArray) {
        if (!properties.appendN(UnboxedLayout::Property(), templateShape->slotSpan()))
            return false;
    }
    JSValueType elementType = JSVAL_TYPE_MAGIC;

    size_t objectCount = 0;
    for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
        JSObject* obj = objects->get(i);
        if (!obj)
            continue;

        if (obj->isSingleton() || obj->group() != group)
            return true;

        objectCount++;

        if (isArray) {
            if (!CombineArrayObjectElements(cx, &obj->as<ArrayObject>(), &elementType))
                return true;
        } else {
            if (!CombinePlainObjectProperties(&obj->as<PlainObject>(), templateShape, properties))
                return true;
        }
    }

    size_t layoutSize = 0;
    if (isArray) {
        // Don't use an unboxed representation if we couldn't determine an
        // element type for the objects.
        if (UnboxedTypeSize(elementType) == 0)
            return true;
    } else {
        if (objectCount <= 1) {
            // If only one of the objects has been created, it is more likely
            // to have new properties added later. This heuristic is not used
            // for array objects, where we might want an unboxed representation
            // even if there is only one large array.
            return true;
        }

        for (size_t i = 0; i < templateShape->slotSpan(); i++) {
            // We can't use an unboxed representation if e.g. all the objects have
            // a null value for one of the properties, as we can't decide what type
            // it is supposed to have.
            if (UnboxedTypeSize(properties[i].type) == 0)
                return true;
        }

        // Make sure that all properties on the template shape are property
        // names, and not indexes.
        for (Shape::Range<NoGC> r(templateShape); !r.empty(); r.popFront()) {
            jsid id = r.front().propid();
            uint32_t dummy;
            if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
                return true;
        }

        layoutSize = ComputePlainObjectLayout(cx, templateShape, properties);

        // The entire object must be allocatable inline.
        if (UnboxedPlainObject::offsetOfData() + layoutSize > JSObject::MAX_BYTE_SIZE)
            return true;
    }

    AutoInitGCManagedObject<UnboxedLayout> layout(group->zone()->make_unique<UnboxedLayout>());
    if (!layout)
        return false;

    if (isArray) {
        layout->initArray(elementType);
    } else {
        if (!layout->initProperties(properties, layoutSize))
            return false;

        // The unboxedLayouts list only tracks layouts for plain objects.
        cx->compartment()->unboxedLayouts.insertFront(layout.get());

        if (!SetLayoutTraceList(cx, layout.get()))
            return false;
    }

    // We've determined that all the preliminary objects can use the new layout
    // just constructed, so convert the existing group to use the unboxed class,
    // and update the preliminary objects to use the new layout. Do the
    // fallible stuff first before modifying any objects.

    // Get an empty shape which we can use for the preliminary objects.
    const Class* clasp = isArray ? &UnboxedArrayObject::class_ : &UnboxedPlainObject::class_;
    Shape* newShape = EmptyShape::getInitialShape(cx, clasp, group->proto(), 0);
    if (!newShape) {
        cx->recoverFromOutOfMemory();
        return false;
    }

    // Accumulate a list of all the values in each preliminary object, and
    // update their shapes.
    AutoValueVector values(cx);
    for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
        JSObject* obj = objects->get(i);
        if (!obj)
            continue;

        bool ok;
        if (isArray)
            ok = GetValuesFromPreliminaryArrayObject(&obj->as<ArrayObject>(), values);
        else
            ok = GetValuesFromPreliminaryPlainObject(&obj->as<PlainObject>(), values);

        if (!ok) {
            cx->recoverFromOutOfMemory();
            return false;
        }
    }

    if (TypeNewScript* newScript = group->newScript())
        layout->setNewScript(newScript);

    for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
        if (JSObject* obj = objects->get(i))
            obj->as<NativeObject>().setLastPropertyMakeNonNative(newShape);
    }

    group->setClasp(clasp);
    group->setUnboxedLayout(layout.release());

    size_t valueCursor = 0;
    for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
        JSObject* obj = objects->get(i);
        if (!obj)
            continue;

        if (isArray)
            obj->as<UnboxedArrayObject>().fillAfterConvert(cx, values, &valueCursor);
        else
            obj->as<UnboxedPlainObject>().fillAfterConvert(cx, values, &valueCursor);
    }

    MOZ_ASSERT(valueCursor == values.length());
    layout.release();
    return true;
}

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);
}
