/* -*- 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/. */

#ifndef jsobjinlines_h
#define jsobjinlines_h

#include "jsobj.h"

#include "jswrapper.h"

#include "vm/NumberObject.h"
#include "vm/Probes.h"
#include "vm/StringObject.h"

#include "jsatominlines.h"
#include "jsfuninlines.h"

#include "vm/ObjectImpl-inl.h"

/* static */ inline bool
JSObject::enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
                    JS::MutableHandleValue statep, JS::MutableHandleId idp)
{
    JSNewEnumerateOp op = obj->getOps()->enumerate;
    return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp);
}

/* static */ inline bool
JSObject::defaultValue(JSContext *cx, js::HandleObject obj, JSType hint, js::MutableHandleValue vp)
{
    JSConvertOp op = obj->getClass()->convert;
    bool ok;
    if (op == JS_ConvertStub)
        ok = js::DefaultValue(cx, obj, hint, vp);
    else
        ok = op(cx, obj, hint, vp);
    JS_ASSERT_IF(ok, vp.isPrimitive());
    return ok;
}

/* static */ inline JSObject *
JSObject::thisObject(JSContext *cx, js::HandleObject obj)
{
    JSObjectOp op = obj->getOps()->thisObject;
    return op ? op(cx, obj) : obj;
}

/* static */ inline JSBool
JSObject::setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     js::HandleId id, js::MutableHandleValue vp, JSBool strict)
{
    if (obj->getOps()->setGeneric)
        return nonNativeSetProperty(cx, obj, id, vp, strict);
    return js::baseops::SetPropertyHelper(cx, obj, receiver, id, 0, vp, strict);
}

/* static */ inline JSBool
JSObject::setProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                      js::PropertyName *name, js::MutableHandleValue vp, JSBool strict)
{
    JS::RootedId id(cx, js::NameToId(name));
    return setGeneric(cx, obj, receiver, id, vp, strict);
}

/* static */ inline JSBool
JSObject::setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     uint32_t index, js::MutableHandleValue vp, JSBool strict)
{
    if (obj->getOps()->setElement)
        return nonNativeSetElement(cx, obj, index, vp, strict);
    return js::baseops::SetElementHelper(cx, obj, receiver, index, 0, vp, strict);
}

/* static */ inline JSBool
JSObject::setSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     js::SpecialId sid, js::MutableHandleValue vp, JSBool strict)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return setGeneric(cx, obj, receiver, id, vp, strict);
}

/* static */ inline JSBool
JSObject::setGenericAttributes(JSContext *cx, js::HandleObject obj,
                               js::HandleId id, unsigned *attrsp)
{
    js::types::MarkTypePropertyConfigured(cx, obj, id);
    js::GenericAttributesOp op = obj->getOps()->setGenericAttributes;
    return (op ? op : js::baseops::SetAttributes)(cx, obj, id, attrsp);
}

/* static */ inline JSBool
JSObject::setPropertyAttributes(JSContext *cx, js::HandleObject obj,
                                js::PropertyName *name, unsigned *attrsp)
{
    JS::RootedId id(cx, js::NameToId(name));
    return setGenericAttributes(cx, obj, id, attrsp);
}

/* static */ inline JSBool
JSObject::setElementAttributes(JSContext *cx, js::HandleObject obj,
                               uint32_t index, unsigned *attrsp)
{
    js::ElementAttributesOp op = obj->getOps()->setElementAttributes;
    return (op ? op : js::baseops::SetElementAttributes)(cx, obj, index, attrsp);
}

/* static */ inline JSBool
JSObject::setSpecialAttributes(JSContext *cx, js::HandleObject obj,
                               js::SpecialId sid, unsigned *attrsp)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return setGenericAttributes(cx, obj, id, attrsp);
}

/* static */ inline bool
JSObject::changePropertyAttributes(JSContext *cx, js::HandleObject obj,
                                   js::HandleShape shape, unsigned attrs)
{
    return !!changeProperty(cx, obj, shape, attrs, 0, shape->getter(), shape->setter());
}

/* static */ inline JSBool
JSObject::getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     js::HandleId id, js::MutableHandleValue vp)
{
    js::GenericIdOp op = obj->getOps()->getGeneric;
    if (op) {
        if (!op(cx, obj, receiver, id, vp))
            return false;
    } else {
        if (!js::baseops::GetProperty(cx, obj, receiver, id, vp))
            return false;
    }
    return true;
}

/* static */ inline JSBool
JSObject::getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
                         jsid id, js::Value *vp)
{
    js::GenericIdOp op = obj->getOps()->getGeneric;
    if (op)
        return false;
    return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                      js::PropertyName *name, js::MutableHandleValue vp)
{
    JS::RootedId id(cx, js::NameToId(name));
    return getGeneric(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
                          js::PropertyName *name, js::Value *vp)
{
    return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
}

/* static */ inline bool
JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandlePropertyName name,
                         JSBool *succeeded)
{
    JS::RootedId id(cx, js::NameToId(name));
    js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
    js::types::MarkTypePropertyConfigured(cx, obj, id);
    js::DeletePropertyOp op = obj->getOps()->deleteProperty;
    return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, succeeded);
}

/* static */ inline bool
JSObject::deleteElement(JSContext *cx, js::HandleObject obj, uint32_t index, JSBool *succeeded)
{
    JS::RootedId id(cx);
    if (!js::IndexToId(cx, index, &id))
        return false;
    js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
    js::types::MarkTypePropertyConfigured(cx, obj, id);
    js::DeleteElementOp op = obj->getOps()->deleteElement;
    return (op ? op : js::baseops::DeleteElement)(cx, obj, index, succeeded);
}

/* static */ inline bool
JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId sid,
                        JSBool *succeeded)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
    js::types::MarkTypePropertyConfigured(cx, obj, id);
    js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
    return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
}

inline void
JSObject::finalize(js::FreeOp *fop)
{
    js::Probes::finalizeObject(this);

#ifdef DEBUG
    JS_ASSERT(isTenured());
    if (!IsBackgroundFinalized(tenuredGetAllocKind())) {
        /* Assert we're on the main thread. */
        fop->runtime()->assertValidThread();
    }
#endif
    js::Class *clasp = getClass();
    if (clasp->finalize)
        clasp->finalize(fop, this);

    finish(fop);
}

