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

/* Inline members for javascript type inference. */

#ifndef vm_TypeInference_inl_h
#define vm_TypeInference_inl_h

#include "vm/TypeInference.h"

#include "mozilla/PodOperations.h"

#include "builtin/SymbolObject.h"
#include "jit/BaselineJIT.h"
#include "vm/ArrayObject.h"
#include "vm/BooleanObject.h"
#include "vm/NumberObject.h"
#include "vm/SharedArrayObject.h"
#include "vm/StringObject.h"
#include "vm/TypedArrayObject.h"
#include "vm/UnboxedObject.h"

#include "jscntxtinlines.h"

#include "vm/ObjectGroup-inl.h"

namespace js {

/////////////////////////////////////////////////////////////////////
// CompilerOutput & RecompileInfo
/////////////////////////////////////////////////////////////////////

inline jit::IonScript*
CompilerOutput::ion() const
{
    // Note: If type constraints are generated before compilation has finished
    // (i.e. after IonBuilder but before CodeGenerator::link) then a valid
    // CompilerOutput may not yet have an associated IonScript.
    MOZ_ASSERT(isValid());
    jit::IonScript* ion = script()->maybeIonScript();
    MOZ_ASSERT(ion != ION_COMPILING_SCRIPT);
    return ion;
}

inline CompilerOutput*
RecompileInfo::compilerOutput(TypeZone& types) const
{
    if (generation != types.generation) {
        if (!types.sweepCompilerOutputs || outputIndex >= types.sweepCompilerOutputs->length())
            return nullptr;
        CompilerOutput* output = &(*types.sweepCompilerOutputs)[outputIndex];
        if (!output->isValid())
            return nullptr;
        output = &(*types.compilerOutputs)[output->sweepIndex()];
        return output->isValid() ? output : nullptr;
    }

    if (!types.compilerOutputs || outputIndex >= types.compilerOutputs->length())
        return nullptr;
    CompilerOutput* output = &(*types.compilerOutputs)[outputIndex];
    return output->isValid() ? output : nullptr;
}

inline CompilerOutput*
RecompileInfo::compilerOutput(JSContext* cx) const
{
    return compilerOutput(cx->zone()->types);
}

inline bool
RecompileInfo::shouldSweep(TypeZone& types)
{
    CompilerOutput* output = compilerOutput(types);
    if (!output || !output->isValid())
        return true;

    // If this info is for a compilation that occurred after sweeping started,
    // the index is already correct.
    MOZ_ASSERT_IF(generation == types.generation,
                  outputIndex == output - types.compilerOutputs->begin());

    // Update this info for the output's index in the zone's compiler outputs.
    outputIndex = output - types.compilerOutputs->begin();
    generation = types.generation;
    return false;
}

/////////////////////////////////////////////////////////////////////
// Types
/////////////////////////////////////////////////////////////////////

/* static */ inline TypeSet::ObjectKey*
TypeSet::ObjectKey::get(JSObject* obj)
{
    MOZ_ASSERT(obj);
    if (obj->isSingleton())
        return (ObjectKey*) (uintptr_t(obj) | 1);
    return (ObjectKey*) obj->group();
}

/* static */ inline TypeSet::ObjectKey*
TypeSet::ObjectKey::get(ObjectGroup* group)
{
    MOZ_ASSERT(group);
    if (group->singleton())
        return (ObjectKey*) (uintptr_t(group->singleton()) | 1);
    return (ObjectKey*) group;
}

inline ObjectGroup*
TypeSet::ObjectKey::groupNoBarrier()
{
    MOZ_ASSERT(isGroup());
    return (ObjectGroup*) this;
}

inline JSObject*
TypeSet::ObjectKey::singletonNoBarrier()
{
    MOZ_ASSERT(isSingleton());
    return (JSObject*) (uintptr_t(this) & ~1);
}

inline ObjectGroup*
TypeSet::ObjectKey::group()
{
    ObjectGroup* res = groupNoBarrier();
    ObjectGroup::readBarrier(res);
    return res;
}

inline JSObject*
TypeSet::ObjectKey::singleton()
{
    JSObject* res = singletonNoBarrier();
    JSObject::readBarrier(res);
    return res;
}

/* static */ inline TypeSet::Type
TypeSet::ObjectType(JSObject* obj)
{
    if (obj->isSingleton())
        return Type(uintptr_t(obj) | 1);
    return Type(uintptr_t(obj->group()));
}

/* static */ inline TypeSet::Type
TypeSet::ObjectType(ObjectGroup* group)
{
    if (group->singleton())
        return Type(uintptr_t(group->singleton()) | 1);
    return Type(uintptr_t(group));
}

/* static */ inline TypeSet::Type
TypeSet::ObjectType(ObjectKey* obj)
{
    return Type(uintptr_t(obj));
}

inline TypeSet::Type
TypeSet::GetValueType(const Value& val)
{
    if (val.isDouble())
        return TypeSet::DoubleType();
    if (val.isObject())
        return TypeSet::ObjectType(&val.toObject());
    return TypeSet::PrimitiveType(val.extractNonDoubleType());
}

inline bool
TypeSet::IsUntrackedValue(const Value& val)
{
    return val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
                             val.whyMagic() == JS_UNINITIALIZED_LEXICAL);
}