inline JSObject *
JSObject::getParent() const
{
    return lastProperty()->getObjectParent();
}

inline JSObject *
JSObject::getMetadata() const
{
    return lastProperty()->getObjectMetadata();
}

inline bool
JSObject::isFixedSlot(size_t slot)
{
    return slot < numFixedSlots();
}

inline size_t
JSObject::dynamicSlotIndex(size_t slot)
{
    JS_ASSERT(slot >= numFixedSlots());
    return slot - numFixedSlots();
}

inline void
JSObject::setLastPropertyInfallible(js::Shape *shape)
{
    JS_ASSERT(!shape->inDictionary());
    JS_ASSERT(shape->compartment() == compartment());
    JS_ASSERT(!inDictionaryMode());
    JS_ASSERT(slotSpan() == shape->slotSpan());
    JS_ASSERT(numFixedSlots() == shape->numFixedSlots());

    shape_ = shape;
}

inline void
JSObject::removeLastProperty(JSContext *cx)
{
    JS_ASSERT(canRemoveLastProperty());
    JS::RootedObject self(cx, this);
    js::RootedShape prev(cx, lastProperty()->previous());
    JS_ALWAYS_TRUE(setLastProperty(cx, self, prev));
}

inline bool
JSObject::canRemoveLastProperty()
{
    /*
     * Check that the information about the object stored in the last
     * property's base shape is consistent with that stored in the previous
     * shape. If not consistent, then the last property cannot be removed as it
     * will induce a change in the object itself, and the object must be
     * converted to dictionary mode instead. See BaseShape comment in jsscope.h
     */
    JS_ASSERT(!inDictionaryMode());
    js::Shape *previous = lastProperty()->previous().get();
    return previous->getObjectParent() == lastProperty()->getObjectParent()
        && previous->getObjectMetadata() == lastProperty()->getObjectMetadata()
        && previous->getObjectFlags() == lastProperty()->getObjectFlags();
}

inline const js::HeapSlot *
JSObject::getRawSlots()
{
    JS_ASSERT(is<js::GlobalObject>());
    return slots;
}

inline void
JSObject::setReservedSlot(uint32_t index, const js::Value &v)
{
    JS_ASSERT(index < JSSLOT_FREE(getClass()));
    setSlot(index, v);
}

inline void
JSObject::initReservedSlot(uint32_t index, const js::Value &v)
{
    JS_ASSERT(index < JSSLOT_FREE(getClass()));
    initSlot(index, v);
}

inline void
JSObject::prepareSlotRangeForOverwrite(size_t start, size_t end)
{
    for (size_t i = start; i < end; i++)
        getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
}

inline void
JSObject::prepareElementRangeForOverwrite(size_t start, size_t end)
{
    JS_ASSERT(end <= getDenseInitializedLength());
    for (size_t i = start; i < end; i++)
        elements[i].js::HeapSlot::~HeapSlot();
}

inline uint32_t
JSObject::getArrayLength() const
{
    JS_ASSERT(isArray());
    return getElementsHeader()->length;
}

inline bool
JSObject::arrayLengthIsWritable() const
{
    JS_ASSERT(isArray());
    return !getElementsHeader()->hasNonwritableArrayLength();
}

/* static */ inline void
JSObject::setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length)
{
    JS_ASSERT(obj->isArray());
    JS_ASSERT(obj->arrayLengthIsWritable());

    if (length > INT32_MAX) {
        /* Track objects with overflowing lengths in type information. */
        js::types::MarkTypeObjectFlags(cx, obj,
                                       js::types::OBJECT_FLAG_LENGTH_OVERFLOW);
        jsid lengthId = js::NameToId(cx->names().length);
        js::types::AddTypePropertyId(cx, obj, lengthId,
                                     js::types::Type::DoubleType());
    }

    obj->getElementsHeader()->length = length;
}

inline void
JSObject::setArrayLengthInt32(uint32_t length)
{
    /* Variant of setArrayLength for use on arrays where the length cannot overflow int32_t. */
    JS_ASSERT(isArray());
    JS_ASSERT(arrayLengthIsWritable());
    JS_ASSERT(length <= INT32_MAX);
    getElementsHeader()->length = length;
}

inline void
JSObject::setDenseInitializedLength(uint32_t length)
{
    JS_ASSERT(isNative());
    JS_ASSERT(length <= getDenseCapacity());
    prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
    getElementsHeader()->initializedLength = length;
}

inline uint32_t
JSObject::getDenseCapacity()
{
    JS_ASSERT(isNative());
    JS_ASSERT(getElementsHeader()->capacity >= getElementsHeader()->initializedLength);
    return getElementsHeader()->capacity;
}

inline bool
JSObject::shouldConvertDoubleElements()
{
    JS_ASSERT(isNative());
    return getElementsHeader()->shouldConvertDoubleElements();
}

inline void
JSObject::setShouldConvertDoubleElements()
{
    JS_ASSERT(isArray() && !hasEmptyElements());
    getElementsHeader()->setShouldConvertDoubleElements();
}

inline bool
JSObject::ensureElements(JSContext *cx, uint32_t capacity)
{
    if (capacity > getDenseCapacity())
        return growElements(cx, capacity);
    return true;
}

inline void
JSObject::setDynamicElements(js::ObjectElements *header)
{
    JS_ASSERT(!hasDynamicElements());
    elements = header->elements();
    JS_ASSERT(hasDynamicElements());
}

inline void
JSObject::setDenseElement(uint32_t index, const js::Value &val)
{
    JS_ASSERT(isNative() && index < getDenseInitializedLength());
    elements[index].set(this, js::HeapSlot::Element, index, val);
}

inline void
JSObject::setDenseElementMaybeConvertDouble(uint32_t index, const js::Value &val)
{
    if (val.isInt32() && shouldConvertDoubleElements())
        setDenseElement(index, js::DoubleValue(val.toInt32()));
    else
        setDenseElement(index, val);
}

inline void
JSObject::initDenseElement(uint32_t index, const js::Value &val)
{
    JS_ASSERT(isNative() && index < getDenseInitializedLength());
    elements[index].init(this, js::HeapSlot::Element, index, val);
}

/* static */ inline void
JSObject::setDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t index,
                                  const js::Value &val)
{
    js::types::AddTypePropertyId(cx, obj, JSID_VOID, val);
    obj->setDenseElementMaybeConvertDouble(index, val);
}