inline TypeSet::Type
TypeSet::GetMaybeUntrackedValueType(const Value& val)
{
    return IsUntrackedValue(val) ? UnknownType() : GetValueType(val);
}

inline TypeFlags
PrimitiveTypeFlag(JSValueType type)
{
    switch (type) {
      case JSVAL_TYPE_UNDEFINED:
        return TYPE_FLAG_UNDEFINED;
      case JSVAL_TYPE_NULL:
        return TYPE_FLAG_NULL;
      case JSVAL_TYPE_BOOLEAN:
        return TYPE_FLAG_BOOLEAN;
      case JSVAL_TYPE_INT32:
        return TYPE_FLAG_INT32;
      case JSVAL_TYPE_DOUBLE:
        return TYPE_FLAG_DOUBLE;
      case JSVAL_TYPE_STRING:
        return TYPE_FLAG_STRING;
      case JSVAL_TYPE_SYMBOL:
        return TYPE_FLAG_SYMBOL;
      case JSVAL_TYPE_MAGIC:
        return TYPE_FLAG_LAZYARGS;
      default:
        MOZ_CRASH("Bad JSValueType");
    }
}

inline JSValueType
TypeFlagPrimitive(TypeFlags flags)
{
    switch (flags) {
      case TYPE_FLAG_UNDEFINED:
        return JSVAL_TYPE_UNDEFINED;
      case TYPE_FLAG_NULL:
        return JSVAL_TYPE_NULL;
      case TYPE_FLAG_BOOLEAN:
        return JSVAL_TYPE_BOOLEAN;
      case TYPE_FLAG_INT32:
        return JSVAL_TYPE_INT32;
      case TYPE_FLAG_DOUBLE:
        return JSVAL_TYPE_DOUBLE;
      case TYPE_FLAG_STRING:
        return JSVAL_TYPE_STRING;
      case TYPE_FLAG_SYMBOL:
        return JSVAL_TYPE_SYMBOL;
      case TYPE_FLAG_LAZYARGS:
        return JSVAL_TYPE_MAGIC;
      default:
        MOZ_CRASH("Bad TypeFlags");
    }
}

/*
 * Get the canonical representation of an id to use when doing inference.  This
 * maintains the constraint that if two different jsids map to the same property
 * in JS (e.g. 3 and "3"), they have the same type representation.
 */
inline jsid
IdToTypeId(jsid id)
{
    MOZ_ASSERT(!JSID_IS_EMPTY(id));

    // All properties which can be stored in an object's dense elements must
    // map to the aggregate property for index types.
    return JSID_IS_INT(id) ? JSID_VOID : id;
}

const char * TypeIdStringImpl(jsid id);

/* Convert an id for printing during debug. */
static inline const char*
TypeIdString(jsid id)
{
#ifdef DEBUG
    return TypeIdStringImpl(id);
#else
    return "(missing)";
#endif
}

/*
 * Structure for type inference entry point functions. All functions which can
 * change type information must use this, and functions which depend on
 * intermediate types (i.e. JITs) can use this to ensure that intermediate
 * information is not collected and does not change.
 *
 * Ensures that GC cannot occur. Does additional sanity checking that inference
 * is not reentrant and that recompilations occur properly.
 */
struct AutoEnterAnalysis
{
    /* Prevent GC activity in the middle of analysis. */
    gc::AutoSuppressGC suppressGC;

    // Allow clearing inference info on OOM during incremental sweeping.
    AutoClearTypeInferenceStateOnOOM oom;

    // Pending recompilations to perform before execution of JIT code can resume.
    RecompileInfoVector pendingRecompiles;

    FreeOp* freeOp;
    Zone* zone;

    explicit AutoEnterAnalysis(ExclusiveContext* cx)
      : suppressGC(cx), oom(cx->zone())
    {
        init(cx->defaultFreeOp(), cx->zone());
    }

    AutoEnterAnalysis(FreeOp* fop, Zone* zone)
      : suppressGC(zone->runtimeFromMainThread()), oom(zone)
    {
        init(fop, zone);
    }

    ~AutoEnterAnalysis()
    {
        if (this != zone->types.activeAnalysis)
            return;

        zone->types.activeAnalysis = nullptr;

        if (!pendingRecompiles.empty())
            zone->types.processPendingRecompiles(freeOp, pendingRecompiles);
    }

  private:
    void init(FreeOp* fop, Zone* zone) {
        this->freeOp = fop;
        this->zone = zone;

        if (!zone->types.activeAnalysis)
            zone->types.activeAnalysis = this;
    }
};

/////////////////////////////////////////////////////////////////////
// Interface functions
/////////////////////////////////////////////////////////////////////

void MarkIteratorUnknownSlow(JSContext* cx);

void TypeMonitorCallSlow(JSContext* cx, JSObject* callee, const CallArgs& args,
                         bool constructing);

/*
 * Monitor a javascript call, either on entry to the interpreter or made
 * from within the interpreter.
 */
inline void
TypeMonitorCall(JSContext* cx, const js::CallArgs& args, bool constructing)
{
    if (args.callee().is<JSFunction>()) {
        JSFunction* fun = &args.callee().as<JSFunction>();
        if (fun->isInterpreted() && fun->nonLazyScript()->types())
            TypeMonitorCallSlow(cx, &args.callee(), args, constructing);
    }
}

inline bool
TrackPropertyTypes(ExclusiveContext* cx, JSObject* obj, jsid id)
{
    if (obj->hasLazyGroup() || obj->group()->unknownProperties())
        return false;

    if (obj->isSingleton() && !obj->group()->maybeGetProperty(id))
        return false;

    return true;
}

void
EnsureTrackPropertyTypes(JSContext* cx, JSObject* obj, jsid id);

inline bool
CanHaveEmptyPropertyTypesForOwnProperty(JSObject* obj)
{
    // Per the comment on TypeSet::propertySet, property type sets for global
    // objects may be empty for 'own' properties if the global property still
    // has its initial undefined value.
    return obj->is<GlobalObject>();
}

inline bool
PropertyHasBeenMarkedNonConstant(JSObject* obj, jsid id)
{
    // Non-constant properties are only relevant for singleton objects.
    if (!obj->isSingleton())
        return true;

    // EnsureTrackPropertyTypes must have been called on this object.
    if (obj->group()->unknownProperties())
        return true;
    HeapTypeSet* types = obj->group()->maybeGetProperty(IdToTypeId(id));
    return types->nonConstantProperty();
}

inline bool
HasTypePropertyId(JSObject* obj, jsid id, TypeSet::Type type)
{
    if (obj->hasLazyGroup())
        return true;

    if (obj->group()->unknownProperties())
        return true;

    if (HeapTypeSet* types = obj->group()->maybeGetProperty(IdToTypeId(id)))
        return types->hasType(type);

    return false;
}

inline bool
HasTypePropertyId(JSObject* obj, jsid id, const Value& value)
{
    return HasTypePropertyId(obj, id, TypeSet::GetValueType(value));
}

void AddTypePropertyId(ExclusiveContext* cx, ObjectGroup* group, JSObject* obj, jsid id, TypeSet::Type type);
void AddTypePropertyId(ExclusiveContext* cx, ObjectGroup* group, JSObject* obj, jsid id, const Value& value);