/* static */ inline void
JSObject::initDenseElementWithType(JSContext *cx, js::HandleObject obj, uint32_t index,
                                   const js::Value &val)
{
    JS_ASSERT(!obj->shouldConvertDoubleElements());
    js::types::AddTypePropertyId(cx, obj, JSID_VOID, val);
    obj->initDenseElement(index, val);
}

/* static */ inline void
JSObject::setDenseElementHole(JSContext *cx, js::HandleObject obj, uint32_t index)
{
    js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_NON_PACKED);
    obj->setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
}

/* static */ inline void
JSObject::removeDenseElementForSparseIndex(JSContext *cx, js::HandleObject obj, uint32_t index)
{
    js::types::MarkTypeObjectFlags(cx, obj,
                                   js::types::OBJECT_FLAG_NON_PACKED |
                                   js::types::OBJECT_FLAG_SPARSE_INDEXES);
    if (obj->containsDenseElement(index))
        obj->setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
}

inline void
JSObject::copyDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count)
{
    JS_ASSERT(dstStart + count <= getDenseCapacity());
    JS::Zone *zone = this->zone();
    for (uint32_t i = 0; i < count; ++i)
        elements[dstStart + i].set(zone, this, js::HeapSlot::Element, dstStart + i, src[i]);
}

inline void
JSObject::initDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count)
{
    JS_ASSERT(dstStart + count <= getDenseCapacity());
    JSRuntime *rt = runtime();
    for (uint32_t i = 0; i < count; ++i)
        elements[dstStart + i].init(rt, this, js::HeapSlot::Element, dstStart + i, src[i]);
}

inline void
JSObject::moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count)
{
    JS_ASSERT(dstStart + count <= getDenseCapacity());
    JS_ASSERT(srcStart + count <= getDenseInitializedLength());

    /*
     * Using memmove here would skip write barriers. Also, we need to consider
     * an array containing [A, B, C], in the following situation:
     *
     * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code.
     * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C].
     * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C).
     *
     * Since normal marking never happens on B, it is very important that the
     * write barrier is invoked here on B, despite the fact that it exists in
     * the array before and after the move.
    */
    JS::Zone *zone = this->zone();
    if (zone->needsBarrier()) {
        if (dstStart < srcStart) {
            js::HeapSlot *dst = elements + dstStart;
            js::HeapSlot *src = elements + srcStart;
            for (uint32_t i = 0; i < count; i++, dst++, src++)
                dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src);
        } else {
            js::HeapSlot *dst = elements + dstStart + count - 1;
            js::HeapSlot *src = elements + srcStart + count - 1;
            for (uint32_t i = 0; i < count; i++, dst--, src--)
                dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src);
        }
    } else {
        memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
        DenseRangeWriteBarrierPost(runtime(), this, dstStart, count);
    }
}

inline void
JSObject::moveDenseElementsUnbarriered(uint32_t dstStart, uint32_t srcStart, uint32_t count)
{
    JS_ASSERT(!zone()->needsBarrier());

    JS_ASSERT(dstStart + count <= getDenseCapacity());
    JS_ASSERT(srcStart + count <= getDenseCapacity());

    memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
}

inline void
JSObject::markDenseElementsNotPacked(JSContext *cx)
{
    JS_ASSERT(isNative());
    MarkTypeObjectFlags(cx, this, js::types::OBJECT_FLAG_NON_PACKED);
}

inline void
JSObject::ensureDenseInitializedLength(JSContext *cx, uint32_t index, uint32_t extra)
{
    /*
     * Ensure that the array's contents have been initialized up to index, and
     * mark the elements through 'index + extra' as initialized in preparation
     * for a write.
     */
    JS_ASSERT(index + extra <= getDenseCapacity());
    uint32_t &initlen = getElementsHeader()->initializedLength;
    if (initlen < index)
        markDenseElementsNotPacked(cx);

    if (initlen < index + extra) {
        JSRuntime *rt = runtime();
        size_t offset = initlen;
        for (js::HeapSlot *sp = elements + initlen;
             sp != elements + (index + extra);
             sp++, offset++)
            sp->init(rt, this, js::HeapSlot::Element, offset, js::MagicValue(JS_ELEMENTS_HOLE));
        initlen = index + extra;
    }
}

JSObject::EnsureDenseResult
JSObject::extendDenseElements(js::ThreadSafeContext *tcx,
                              uint32_t requiredCapacity, uint32_t extra)
{
    /*
     * Don't grow elements for non-extensible objects or watched objects. Dense
     * elements can be added/written with no extensible or watchpoint checks as
     * long as there is capacity for them.
     */
    if (!isExtensible() || watched()) {
        JS_ASSERT(getDenseCapacity() == 0);
        return ED_SPARSE;
    }

    /*
     * Don't grow elements for objects which already have sparse indexes.
     * This avoids needing to count non-hole elements in willBeSparseElements
     * every time a new index is added.
     */
    if (isIndexed())
        return ED_SPARSE;

    /*
     * We use the extra argument also as a hint about number of non-hole
     * elements to be inserted.
     */
    if (requiredCapacity > MIN_SPARSE_INDEX &&
        willBeSparseElements(requiredCapacity, extra)) {
        return ED_SPARSE;
    }

    if (!growElements(tcx, requiredCapacity))
        return ED_FAILED;

    return ED_OK;
}

inline JSObject::EnsureDenseResult
JSObject::parExtendDenseElements(js::ThreadSafeContext *tcx, js::Value *v, uint32_t extra)
{
    JS_ASSERT(isNative());
    JS_ASSERT_IF(isArray(), arrayLengthIsWritable());

    js::ObjectElements *header = getElementsHeader();
    uint32_t initializedLength = header->initializedLength;
    uint32_t requiredCapacity = initializedLength + extra;
    if (requiredCapacity < initializedLength)
        return ED_SPARSE; /* Overflow. */

    if (requiredCapacity > header->capacity) {
        EnsureDenseResult edr = extendDenseElements(tcx, requiredCapacity, extra);
        if (edr != ED_OK)
            return edr;
    }

    // Watch out lest the header has been reallocated by
    // extendDenseElements():
    header = getElementsHeader();

    js::HeapSlot *sp = elements + initializedLength;
    if (v) {
        for (uint32_t i = 0; i < extra; i++) {
            JS_ASSERT_IF(v[i].isMarkable(), static_cast<js::gc::Cell *>(v[i].toGCThing())->isTenured());
            *sp[i].unsafeGet() = v[i];
        }
    } else {
        for (uint32_t i = 0; i < extra; i++)
            *sp[i].unsafeGet() = js::MagicValue(JS_ELEMENTS_HOLE);
    }
    header->initializedLength = requiredCapacity;
    if (header->length < requiredCapacity)
        header->length = requiredCapacity;
    return ED_OK;
}