/* Add a possible type for a property of obj. */
inline void
AddTypePropertyId(ExclusiveContext* cx, JSObject* obj, jsid id, TypeSet::Type type)
{
    id = IdToTypeId(id);
    if (TrackPropertyTypes(cx, obj, id))
        AddTypePropertyId(cx, obj->group(), obj, id, type);
}

inline void
AddTypePropertyId(ExclusiveContext* cx, JSObject* obj, jsid id, const Value& value)
{
    id = IdToTypeId(id);
    if (TrackPropertyTypes(cx, obj, id))
        AddTypePropertyId(cx, obj->group(), obj, id, value);
}

inline void
MarkObjectGroupFlags(ExclusiveContext* cx, JSObject* obj, ObjectGroupFlags flags)
{
    if (!obj->hasLazyGroup() && !obj->group()->hasAllFlags(flags))
        obj->group()->setFlags(cx, flags);
}

inline void
MarkObjectGroupUnknownProperties(ExclusiveContext* cx, ObjectGroup* obj)
{
    if (!obj->unknownProperties())
        obj->markUnknown(cx);
}

inline void
MarkTypePropertyNonData(ExclusiveContext* cx, JSObject* obj, jsid id)
{
    id = IdToTypeId(id);
    if (TrackPropertyTypes(cx, obj, id))
        obj->group()->markPropertyNonData(cx, obj, id);
}

inline void
MarkTypePropertyNonWritable(ExclusiveContext* cx, JSObject* obj, jsid id)
{
    id = IdToTypeId(id);
    if (TrackPropertyTypes(cx, obj, id))
        obj->group()->markPropertyNonWritable(cx, obj, id);
}

/* Mark a state change on a particular object. */
inline void
MarkObjectStateChange(ExclusiveContext* cx, JSObject* obj)
{
    if (!obj->hasLazyGroup() && !obj->group()->unknownProperties())
        obj->group()->markStateChange(cx);
}

/* Interface helpers for JSScript*. */
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type);
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval);

/////////////////////////////////////////////////////////////////////
// Script interface functions
/////////////////////////////////////////////////////////////////////

/* static */ inline unsigned
TypeScript::NumTypeSets(JSScript* script)
{
    size_t num = script->nTypeSets() + 1 /* this */;
    if (JSFunction* fun = script->functionNonDelazifying())
        num += fun->nargs();
    return num;
}

/* static */ inline StackTypeSet*
TypeScript::ThisTypes(JSScript* script)
{
    TypeScript* types = script->types();
    return types ? types->typeArray() + script->nTypeSets() : nullptr;
}

/*
 * Note: for non-escaping arguments, argTypes reflect only the initial type of
 * the variable (e.g. passed values for argTypes, or undefined for localTypes)
 * and not types from subsequent assignments.
 */

/* static */ inline StackTypeSet*
TypeScript::ArgTypes(JSScript* script, unsigned i)
{
    MOZ_ASSERT(i < script->functionNonDelazifying()->nargs());
    TypeScript* types = script->types();
    return types ? types->typeArray() + script->nTypeSets() + 1 + i : nullptr;
}

template <typename TYPESET>
/* static */ inline TYPESET*
TypeScript::BytecodeTypes(JSScript* script, jsbytecode* pc, uint32_t* bytecodeMap,
                          uint32_t* hint, TYPESET* typeArray)
{
    MOZ_ASSERT(CodeSpec[*pc].format & JOF_TYPESET);
    uint32_t offset = script->pcToOffset(pc);

    // See if this pc is the next typeset opcode after the last one looked up.
    if ((*hint + 1) < script->nTypeSets() && bytecodeMap[*hint + 1] == offset) {
        (*hint)++;
        return typeArray + *hint;
    }

    // See if this pc is the same as the last one looked up.
    if (bytecodeMap[*hint] == offset)
        return typeArray + *hint;

    // Fall back to a binary search.
    size_t bottom = 0;
    size_t top = script->nTypeSets() - 1;
    size_t mid = bottom + (top - bottom) / 2;
    while (mid < top) {
        if (bytecodeMap[mid] < offset)
            bottom = mid + 1;
        else if (bytecodeMap[mid] > offset)
            top = mid;
        else
            break;
        mid = bottom + (top - bottom) / 2;
    }

    // We should have have zeroed in on either the exact offset, unless there
    // are more JOF_TYPESET opcodes than nTypeSets in the script (as can happen
    // if the script is very long).
    MOZ_ASSERT(bytecodeMap[mid] == offset || mid == top);

    *hint = mid;
    return typeArray + *hint;
}

/* static */ inline StackTypeSet*
TypeScript::BytecodeTypes(JSScript* script, jsbytecode* pc)
{
    MOZ_ASSERT(CurrentThreadCanAccessRuntime(script->runtimeFromMainThread()));
    TypeScript* types = script->types();
    if (!types)
        return nullptr;
    uint32_t* hint = script->baselineScript()->bytecodeTypeMap() + script->nTypeSets();
    return BytecodeTypes(script, pc, script->baselineScript()->bytecodeTypeMap(),
                         hint, types->typeArray());
}

/* static */ inline void
TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval)
{
    TypeMonitorResult(cx, script, pc, rval);
}

/* static */ inline void
TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type)
{
    TypeMonitorResult(cx, script, pc, type);
}

/* static */ inline void
TypeScript::Monitor(JSContext* cx, const js::Value& rval)
{
    jsbytecode* pc;
    RootedScript script(cx, cx->currentScript(&pc));
    Monitor(cx, script, pc, rval);
}

/* static */ inline void
TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id)
{
    if (!obj->isSingleton()) {
        /*
         * Mark as unknown any object which has had dynamic assignments to
         * non-integer properties at SETELEM opcodes. This avoids making large
         * numbers of type properties for hashmap-style objects. We don't need
         * to do this for objects with singleton type, because type properties
         * are only constructed for them when analyzed scripts depend on those
         * specific properties.
         */
        uint32_t i;
        if (IdIsIndex(id, &i))
            return;

        // But if we don't have too many properties yet, don't do anything.  The
        // idea here is that normal object initialization should not trigger
        // deoptimization in most cases, while actual usage as a hashmap should.
        ObjectGroup* group = obj->group();
        if (group->basePropertyCount() < 128)
            return;
        MarkObjectGroupUnknownProperties(cx, group);
    }
}

/* static */ inline void
TypeScript::SetThis(JSContext* cx, JSScript* script, TypeSet::Type type)
{
    StackTypeSet* types = ThisTypes(script);
    if (!types)
        return;

    if (!types->hasType(type)) {
        AutoEnterAnalysis enter(cx);

        InferSpew(ISpewOps, "externalType: setThis %p: %s",
                  script, TypeSet::TypeString(type));
        types->addType(cx, type);
    }
}

/* static */ inline void
TypeScript::SetThis(JSContext* cx, JSScript* script, const js::Value& value)
{
    SetThis(cx, script, TypeSet::GetValueType(value));
}

/* static */ inline void
TypeScript::SetArgument(JSContext* cx, JSScript* script, unsigned arg, TypeSet::Type type)
{
    StackTypeSet* types = ArgTypes(script, arg);
    if (!types)
        return;

    if (!types->hasType(type)) {
        AutoEnterAnalysis enter(cx);

        InferSpew(ISpewOps, "externalType: setArg %p %u: %s",
                  script, arg, TypeSet::TypeString(type));
        types->addType(cx, type);
    }
}

/* static */ inline void
TypeScript::SetArgument(JSContext* cx, JSScript* script, unsigned arg, const js::Value& value)
{
    SetArgument(cx, script, arg, TypeSet::GetValueType(value));
}

/////////////////////////////////////////////////////////////////////
// TypeHashSet
/////////////////////////////////////////////////////////////////////

// Hashing code shared by objects in TypeSets and properties in ObjectGroups.
struct TypeHashSet
{
    // The sets of objects in a type set grow monotonically, are usually empty,
    // almost always small, and sometimes big. For empty or singleton sets, the
    // the pointer refers directly to the value.  For sets fitting into
    // SET_ARRAY_SIZE, an array of this length is used to store the elements.
    // For larger sets, a hash table filled to 25%-50% of capacity is used,
    // with collisions resolved by linear probing.
    static const unsigned SET_ARRAY_SIZE = 8;
    static const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;