inline JSObject::EnsureDenseResult
JSObject::ensureDenseElements(JSContext *cx, uint32_t index, uint32_t extra)
{
    JS_ASSERT(isNative());

    uint32_t currentCapacity = getDenseCapacity();

    uint32_t requiredCapacity;
    if (extra == 1) {
        /* Optimize for the common case. */
        if (index < currentCapacity) {
            ensureDenseInitializedLength(cx, index, 1);
            return ED_OK;
        }
        requiredCapacity = index + 1;
        if (requiredCapacity == 0) {
            /* Overflow. */
            return ED_SPARSE;
        }
    } else {
        requiredCapacity = index + extra;
        if (requiredCapacity < index) {
            /* Overflow. */
            return ED_SPARSE;
        }
        if (requiredCapacity <= currentCapacity) {
            ensureDenseInitializedLength(cx, index, extra);
            return ED_OK;
        }
    }

    EnsureDenseResult edr = extendDenseElements(cx, requiredCapacity, extra);
    if (edr != ED_OK)
        return edr;

    ensureDenseInitializedLength(cx, index, extra);
    return ED_OK;
}

namespace js {

/*
 * Any name atom for a function which will be added as a DeclEnv object to the
 * scope chain above call objects for fun.
 */
static inline JSAtom *
CallObjectLambdaName(JSFunction &fun)
{
    return fun.isNamedLambda() ? fun.atom() : NULL;
}

} /* namespace js */

inline const js::Value &
JSObject::getDateUTCTime() const
{
    JS_ASSERT(isDate());
    return getFixedSlot(JSSLOT_DATE_UTC_TIME);
}

inline void
JSObject::setDateUTCTime(const js::Value &time)
{
    JS_ASSERT(isDate());
    setFixedSlot(JSSLOT_DATE_UTC_TIME, time);
}

/* static */ inline bool
JSObject::setSingletonType(JSContext *cx, js::HandleObject obj)
{
    JS_ASSERT(!IsInsideNursery(cx->runtime(), obj.get()));

    if (!cx->typeInferenceEnabled())
        return true;

    js::types::TypeObject *type =
        cx->compartment()->getLazyType(cx, obj->getClass(), obj->getTaggedProto());
    if (!type)
        return false;

    obj->type_ = type;
    return true;
}

inline js::types::TypeObject*
JSObject::getType(JSContext *cx)
{
    JS_ASSERT(cx->compartment() == compartment());
    if (hasLazyType()) {
        JS::RootedObject self(cx, this);
        if (cx->compartment() != compartment())
            MOZ_CRASH();
        return makeLazyType(cx, self);
    }
    return static_cast<js::types::TypeObject*>(type_);
}

/* static */ inline bool
JSObject::clearType(JSContext *cx, js::HandleObject obj)
{
    JS_ASSERT(!obj->hasSingletonType());
    JS_ASSERT(cx->compartment() == obj->compartment());

    js::types::TypeObject *type = cx->compartment()->getNewType(cx, obj->getClass(), NULL);
    if (!type)
        return false;

    obj->type_ = type;
    return true;
}

inline void
JSObject::setType(js::types::TypeObject *newType)
{
    JS_ASSERT(newType);
    JS_ASSERT_IF(getClass()->emulatesUndefined(),
                 newType->hasAnyFlags(js::types::OBJECT_FLAG_EMULATES_UNDEFINED));
    JS_ASSERT(!hasSingletonType());
    type_ = newType;
}

inline JSObject *
JSObject::getProto() const
{
    JS_ASSERT(!isProxy());
    return js::ObjectImpl::getProto();
}

/* static */ inline bool
JSObject::getProto(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
{
    if (obj->getTaggedProto().isLazy()) {
        JS_ASSERT(obj->isProxy());
        return js::Proxy::getPrototypeOf(cx, obj, protop);
    } else {
        protop.set(obj->js::ObjectImpl::getProto());
        return true;
    }
}

inline bool JSObject::setIteratedSingleton(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
}

inline bool JSObject::setDelegate(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
}

inline bool JSObject::isVarObj()
{
    if (is<js::DebugScopeObject>())
        return as<js::DebugScopeObject>().scope().isVarObj();
    return lastProperty()->hasObjectFlag(js::BaseShape::VAROBJ);
}

inline bool JSObject::setVarObj(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::VAROBJ);
}

inline bool JSObject::setWatched(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
}

inline bool JSObject::hasUncacheableProto() const
{
    return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
}

inline bool JSObject::setUncacheableProto(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
}

inline bool JSObject::hadElementsAccess() const
{
    return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS);
}

inline bool JSObject::setHadElementsAccess(JSContext *cx)
{
    return setFlag(cx, js::BaseShape::HAD_ELEMENTS_ACCESS);
}

inline bool JSObject::isBoundFunction() const
{
    return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
}

inline bool JSObject::isIndexed() const
{
    return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED);
}

inline bool JSObject::watched() const
{
    return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
}

inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }

/* static */ inline JSObject *
JSObject::create(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
                 js::HandleShape shape, js::HandleTypeObject type,
                 js::HeapSlot *extantSlots /* = NULL */)
{
    /*
     * Callers must use dynamicSlotsCount to size the initial slot array of the
     * object. We can't check the allocated capacity of the dynamic slots, but
     * make sure their presence is consistent with the shape.
     */
    JS_ASSERT(shape && type);
    JS_ASSERT(type->clasp == shape->getObjectClass());
    JS_ASSERT(type->clasp != &js::ArrayClass);
    JS_ASSERT(js::gc::GetGCKindSlots(kind, type->clasp) == shape->numFixedSlots());
    JS_ASSERT_IF(type->clasp->flags & JSCLASS_BACKGROUND_FINALIZE, IsBackgroundFinalized(kind));
    JS_ASSERT_IF(type->clasp->finalize, heap == js::gc::TenuredHeap);
    JS_ASSERT_IF(extantSlots, dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()));

    js::HeapSlot *slots = extantSlots;
    if (!slots) {
        size_t nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan());
        if (nDynamicSlots) {
            slots = cx->pod_malloc<js::HeapSlot>(nDynamicSlots);
            if (!slots)
                return NULL;
            js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
        }
    }

    JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind, heap);
    if (!obj) {
        js_free(slots);
        return NULL;
    }

#ifdef JSGC_GENERATIONAL
    cx->runtime()->gcNursery.notifyInitialSlots(obj, slots);
#endif

    obj->shape_.init(shape);
    obj->type_.init(type);
    obj->slots = slots;
    obj->elements = js::emptyObjectElements;

    const js::Class *clasp = type->clasp;
    if (clasp->hasPrivate())
        obj->privateRef(shape->numFixedSlots()) = NULL;

    size_t span = shape->slotSpan();
    if (span && clasp != &js::ArrayBufferObject::class_)
        obj->initializeSlotRange(0, span);

    return obj;
}

/* static */ inline JSObject *
JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
                      js::HandleShape shape, js::HandleTypeObject type,
                      uint32_t length)
{
    JS_ASSERT(shape && type);
    JS_ASSERT(type->clasp == shape->getObjectClass());
    JS_ASSERT(type->clasp == &js::ArrayClass);
    JS_ASSERT_IF(type->clasp->finalize, heap == js::gc::TenuredHeap);

    /*
     * Arrays use their fixed slots to store elements, and must have enough
     * space for the elements header and also be marked as having no space for
     * named properties stored in those fixed slots.
     */
    JS_ASSERT(shape->numFixedSlots() == 0);

    /*
     * The array initially stores its elements inline, there must be enough
     * space for an elements header.
     */
    JS_ASSERT(js::gc::GetGCKindSlots(kind) >= js::ObjectElements::VALUES_PER_HEADER);

    uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;

    JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind, heap);
    if (!obj) {
        js_ReportOutOfMemory(cx);
        return NULL;
    }

    obj->shape_.init(shape);
    obj->type_.init(type);
    obj->slots = NULL;
    obj->setFixedElements();
    new (obj->getElementsHeader()) js::ObjectElements(capacity, length);

    return obj;
}

inline void
JSObject::finish(js::FreeOp *fop)
{
    if (hasDynamicSlots())
        fop->free_(slots);
    if (hasDynamicElements()) {
        js::ObjectElements *elements = getElementsHeader();
        if (JS_UNLIKELY(elements->isAsmJSArrayBuffer()))
            js::ArrayBufferObject::releaseAsmJSArrayBuffer(fop, this);
        else
            fop->free_(elements);
    }
}

/* static */ inline bool
JSObject::hasProperty(JSContext *cx, js::HandleObject obj,
                      js::HandleId id, bool *foundp, unsigned flags)
{
    JS::RootedObject pobj(cx);
    js::RootedShape prop(cx);
    JSAutoResolveFlags rf(cx, flags);
    if (!lookupGeneric(cx, obj, id, &pobj, &prop)) {
        *foundp = false;  /* initialize to shut GCC up */
        return false;
    }
    *foundp = !!prop;
    return true;
}

inline bool
JSObject::isCallable()
{
    return getClass()->isCallable();
}

inline void
JSObject::nativeSetSlot(uint32_t slot, const js::Value &value)
{
    JS_ASSERT(isNative());
    JS_ASSERT(slot < slotSpan());
    return setSlot(slot, value);
}

/* static */ inline void
JSObject::nativeSetSlotWithType(JSContext *cx, js::HandleObject obj, js::Shape *shape,
                                const js::Value &value)
{
    obj->nativeSetSlot(shape->slot(), value);
    js::types::AddTypePropertyId(cx, obj, shape->propid(), value);
}

inline bool
JSObject::nativeEmpty() const
{
    return lastProperty()->isEmptyShape();
}

inline uint32_t
JSObject::propertyCount() const
{
    return lastProperty()->entryCount();
}

inline bool
JSObject::hasShapeTable() const
{
    return lastProperty()->hasTable();
}

/* static */ inline JSBool
JSObject::lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id,
                        js::MutableHandleObject objp, js::MutableHandleShape propp)
{
    /* NB: The logic of lookupGeneric is implicitly reflected in IonBuilder.cpp's
     *     |CanEffectlesslyCallLookupGenericOnObject| logic.
     *     If this changes, please remember to update the logic there as well.
     */
    js::LookupGenericOp op = obj->getOps()->lookupGeneric;
    if (op)
        return op(cx, obj, id, objp, propp);
    return js::baseops::LookupProperty<js::CanGC>(cx, obj, id, objp, propp);
}

/* static */ inline JSBool
JSObject::lookupProperty(JSContext *cx, js::HandleObject obj, js::PropertyName *name,
                         js::MutableHandleObject objp, js::MutableHandleShape propp)
{
    JS::RootedId id(cx, js::NameToId(name));
    return lookupGeneric(cx, obj, id, objp, propp);
}

/* static */ inline JSBool
JSObject::defineGeneric(JSContext *cx, js::HandleObject obj,
                        js::HandleId id, js::HandleValue value,
                        JSPropertyOp getter /* = JS_PropertyStub */,
                        JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                        unsigned attrs /* = JSPROP_ENUMERATE */)
{
    JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
    js::DefineGenericOp op = obj->getOps()->defineGeneric;
    return (op ? op : js::baseops::DefineGeneric)(cx, obj, id, value, getter, setter, attrs);
}

/* static */ inline JSBool
JSObject::defineProperty(JSContext *cx, js::HandleObject obj,
                         js::PropertyName *name, js::HandleValue value,
                        JSPropertyOp getter /* = JS_PropertyStub */,
                        JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                        unsigned attrs /* = JSPROP_ENUMERATE */)
{
    JS::RootedId id(cx, js::NameToId(name));
    return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}

/* static */ inline JSBool
JSObject::defineElement(JSContext *cx, js::HandleObject obj,
                        uint32_t index, js::HandleValue value,
                        JSPropertyOp getter /* = JS_PropertyStub */,
                        JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                        unsigned attrs /* = JSPROP_ENUMERATE */)
{
    js::DefineElementOp op = obj->getOps()->defineElement;
    return (op ? op : js::baseops::DefineElement)(cx, obj, index, value, getter, setter, attrs);
}