    // Get the capacity of a set with the given element count.
    static inline unsigned
    Capacity(unsigned count)
    {
        MOZ_ASSERT(count >= 2);
        MOZ_ASSERT(count < SET_CAPACITY_OVERFLOW);

        if (count <= SET_ARRAY_SIZE)
            return SET_ARRAY_SIZE;

        return 1u << (mozilla::FloorLog2(count) + 2);
    }

    // Compute the FNV hash for the low 32 bits of v.
    template <class T, class KEY>
    static inline uint32_t
    HashKey(T v)
    {
        uint32_t nv = KEY::keyBits(v);

        uint32_t hash = 84696351 ^ (nv & 0xff);
        hash = (hash * 16777619) ^ ((nv >> 8) & 0xff);
        hash = (hash * 16777619) ^ ((nv >> 16) & 0xff);
        return (hash * 16777619) ^ ((nv >> 24) & 0xff);
    }

    // Insert space for an element into the specified set and grow its capacity
    // if needed. returned value is an existing or new entry (nullptr if new).
    template <class T, class U, class KEY>
    static U**
    InsertTry(LifoAlloc& alloc, U**& values, unsigned& count, T key)
    {
        unsigned capacity = Capacity(count);
        unsigned insertpos = HashKey<T,KEY>(key) & (capacity - 1);

        // Whether we are converting from a fixed array to hashtable.
        bool converting = (count == SET_ARRAY_SIZE);

        if (!converting) {
            while (values[insertpos] != nullptr) {
                if (KEY::getKey(values[insertpos]) == key)
                    return &values[insertpos];
                insertpos = (insertpos + 1) & (capacity - 1);
            }
        }

        if (count >= SET_CAPACITY_OVERFLOW)
            return nullptr;

        count++;
        unsigned newCapacity = Capacity(count);

        if (newCapacity == capacity) {
            MOZ_ASSERT(!converting);
            return &values[insertpos];
        }

        U** newValues = alloc.newArray<U*>(newCapacity);
        if (!newValues)
            return nullptr;
        mozilla::PodZero(newValues, newCapacity);

        for (unsigned i = 0; i < capacity; i++) {
            if (values[i]) {
                unsigned pos = HashKey<T,KEY>(KEY::getKey(values[i])) & (newCapacity - 1);
                while (newValues[pos] != nullptr)
                    pos = (pos + 1) & (newCapacity - 1);
                newValues[pos] = values[i];
            }
        }

        values = newValues;

        insertpos = HashKey<T,KEY>(key) & (newCapacity - 1);
        while (values[insertpos] != nullptr)
            insertpos = (insertpos + 1) & (newCapacity - 1);
        return &values[insertpos];
    }

    // Insert an element into the specified set if it is not already there,
    // returning an entry which is nullptr if the element was not there.
    template <class T, class U, class KEY>
    static inline U**
    Insert(LifoAlloc& alloc, U**& values, unsigned& count, T key)
    {
        if (count == 0) {
            MOZ_ASSERT(values == nullptr);
            count++;
            return (U**) &values;
        }

        if (count == 1) {
            U* oldData = (U*) values;
            if (KEY::getKey(oldData) == key)
                return (U**) &values;

            values = alloc.newArray<U*>(SET_ARRAY_SIZE);
            if (!values) {
                values = (U**) oldData;
                return nullptr;
            }
            mozilla::PodZero(values, SET_ARRAY_SIZE);
            count++;

            values[0] = oldData;
            return &values[1];
        }

        if (count <= SET_ARRAY_SIZE) {
            for (unsigned i = 0; i < count; i++) {
                if (KEY::getKey(values[i]) == key)
                    return &values[i];
            }

            if (count < SET_ARRAY_SIZE) {
                count++;
                return &values[count - 1];
            }
        }

        return InsertTry<T,U,KEY>(alloc, values, count, key);
    }