/* static */ inline JSBool
JSObject::defineSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid, js::HandleValue value,
                        JSPropertyOp getter /* = JS_PropertyStub */,
                        JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                        unsigned attrs /* = JSPROP_ENUMERATE */)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return defineGeneric(cx, obj, id, value, getter, setter, attrs);
}

/* static */ inline JSBool
JSObject::lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index,
                        js::MutableHandleObject objp, js::MutableHandleShape propp)
{
    js::LookupElementOp op = obj->getOps()->lookupElement;
    return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp);
}

/* static */ inline JSBool
JSObject::lookupSpecial(JSContext *cx, js::HandleObject obj, js::SpecialId sid,
                        js::MutableHandleObject objp, js::MutableHandleShape propp)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return lookupGeneric(cx, obj, id, objp, propp);
}

/* static */ inline JSBool
JSObject::getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     uint32_t index, js::MutableHandleValue vp)
{
    js::ElementIdOp op = obj->getOps()->getElement;
    if (op)
        return op(cx, obj, receiver, index, vp);

    JS::RootedId id(cx);
    if (!js::IndexToId(cx, index, &id))
        return false;
    return getGeneric(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
                         uint32_t index, js::Value *vp)
{
    js::ElementIdOp op = obj->getOps()->getElement;
    if (op)
        return false;

    jsid id;
    if (!js::IndexToIdNoGC(cx, index, &id))
        return false;
    return getGenericNoGC(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getElementIfPresent(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                              uint32_t index, js::MutableHandleValue vp,
                              bool *present)
{
    js::ElementIfPresentOp op = obj->getOps()->getElementIfPresent;
    if (op)
        return op(cx, obj, receiver, index, vp, present);

    /*
     * For now, do the index-to-id conversion just once, then use
     * lookupGeneric/getGeneric.  Once lookupElement and getElement stop both
     * doing index-to-id conversions, we can use those here.
     */
    JS::RootedId id(cx);
    if (!js::IndexToId(cx, index, &id))
        return false;

    JS::RootedObject obj2(cx);
    js::RootedShape prop(cx);
    if (!lookupGeneric(cx, obj, id, &obj2, &prop))
        return false;

    if (!prop) {
        *present = false;
        return true;
    }

    *present = true;
    return getGeneric(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getSpecial(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                     js::SpecialId sid, js::MutableHandleValue vp)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return getGeneric(cx, obj, receiver, id, vp);
}

/* static */ inline JSBool
JSObject::getGenericAttributes(JSContext *cx, js::HandleObject obj,
                               js::HandleId id, unsigned *attrsp)
{
    js::GenericAttributesOp op = obj->getOps()->getGenericAttributes;
    return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
}

/* static */ inline JSBool
JSObject::getPropertyAttributes(JSContext *cx, js::HandleObject obj,
                                js::PropertyName *name, unsigned *attrsp)
{
    JS::RootedId id(cx, js::NameToId(name));
    return getGenericAttributes(cx, obj, id, attrsp);
}

/* static */ inline JSBool
JSObject::getElementAttributes(JSContext *cx, js::HandleObject obj,
                               uint32_t index, unsigned *attrsp)
{
    JS::RootedId id(cx);
    if (!js::IndexToId(cx, index, &id))
        return false;
    return getGenericAttributes(cx, obj, id, attrsp);
}

/* static */ inline JSBool
JSObject::getSpecialAttributes(JSContext *cx, js::HandleObject obj,
                               js::SpecialId sid, unsigned *attrsp)
{
    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
    return getGenericAttributes(cx, obj, id, attrsp);
}

inline bool
JSObject::isCrossCompartmentWrapper() const
{
    return js::IsCrossCompartmentWrapper(const_cast<JSObject*>(this));
}

inline bool
JSObject::isWrapper() const
{
    return js::IsWrapper(const_cast<JSObject*>(this));
}

inline js::GlobalObject &
JSObject::global() const
{
#ifdef DEBUG
    JSObject *obj = const_cast<JSObject *>(this);
    while (JSObject *parent = obj->getParent())
        obj = parent;
#endif
    return *compartment()->maybeGlobal();
}

static inline bool
js_IsCallable(const js::Value &v)
{
    return v.isObject() && v.toObject().isCallable();
}

namespace js {

PropDesc::PropDesc(const Value &getter, const Value &setter,
                   Enumerability enumerable, Configurability configurable)
  : pd_(UndefinedValue()),
    value_(UndefinedValue()),
    get_(getter), set_(setter),
    attrs(JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED |
          (enumerable ? JSPROP_ENUMERATE : 0) |
          (configurable ? 0 : JSPROP_PERMANENT)),
    hasGet_(true), hasSet_(true),
    hasValue_(false), hasWritable_(false), hasEnumerable_(true), hasConfigurable_(true),
    isUndefined_(false)
{
    MOZ_ASSERT(getter.isUndefined() || js_IsCallable(getter));
    MOZ_ASSERT(setter.isUndefined() || js_IsCallable(setter));
}

inline JSObject *
GetInnerObject(JSContext *cx, HandleObject obj)
{
    if (JSObjectOp op = obj->getClass()->ext.innerObject)
        return op(cx, obj);
    return obj;
}

inline JSObject *
GetOuterObject(JSContext *cx, HandleObject obj)
{
    if (JSObjectOp op = obj->getClass()->ext.outerObject)
        return op(cx, obj);
    return obj;
}

static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v)
{
    return v.isObject() && v.toObject().is<JSFunction>();
}

static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v, JSFunction **fun)
{
    if (v.isObject() && v.toObject().is<JSFunction>()) {
        *fun = &v.toObject().as<JSFunction>();
        return true;
    }
    return false;
}

static JS_ALWAYS_INLINE bool
IsNativeFunction(const js::Value &v)
{
    JSFunction *fun;
    return IsFunctionObject(v, &fun) && fun->isNative();
}

static JS_ALWAYS_INLINE bool
IsNativeFunction(const js::Value &v, JSFunction **fun)
{
    return IsFunctionObject(v, fun) && (*fun)->isNative();
}

static JS_ALWAYS_INLINE bool
IsNativeFunction(const js::Value &v, JSNative native)
{
    JSFunction *fun;
    return IsFunctionObject(v, &fun) && fun->maybeNative() == native;
}

/*
 * When we have an object of a builtin class, we don't quite know what its
 * valueOf/toString methods are, since these methods may have been overwritten
 * or shadowed. However, we can still do better than the general case by
 * hard-coding the necessary properties for us to find the native we expect.
 *
 * TODO: a per-thread shape-based cache would be faster and simpler.
 */
static JS_ALWAYS_INLINE bool
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid, JSNative native)
{
    JS_ASSERT(!obj->isProxy());
    JS_ASSERT(obj->getClass() == clasp);

    Value v;
    if (!HasDataProperty(cx, obj, methodid, &v)) {
        JSObject *proto = obj->getProto();
        if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, proto, methodid, &v))
            return false;
    }

    return js::IsNativeFunction(v, native);
}