    // Lookup an entry in a hash set, return nullptr if it does not exist.
    template <class T, class U, class KEY>
    static inline U*
    Lookup(U** values, unsigned count, T key)
    {
        if (count == 0)
            return nullptr;

        if (count == 1)
            return (KEY::getKey((U*) values) == key) ? (U*) values : nullptr;

        if (count <= SET_ARRAY_SIZE) {
            for (unsigned i = 0; i < count; i++) {
                if (KEY::getKey(values[i]) == key)
                    return values[i];
            }
            return nullptr;
        }

        unsigned capacity = Capacity(count);
        unsigned pos = HashKey<T,KEY>(key) & (capacity - 1);

        while (values[pos] != nullptr) {
            if (KEY::getKey(values[pos]) == key)
                return values[pos];
            pos = (pos + 1) & (capacity - 1);
        }

        return nullptr;
    }
};

/////////////////////////////////////////////////////////////////////
// TypeSet
/////////////////////////////////////////////////////////////////////

inline TypeSet::ObjectKey*
TypeSet::Type::objectKey() const
{
    MOZ_ASSERT(isObject());
    return (ObjectKey*) data;
}

inline JSObject*
TypeSet::Type::singleton() const
{
    return objectKey()->singleton();
}

inline ObjectGroup*
TypeSet::Type::group() const
{
    return objectKey()->group();
}

inline JSObject*
TypeSet::Type::singletonNoBarrier() const
{
    return objectKey()->singletonNoBarrier();
}

inline ObjectGroup*
TypeSet::Type::groupNoBarrier() const
{
    return objectKey()->groupNoBarrier();
}

inline bool
TypeSet::hasType(Type type) const
{
    if (unknown())
        return true;

    if (type.isUnknown()) {
        return false;
    } else if (type.isPrimitive()) {
        return !!(flags & PrimitiveTypeFlag(type.primitive()));
    } else if (type.isAnyObject()) {
        return !!(flags & TYPE_FLAG_ANYOBJECT);
    } else {
        return !!(flags & TYPE_FLAG_ANYOBJECT) ||
               TypeHashSet::Lookup<ObjectKey*, ObjectKey, ObjectKey>
                   (objectSet, baseObjectCount(), type.objectKey()) != nullptr;
    }
}

inline void
TypeSet::setBaseObjectCount(uint32_t count)
{
    MOZ_ASSERT(count <= TYPE_FLAG_DOMOBJECT_COUNT_LIMIT);
    flags = (flags & ~TYPE_FLAG_OBJECT_COUNT_MASK)
          | (count << TYPE_FLAG_OBJECT_COUNT_SHIFT);
}

inline void
HeapTypeSet::newPropertyState(ExclusiveContext* cxArg)
{
    /* Propagate the change to all constraints. */
    if (JSContext* cx = cxArg->maybeJSContext()) {
        TypeConstraint* constraint = constraintList;
        while (constraint) {
            constraint->newPropertyState(cx, this);
            constraint = constraint->next;
        }
    } else {
        MOZ_ASSERT(!constraintList);
    }
}

inline void
HeapTypeSet::setNonDataProperty(ExclusiveContext* cx)
{
    if (flags & TYPE_FLAG_NON_DATA_PROPERTY)
        return;

    flags |= TYPE_FLAG_NON_DATA_PROPERTY;
    newPropertyState(cx);
}

inline void
HeapTypeSet::setNonWritableProperty(ExclusiveContext* cx)
{
    if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY)
        return;

    flags |= TYPE_FLAG_NON_WRITABLE_PROPERTY;
    newPropertyState(cx);
}

inline void
HeapTypeSet::setNonConstantProperty(ExclusiveContext* cx)
{
    if (flags & TYPE_FLAG_NON_CONSTANT_PROPERTY)
        return;

    flags |= TYPE_FLAG_NON_CONSTANT_PROPERTY;
    newPropertyState(cx);
}

inline unsigned
TypeSet::getObjectCount() const
{
    MOZ_ASSERT(!unknownObject());
    uint32_t count = baseObjectCount();
    if (count > TypeHashSet::SET_ARRAY_SIZE)
        return TypeHashSet::Capacity(count);
    return count;
}

inline TypeSet::ObjectKey*
TypeSet::getObject(unsigned i) const
{
    MOZ_ASSERT(i < getObjectCount());
    if (baseObjectCount() == 1) {
        MOZ_ASSERT(i == 0);
        return (ObjectKey*) objectSet;
    }
    return objectSet[i];
}