/* ES5 9.1 ToPrimitive(input). */
static JS_ALWAYS_INLINE bool
ToPrimitive(JSContext *cx, MutableHandleValue vp)
{
    if (vp.isPrimitive())
        return true;

    JSObject *obj = &vp.toObject();

    /* Optimize new String(...).valueOf(). */
    if (obj->is<StringObject>()) {
        jsid id = NameToId(cx->names().valueOf);
        if (ClassMethodIsNative(cx, obj, &StringObject::class_, id, js_str_toString)) {
            vp.setString(obj->as<StringObject>().unbox());
            return true;
        }
    }

    /* Optimize new Number(...).valueOf(). */
    if (obj->is<NumberObject>()) {
        jsid id = NameToId(cx->names().valueOf);
        if (ClassMethodIsNative(cx, obj, &NumberObject::class_, id, js_num_valueOf)) {
            vp.setNumber(obj->as<NumberObject>().unbox());
            return true;
        }
    }

    RootedObject objRoot(cx, obj);
    return JSObject::defaultValue(cx, objRoot, JSTYPE_VOID, vp);
}

/* ES5 9.1 ToPrimitive(input, PreferredType). */
static JS_ALWAYS_INLINE bool
ToPrimitive(JSContext *cx, JSType preferredType, MutableHandleValue vp)
{
    JS_ASSERT(preferredType != JSTYPE_VOID); /* Use the other ToPrimitive! */
    if (vp.isPrimitive())
        return true;
    RootedObject obj(cx, &vp.toObject());
    return JSObject::defaultValue(cx, obj, preferredType, vp);
}

/*
 * Return true if this is a compiler-created internal function accessed by
 * its own object. Such a function object must not be accessible to script
 * or embedding code.
 */
inline bool
IsInternalFunctionObject(JSObject *funobj)
{
    JSFunction *fun = &funobj->as<JSFunction>();
    return fun->isLambda() && !funobj->getParent();
}

class AutoPropDescArrayRooter : private AutoGCRooter
{
  public:
    AutoPropDescArrayRooter(JSContext *cx)
      : AutoGCRooter(cx, DESCRIPTORS), descriptors(cx), skip(cx, &descriptors)
    { }

    PropDesc *append() {
        if (!descriptors.append(PropDesc()))
            return NULL;
        return &descriptors.back();
    }

    bool reserve(size_t n) {
        return descriptors.reserve(n);
    }

    PropDesc& operator[](size_t i) {
        JS_ASSERT(i < descriptors.length());
        return descriptors[i];
    }

    friend void AutoGCRooter::trace(JSTracer *trc);

  private:
    PropDescArray descriptors;
    SkipRoot skip;
};

class AutoPropertyDescriptorRooter : private AutoGCRooter, public PropertyDescriptor
{
    SkipRoot skip;

    AutoPropertyDescriptorRooter *thisDuringConstruction() { return this; }

  public:
    AutoPropertyDescriptorRooter(JSContext *cx)
      : AutoGCRooter(cx, DESCRIPTOR), skip(cx, thisDuringConstruction())
    {
        obj = NULL;
        attrs = 0;
        getter = (PropertyOp) NULL;
        setter = (StrictPropertyOp) NULL;
        value.setUndefined();
    }

    AutoPropertyDescriptorRooter(JSContext *cx, PropertyDescriptor *desc)
      : AutoGCRooter(cx, DESCRIPTOR), skip(cx, thisDuringConstruction())
    {
        obj = desc->obj;
        attrs = desc->attrs;
        getter = desc->getter;
        setter = desc->setter;
        value = desc->value;
    }

    friend void AutoGCRooter::trace(JSTracer *trc);
};

/*
 * Make an object with the specified prototype. If parent is null, it will
 * default to the prototype's global if the prototype is non-null.
 */
JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
                        gc::AllocKind allocKind, NewObjectKind newKind);

inline JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, TaggedProto proto, JSObject *parent,
                        NewObjectKind newKind = GenericObject)
{
    gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
    return NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind);
}

inline JSObject *
NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
                        NewObjectKind newKind = GenericObject)
{
    return NewObjectWithGivenProto(cx, clasp, TaggedProto(proto), parent, newKind);
}

inline JSProtoKey
GetClassProtoKey(js::Class *clasp)
{
    JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
    if (key != JSProto_Null)
        return key;
    if (clasp->flags & JSCLASS_IS_ANONYMOUS)
        return JSProto_Object;
    return JSProto_Null;
}

inline bool
FindProto(JSContext *cx, js::Class *clasp, MutableHandleObject proto)
{
    JSProtoKey protoKey = GetClassProtoKey(clasp);
    if (!js_GetClassPrototype(cx, protoKey, proto, clasp))
        return false;
    if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto))
        return false;
    return true;
}

/*
 * Make an object with the prototype set according to the specified prototype or class:
 *
 * if proto is non-null:
 *   use the specified proto
 * for a built-in class:
 *   use the memoized original value of the class constructor .prototype
 *   property object
 * else if available
 *   the current value of .prototype
 * else
 *   Object.prototype.
 *
 * The class prototype will be fetched from the parent's global. If global is
 * null, the context's active global will be used, and the resulting object's
 * parent will be that global.
 */
JSObject *
NewObjectWithClassProtoCommon(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
                              gc::AllocKind allocKind, NewObjectKind newKind);

inline JSObject *
NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
                        gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
{
    return NewObjectWithClassProtoCommon(cx, clasp, proto, parent, allocKind, newKind);
}

inline JSObject *
NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
                        NewObjectKind newKind = GenericObject)
{
    gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
    return NewObjectWithClassProto(cx, clasp, proto, parent, allocKind, newKind);
}

/*
 * Create a native instance of the given class with parent and proto set
 * according to the context's active global.
 */
inline JSObject *
NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::AllocKind allocKind,
                        NewObjectKind newKind = GenericObject)
{
    return NewObjectWithClassProto(cx, clasp, NULL, NULL, allocKind, newKind);
}

inline JSObject *
NewBuiltinClassInstance(JSContext *cx, Class *clasp, NewObjectKind newKind = GenericObject)
{
    gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
    return NewBuiltinClassInstance(cx, clasp, allocKind, newKind);
}

bool
FindClassPrototype(JSContext *cx, HandleObject scope, JSProtoKey protoKey,
                   MutableHandleObject protop, Class *clasp);

/*
 * Create a plain object with the specified type. This bypasses getNewType to
 * avoid losing creation site information for objects made by scripted 'new'.
 */
JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
                  NewObjectKind newKind = GenericObject);

// Used to optimize calls to (new Object())
bool
NewObjectScriptedCall(JSContext *cx, MutableHandleObject obj);

/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
static inline JSObject *
CopyInitializerObject(JSContext *cx, HandleObject baseobj, NewObjectKind newKind = GenericObject)
{
    JS_ASSERT(baseobj->getClass() == &ObjectClass);
    JS_ASSERT(!baseobj->inDictionaryMode());

    gc::AllocKind allocKind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
    allocKind = gc::GetBackgroundAllocKind(allocKind);
    JS_ASSERT_IF(baseobj->isTenured(), allocKind == baseobj->tenuredGetAllocKind());
    RootedObject obj(cx);
    obj = NewBuiltinClassInstance(cx, &ObjectClass, allocKind, newKind);
    if (!obj)
        return NULL;

    RootedObject metadata(cx, obj->getMetadata());
    RootedShape lastProp(cx, baseobj->lastProperty());
    if (!JSObject::setLastProperty(cx, obj, lastProp))
        return NULL;
    if (metadata && !JSObject::setMetadata(cx, obj, metadata))
        return NULL;

    return obj;
}

JSObject *
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
                  gc::AllocKind kind, HandleShape shape);

/*
 * As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
 * the object, zero if the final size is unknown. This should only be used for
 * objects that do not require any fixed slots.
 */
static inline gc::AllocKind
GuessObjectGCKind(size_t numSlots)
{
    if (numSlots)
        return gc::GetGCObjectKind(numSlots);
    return gc::FINALIZE_OBJECT4;
}

static inline gc::AllocKind
GuessArrayGCKind(size_t numSlots)
{
    if (numSlots)
        return gc::GetGCArrayKind(numSlots);
    return gc::FINALIZE_OBJECT8;
}

inline bool
DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
                              JSProtoKey key, HandleObject ctor, HandleObject proto)
{
    JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
    JS_ASSERT(ctor);
    JS_ASSERT(proto);

    RootedId id(cx, NameToId(ClassName(key, cx)));
    JS_ASSERT(!global->nativeLookup(cx, id));

    /* Set these first in case AddTypePropertyId looks for this class. */
    global->setSlot(key, ObjectValue(*ctor));
    global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
    global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));

    types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
    if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
        global->setSlot(key, UndefinedValue());
        global->setSlot(key + JSProto_LIMIT, UndefinedValue());
        global->setSlot(key + JSProto_LIMIT * 2, UndefinedValue());
        return false;
    }

    return true;
}

inline bool
ObjectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx)
{
    if (JS_UNLIKELY(obj->isProxy()))
        return Proxy::objectClassIs(obj, classValue, cx);

    switch (classValue) {
      case ESClass_Array: return obj->isArray();
      case ESClass_Number: return obj->is<NumberObject>();
      case ESClass_String: return obj->is<StringObject>();
      case ESClass_Boolean: return obj->is<BooleanObject>();
      case ESClass_RegExp: return obj->is<RegExpObject>();
      case ESClass_ArrayBuffer: return obj->is<ArrayBufferObject>();
      case ESClass_Date: return obj->isDate();
    }
    JS_NOT_REACHED("bad classValue");
    return false;
}

inline bool
IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
{
    if (!v.isObject())
        return false;
    RootedObject obj(cx, &v.toObject());
    return ObjectClassIs(obj, classValue, cx);
}

static JS_ALWAYS_INLINE bool
ValueMightBeSpecial(const Value &propval)
{
    return propval.isObject();
}

static JS_ALWAYS_INLINE bool
ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle<SpecialId> sidp,
               JSContext *cx)
{
    return false;
}

JSObject *
DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
                              JSObject *protoProto, Class *clasp,
                              Native constructor, unsigned nargs,
                              const JSPropertySpec *ps, const JSFunctionSpec *fs,
                              const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
                              JSObject **ctorp = NULL,
                              gc::AllocKind ctorKind = JSFunction::FinalizeKind);

static JS_ALWAYS_INLINE JSObject *
NewObjectMetadata(JSContext *cx)
{
    // The metadata callback is invoked before each created object, except when
    // analysis is active as the callback may reenter JS.
    if (JS_UNLIKELY((size_t)cx->compartment()->objectMetadataCallback) &&
        !cx->compartment()->activeAnalysis)
    {
        gc::AutoSuppressGC suppress(cx);
        return cx->compartment()->objectMetadataCallback(cx);
    }
    return NULL;
}

} /* namespace js */

extern JSObject *
js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
             js::Class *clasp, JSNative constructor, unsigned nargs,
             const JSPropertySpec *ps, const JSFunctionSpec *fs,
             const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
             JSObject **ctorp = NULL,
             js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);

/*
 * js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
 * scope, else it reshapes the scope and prototype chains it links. It calls
 * js_PurgeScopeChainHelper, which asserts that obj is flagged as a delegate
 * (i.e., obj has ever been on a prototype or parent chain).
 */
extern bool
js_PurgeScopeChainHelper(JSContext *cx, JS::HandleObject obj, JS::HandleId id);

inline bool
js_PurgeScopeChain(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
{
    if (obj->isDelegate())
        return js_PurgeScopeChainHelper(cx, obj, id);
    return true;
}

inline void
js::DestroyIdArray(FreeOp *fop, JSIdArray *ida)
{
    fop->free_(ida);
}

#endif /* jsobjinlines_h */