inline JSObject*
TypeSet::getSingleton(unsigned i) const
{
    ObjectKey* key = getObject(i);
    return (key && key->isSingleton()) ? key->singleton() : nullptr;
}

inline ObjectGroup*
TypeSet::getGroup(unsigned i) const
{
    ObjectKey* key = getObject(i);
    return (key && key->isGroup()) ? key->group() : nullptr;
}

inline JSObject*
TypeSet::getSingletonNoBarrier(unsigned i) const
{
    ObjectKey* key = getObject(i);
    return (key && key->isSingleton()) ? key->singletonNoBarrier() : nullptr;
}

inline ObjectGroup*
TypeSet::getGroupNoBarrier(unsigned i) const
{
    ObjectKey* key = getObject(i);
    return (key && key->isGroup()) ? key->groupNoBarrier() : nullptr;
}

inline const Class*
TypeSet::getObjectClass(unsigned i) const
{
    if (JSObject* object = getSingleton(i))
        return object->getClass();
    if (ObjectGroup* group = getGroup(i))
        return group->clasp();
    return nullptr;
}

/////////////////////////////////////////////////////////////////////
// ObjectGroup
/////////////////////////////////////////////////////////////////////

inline uint32_t
ObjectGroup::basePropertyCount()
{
    return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT;
}

inline void
ObjectGroup::setBasePropertyCount(uint32_t count)
{
    // Note: Callers must ensure they are performing threadsafe operations.
    MOZ_ASSERT(count <= OBJECT_FLAG_PROPERTY_COUNT_LIMIT);
    flags_ = (flags() & ~OBJECT_FLAG_PROPERTY_COUNT_MASK)
           | (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
}

inline HeapTypeSet*
ObjectGroup::getProperty(ExclusiveContext* cx, JSObject* obj, jsid id)
{
    MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
    MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
    MOZ_ASSERT(!unknownProperties());
    MOZ_ASSERT_IF(obj, obj->group() == this);
    MOZ_ASSERT_IF(singleton(), obj);

    if (HeapTypeSet* types = maybeGetProperty(id))
        return types;

    Property* base = cx->typeLifoAlloc().new_<Property>(id);
    if (!base) {
        markUnknown(cx);
        return nullptr;
    }

    uint32_t propertyCount = basePropertyCount();
    Property** pprop = TypeHashSet::Insert<jsid, Property, Property>
                           (cx->typeLifoAlloc(), propertySet, propertyCount, id);
    if (!pprop) {
        markUnknown(cx);
        return nullptr;
    }

    MOZ_ASSERT(!*pprop);

    setBasePropertyCount(propertyCount);
    *pprop = base;

    updateNewPropertyTypes(cx, obj, id, &base->types);

    if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
        // We hit the maximum number of properties the object can have, mark
        // the object unknown so that new properties will not be added in the
        // future.
        markUnknown(cx);
    }

    return &base->types;
}

inline HeapTypeSet*
ObjectGroup::maybeGetProperty(jsid id)
{
    MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
    MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
    MOZ_ASSERT(!unknownProperties());

    Property* prop = TypeHashSet::Lookup<jsid, Property, Property>
                         (propertySet, basePropertyCount(), id);

    return prop ? &prop->types : nullptr;
}

inline unsigned
ObjectGroup::getPropertyCount()
{
    uint32_t count = basePropertyCount();
    if (count > TypeHashSet::SET_ARRAY_SIZE)
        return TypeHashSet::Capacity(count);
    return count;
}

inline ObjectGroup::Property*
ObjectGroup::getProperty(unsigned i)
{
    MOZ_ASSERT(i < getPropertyCount());
    if (basePropertyCount() == 1) {
        MOZ_ASSERT(i == 0);
        return (Property*) propertySet;
    }
    return propertySet[i];
}

} // namespace js

inline js::TypeScript*
JSScript::types()
{
    maybeSweepTypes(nullptr);
    return types_;
}

inline bool
JSScript::ensureHasTypes(JSContext* cx)
{
    return types() || makeTypes(cx);
}

#endif /* vm_TypeInference_inl_h */
