/* -*- 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 "jit/MIR.h"

#include "mozilla/FloatingPoint.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/SizePrintfMacros.h"

#include <ctype.h>

#include "jslibmath.h"
#include "jsstr.h"

#include "jit/AtomicOperations.h"
#include "jit/BaselineInspector.h"
#include "jit/IonBuilder.h"
#include "jit/JitSpewer.h"
#include "jit/MIRGraph.h"
#include "jit/RangeAnalysis.h"
#include "js/Conversions.h"

#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"

using namespace js;
using namespace js::jit;

using JS::ToInt32;

using mozilla::NumbersAreIdentical;
using mozilla::IsFloat32Representable;
using mozilla::IsNaN;
using mozilla::Maybe;
using mozilla::DebugOnly;

#ifdef DEBUG
size_t MUse::index() const
{
    return consumer()->indexOf(this);
}
#endif

template<size_t Op> static void
ConvertDefinitionToDouble(TempAllocator& alloc, MDefinition* def, MInstruction* consumer)
{
    MInstruction* replace = MToDouble::New(alloc, def);
    consumer->replaceOperand(Op, replace);
    consumer->block()->insertBefore(consumer, replace);
}

static bool
CheckUsesAreFloat32Consumers(const MInstruction* ins)
{
    bool allConsumerUses = true;
    for (MUseDefIterator use(ins); allConsumerUses && use; use++)
        allConsumerUses &= use.def()->canConsumeFloat32(use.use());
    return allConsumerUses;
}

void
MDefinition::PrintOpcodeName(GenericPrinter& out, MDefinition::Opcode op)
{
    static const char * const names[] =
    {
#define NAME(x) #x,
        MIR_OPCODE_LIST(NAME)
#undef NAME
    };
    const char* name = names[op];
    size_t len = strlen(name);
    for (size_t i = 0; i < len; i++)
        out.printf("%c", tolower(name[i]));
}

const Value&
MDefinition::constantValue()
{
    MOZ_ASSERT(isConstantValue());

    if (isBox())
        return getOperand(0)->constantValue();
    return toConstant()->value();
}

const Value*
MDefinition::constantVp()
{
    MOZ_ASSERT(isConstantValue());
    if (isBox())
        return getOperand(0)->constantVp();
    return toConstant()->vp();
}

bool
MDefinition::constantToBoolean()
{
    MOZ_ASSERT(isConstantValue());
    if (isBox())
        return getOperand(0)->constantToBoolean();
    return toConstant()->valueToBoolean();
}

static MConstant*
EvaluateConstantOperands(TempAllocator& alloc, MBinaryInstruction* ins, bool* ptypeChange = nullptr)
{
    MDefinition* left = ins->getOperand(0);
    MDefinition* right = ins->getOperand(1);

    MOZ_ASSERT(IsNumberType(left->type()) && IsNumberType(right->type()));

    if (!left->isConstantValue() || !right->isConstantValue())
        return nullptr;

    Value lhs = left->constantValue();
    Value rhs = right->constantValue();
    Value ret = UndefinedValue();

    switch (ins->op()) {
      case MDefinition::Op_BitAnd:
        ret = Int32Value(lhs.toInt32() & rhs.toInt32());
        break;
      case MDefinition::Op_BitOr:
        ret = Int32Value(lhs.toInt32() | rhs.toInt32());
        break;
      case MDefinition::Op_BitXor:
        ret = Int32Value(lhs.toInt32() ^ rhs.toInt32());
        break;
      case MDefinition::Op_Lsh:
        ret = Int32Value(uint32_t(lhs.toInt32()) << (rhs.toInt32() & 0x1F));
        break;
      case MDefinition::Op_Rsh:
        ret = Int32Value(lhs.toInt32() >> (rhs.toInt32() & 0x1F));
        break;
      case MDefinition::Op_Ursh:
        ret.setNumber(uint32_t(lhs.toInt32()) >> (rhs.toInt32() & 0x1F));
        break;
      case MDefinition::Op_Add:
        ret.setNumber(lhs.toNumber() + rhs.toNumber());
        break;
      case MDefinition::Op_Sub:
        ret.setNumber(lhs.toNumber() - rhs.toNumber());
        break;
      case MDefinition::Op_Mul:
        ret.setNumber(lhs.toNumber() * rhs.toNumber());
        break;
      case MDefinition::Op_Div:
        if (ins->toDiv()->isUnsigned())
            ret.setInt32(rhs.isInt32(0) ? 0 : uint32_t(lhs.toInt32()) / uint32_t(rhs.toInt32()));
        else
            ret.setNumber(NumberDiv(lhs.toNumber(), rhs.toNumber()));
        break;
      case MDefinition::Op_Mod:
        if (ins->toMod()->isUnsigned())
            ret.setInt32(rhs.isInt32(0) ? 0 : uint32_t(lhs.toInt32()) % uint32_t(rhs.toInt32()));
        else
            ret.setNumber(NumberMod(lhs.toNumber(), rhs.toNumber()));
        break;
      default:
        MOZ_CRASH("NYI");
    }

    // setNumber eagerly transforms a number to int32.
    // Transform back to double, if the output type is double.
    if (ins->type() == MIRType_Double && ret.isInt32())
        ret.setDouble(ret.toNumber());

    if (ins->type() != MIRTypeFromValue(ret)) {
        if (ptypeChange)
            *ptypeChange = true;
        return nullptr;
    }

    return MConstant::New(alloc, ret);
}

static MMul*
EvaluateExactReciprocal(TempAllocator& alloc, MDiv* ins)
{
    // we should fold only when it is a floating point operation
    if (!IsFloatingPointType(ins->type()))
        return nullptr;

    MDefinition* left = ins->getOperand(0);
    MDefinition* right = ins->getOperand(1);

    if (!right->isConstantValue())
        return nullptr;

    Value rhs = right->constantValue();

    int32_t num;
    if (!mozilla::NumberIsInt32(rhs.toNumber(), &num))
        return nullptr;

    // check if rhs is a power of two
    if (mozilla::Abs(num) & (mozilla::Abs(num) - 1))
        return nullptr;

    Value ret;
    ret.setDouble(1.0 / (double) num);
    MConstant* foldedRhs = MConstant::New(alloc, ret);
    foldedRhs->setResultType(ins->type());
    ins->block()->insertBefore(ins, foldedRhs);

    MMul* mul = MMul::New(alloc, left, foldedRhs, ins->type());
    mul->setCommutative();
    return mul;
}

void
MDefinition::printName(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    out.printf("%u", id());
}

HashNumber
MDefinition::addU32ToHash(HashNumber hash, uint32_t data)
{
    return data + (hash << 6) + (hash << 16) - hash;
}

HashNumber
MDefinition::valueHash() const
{
    HashNumber out = op();
    for (size_t i = 0, e = numOperands(); i < e; i++)
        out = addU32ToHash(out, getOperand(i)->id());
    if (MInstruction* dep = dependency())
        out = addU32ToHash(out, dep->id());
    return out;
}

bool
MDefinition::congruentIfOperandsEqual(const MDefinition* ins) const
{
    if (op() != ins->op())
        return false;

    if (type() != ins->type())
        return false;

    if (isEffectful() || ins->isEffectful())
        return false;

    if (numOperands() != ins->numOperands())
        return false;

    for (size_t i = 0, e = numOperands(); i < e; i++) {
        if (getOperand(i) != ins->getOperand(i))
            return false;
    }

    return true;
}

MDefinition*
MDefinition::foldsTo(TempAllocator& alloc)
{
    // In the default case, there are no constants to fold.
    return this;
}

bool
MDefinition::mightBeMagicType() const
{
    if (IsMagicType(type()))
        return true;

    if (MIRType_Value != type())
        return false;

    return !resultTypeSet() || resultTypeSet()->hasType(TypeSet::MagicArgType());
}

MDefinition*
MInstruction::foldsToStoredValue(TempAllocator& alloc, MDefinition* loaded)
{
    // If the type are matching then we return the value which is used as
    // argument of the store.
    if (loaded->type() != type()) {
        // If we expect to read a type which is more generic than the type seen
        // by the store, then we box the value used by the store.
        if (type() != MIRType_Value)
            return this;

        MOZ_ASSERT(loaded->type() < MIRType_Value);
        MBox* box = MBox::New(alloc, loaded);
        loaded = box;
    }

    return loaded;
}

void
MDefinition::analyzeEdgeCasesForward()
{
}

void
MDefinition::analyzeEdgeCasesBackward()
{
}

void
MInstruction::setResumePoint(MResumePoint* resumePoint)
{
    MOZ_ASSERT(!resumePoint_);
    resumePoint_ = resumePoint;
    resumePoint_->setInstruction(this);
}

void
MInstruction::stealResumePoint(MInstruction* ins)
{
    MOZ_ASSERT(ins->resumePoint_->instruction() == ins);
    resumePoint_ = ins->resumePoint_;
    ins->resumePoint_ = nullptr;
    resumePoint_->replaceInstruction(this);
}

void
MInstruction::moveResumePointAsEntry()
{
    MOZ_ASSERT(isNop());
    block()->clearEntryResumePoint();
    block()->setEntryResumePoint(resumePoint_);
    resumePoint_->resetInstruction();
    resumePoint_ = nullptr;
}

void
MInstruction::clearResumePoint()
{
    resumePoint_->resetInstruction();
    block()->discardPreAllocatedResumePoint(resumePoint_);
    resumePoint_ = nullptr;
}

bool
MDefinition::maybeEmulatesUndefined(CompilerConstraintList* constraints)
{
    if (!mightBeType(MIRType_Object))
        return false;

    TemporaryTypeSet* types = resultTypeSet();
    if (!types)
        return true;

    return types->maybeEmulatesUndefined(constraints);
}

static bool
MaybeCallable(CompilerConstraintList* constraints, MDefinition* op)
{
    if (!op->mightBeType(MIRType_Object))
        return false;

    TemporaryTypeSet* types = op->resultTypeSet();
    if (!types)
        return true;

    return types->maybeCallable(constraints);
}

MTest*
MTest::New(TempAllocator& alloc, MDefinition* ins, MBasicBlock* ifTrue, MBasicBlock* ifFalse)
{
    return new(alloc) MTest(ins, ifTrue, ifFalse);
}

void
MTest::cacheOperandMightEmulateUndefined(CompilerConstraintList* constraints)
{
    MOZ_ASSERT(operandMightEmulateUndefined());

    if (!getOperand(0)->maybeEmulatesUndefined(constraints))
        markNoOperandEmulatesUndefined();
}

MDefinition*
MTest::foldsTo(TempAllocator& alloc)
{
    MDefinition* op = getOperand(0);

    if (op->isNot()) {
        // If the operand of the Not is itself a Not, they cancel out.
        MDefinition* opop = op->getOperand(0);
        if (opop->isNot())
            return MTest::New(alloc, opop->toNot()->input(), ifTrue(), ifFalse());
        return MTest::New(alloc, op->toNot()->input(), ifFalse(), ifTrue());
    }

    if (op->isConstantValue() && !op->constantValue().isMagic())
        return MGoto::New(alloc, op->constantToBoolean() ? ifTrue() : ifFalse());

    switch (op->type()) {
      case MIRType_Undefined:
      case MIRType_Null:
        return MGoto::New(alloc, ifFalse());
      case MIRType_Symbol:
        return MGoto::New(alloc, ifTrue());
      case MIRType_Object:
        if (!operandMightEmulateUndefined())
            return MGoto::New(alloc, ifTrue());
        break;
      default:
        break;
    }

    return this;
}

void
MTest::filtersUndefinedOrNull(bool trueBranch, MDefinition** subject, bool* filtersUndefined,
                              bool* filtersNull)
{
    MDefinition* ins = getOperand(0);
    if (ins->isCompare()) {
        ins->toCompare()->filtersUndefinedOrNull(trueBranch, subject, filtersUndefined, filtersNull);
        return;
    }

    if (!trueBranch && ins->isNot()) {
        *subject = ins->getOperand(0);
        *filtersUndefined = *filtersNull = true;
        return;
    }

    if (trueBranch) {
        *subject = ins;
        *filtersUndefined = *filtersNull = true;
        return;
    }

    *filtersUndefined = *filtersNull = false;
    *subject = nullptr;
}

void
MDefinition::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    for (size_t j = 0, e = numOperands(); j < e; j++) {
        out.printf(" ");
        if (getUseFor(j)->hasProducer())
            getOperand(j)->printName(out);
        else
            out.printf("(null)");
    }
}

void
MDefinition::dump(GenericPrinter& out) const
{
    printName(out);
    out.printf(" = ");
    printOpcode(out);
    out.printf("\n");

    if (isInstruction()) {
        if (MResumePoint* resume = toInstruction()->resumePoint())
            resume->dump(out);
    }
}

void
MDefinition::dump() const
{
    Fprinter out(stderr);
    dump(out);
    out.finish();
}

void
MDefinition::dumpLocation(GenericPrinter& out) const
{
    MResumePoint* rp = nullptr;
    const char* linkWord = nullptr;
    if (isInstruction() && toInstruction()->resumePoint()) {
        rp = toInstruction()->resumePoint();
        linkWord = "at";
    } else {
        rp = block()->entryResumePoint();
        linkWord = "after";
    }

    while (rp) {
        JSScript* script = rp->block()->info().script();
        uint32_t lineno = PCToLineNumber(rp->block()->info().script(), rp->pc());
        out.printf("  %s %s:%d\n", linkWord, script->filename(), lineno);
        rp = rp->caller();
        linkWord = "in";
    }
}

void
MDefinition::dumpLocation() const
{
    Fprinter out(stderr);
    dumpLocation(out);
    out.finish();
}

#if defined(DEBUG) || defined(JS_JITSPEW)
size_t
MDefinition::useCount() const
{
    size_t count = 0;
    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++)
        count++;
    return count;
}

size_t
MDefinition::defUseCount() const
{
    size_t count = 0;
    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++)
        if ((*i)->consumer()->isDefinition())
            count++;
    return count;
}
#endif

bool
MDefinition::hasOneUse() const
{
    MUseIterator i(uses_.begin());
    if (i == uses_.end())
        return false;
    i++;
    return i == uses_.end();
}

bool
MDefinition::hasOneDefUse() const
{
    bool hasOneDefUse = false;
    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++) {
        if (!(*i)->consumer()->isDefinition())
            continue;

        // We already have a definition use. So 1+
        if (hasOneDefUse)
            return false;

        // We saw one definition. Loop to test if there is another.
        hasOneDefUse = true;
    }

    return hasOneDefUse;
}

bool
MDefinition::hasDefUses() const
{
    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++) {
        if ((*i)->consumer()->isDefinition())
            return true;
    }

    return false;
}

bool
MDefinition::hasLiveDefUses() const
{
    for (MUseIterator i(uses_.begin()); i != uses_.end(); i++) {
        MNode* ins = (*i)->consumer();
        if (ins->isDefinition()) {
            if (!ins->toDefinition()->isRecoveredOnBailout())
                return true;
        } else {
            MOZ_ASSERT(ins->isResumePoint());
            if (!ins->toResumePoint()->isRecoverableOperand(*i))
                return true;
        }
    }

    return false;
}

void
MDefinition::replaceAllUsesWith(MDefinition* dom)
{
    for (size_t i = 0, e = numOperands(); i < e; ++i)
        getOperand(i)->setUseRemovedUnchecked();

    justReplaceAllUsesWith(dom);
}

void
MDefinition::justReplaceAllUsesWith(MDefinition* dom)
{
    MOZ_ASSERT(dom != nullptr);
    MOZ_ASSERT(dom != this);

    // Carry over the fact the value has uses which are no longer inspectable
    // with the graph.
    if (isUseRemoved())
        dom->setUseRemovedUnchecked();

    for (MUseIterator i(usesBegin()), e(usesEnd()); i != e; ++i)
        i->setProducerUnchecked(dom);
    dom->uses_.takeElements(uses_);
}

void
MDefinition::justReplaceAllUsesWithExcept(MDefinition* dom)
{
    MOZ_ASSERT(dom != nullptr);
    MOZ_ASSERT(dom != this);

    // Carry over the fact the value has uses which are no longer inspectable
    // with the graph.
    if (isUseRemoved())
        dom->setUseRemovedUnchecked();

    // Move all uses to new dom. Save the use of the dominating instruction.
    MUse *exceptUse = nullptr;
    for (MUseIterator i(usesBegin()), e(usesEnd()); i != e; ++i) {
        if (i->consumer() != dom) {
            i->setProducerUnchecked(dom);
        } else {
            MOZ_ASSERT(!exceptUse);
            exceptUse = *i;
        }
    }
    dom->uses_.takeElements(uses_);

    // Restore the use to the original definition.
    dom->uses_.remove(exceptUse);
    exceptUse->setProducerUnchecked(this);
    uses_.pushFront(exceptUse);
}

void
MDefinition::optimizeOutAllUses(TempAllocator& alloc)
{
    for (MUseIterator i(usesBegin()), e(usesEnd()); i != e;) {
        MUse* use = *i++;
        MConstant* constant = use->consumer()->block()->optimizedOutConstant(alloc);

        // Update the resume point operand to use the optimized-out constant.
        use->setProducerUnchecked(constant);
        constant->addUseUnchecked(use);
    }

    // Remove dangling pointers.
    this->uses_.clear();
}

void
MDefinition::replaceAllLiveUsesWith(MDefinition* dom)
{
    for (MUseIterator i(usesBegin()), e(usesEnd()); i != e; ) {
        MUse* use = *i++;
        MNode* consumer = use->consumer();
        if (consumer->isResumePoint())
            continue;
        if (consumer->isDefinition() && consumer->toDefinition()->isRecoveredOnBailout())
            continue;

        // Update the operand to use the dominating definition.
        use->replaceProducer(dom);
    }
}

bool
MDefinition::emptyResultTypeSet() const
{
    return resultTypeSet() && resultTypeSet()->empty();
}

MConstant*
MConstant::New(TempAllocator& alloc, const Value& v, CompilerConstraintList* constraints)
{
    return new(alloc) MConstant(v, constraints);
}

MConstant*
MConstant::NewTypedValue(TempAllocator& alloc, const Value& v, MIRType type,
                         CompilerConstraintList* constraints)
{
    MOZ_ASSERT(!IsSimdType(type));
    MOZ_ASSERT_IF(type == MIRType_Float32,
                  IsNaN(v.toDouble()) || v.toDouble() == double(float(v.toDouble())));
    MConstant* constant = new(alloc) MConstant(v, constraints);
    constant->setResultType(type);
    return constant;
}

MConstant*
MConstant::NewAsmJS(TempAllocator& alloc, const Value& v, MIRType type)
{
    if (type == MIRType_Float32)
        return NewTypedValue(alloc, Float32Value(v.toNumber()), type);
    return NewTypedValue(alloc, v, type);
}

MConstant*
MConstant::NewConstraintlessObject(TempAllocator& alloc, JSObject* v)
{
    return new(alloc) MConstant(v);
}

static TemporaryTypeSet*
MakeSingletonTypeSetFromKey(CompilerConstraintList* constraints, TypeSet::ObjectKey* key)
{
    // Invalidate when this object's ObjectGroup gets unknown properties. This
    // happens for instance when we mutate an object's __proto__, in this case
    // we want to invalidate and mark this TypeSet as containing AnyObject
    // (because mutating __proto__ will change an object's ObjectGroup).
    MOZ_ASSERT(constraints);
    key->hasStableClassAndProto(constraints);

    LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
    return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::ObjectType(key));
}

TemporaryTypeSet*
jit::MakeSingletonTypeSet(CompilerConstraintList* constraints, JSObject* obj)
{
    return MakeSingletonTypeSetFromKey(constraints, TypeSet::ObjectKey::get(obj));
}

TemporaryTypeSet*
jit::MakeSingletonTypeSet(CompilerConstraintList* constraints, ObjectGroup* obj)
{
    return MakeSingletonTypeSetFromKey(constraints, TypeSet::ObjectKey::get(obj));
}

static TemporaryTypeSet*
MakeUnknownTypeSet()
{
    LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
    return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::UnknownType());
}

#ifdef DEBUG

bool
jit::IonCompilationCanUseNurseryPointers()
{
    // If we are doing backend compilation, which could occur on a helper
    // thread but might actually be on the main thread, check the flag set on
    // the PerThreadData by AutoEnterIonCompilation.
    if (CurrentThreadIsIonCompiling())
        return !CurrentThreadIsIonCompilingSafeForMinorGC();

    // Otherwise, we must be on the main thread during MIR construction. The
    // store buffer must have been notified that minor GCs must cancel pending
    // or in progress Ion compilations.
    JSRuntime* rt = TlsPerThreadData.get()->runtimeFromMainThread();
    return rt->gc.storeBuffer.cancelIonCompilations();
}

#endif // DEBUG

MConstant::MConstant(const js::Value& vp, CompilerConstraintList* constraints)
  : value_(vp)
{
    setResultType(MIRTypeFromValue(vp));
    if (vp.isObject()) {
        // Create a singleton type set for the object. This isn't necessary for
        // other types as the result type encodes all needed information.
        MOZ_ASSERT_IF(IsInsideNursery(&vp.toObject()), IonCompilationCanUseNurseryPointers());
        setResultTypeSet(MakeSingletonTypeSet(constraints, &vp.toObject()));
    }
    if (vp.isMagic() && vp.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
        // JS_UNINITIALIZED_LEXICAL does not escape to script and is not
        // observed in type sets. However, it may flow around freely during
        // Ion compilation. Give it an unknown typeset to poison any type sets
        // it merges with.
        //
        // TODO We could track uninitialized lexicals more precisely by tracking
        // them in type sets.
        setResultTypeSet(MakeUnknownTypeSet());
    }

    MOZ_ASSERT_IF(vp.isString(), vp.toString()->isAtom());

    setMovable();
}

MConstant::MConstant(JSObject* obj)
  : value_(ObjectValue(*obj))
{
    MOZ_ASSERT_IF(IsInsideNursery(obj), IonCompilationCanUseNurseryPointers());
    setResultType(MIRType_Object);
    setMovable();
}

HashNumber
MConstant::valueHash() const
{
    // Fold all 64 bits into the 32-bit result. It's tempting to just discard
    // half of the bits, as this is just a hash, however there are many common
    // patterns of values where only the low or the high bits vary, so
    // discarding either side would lead to excessive hash collisions.
    uint64_t bits = JSVAL_TO_IMPL(value_).asBits;
    return (HashNumber)bits ^ (HashNumber)(bits >> 32);
}

bool
MConstant::congruentTo(const MDefinition* ins) const
{
    if (!ins->isConstant())
        return false;
    return ins->toConstant()->value() == value();
}

void
MConstant::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    out.printf(" ");
    switch (type()) {
      case MIRType_Undefined:
        out.printf("undefined");
        break;
      case MIRType_Null:
        out.printf("null");
        break;
      case MIRType_Boolean:
        out.printf(value().toBoolean() ? "true" : "false");
        break;
      case MIRType_Int32:
        out.printf("0x%x", value().toInt32());
        break;
      case MIRType_Double:
        out.printf("%.16g", value().toDouble());
        break;
      case MIRType_Float32:
      {
        float val = value().toDouble();
        out.printf("%.16g", val);
        break;
      }
      case MIRType_Object:
        if (value().toObject().is<JSFunction>()) {
            JSFunction* fun = &value().toObject().as<JSFunction>();
            if (fun->displayAtom()) {
                out.put("function ");
                EscapedStringPrinter(out, fun->displayAtom(), 0);
            } else {
                out.put("unnamed function");
            }
            if (fun->hasScript()) {
                JSScript* script = fun->nonLazyScript();
                out.printf(" (%s:%" PRIuSIZE ")",
                        script->filename() ? script->filename() : "", script->lineno());
            }
            out.printf(" at %p", (void*) fun);
            break;
        }
        out.printf("object %p (%s)", (void*)&value().toObject(),
                value().toObject().getClass()->name);
        break;
      case MIRType_Symbol:
        out.printf("symbol at %p", (void*)value().toSymbol());
        break;
      case MIRType_String:
        out.printf("string %p", (void*)value().toString());
        break;
      case MIRType_MagicOptimizedArguments:
        out.printf("magic lazyargs");
        break;
      case MIRType_MagicHole:
        out.printf("magic hole");
        break;
      case MIRType_MagicIsConstructing:
        out.printf("magic is-constructing");
        break;
      case MIRType_MagicOptimizedOut:
        out.printf("magic optimized-out");
        break;
      case MIRType_MagicUninitializedLexical:
        out.printf("magic uninitialized-lexical");
        break;
      default:
        MOZ_CRASH("unexpected type");
    }
}

bool
MConstant::canProduceFloat32() const
{
    if (!IsNumberType(type()))
        return false;

    if (type() == MIRType_Int32)
        return IsFloat32Representable(static_cast<double>(value_.toInt32()));
    if (type() == MIRType_Double)
        return IsFloat32Representable(value_.toDouble());
    return true;
}

MDefinition*
MSimdValueX4::foldsTo(TempAllocator& alloc)
{
    DebugOnly<MIRType> laneType = SimdTypeToLaneType(type());
    bool allConstants = true;
    bool allSame = true;

    for (size_t i = 0; i < 4; ++i) {
        MDefinition* op = getOperand(i);
        MOZ_ASSERT(op->type() == laneType);
        if (!op->isConstantValue())
            allConstants = false;
        if (i > 0 && op != getOperand(i - 1))
            allSame = false;
    }

    if (!allConstants && !allSame)
        return this;

    if (allConstants) {
        SimdConstant cst;
        switch (type()) {
          case MIRType_Int32x4: {
            int32_t a[4];
            for (size_t i = 0; i < 4; ++i)
                a[i] = getOperand(i)->constantValue().toInt32();
            cst = SimdConstant::CreateX4(a);
            break;
          }
          case MIRType_Float32x4: {
            float a[4];
            for (size_t i = 0; i < 4; ++i)
                a[i] = getOperand(i)->constantValue().toNumber();
            cst = SimdConstant::CreateX4(a);
            break;
          }
          default: MOZ_CRASH("unexpected type in MSimdValueX4::foldsTo");
        }

        return MSimdConstant::New(alloc, cst, type());
    }

    MOZ_ASSERT(allSame);
    return MSimdSplatX4::New(alloc, getOperand(0), type());
}

MDefinition*
MSimdSplatX4::foldsTo(TempAllocator& alloc)
{
    DebugOnly<MIRType> laneType = SimdTypeToLaneType(type());
    MDefinition* op = getOperand(0);
    if (!op->isConstantValue())
        return this;
    MOZ_ASSERT(op->type() == laneType);

    SimdConstant cst;
    switch (type()) {
      case MIRType_Int32x4: {
        int32_t a[4];
        int32_t v = getOperand(0)->constantValue().toInt32();
        for (size_t i = 0; i < 4; ++i)
            a[i] = v;
        cst = SimdConstant::CreateX4(a);
        break;
      }
      case MIRType_Float32x4: {
        float a[4];
        float v = getOperand(0)->constantValue().toNumber();
        for (size_t i = 0; i < 4; ++i)
            a[i] = v;
        cst = SimdConstant::CreateX4(a);
        break;
      }
      default: MOZ_CRASH("unexpected type in MSimdSplatX4::foldsTo");
    }

    return MSimdConstant::New(alloc, cst, type());
}

MDefinition*
MSimdUnbox::foldsTo(TempAllocator& alloc)
{
    MDefinition* in = input();

    if (in->isSimdBox()) {
        // If the operand is a MSimdBox, then we just reuse the operand of the
        // MSimdBox as long as the type corresponds to what we are supposed to
        // unbox.
        in = in->toSimdBox()->input();
        if (in->type() != type())
            return this;
        return in;
    }

    return this;
}

MDefinition*
MSimdSwizzle::foldsTo(TempAllocator& alloc)
{
    if (lanesMatch(0, 1, 2, 3))
        return input();
    return this;
}

MDefinition*
MSimdGeneralShuffle::foldsTo(TempAllocator& alloc)
{
    FixedList<uint32_t> lanes;
    if (!lanes.init(alloc, numLanes()))
        return this;

    for (size_t i = 0; i < numLanes(); i++) {
        if (!lane(i)->isConstant() || lane(i)->type() != MIRType_Int32)
            return this;
        int32_t temp = lane(i)->toConstant()->value().toInt32();
        if (temp < 0 || uint32_t(temp) >= numLanes() * numVectors())
            return this;
        lanes[i] = uint32_t(temp);
    }

    if (numVectors() == 1)
        return MSimdSwizzle::New(alloc, vector(0), type(), lanes[0], lanes[1], lanes[2], lanes[3]);

    MOZ_ASSERT(numVectors() == 2);
    return MSimdShuffle::New(alloc, vector(0), vector(1), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
}

template <typename T>
static void
PrintOpcodeOperation(T* mir, GenericPrinter& out)
{
    mir->MDefinition::printOpcode(out);
    out.printf(" (%s)", T::OperationName(mir->operation()));
}

void
MSimdBinaryArith::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeOperation(this, out);
}
void
MSimdBinaryBitwise::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeOperation(this, out);
}
void
MSimdUnaryArith::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeOperation(this, out);
}
void
MSimdBinaryComp::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeOperation(this, out);
}
void
MSimdShift::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeOperation(this, out);
}

void
MSimdInsertElement::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    out.printf(" (%s)", MSimdInsertElement::LaneName(lane()));
}

MCloneLiteral*
MCloneLiteral::New(TempAllocator& alloc, MDefinition* obj)
{
    return new(alloc) MCloneLiteral(obj);
}

void
MControlInstruction::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    for (size_t j = 0; j < numSuccessors(); j++)
        out.printf(" block%u", getSuccessor(j)->id());
}

void
MCompare::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    out.printf(" %s", CodeName[jsop()]);
}

void
MConstantElements::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    out.printf(" 0x%" PRIxPTR, value().asValue());
}

void
MLoadUnboxedScalar::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    out.printf(" %s", ScalarTypeDescr::typeName(storageType()));
}

void
MAssertRange::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    out.put(" ");
    assertedRange()->dump(out);
}

const char*
MMathFunction::FunctionName(Function function)
{
    switch (function) {
      case Log:    return "Log";
      case Sin:    return "Sin";
      case Cos:    return "Cos";
      case Exp:    return "Exp";
      case Tan:    return "Tan";
      case ACos:   return "ACos";
      case ASin:   return "ASin";
      case ATan:   return "ATan";
      case Log10:  return "Log10";
      case Log2:   return "Log2";
      case Log1P:  return "Log1P";
      case ExpM1:  return "ExpM1";
      case CosH:   return "CosH";
      case SinH:   return "SinH";
      case TanH:   return "TanH";
      case ACosH:  return "ACosH";
      case ASinH:  return "ASinH";
      case ATanH:  return "ATanH";
      case Sign:   return "Sign";
      case Trunc:  return "Trunc";
      case Cbrt:   return "Cbrt";
      case Floor:  return "Floor";
      case Ceil:   return "Ceil";
      case Round:  return "Round";
      default:
        MOZ_CRASH("Unknown math function");
    }
}

void
MMathFunction::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);
    out.printf(" %s", FunctionName(function()));
}

MDefinition*
MMathFunction::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);
    if (!input->isConstant())
        return this;

    Value val = input->toConstant()->value();
    if (!val.isNumber())
        return this;

    double in = val.toNumber();
    double out;
    switch (function_) {
      case Log:
        out = js::math_log_uncached(in);
        break;
      case Sin:
        out = js::math_sin_uncached(in);
        break;
      case Cos:
        out = js::math_cos_uncached(in);
        break;
      case Exp:
        out = js::math_exp_uncached(in);
        break;
      case Tan:
        out = js::math_tan_uncached(in);
        break;
      case ACos:
        out = js::math_acos_uncached(in);
        break;
      case ASin:
        out = js::math_asin_uncached(in);
        break;
      case ATan:
        out = js::math_atan_uncached(in);
        break;
      case Log10:
        out = js::math_log10_uncached(in);
        break;
      case Log2:
        out = js::math_log2_uncached(in);
        break;
      case Log1P:
        out = js::math_log1p_uncached(in);
        break;
      case ExpM1:
        out = js::math_expm1_uncached(in);
        break;
      case CosH:
        out = js::math_cosh_uncached(in);
        break;
      case SinH:
        out = js::math_sinh_uncached(in);
        break;
      case TanH:
        out = js::math_tanh_uncached(in);
        break;
      case ACosH:
        out = js::math_acosh_uncached(in);
        break;
      case ASinH:
        out = js::math_asinh_uncached(in);
        break;
      case ATanH:
        out = js::math_atanh_uncached(in);
        break;
      case Sign:
        out = js::math_sign_uncached(in);
        break;
      case Trunc:
        out = js::math_trunc_uncached(in);
        break;
      case Cbrt:
        out = js::math_cbrt_uncached(in);
        break;
      case Floor:
        out = js::math_floor_impl(in);
        break;
      case Ceil:
        out = js::math_ceil_impl(in);
        break;
      case Round:
        out = js::math_round_impl(in);
        break;
      default:
        return this;
    }

    if (input->type() == MIRType_Float32)
        return MConstant::NewTypedValue(alloc, DoubleValue(out), MIRType_Float32);
    return MConstant::New(alloc, DoubleValue(out));
}

MDefinition*
MAtomicIsLockFree::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);
    if (!input->isConstantValue())
        return this;

    Value val = input->constantValue();
    if (!val.isInt32())
        return this;

    return MConstant::New(alloc, BooleanValue(AtomicOperations::isLockfree(val.toInt32())));
}

MParameter*
MParameter::New(TempAllocator& alloc, int32_t index, TemporaryTypeSet* types)
{
    return new(alloc) MParameter(index, types);
}

void
MParameter::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    if (index() == THIS_SLOT)
        out.printf(" THIS_SLOT");
    else
        out.printf(" %d", index());
}

HashNumber
MParameter::valueHash() const
{
    HashNumber hash = MDefinition::valueHash();
    hash = addU32ToHash(hash, index_);
    return hash;
}

bool
MParameter::congruentTo(const MDefinition* ins) const
{
    if (!ins->isParameter())
        return false;

    return ins->toParameter()->index() == index_;
}

MCall*
MCall::New(TempAllocator& alloc, JSFunction* target, size_t maxArgc, size_t numActualArgs,
           bool construct, bool isDOMCall)
{
    MOZ_ASSERT(maxArgc >= numActualArgs);
    MCall* ins;
    if (isDOMCall) {
        MOZ_ASSERT(!construct);
        ins = new(alloc) MCallDOMNative(target, numActualArgs);
    } else {
        ins = new(alloc) MCall(target, numActualArgs, construct);
    }
    if (!ins->init(alloc, maxArgc + NumNonArgumentOperands))
        return nullptr;
    return ins;
}

AliasSet
MCallDOMNative::getAliasSet() const
{
    const JSJitInfo* jitInfo = getJitInfo();

    // If we don't know anything about the types of our arguments, we have to
    // assume that type-coercions can have side-effects, so we need to alias
    // everything.
    if (jitInfo->aliasSet() == JSJitInfo::AliasEverything || !jitInfo->isTypedMethodJitInfo())
        return AliasSet::Store(AliasSet::Any);

    uint32_t argIndex = 0;
    const JSTypedMethodJitInfo* methodInfo =
        reinterpret_cast<const JSTypedMethodJitInfo*>(jitInfo);
    for (const JSJitInfo::ArgType* argType = methodInfo->argTypes;
         *argType != JSJitInfo::ArgTypeListEnd;
         ++argType, ++argIndex)
    {
        if (argIndex >= numActualArgs()) {
            // Passing through undefined can't have side-effects
            continue;
        }
        // getArg(0) is "this", so skip it
        MDefinition* arg = getArg(argIndex+1);
        MIRType actualType = arg->type();
        // The only way to reliably avoid side-effects given the information we
        // have here is if we're passing in a known primitive value to an
        // argument that expects a primitive value.
        //
        // XXXbz maybe we need to communicate better information.  For example,
        // a sequence argument will sort of unavoidably have side effects, while
        // a typed array argument won't have any, but both are claimed to be
        // JSJitInfo::Object.  But if we do that, we need to watch out for our
        // movability/DCE-ability bits: if we have an arg type that can reliably
        // throw an exception on conversion, that might not affect our alias set
        // per se, but it should prevent us being moved or DCE-ed, unless we
        // know the incoming things match that arg type and won't throw.
        //
        if ((actualType == MIRType_Value || actualType == MIRType_Object) ||
            (*argType & JSJitInfo::Object))
         {
             return AliasSet::Store(AliasSet::Any);
         }
    }

    // We checked all the args, and they check out.  So we only alias DOM
    // mutations or alias nothing, depending on the alias set in the jitinfo.
    if (jitInfo->aliasSet() == JSJitInfo::AliasNone)
        return AliasSet::None();

    MOZ_ASSERT(jitInfo->aliasSet() == JSJitInfo::AliasDOMSets);
    return AliasSet::Load(AliasSet::DOMProperty);
}

void
MCallDOMNative::computeMovable()
{
    // We are movable if the jitinfo says we can be and if we're also not
    // effectful.  The jitinfo can't check for the latter, since it depends on
    // the types of our arguments.
    const JSJitInfo* jitInfo = getJitInfo();

    MOZ_ASSERT_IF(jitInfo->isMovable,
                  jitInfo->aliasSet() != JSJitInfo::AliasEverything);

    if (jitInfo->isMovable && !isEffectful())
        setMovable();
}

bool
MCallDOMNative::congruentTo(const MDefinition* ins) const
{
    if (!isMovable())
        return false;

    if (!ins->isCall())
        return false;

    const MCall* call = ins->toCall();

    if (!call->isCallDOMNative())
        return false;

    if (getSingleTarget() != call->getSingleTarget())
        return false;

    if (isConstructing() != call->isConstructing())
        return false;

    if (numActualArgs() != call->numActualArgs())
        return false;

    if (needsArgCheck() != call->needsArgCheck())
        return false;

    if (!congruentIfOperandsEqual(call))
        return false;

    // The other call had better be movable at this point!
    MOZ_ASSERT(call->isMovable());

    return true;
}

const JSJitInfo*
MCallDOMNative::getJitInfo() const
{
    MOZ_ASSERT(getSingleTarget() && getSingleTarget()->isNative());

    const JSJitInfo* jitInfo = getSingleTarget()->jitInfo();
    MOZ_ASSERT(jitInfo);

    return jitInfo;
}

MApplyArgs*
MApplyArgs::New(TempAllocator& alloc, JSFunction* target, MDefinition* fun, MDefinition* argc,
                MDefinition* self)
{
    return new(alloc) MApplyArgs(target, fun, argc, self);
}

MApplyArray*
MApplyArray::New(TempAllocator& alloc, JSFunction* target, MDefinition* fun, MDefinition* elements,
                 MDefinition* self)
{
    return new(alloc) MApplyArray(target, fun, elements, self);
}

MDefinition*
MStringLength::foldsTo(TempAllocator& alloc)
{
    if ((type() == MIRType_Int32) && (string()->isConstantValue())) {
        Value value = string()->constantValue();
        JSAtom* atom = &value.toString()->asAtom();
        return MConstant::New(alloc, Int32Value(atom->length()));
    }

    return this;
}

MDefinition*
MConcat::foldsTo(TempAllocator& alloc)
{
    if (lhs()->isConstantValue() && lhs()->constantValue().toString()->empty())
        return rhs();

    if (rhs()->isConstantValue() && rhs()->constantValue().toString()->empty())
        return lhs();

    return this;
}

static bool
EnsureFloatInputOrConvert(MUnaryInstruction* owner, TempAllocator& alloc)
{
    MDefinition* input = owner->input();
    if (!input->canProduceFloat32()) {
        if (input->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, input, owner);
        return false;
    }
    return true;
}

void
MFloor::trySpecializeFloat32(TempAllocator& alloc)
{
    MOZ_ASSERT(type() == MIRType_Int32);
    if (EnsureFloatInputOrConvert(this, alloc))
        specialization_ = MIRType_Float32;
}

void
MCeil::trySpecializeFloat32(TempAllocator& alloc)
{
    MOZ_ASSERT(type() == MIRType_Int32);
    if (EnsureFloatInputOrConvert(this, alloc))
        specialization_ = MIRType_Float32;
}

void
MRound::trySpecializeFloat32(TempAllocator& alloc)
{
    MOZ_ASSERT(type() == MIRType_Int32);
    if (EnsureFloatInputOrConvert(this, alloc))
        specialization_ = MIRType_Float32;
}

MCompare*
MCompare::New(TempAllocator& alloc, MDefinition* left, MDefinition* right, JSOp op)
{
    return new(alloc) MCompare(left, right, op);
}

MCompare*
MCompare::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right, JSOp op,
                   CompareType compareType)
{
    MOZ_ASSERT(compareType == Compare_Int32 || compareType == Compare_UInt32 ||
               compareType == Compare_Double || compareType == Compare_Float32);
    MCompare* comp = new(alloc) MCompare(left, right, op);
    comp->compareType_ = compareType;
    comp->operandMightEmulateUndefined_ = false;
    comp->setResultType(MIRType_Int32);
    return comp;
}

MTableSwitch*
MTableSwitch::New(TempAllocator& alloc, MDefinition* ins, int32_t low, int32_t high)
{
    return new(alloc) MTableSwitch(alloc, ins, low, high);
}

MGoto*
MGoto::New(TempAllocator& alloc, MBasicBlock* target)
{
    MOZ_ASSERT(target);
    return new(alloc) MGoto(target);
}

void
MUnbox::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    out.printf(" ");
    getOperand(0)->printName(out);
    out.printf(" ");

    switch (type()) {
      case MIRType_Int32: out.printf("to Int32"); break;
      case MIRType_Double: out.printf("to Double"); break;
      case MIRType_Boolean: out.printf("to Boolean"); break;
      case MIRType_String: out.printf("to String"); break;
      case MIRType_Symbol: out.printf("to Symbol"); break;
      case MIRType_Object: out.printf("to Object"); break;
      default: break;
    }

    switch (mode()) {
      case Fallible: out.printf(" (fallible)"); break;
      case Infallible: out.printf(" (infallible)"); break;
      case TypeBarrier: out.printf(" (typebarrier)"); break;
      default: break;
    }
}

MDefinition*
MUnbox::foldsTo(TempAllocator &alloc)
{
    if (!input()->isLoadFixedSlot())
        return this;
    MLoadFixedSlot* load = input()->toLoadFixedSlot();
    if (load->type() != MIRType_Value)
        return this;
    if (type() != MIRType_Boolean && !IsNumberType(type()))
        return this;
    // Only optimize if the load comes immediately before the unbox, so it's
    // safe to copy the load's dependency field.
    MInstructionIterator iter(load->block()->begin(load));
    ++iter;
    if (*iter != this)
        return this;

    MLoadFixedSlotAndUnbox* ins = MLoadFixedSlotAndUnbox::New(alloc, load->object(), load->slot(),
                                                              mode(), type(), bailoutKind());
    // As GVN runs after the Alias Analysis, we have to set the dependency by hand
    ins->setDependency(load->dependency());
    return ins;
}

void
MTypeBarrier::printOpcode(GenericPrinter& out) const
{
    PrintOpcodeName(out, op());
    out.printf(" ");
    getOperand(0)->printName(out);
}

bool
MTypeBarrier::congruentTo(const MDefinition* def) const
{
    if (!def->isTypeBarrier())
        return false;
    const MTypeBarrier* other = def->toTypeBarrier();
    if (barrierKind() != other->barrierKind() || isGuard() != other->isGuard())
        return false;
    if (!resultTypeSet()->equals(other->resultTypeSet()))
        return false;
    return congruentIfOperandsEqual(other);
}

#ifdef DEBUG
void
MPhi::assertLoopPhi() const
{
    // getLoopPredecessorOperand and getLoopBackedgeOperand rely on these
    // predecessors being at indices 0 and 1.
    MBasicBlock* pred = block()->getPredecessor(0);
    MBasicBlock* back = block()->getPredecessor(1);
    MOZ_ASSERT(pred == block()->loopPredecessor());
    MOZ_ASSERT(pred->successorWithPhis() == block());
    MOZ_ASSERT(pred->positionInPhiSuccessor() == 0);
    MOZ_ASSERT(back == block()->backedge());
    MOZ_ASSERT(back->successorWithPhis() == block());
    MOZ_ASSERT(back->positionInPhiSuccessor() == 1);
}
#endif

void
MPhi::removeOperand(size_t index)
{
    MOZ_ASSERT(index < numOperands());
    MOZ_ASSERT(getUseFor(index)->index() == index);
    MOZ_ASSERT(getUseFor(index)->consumer() == this);

    // If we have phi(..., a, b, c, d, ..., z) and we plan
    // on removing a, then first shift downward so that we have
    // phi(..., b, c, d, ..., z, z):
    MUse* p = inputs_.begin() + index;
    MUse* e = inputs_.end();
    p->producer()->removeUse(p);
    for (; p < e - 1; ++p) {
        MDefinition* producer = (p + 1)->producer();
        p->setProducerUnchecked(producer);
        producer->replaceUse(p + 1, p);
    }

    // truncate the inputs_ list:
    inputs_.popBack();
}

void
MPhi::removeAllOperands()
{
    for (MUse& p : inputs_)
        p.producer()->removeUse(&p);
    inputs_.clear();
}

MDefinition*
MPhi::foldsTernary()
{
    /* Look if this MPhi is a ternary construct.
     * This is a very loose term as it actually only checks for
     *
     *      MTest X
     *       /  \
     *    ...    ...
     *       \  /
     *     MPhi X Y
     *
     * Which we will simply call:
     * x ? x : y or x ? y : x
     */

    if (numOperands() != 2)
        return nullptr;

    MOZ_ASSERT(block()->numPredecessors() == 2);

    MBasicBlock* pred = block()->immediateDominator();
    if (!pred || !pred->lastIns()->isTest())
        return nullptr;

    MTest* test = pred->lastIns()->toTest();

    // True branch may only dominate one edge of MPhi.
    if (test->ifTrue()->dominates(block()->getPredecessor(0)) ==
        test->ifTrue()->dominates(block()->getPredecessor(1)))
    {
        return nullptr;
    }

    // False branch may only dominate one edge of MPhi.
    if (test->ifFalse()->dominates(block()->getPredecessor(0)) ==
        test->ifFalse()->dominates(block()->getPredecessor(1)))
    {
        return nullptr;
    }

    // True and false branch must dominate different edges of MPhi.
    if (test->ifTrue()->dominates(block()->getPredecessor(0)) ==
        test->ifFalse()->dominates(block()->getPredecessor(0)))
    {
        return nullptr;
    }

    // We found a ternary construct.
    bool firstIsTrueBranch = test->ifTrue()->dominates(block()->getPredecessor(0));
    MDefinition* trueDef = firstIsTrueBranch ? getOperand(0) : getOperand(1);
    MDefinition* falseDef = firstIsTrueBranch ? getOperand(1) : getOperand(0);

    // Accept either
    // testArg ? testArg : constant or
    // testArg ? constant : testArg
    if (!trueDef->isConstant() && !falseDef->isConstant())
        return nullptr;

    MConstant* c = trueDef->isConstant() ? trueDef->toConstant() : falseDef->toConstant();
    MDefinition* testArg = (trueDef == c) ? falseDef : trueDef;
    if (testArg != test->input())
        return nullptr;

    // This check should be a tautology, except that the constant might be the
    // result of the removal of a branch.  In such case the domination scope of
    // the block which is holding the constant might be incomplete. This
    // condition is used to prevent doing this optimization based on incomplete
    // information.
    //
    // As GVN removed a branch, it will update the dominations rules before
    // trying to fold this MPhi again. Thus, this condition does not inhibit
    // this optimization.
    MBasicBlock* truePred = block()->getPredecessor(firstIsTrueBranch ? 0 : 1);
    MBasicBlock* falsePred = block()->getPredecessor(firstIsTrueBranch ? 1 : 0);
    if (!trueDef->block()->dominates(truePred) ||
        !falseDef->block()->dominates(falsePred))
    {
        return nullptr;
    }

    // If testArg is an int32 type we can:
    // - fold testArg ? testArg : 0 to testArg
    // - fold testArg ? 0 : testArg to 0
    if (testArg->type() == MIRType_Int32 && c->vp()->toNumber() == 0) {
        // When folding to the constant we need to hoist it.
        if (trueDef == c && !c->block()->dominates(block()))
            c->block()->moveBefore(pred->lastIns(), c);
        return trueDef;
    }

    // If testArg is a string type we can:
    // - fold testArg ? testArg : "" to testArg
    // - fold testArg ? "" : testArg to ""
    if (testArg->type() == MIRType_String &&
        c->vp()->toString() == GetJitContext()->runtime->emptyString())
    {
        // When folding to the constant we need to hoist it.
        if (trueDef == c && !c->block()->dominates(block()))
            c->block()->moveBefore(pred->lastIns(), c);
        return trueDef;
    }

    return nullptr;
}

MDefinition*
MPhi::operandIfRedundant()
{
    if (inputs_.length() == 0)
        return nullptr;

    // If this phi is redundant (e.g., phi(a,a) or b=phi(a,this)),
    // returns the operand that it will always be equal to (a, in
    // those two cases).
    MDefinition* first = getOperand(0);
    for (size_t i = 1, e = numOperands(); i < e; i++) {
        MDefinition* op = getOperand(i);
        if (op != first && op != this)
            return nullptr;
    }
    return first;
}

MDefinition*
MPhi::foldsFilterTypeSet()
{
    // Fold phi with as operands a combination of 'subject' and
    // MFilterTypeSet(subject) to 'subject'.

    if (inputs_.length() == 0)
        return nullptr;

    MDefinition* subject = getOperand(0);
    if (subject->isFilterTypeSet())
        subject = subject->toFilterTypeSet()->input();

    // Not same type, don't fold.
    if (subject->type() != type())
        return nullptr;

    // Phi is better typed (has typeset). Don't fold.
    if (resultTypeSet() && !subject->resultTypeSet())
        return nullptr;

    // Phi is better typed (according to typeset). Don't fold.
    if (subject->resultTypeSet() && resultTypeSet()) {
        if (!subject->resultTypeSet()->isSubset(resultTypeSet()))
            return nullptr;
    }

    for (size_t i = 1, e = numOperands(); i < e; i++) {
        MDefinition* op = getOperand(i);
        if (op == subject)
            continue;
        if (op->isFilterTypeSet() && op->toFilterTypeSet()->input() == subject)
            continue;

        return nullptr;
    }

    return subject;
}

MDefinition*
MPhi::foldsTo(TempAllocator& alloc)
{
    if (MDefinition* def = operandIfRedundant())
        return def;

    if (MDefinition* def = foldsTernary())
        return def;

    if (MDefinition* def = foldsFilterTypeSet())
        return def;

    return this;
}

bool
MPhi::congruentTo(const MDefinition* ins) const
{
    if (!ins->isPhi())
        return false;

    // Phis in different blocks may have different control conditions.
    // For example, these phis:
    //
    //   if (p)
    //     goto a
    //   a:
    //     t = phi(x, y)
    //
    //   if (q)
    //     goto b
    //   b:
    //     s = phi(x, y)
    //
    // have identical operands, but they are not equvalent because t is
    // effectively p?x:y and s is effectively q?x:y.
    //
    // For now, consider phis in different blocks incongruent.
    if (ins->block() != block())
        return false;

    return congruentIfOperandsEqual(ins);
}

static inline TemporaryTypeSet*
MakeMIRTypeSet(MIRType type)
{
    MOZ_ASSERT(type != MIRType_Value);
    TypeSet::Type ntype = type == MIRType_Object
                          ? TypeSet::AnyObjectType()
                          : TypeSet::PrimitiveType(ValueTypeFromMIRType(type));
    LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
    return alloc->new_<TemporaryTypeSet>(alloc, ntype);
}

bool
jit::MergeTypes(MIRType* ptype, TemporaryTypeSet** ptypeSet,
                MIRType newType, TemporaryTypeSet* newTypeSet)
{
    if (newTypeSet && newTypeSet->empty())
        return true;
    if (newType != *ptype) {
        if (IsNumberType(newType) && IsNumberType(*ptype)) {
            *ptype = MIRType_Double;
        } else if (*ptype != MIRType_Value) {
            if (!*ptypeSet) {
                *ptypeSet = MakeMIRTypeSet(*ptype);
                if (!*ptypeSet)
                    return false;
            }
            *ptype = MIRType_Value;
        } else if (*ptypeSet && (*ptypeSet)->empty()) {
            *ptype = newType;
        }
    }
    if (*ptypeSet) {
        LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
        if (!newTypeSet && newType != MIRType_Value) {
            newTypeSet = MakeMIRTypeSet(newType);
            if (!newTypeSet)
                return false;
        }
        if (newTypeSet) {
            if (!newTypeSet->isSubset(*ptypeSet)) {
                *ptypeSet = TypeSet::unionSets(*ptypeSet, newTypeSet, alloc);
                if (!*ptypeSet)
                    return false;
            }
        } else {
            *ptypeSet = nullptr;
        }
    }
    return true;
}

// Tests whether 'types' includes all possible values represented by
// input/inputTypes.
bool
jit::TypeSetIncludes(TypeSet* types, MIRType input, TypeSet* inputTypes)
{
    if (!types)
        return inputTypes && inputTypes->empty();

    switch (input) {
      case MIRType_Undefined:
      case MIRType_Null:
      case MIRType_Boolean:
      case MIRType_Int32:
      case MIRType_Double:
      case MIRType_Float32:
      case MIRType_String:
      case MIRType_Symbol:
      case MIRType_MagicOptimizedArguments:
        return types->hasType(TypeSet::PrimitiveType(ValueTypeFromMIRType(input)));

      case MIRType_Object:
        return types->unknownObject() || (inputTypes && inputTypes->isSubset(types));

      case MIRType_Value:
        return types->unknown() || (inputTypes && inputTypes->isSubset(types));

      default:
        MOZ_CRASH("Bad input type");
    }
}

// Tests if two type combos (type/typeset) are equal.
bool
jit::EqualTypes(MIRType type1, TemporaryTypeSet* typeset1,
                MIRType type2, TemporaryTypeSet* typeset2)
{
    // Types should equal.
    if (type1 != type2)
        return false;

    // Both have equal type and no typeset.
    if (!typeset1 && !typeset2)
        return true;

    // If only one instructions has a typeset.
    // Test if the typset contains the same information as the MIRType.
    if (typeset1 && !typeset2)
        return TypeSetIncludes(typeset1, type2, nullptr);
    if (!typeset1 && typeset2)
        return TypeSetIncludes(typeset2, type1, nullptr);

    // Typesets should equal.
    return typeset1->equals(typeset2);
}

// Tests whether input/inputTypes can always be stored to an unboxed
// object/array property with the given unboxed type.
bool
jit::CanStoreUnboxedType(TempAllocator& alloc,
                         JSValueType unboxedType, MIRType input, TypeSet* inputTypes)
{
    TemporaryTypeSet types;

    switch (unboxedType) {
      case JSVAL_TYPE_BOOLEAN:
      case JSVAL_TYPE_INT32:
      case JSVAL_TYPE_DOUBLE:
      case JSVAL_TYPE_STRING:
        types.addType(TypeSet::PrimitiveType(unboxedType), alloc.lifoAlloc());
        break;

      case JSVAL_TYPE_OBJECT:
        types.addType(TypeSet::AnyObjectType(), alloc.lifoAlloc());
        types.addType(TypeSet::NullType(), alloc.lifoAlloc());
        break;

      default:
        MOZ_CRASH("Bad unboxed type");
    }

    return TypeSetIncludes(&types, input, inputTypes);
}

static bool
CanStoreUnboxedType(TempAllocator& alloc, JSValueType unboxedType, MDefinition* value)
{
    return CanStoreUnboxedType(alloc, unboxedType, value->type(), value->resultTypeSet());
}

bool
MPhi::specializeType()
{
#ifdef DEBUG
    MOZ_ASSERT(!specialized_);
    specialized_ = true;
#endif

    MOZ_ASSERT(!inputs_.empty());

    size_t start;
    if (hasBackedgeType_) {
        // The type of this phi has already been populated with potential types
        // that could come in via loop backedges.
        start = 0;
    } else {
        setResultType(getOperand(0)->type());
        setResultTypeSet(getOperand(0)->resultTypeSet());
        start = 1;
    }

    MIRType resultType = this->type();
    TemporaryTypeSet* resultTypeSet = this->resultTypeSet();

    for (size_t i = start; i < inputs_.length(); i++) {
        MDefinition* def = getOperand(i);
        if (!MergeTypes(&resultType, &resultTypeSet, def->type(), def->resultTypeSet()))
            return false;
    }

    setResultType(resultType);
    setResultTypeSet(resultTypeSet);
    return true;
}

bool
MPhi::addBackedgeType(MIRType type, TemporaryTypeSet* typeSet)
{
    MOZ_ASSERT(!specialized_);

    if (hasBackedgeType_) {
        MIRType resultType = this->type();
        TemporaryTypeSet* resultTypeSet = this->resultTypeSet();

        if (!MergeTypes(&resultType, &resultTypeSet, type, typeSet))
            return false;

        setResultType(resultType);
        setResultTypeSet(resultTypeSet);
    } else {
        setResultType(type);
        setResultTypeSet(typeSet);
        hasBackedgeType_ = true;
    }
    return true;
}

bool
MPhi::typeIncludes(MDefinition* def)
{
    if (def->type() == MIRType_Int32 && this->type() == MIRType_Double)
        return true;

    if (TemporaryTypeSet* types = def->resultTypeSet()) {
        if (this->resultTypeSet())
            return types->isSubset(this->resultTypeSet());
        if (this->type() == MIRType_Value || types->empty())
            return true;
        return this->type() == types->getKnownMIRType();
    }

    if (def->type() == MIRType_Value) {
        // This phi must be able to be any value.
        return this->type() == MIRType_Value
            && (!this->resultTypeSet() || this->resultTypeSet()->unknown());
    }

    return this->mightBeType(def->type());
}

bool
MPhi::checkForTypeChange(MDefinition* ins, bool* ptypeChange)
{
    MIRType resultType = this->type();
    TemporaryTypeSet* resultTypeSet = this->resultTypeSet();

    if (!MergeTypes(&resultType, &resultTypeSet, ins->type(), ins->resultTypeSet()))
        return false;

    if (resultType != this->type() || resultTypeSet != this->resultTypeSet()) {
        *ptypeChange = true;
        setResultType(resultType);
        setResultTypeSet(resultTypeSet);
    }
    return true;
}

void
MCall::addArg(size_t argnum, MDefinition* arg)
{
    // The operand vector is initialized in reverse order by the IonBuilder.
    // It cannot be checked for consistency until all arguments are added.
    // FixedList doesn't initialize its elements, so do an unchecked init.
    initOperand(argnum + NumNonArgumentOperands, arg);
}

static inline bool
IsConstant(MDefinition* def, double v)
{
    if (!def->isConstant())
        return false;

    return NumbersAreIdentical(def->toConstant()->value().toNumber(), v);
}

MDefinition*
MBinaryBitwiseInstruction::foldsTo(TempAllocator& alloc)
{
    if (specialization_ != MIRType_Int32)
        return this;

    if (MDefinition* folded = EvaluateConstantOperands(alloc, this))
        return folded;

    return this;
}

MDefinition*
MBinaryBitwiseInstruction::foldUnnecessaryBitop()
{
    if (specialization_ != MIRType_Int32)
        return this;

    // Eliminate bitwise operations that are no-ops when used on integer
    // inputs, such as (x | 0).

    MDefinition* lhs = getOperand(0);
    MDefinition* rhs = getOperand(1);

    if (IsConstant(lhs, 0))
        return foldIfZero(0);

    if (IsConstant(rhs, 0))
        return foldIfZero(1);

    if (IsConstant(lhs, -1))
        return foldIfNegOne(0);

    if (IsConstant(rhs, -1))
        return foldIfNegOne(1);

    if (lhs == rhs)
        return foldIfEqual();

    return this;
}

void
MBinaryBitwiseInstruction::infer(BaselineInspector*, jsbytecode*)
{
    if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(0)->mightBeType(MIRType_Symbol) ||
        getOperand(1)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Symbol))
    {
        specialization_ = MIRType_None;
    } else {
        specializeAsInt32();
    }
}

void
MBinaryBitwiseInstruction::specializeAsInt32()
{
    specialization_ = MIRType_Int32;
    MOZ_ASSERT(type() == MIRType_Int32);

    if (isBitOr() || isBitAnd() || isBitXor())
        setCommutative();
}

void
MShiftInstruction::infer(BaselineInspector*, jsbytecode*)
{
    if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object) ||
        getOperand(0)->mightBeType(MIRType_Symbol) || getOperand(1)->mightBeType(MIRType_Symbol))
        specialization_ = MIRType_None;
    else
        specialization_ = MIRType_Int32;
}

void
MUrsh::infer(BaselineInspector* inspector, jsbytecode* pc)
{
    if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object) ||
        getOperand(0)->mightBeType(MIRType_Symbol) || getOperand(1)->mightBeType(MIRType_Symbol))
    {
        specialization_ = MIRType_None;
        setResultType(MIRType_Value);
        return;
    }

    if (inspector->hasSeenDoubleResult(pc)) {
        specialization_ = MIRType_Double;
        setResultType(MIRType_Double);
        return;
    }

    specialization_ = MIRType_Int32;
    setResultType(MIRType_Int32);
}

static inline bool
CanProduceNegativeZero(MDefinition* def) {
    // Test if this instruction can produce negative zero even when bailing out
    // and changing types.
    switch (def->op()) {
        case MDefinition::Op_Constant:
            if (def->type() == MIRType_Double && def->constantValue().toDouble() == -0.0)
                return true;
        case MDefinition::Op_BitAnd:
        case MDefinition::Op_BitOr:
        case MDefinition::Op_BitXor:
        case MDefinition::Op_BitNot:
        case MDefinition::Op_Lsh:
        case MDefinition::Op_Rsh:
            return false;
        default:
            return true;
    }
}

static inline bool
NeedNegativeZeroCheck(MDefinition* def)
{
    // Test if all uses have the same semantics for -0 and 0
    for (MUseIterator use = def->usesBegin(); use != def->usesEnd(); use++) {
        if (use->consumer()->isResumePoint())
            continue;

        MDefinition* use_def = use->consumer()->toDefinition();
        switch (use_def->op()) {
          case MDefinition::Op_Add: {
            // If add is truncating -0 and 0 are observed as the same.
            if (use_def->toAdd()->isTruncated())
                break;

            // x + y gives -0, when both x and y are -0

            // Figure out the order in which the addition's operands will
            // execute. EdgeCaseAnalysis::analyzeLate has renumbered the MIR
            // definitions for us so that this just requires comparing ids.
            MDefinition* first = use_def->toAdd()->lhs();
            MDefinition* second = use_def->toAdd()->rhs();
            if (first->id() > second->id()) {
                MDefinition* temp = first;
                first = second;
                second = temp;
            }
            // Negative zero checks can be removed on the first executed
            // operand only if it is guaranteed the second executed operand
            // will produce a value other than -0. While the second is
            // typed as an int32, a bailout taken between execution of the
            // operands may change that type and cause a -0 to flow to the
            // second.
            //
            // There is no way to test whether there are any bailouts
            // between execution of the operands, so remove negative
            // zero checks from the first only if the second's type is
            // independent from type changes that may occur after bailing.
            if (def == first && CanProduceNegativeZero(second))
                return true;

            // The negative zero check can always be removed on the second
            // executed operand; by the time this executes the first will have
            // been evaluated as int32 and the addition's result cannot be -0.
            break;
          }
          case MDefinition::Op_Sub: {
            // If sub is truncating -0 and 0 are observed as the same
            if (use_def->toSub()->isTruncated())
                break;

            // x + y gives -0, when x is -0 and y is 0

            // We can remove the negative zero check on the rhs, only if we
            // are sure the lhs isn't negative zero.

            // The lhs is typed as integer (i.e. not -0.0), but it can bailout
            // and change type. This should be fine if the lhs is executed
            // first. However if the rhs is executed first, the lhs can bail,
            // change type and become -0.0 while the rhs has already been
            // optimized to not make a difference between zero and negative zero.
            MDefinition* lhs = use_def->toSub()->lhs();
            MDefinition* rhs = use_def->toSub()->rhs();
            if (rhs->id() < lhs->id() && CanProduceNegativeZero(lhs))
                return true;

            /* Fall through...  */
          }
          case MDefinition::Op_StoreElement:
          case MDefinition::Op_StoreElementHole:
          case MDefinition::Op_LoadElement:
          case MDefinition::Op_LoadElementHole:
          case MDefinition::Op_LoadUnboxedScalar:
          case MDefinition::Op_LoadTypedArrayElementHole:
          case MDefinition::Op_CharCodeAt:
          case MDefinition::Op_Mod:
            // Only allowed to remove check when definition is the second operand
            if (use_def->getOperand(0) == def)
                return true;
            for (size_t i = 2, e = use_def->numOperands(); i < e; i++) {
                if (use_def->getOperand(i) == def)
                    return true;
            }
            break;
          case MDefinition::Op_BoundsCheck:
            // Only allowed to remove check when definition is the first operand
            if (use_def->toBoundsCheck()->getOperand(1) == def)
                return true;
            break;
          case MDefinition::Op_ToString:
          case MDefinition::Op_FromCharCode:
          case MDefinition::Op_TableSwitch:
          case MDefinition::Op_Compare:
          case MDefinition::Op_BitAnd:
          case MDefinition::Op_BitOr:
          case MDefinition::Op_BitXor:
          case MDefinition::Op_Abs:
          case MDefinition::Op_TruncateToInt32:
            // Always allowed to remove check. No matter which operand.
            break;
          default:
            return true;
        }
    }
    return false;
}

MBinaryArithInstruction*
MBinaryArithInstruction::New(TempAllocator& alloc, Opcode op,
                             MDefinition* left, MDefinition* right)
{
    switch (op) {
      case Op_Add:
        return MAdd::New(alloc, left, right);
      case Op_Sub:
        return MSub::New(alloc, left, right);
      case Op_Mul:
        return MMul::New(alloc, left, right);
      case Op_Div:
        return MDiv::New(alloc, left, right);
      case Op_Mod:
        return MMod::New(alloc, left, right);
      default:
        MOZ_CRASH("unexpected binary opcode");
    }
}

void
MBinaryArithInstruction::setNumberSpecialization(TempAllocator& alloc, BaselineInspector* inspector,
                                                 jsbytecode* pc)
{
    setSpecialization(MIRType_Double);

    // Try to specialize as int32.
    if (getOperand(0)->type() == MIRType_Int32 && getOperand(1)->type() == MIRType_Int32) {
        bool seenDouble = inspector->hasSeenDoubleResult(pc);

        // Use int32 specialization if the operation doesn't overflow on its
        // constant operands and if the operation has never overflowed.
        if (!seenDouble && !constantDoubleResult(alloc))
            setInt32Specialization();
    }
}

bool
MBinaryArithInstruction::constantDoubleResult(TempAllocator& alloc)
{
    bool typeChange = false;
    EvaluateConstantOperands(alloc, this, &typeChange);
    return typeChange;
}

MDefinition*
MBinaryArithInstruction::foldsTo(TempAllocator& alloc)
{
    if (specialization_ == MIRType_None)
        return this;

    MDefinition* lhs = getOperand(0);
    MDefinition* rhs = getOperand(1);
    if (MConstant* folded = EvaluateConstantOperands(alloc, this)) {
        if (isTruncated()) {
            if (!folded->block())
                block()->insertBefore(this, folded);
            return MTruncateToInt32::New(alloc, folded);
        }
        return folded;
    }

    // 0 + -0 = 0. So we can't remove addition
    if (isAdd() && specialization_ != MIRType_Int32)
        return this;

    if (IsConstant(rhs, getIdentity())) {
        if (isTruncated())
            return MTruncateToInt32::New(alloc, lhs);
        return lhs;
    }

    // subtraction isn't commutative. So we can't remove subtraction when lhs equals 0
    if (isSub())
        return this;

    if (IsConstant(lhs, getIdentity())) {
        if (isTruncated())
            return MTruncateToInt32::New(alloc, rhs);
        return rhs; // x op id => x
    }

    return this;
}

void
MFilterTypeSet::trySpecializeFloat32(TempAllocator& alloc)
{
    MDefinition* in = input();
    if (in->type() != MIRType_Float32)
        return;

    setResultType(MIRType_Float32);
}

bool
MFilterTypeSet::canProduceFloat32() const
{
    // A FilterTypeSet should be a producer if the input is a producer too.
    // Also, be overly conservative by marking as not float32 producer when the
    // input is a phi, as phis can be cyclic (phiA -> FilterTypeSet -> phiB ->
    // phiA) and FilterTypeSet doesn't belong in the Float32 phi analysis.
    return !input()->isPhi() && input()->canProduceFloat32();
}

bool
MFilterTypeSet::canConsumeFloat32(MUse* operand) const
{
    MOZ_ASSERT(getUseFor(0) == operand);
    // A FilterTypeSet should be a consumer if all uses are consumer. See also
    // comment below MFilterTypeSet::canProduceFloat32.
    bool allConsumerUses = true;
    for (MUseDefIterator use(this); allConsumerUses && use; use++)
        allConsumerUses &= !use.def()->isPhi() && use.def()->canConsumeFloat32(use.use());
    return allConsumerUses;
}

void
MBinaryArithInstruction::trySpecializeFloat32(TempAllocator& alloc)
{
    // Do not use Float32 if we can use int32.
    if (specialization_ == MIRType_Int32)
        return;
    if (specialization_ == MIRType_None)
        return;

    MDefinition* left = lhs();
    MDefinition* right = rhs();

    if (!left->canProduceFloat32() || !right->canProduceFloat32() ||
        !CheckUsesAreFloat32Consumers(this))
    {
        if (left->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, left, this);
        if (right->type() == MIRType_Float32)
            ConvertDefinitionToDouble<1>(alloc, right, this);
        return;
    }

    specialization_ = MIRType_Float32;
    setResultType(MIRType_Float32);
}

void
MMinMax::trySpecializeFloat32(TempAllocator& alloc)
{
    if (specialization_ == MIRType_Int32)
        return;

    MDefinition* left = lhs();
    MDefinition* right = rhs();

    if (!(left->canProduceFloat32() || (left->isMinMax() && left->type() == MIRType_Float32)) ||
        !(right->canProduceFloat32() || (right->isMinMax() && right->type() == MIRType_Float32)))
    {
        if (left->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, left, this);
        if (right->type() == MIRType_Float32)
            ConvertDefinitionToDouble<1>(alloc, right, this);
        return;
    }

    specialization_ = MIRType_Float32;
    setResultType(MIRType_Float32);
}

MDefinition*
MMinMax::foldsTo(TempAllocator& alloc)
{
    if (!lhs()->isConstant() && !rhs()->isConstant())
        return this;

    // Directly apply math utility to compare the rhs() and lhs() when
    // they are both constants.
    if (lhs()->isConstant() && rhs()->isConstant()) {
        Value lval = lhs()->toConstant()->value();
        Value rval = rhs()->toConstant()->value();
        if (!lval.isNumber() || !rval.isNumber())
            return this;

        double lnum = lval.toNumber();
        double rnum = rval.toNumber();
        double result;
        if (isMax())
            result = js::math_max_impl(lnum, rnum);
        else
            result = js::math_min_impl(lnum, rnum);

        // The folded MConstant should maintain the same MIRType with
        // the original MMinMax.
        if (type() == MIRType_Int32) {
            int32_t cast;
            if (mozilla::NumberEqualsInt32(result, &cast))
                return MConstant::New(alloc, Int32Value(cast));
        } else {
            MOZ_ASSERT(IsFloatingPointType(type()));
            MConstant* constant = MConstant::New(alloc, DoubleValue(result));
            if (type() == MIRType_Float32)
                constant->setResultType(MIRType_Float32);
            return constant;
        }
    }

    MDefinition* operand = lhs()->isConstantValue() ? rhs() : lhs();
    const js::Value& val = lhs()->isConstantValue() ? lhs()->constantValue() : rhs()->constantValue();

    if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
        // min(int32, cte >= INT32_MAX) = int32
        if (val.isDouble() && val.toDouble() >= INT32_MAX && !isMax()) {
            MLimitedTruncate* limit =
                MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
            block()->insertBefore(this, limit);
            MToDouble* toDouble = MToDouble::New(alloc, limit);
            return toDouble;
        }

        // max(int32, cte <= INT32_MIN) = int32
        if (val.isDouble() && val.toDouble() <= INT32_MIN && isMax()) {
            MLimitedTruncate* limit =
                MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
            block()->insertBefore(this, limit);
            MToDouble* toDouble = MToDouble::New(alloc, limit);
            return toDouble;
        }
    }
    return this;
}

bool
MAbs::fallible() const
{
    return !implicitTruncate_ && (!range() || !range()->hasInt32Bounds());
}

void
MAbs::trySpecializeFloat32(TempAllocator& alloc)
{
    // Do not use Float32 if we can use int32.
    if (input()->type() == MIRType_Int32)
        return;

    if (!input()->canProduceFloat32() || !CheckUsesAreFloat32Consumers(this)) {
        if (input()->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, input(), this);
        return;
    }

    setResultType(MIRType_Float32);
    specialization_ = MIRType_Float32;
}

MDefinition*
MDiv::foldsTo(TempAllocator& alloc)
{
    if (specialization_ == MIRType_None)
        return this;

    if (MDefinition* folded = EvaluateConstantOperands(alloc, this))
        return folded;

    if (MDefinition* folded = EvaluateExactReciprocal(alloc, this))
        return folded;

    return this;
}

void
MDiv::analyzeEdgeCasesForward()
{
    // This is only meaningful when doing integer division.
    if (specialization_ != MIRType_Int32)
        return;

    // Try removing divide by zero check
    if (rhs()->isConstantValue() && !rhs()->constantValue().isInt32(0))
        canBeDivideByZero_ = false;

    // If lhs is a constant int != INT32_MIN, then
    // negative overflow check can be skipped.
    if (lhs()->isConstantValue() && !lhs()->constantValue().isInt32(INT32_MIN))
        canBeNegativeOverflow_ = false;

    // If rhs is a constant int != -1, likewise.
    if (rhs()->isConstantValue() && !rhs()->constantValue().isInt32(-1))
        canBeNegativeOverflow_ = false;

    // If lhs is != 0, then negative zero check can be skipped.
    if (lhs()->isConstantValue() && !lhs()->constantValue().isInt32(0))
        setCanBeNegativeZero(false);

    // If rhs is >= 0, likewise.
    if (rhs()->isConstantValue()) {
        const js::Value& val = rhs()->constantValue();
        if (val.isInt32() && val.toInt32() >= 0)
            setCanBeNegativeZero(false);
    }
}

void
MDiv::analyzeEdgeCasesBackward()
{
    if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
        setCanBeNegativeZero(false);
}

bool
MDiv::fallible() const
{
    return !isTruncated();
}

MDefinition*
MMod::foldsTo(TempAllocator& alloc)
{
    if (specialization_ == MIRType_None)
        return this;

    if (MDefinition* folded = EvaluateConstantOperands(alloc, this))
        return folded;

    return this;
}

void
MMod::analyzeEdgeCasesForward()
{
    // These optimizations make sense only for integer division
    if (specialization_ != MIRType_Int32)
        return;

    if (rhs()->isConstantValue() && !rhs()->constantValue().isInt32(0))
        canBeDivideByZero_ = false;

    if (rhs()->isConstantValue()) {
        int32_t n = rhs()->constantValue().toInt32();
        if (n > 0 && !IsPowerOfTwo(n))
            canBePowerOfTwoDivisor_ = false;
    }
}

bool
MMod::fallible() const
{
    return !isTruncated() &&
           (isUnsigned() || canBeDivideByZero() || canBeNegativeDividend());
}

void
MMathFunction::trySpecializeFloat32(TempAllocator& alloc)
{
    if (!input()->canProduceFloat32() || !CheckUsesAreFloat32Consumers(this)) {
        if (input()->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, input(), this);
        return;
    }

    setResultType(MIRType_Float32);
    specialization_ = MIRType_Float32;
}

MHypot* MHypot::New(TempAllocator& alloc, const MDefinitionVector & vector)
{
    uint32_t length = vector.length();
    MHypot * hypot = new(alloc) MHypot;
    if (!hypot->init(alloc, length))
        return nullptr;

    for (uint32_t i = 0; i < length; ++i)
        hypot->initOperand(i, vector[i]);
    return hypot;
}

bool
MAdd::fallible() const
{
    // the add is fallible if range analysis does not say that it is finite, AND
    // either the truncation analysis shows that there are non-truncated uses.
    if (truncateKind() >= IndirectTruncate)
        return false;
    if (range() && range()->hasInt32Bounds())
        return false;
    return true;
}

bool
MSub::fallible() const
{
    // see comment in MAdd::fallible()
    if (truncateKind() >= IndirectTruncate)
        return false;
    if (range() && range()->hasInt32Bounds())
        return false;
    return true;
}

MDefinition*
MMul::foldsTo(TempAllocator& alloc)
{
    MDefinition* out = MBinaryArithInstruction::foldsTo(alloc);
    if (out != this)
        return out;

    if (specialization() != MIRType_Int32)
        return this;

    if (lhs() == rhs())
        setCanBeNegativeZero(false);

    return this;
}

void
MMul::analyzeEdgeCasesForward()
{
    // Try to remove the check for negative zero
    // This only makes sense when using the integer multiplication
    if (specialization() != MIRType_Int32)
        return;

    // If lhs is > 0, no need for negative zero check.
    if (lhs()->isConstantValue()) {
        const js::Value& val = lhs()->constantValue();
        if (val.isInt32() && val.toInt32() > 0)
            setCanBeNegativeZero(false);
    }

    // If rhs is > 0, likewise.
    if (rhs()->isConstantValue()) {
        const js::Value& val = rhs()->constantValue();
        if (val.isInt32() && val.toInt32() > 0)
            setCanBeNegativeZero(false);
    }
}

void
MMul::analyzeEdgeCasesBackward()
{
    if (canBeNegativeZero() && !NeedNegativeZeroCheck(this))
        setCanBeNegativeZero(false);
}

bool
MMul::updateForReplacement(MDefinition* ins_)
{
    MMul* ins = ins_->toMul();
    bool negativeZero = canBeNegativeZero() || ins->canBeNegativeZero();
    setCanBeNegativeZero(negativeZero);
    // Remove the imul annotation when merging imul and normal multiplication.
    if (mode_ == Integer && ins->mode() != Integer)
        mode_ = Normal;
    return true;
}

bool
MMul::canOverflow() const
{
    if (isTruncated())
        return false;
    return !range() || !range()->hasInt32Bounds();
}

bool
MUrsh::fallible() const
{
    if (bailoutsDisabled())
        return false;
    return !range() || !range()->hasInt32Bounds();
}

static inline bool
SimpleArithOperand(MDefinition* op)
{
    return !op->mightBeType(MIRType_Object)
        && !op->mightBeType(MIRType_String)
        && !op->mightBeType(MIRType_Symbol)
        && !op->mightBeType(MIRType_MagicOptimizedArguments)
        && !op->mightBeType(MIRType_MagicHole)
        && !op->mightBeType(MIRType_MagicIsConstructing);
}

static bool
SafelyCoercesToDouble(MDefinition* op)
{
    // Strings and symbols are unhandled -- visitToDouble() doesn't support them yet.
    // Null is unhandled -- ToDouble(null) == 0, but (0 == null) is false.
    return SimpleArithOperand(op) && !op->mightBeType(MIRType_Null);
}

MIRType
MCompare::inputType()
{
    switch(compareType_) {
      case Compare_Undefined:
        return MIRType_Undefined;
      case Compare_Null:
        return MIRType_Null;
      case Compare_Boolean:
        return MIRType_Boolean;
      case Compare_UInt32:
      case Compare_Int32:
      case Compare_Int32MaybeCoerceBoth:
      case Compare_Int32MaybeCoerceLHS:
      case Compare_Int32MaybeCoerceRHS:
        return MIRType_Int32;
      case Compare_Double:
      case Compare_DoubleMaybeCoerceLHS:
      case Compare_DoubleMaybeCoerceRHS:
        return MIRType_Double;
      case Compare_Float32:
        return MIRType_Float32;
      case Compare_String:
      case Compare_StrictString:
        return MIRType_String;
      case Compare_Object:
        return MIRType_Object;
      case Compare_Unknown:
      case Compare_Bitwise:
        return MIRType_Value;
      default:
        MOZ_CRASH("No known conversion");
    }
}

static inline bool
MustBeUInt32(MDefinition* def, MDefinition** pwrapped)
{
    if (def->isUrsh()) {
        *pwrapped = def->toUrsh()->getOperand(0);
        MDefinition* rhs = def->toUrsh()->getOperand(1);
        return def->toUrsh()->bailoutsDisabled()
            && rhs->isConstantValue()
            && rhs->constantValue().isInt32()
            && rhs->constantValue().toInt32() == 0;
    }

    if (def->isConstantValue()) {
        if (def->isBox())
            def = def->toBox()->getOperand(0);
        *pwrapped = def;
        return def->constantValue().isInt32()
            && def->constantValue().toInt32() >= 0;
    }

    return false;
}

/* static */ bool
MBinaryInstruction::unsignedOperands(MDefinition* left, MDefinition* right)
{
    MDefinition* replace;
    if (!MustBeUInt32(left, &replace))
        return false;
    if (replace->type() != MIRType_Int32)
        return false;
    if (!MustBeUInt32(right, &replace))
        return false;
    if (replace->type() != MIRType_Int32)
        return false;
    return true;
}

bool
MBinaryInstruction::unsignedOperands()
{
    return unsignedOperands(getOperand(0), getOperand(1));
}

void
MBinaryInstruction::replaceWithUnsignedOperands()
{
    MOZ_ASSERT(unsignedOperands());

    for (size_t i = 0; i < numOperands(); i++) {
        MDefinition* replace;
        MustBeUInt32(getOperand(i), &replace);
        if (replace == getOperand(i))
            continue;

        getOperand(i)->setImplicitlyUsedUnchecked();
        replaceOperand(i, replace);
    }
}

MCompare::CompareType
MCompare::determineCompareType(JSOp op, MDefinition* left, MDefinition* right)
{
    MIRType lhs = left->type();
    MIRType rhs = right->type();

    bool looseEq = op == JSOP_EQ || op == JSOP_NE;
    bool strictEq = op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
    bool relationalEq = !(looseEq || strictEq);

    // Comparisons on unsigned integers may be treated as UInt32.
    if (unsignedOperands(left, right))
        return Compare_UInt32;

    // Integer to integer or boolean to boolean comparisons may be treated as Int32.
    if ((lhs == MIRType_Int32 && rhs == MIRType_Int32) ||
        (lhs == MIRType_Boolean && rhs == MIRType_Boolean))
    {
        return Compare_Int32MaybeCoerceBoth;
    }

    // Loose/relational cross-integer/boolean comparisons may be treated as Int32.
    if (!strictEq &&
        (lhs == MIRType_Int32 || lhs == MIRType_Boolean) &&
        (rhs == MIRType_Int32 || rhs == MIRType_Boolean))
    {
        return Compare_Int32MaybeCoerceBoth;
    }

    // Numeric comparisons against a double coerce to double.
    if (IsNumberType(lhs) && IsNumberType(rhs))
        return Compare_Double;

    // Any comparison is allowed except strict eq.
    if (!strictEq && IsFloatingPointType(rhs) && SafelyCoercesToDouble(left))
        return Compare_DoubleMaybeCoerceLHS;
    if (!strictEq && IsFloatingPointType(lhs) && SafelyCoercesToDouble(right))
        return Compare_DoubleMaybeCoerceRHS;

    // Handle object comparison.
    if (!relationalEq && lhs == MIRType_Object && rhs == MIRType_Object)
        return Compare_Object;

    // Handle string comparisons. (Relational string compares are still unsupported).
    if (!relationalEq && lhs == MIRType_String && rhs == MIRType_String)
        return Compare_String;

    // Handle strict string compare.
    if (strictEq && lhs == MIRType_String)
        return Compare_StrictString;
    if (strictEq && rhs == MIRType_String)
        return Compare_StrictString;

    // Handle compare with lhs or rhs being Undefined or Null.
    if (!relationalEq && IsNullOrUndefined(lhs))
        return (lhs == MIRType_Null) ? Compare_Null : Compare_Undefined;
    if (!relationalEq && IsNullOrUndefined(rhs))
        return (rhs == MIRType_Null) ? Compare_Null : Compare_Undefined;

    // Handle strict comparison with lhs/rhs being typed Boolean.
    if (strictEq && (lhs == MIRType_Boolean || rhs == MIRType_Boolean)) {
        // bool/bool case got an int32 specialization earlier.
        MOZ_ASSERT(!(lhs == MIRType_Boolean && rhs == MIRType_Boolean));
        return Compare_Boolean;
    }

    return Compare_Unknown;
}

void
MCompare::cacheOperandMightEmulateUndefined(CompilerConstraintList* constraints)
{
    MOZ_ASSERT(operandMightEmulateUndefined());

    if (getOperand(0)->maybeEmulatesUndefined(constraints))
        return;
    if (getOperand(1)->maybeEmulatesUndefined(constraints))
        return;

    markNoOperandEmulatesUndefined();
}

MBitNot*
MBitNot::New(TempAllocator& alloc, MDefinition* input)
{
    return new(alloc) MBitNot(input);
}

MBitNot*
MBitNot::NewAsmJS(TempAllocator& alloc, MDefinition* input)
{
    MBitNot* ins = new(alloc) MBitNot(input);
    ins->specialization_ = MIRType_Int32;
    MOZ_ASSERT(ins->type() == MIRType_Int32);
    return ins;
}

MDefinition*
MBitNot::foldsTo(TempAllocator& alloc)
{
    if (specialization_ != MIRType_Int32)
        return this;

    MDefinition* input = getOperand(0);

    if (input->isConstant()) {
        js::Value v = Int32Value(~(input->constantValue().toInt32()));
        return MConstant::New(alloc, v);
    }

    if (input->isBitNot() && input->toBitNot()->specialization_ == MIRType_Int32) {
        MOZ_ASSERT(input->toBitNot()->getOperand(0)->type() == MIRType_Int32);
        return MTruncateToInt32::New(alloc, input->toBitNot()->input()); // ~~x => x | 0
    }

    return this;
}

MDefinition*
MTypeOf::foldsTo(TempAllocator& alloc)
{
    // Note: we can't use input->type() here, type analysis has
    // boxed the input.
    MOZ_ASSERT(input()->type() == MIRType_Value);

    JSType type;

    switch (inputType()) {
      case MIRType_Double:
      case MIRType_Float32:
      case MIRType_Int32:
        type = JSTYPE_NUMBER;
        break;
      case MIRType_String:
        type = JSTYPE_STRING;
        break;
      case MIRType_Symbol:
        type = JSTYPE_SYMBOL;
        break;
      case MIRType_Null:
        type = JSTYPE_OBJECT;
        break;
      case MIRType_Undefined:
        type = JSTYPE_VOID;
        break;
      case MIRType_Boolean:
        type = JSTYPE_BOOLEAN;
        break;
      case MIRType_Object:
        if (!inputMaybeCallableOrEmulatesUndefined()) {
            // Object is not callable and does not emulate undefined, so it's
            // safe to fold to "object".
            type = JSTYPE_OBJECT;
            break;
        }
        // FALL THROUGH
      default:
        return this;
    }

    return MConstant::New(alloc, StringValue(TypeName(type, GetJitContext()->runtime->names())));
}

void
MTypeOf::cacheInputMaybeCallableOrEmulatesUndefined(CompilerConstraintList* constraints)
{
    MOZ_ASSERT(inputMaybeCallableOrEmulatesUndefined());

    if (!input()->maybeEmulatesUndefined(constraints) && !MaybeCallable(constraints, input()))
        markInputNotCallableOrEmulatesUndefined();
}

MBitAnd*
MBitAnd::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MBitAnd(left, right);
}

MBitAnd*
MBitAnd::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MBitAnd* ins = new(alloc) MBitAnd(left, right);
    ins->specializeAsInt32();
    return ins;
}

MBitOr*
MBitOr::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MBitOr(left, right);
}

MBitOr*
MBitOr::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MBitOr* ins = new(alloc) MBitOr(left, right);
    ins->specializeAsInt32();
    return ins;
}

MBitXor*
MBitXor::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MBitXor(left, right);
}

MBitXor*
MBitXor::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MBitXor* ins = new(alloc) MBitXor(left, right);
    ins->specializeAsInt32();
    return ins;
}

MLsh*
MLsh::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MLsh(left, right);
}

MLsh*
MLsh::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MLsh* ins = new(alloc) MLsh(left, right);
    ins->specializeAsInt32();
    return ins;
}

MRsh*
MRsh::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MRsh(left, right);
}

MRsh*
MRsh::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MRsh* ins = new(alloc) MRsh(left, right);
    ins->specializeAsInt32();
    return ins;
}

MUrsh*
MUrsh::New(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    return new(alloc) MUrsh(left, right);
}

MUrsh*
MUrsh::NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right)
{
    MUrsh* ins = new(alloc) MUrsh(left, right);
    ins->specializeAsInt32();

    // Since Ion has no UInt32 type, we use Int32 and we have a special
    // exception to the type rules: we can return values in
    // (INT32_MIN,UINT32_MAX] and still claim that we have an Int32 type
    // without bailing out. This is necessary because Ion has no UInt32
    // type and we can't have bailouts in asm.js code.
    ins->bailoutsDisabled_ = true;

    return ins;
}

MResumePoint*
MResumePoint::New(TempAllocator& alloc, MBasicBlock* block, jsbytecode* pc,
                  Mode mode)
{
    MResumePoint* resume = new(alloc) MResumePoint(block, pc, mode);
    if (!resume->init(alloc))
        return nullptr;
    resume->inherit(block);
    return resume;
}

MResumePoint*
MResumePoint::New(TempAllocator& alloc, MBasicBlock* block, MResumePoint* model,
                  const MDefinitionVector& operands)
{
    MResumePoint* resume = new(alloc) MResumePoint(block, model->pc(), model->mode());

    // Allocate the same number of operands as the original resume point, and
    // copy operands from the operands vector and not the not from the current
    // block stack.
    if (!resume->operands_.init(alloc, model->numAllocatedOperands()))
        return nullptr;

    // Copy the operands.
    for (size_t i = 0; i < operands.length(); i++)
        resume->initOperand(i, operands[i]);

    return resume;
}

MResumePoint*
MResumePoint::Copy(TempAllocator& alloc, MResumePoint* src)
{
    MResumePoint* resume = new(alloc) MResumePoint(src->block(), src->pc(),
                                                   src->mode());
    // Copy the operands from the original resume point, and not from the
    // current block stack.
    if (!resume->operands_.init(alloc, src->numAllocatedOperands()))
        return nullptr;

    // Copy the operands.
    for (size_t i = 0; i < resume->numOperands(); i++)
        resume->initOperand(i, src->getOperand(i));
    return resume;
}

MResumePoint::MResumePoint(MBasicBlock* block, jsbytecode* pc, Mode mode)
  : MNode(block),
    pc_(pc),
    instruction_(nullptr),
    mode_(mode)
{
    block->addResumePoint(this);
}

bool
MResumePoint::init(TempAllocator& alloc)
{
    return operands_.init(alloc, block()->stackDepth());
}

MResumePoint*
MResumePoint::caller() const
{
    return block_->callerResumePoint();
}

void
MResumePoint::inherit(MBasicBlock* block)
{
    // FixedList doesn't initialize its elements, so do unchecked inits.
    for (size_t i = 0; i < stackDepth(); i++)
        initOperand(i, block->getSlot(i));
}

void
MResumePoint::addStore(TempAllocator& alloc, MDefinition* store, const MResumePoint* cache)
{
    MOZ_ASSERT(block()->outerResumePoint() != this);
    MOZ_ASSERT_IF(cache, !cache->stores_.empty());

    if (cache && cache->stores_.begin()->operand == store) {
        // If the last resume point had the same side-effect stack, then we can
        // reuse the current side effect without cloning it. This is a simple
        // way to share common context by making a spaghetti stack.
        if (++cache->stores_.begin() == stores_.begin()) {
            stores_.copy(cache->stores_);
            return;
        }
    }

    // Ensure that the store would not be deleted by DCE.
    MOZ_ASSERT(store->isEffectful());

    MStoreToRecover* top = new(alloc) MStoreToRecover(store);
    stores_.push(top);
}

void
MResumePoint::dump(GenericPrinter& out) const
{
    out.printf("resumepoint mode=");

    switch (mode()) {
      case MResumePoint::ResumeAt:
        out.printf("At");
        break;
      case MResumePoint::ResumeAfter:
        out.printf("After");
        break;
      case MResumePoint::Outer:
        out.printf("Outer");
        break;
    }

    if (MResumePoint* c = caller())
        out.printf(" (caller in block%u)", c->block()->id());

    for (size_t i = 0; i < numOperands(); i++) {
        out.printf(" ");
        if (operands_[i].hasProducer())
            getOperand(i)->printName(out);
        else
            out.printf("(null)");
    }
    out.printf("\n");
}

void
MResumePoint::dump() const
{
    Fprinter out(stderr);
    dump(out);
    out.finish();
}

bool
MResumePoint::isObservableOperand(MUse* u) const
{
    return isObservableOperand(indexOf(u));
}

bool
MResumePoint::isObservableOperand(size_t index) const
{
    return block()->info().isObservableSlot(index);
}

bool
MResumePoint::isRecoverableOperand(MUse* u) const
{
    return block()->info().isRecoverableOperand(indexOf(u));
}

MDefinition*
MToInt32::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);

    // Fold this operation if the input operand is constant.
    if (input->isConstant()) {
        Value val = input->toConstant()->value();
        DebugOnly<MacroAssembler::IntConversionInputKind> convert = conversion();
        switch (input->type()) {
          case MIRType_Null:
            MOZ_ASSERT(convert == MacroAssembler::IntConversion_Any);
            return MConstant::New(alloc, Int32Value(0));
          case MIRType_Boolean:
            MOZ_ASSERT(convert == MacroAssembler::IntConversion_Any ||
                       convert == MacroAssembler::IntConversion_NumbersOrBoolsOnly);
            return MConstant::New(alloc, Int32Value(val.toBoolean()));
          case MIRType_Int32:
            return MConstant::New(alloc, Int32Value(val.toInt32()));
          case MIRType_Float32:
          case MIRType_Double:
            int32_t ival;
            // Only the value within the range of Int32 can be substitued as constant.
            if (mozilla::NumberEqualsInt32(val.toNumber(), &ival))
                return MConstant::New(alloc, Int32Value(ival));
          default:
            break;
        }
    }

    if (input->type() == MIRType_Int32)
        return input;
    return this;
}

void
MToInt32::analyzeEdgeCasesBackward()
{
    if (!NeedNegativeZeroCheck(this))
        setCanBeNegativeZero(false);
}

MDefinition*
MTruncateToInt32::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);
    if (input->isBox())
        input = input->getOperand(0);

    if (input->type() == MIRType_Int32)
        return input;

    if (input->type() == MIRType_Double && input->isConstant()) {
        const Value& v = input->constantValue();
        int32_t ret = ToInt32(v.toDouble());
        return MConstant::New(alloc, Int32Value(ret));
    }

    return this;
}

MDefinition*
MToDouble::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);
    if (input->isBox())
        input = input->getOperand(0);

    if (input->type() == MIRType_Double)
        return input;

    if (input->isConstant()) {
        const Value& v = input->toConstant()->value();
        if (v.isNumber()) {
            double out = v.toNumber();
            return MConstant::New(alloc, DoubleValue(out));
        }
    }

    return this;
}

MDefinition*
MToFloat32::foldsTo(TempAllocator& alloc)
{
    MDefinition* input = getOperand(0);
    if (input->isBox())
        input = input->getOperand(0);

    if (input->type() == MIRType_Float32)
        return input;

    // If x is a Float32, Float32(Double(x)) == x
    if (input->isToDouble() && input->toToDouble()->input()->type() == MIRType_Float32)
        return input->toToDouble()->input();

    if (input->isConstant()) {
        const Value& v = input->toConstant()->value();
        if (v.isNumber()) {
            float out = v.toNumber();
            MConstant* c = MConstant::New(alloc, DoubleValue(out));
            c->setResultType(MIRType_Float32);
            return c;
        }
    }
    return this;
}

MDefinition*
MToString::foldsTo(TempAllocator& alloc)
{
    MDefinition* in = input();
    if (in->isBox())
        in = in->getOperand(0);

    if (in->type() == MIRType_String)
        return in;
    return this;
}

MDefinition*
MClampToUint8::foldsTo(TempAllocator& alloc)
{
    if (input()->isConstantValue()) {
        const Value& v = input()->constantValue();
        if (v.isDouble()) {
            int32_t clamped = ClampDoubleToUint8(v.toDouble());
            return MConstant::New(alloc, Int32Value(clamped));
        }
        if (v.isInt32()) {
            int32_t clamped = ClampIntForUint8Array(v.toInt32());
            return MConstant::New(alloc, Int32Value(clamped));
        }
    }
    return this;
}

bool
MCompare::tryFoldEqualOperands(bool* result)
{
    if (lhs() != rhs())
        return false;

    // Intuitively somebody would think that if lhs == rhs,
    // then we can just return true. (Or false for !==)
    // However NaN !== NaN is true! So we spend some time trying
    // to eliminate this case.

    if (jsop() != JSOP_STRICTEQ && jsop() != JSOP_STRICTNE)
        return false;

    if (compareType_ == Compare_Unknown)
        return false;

    MOZ_ASSERT(compareType_ == Compare_Undefined || compareType_ == Compare_Null ||
               compareType_ == Compare_Boolean || compareType_ == Compare_Int32 ||
               compareType_ == Compare_Int32MaybeCoerceBoth ||
               compareType_ == Compare_Int32MaybeCoerceLHS ||
               compareType_ == Compare_Int32MaybeCoerceRHS || compareType_ == Compare_UInt32 ||
               compareType_ == Compare_Double || compareType_ == Compare_DoubleMaybeCoerceLHS ||
               compareType_ == Compare_DoubleMaybeCoerceRHS || compareType_ == Compare_Float32 ||
               compareType_ == Compare_String || compareType_ == Compare_StrictString ||
               compareType_ == Compare_Object || compareType_ == Compare_Bitwise);

    if (isDoubleComparison() || isFloat32Comparison()) {
        if (!operandsAreNeverNaN())
            return false;
    }

    if (DeadIfUnused(lhs()))
        lhs()->setGuardRangeBailouts();

    *result = (jsop() == JSOP_STRICTEQ);
    return true;
}

bool
MCompare::tryFoldTypeOf(bool* result)
{
    if (!lhs()->isTypeOf() && !rhs()->isTypeOf())
        return false;
    if (!lhs()->isConstantValue() && !rhs()->isConstantValue())
        return false;

    MTypeOf* typeOf = lhs()->isTypeOf() ? lhs()->toTypeOf() : rhs()->toTypeOf();
    const Value* constant = lhs()->isConstantValue() ? lhs()->constantVp() : rhs()->constantVp();

    if (!constant->isString())
        return false;

    if (jsop() != JSOP_STRICTEQ && jsop() != JSOP_STRICTNE &&
        jsop() != JSOP_EQ && jsop() != JSOP_NE)
    {
        return false;
    }

    const JSAtomState& names = GetJitContext()->runtime->names();
    if (constant->toString() == TypeName(JSTYPE_VOID, names)) {
        if (!typeOf->input()->mightBeType(MIRType_Undefined) &&
            !typeOf->inputMaybeCallableOrEmulatesUndefined())
        {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_BOOLEAN, names)) {
        if (!typeOf->input()->mightBeType(MIRType_Boolean)) {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_NUMBER, names)) {
        if (!typeOf->input()->mightBeType(MIRType_Int32) &&
            !typeOf->input()->mightBeType(MIRType_Float32) &&
            !typeOf->input()->mightBeType(MIRType_Double))
        {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_STRING, names)) {
        if (!typeOf->input()->mightBeType(MIRType_String)) {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_SYMBOL, names)) {
        if (!typeOf->input()->mightBeType(MIRType_Symbol)) {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_OBJECT, names)) {
        if (!typeOf->input()->mightBeType(MIRType_Object) &&
            !typeOf->input()->mightBeType(MIRType_Null))
        {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    } else if (constant->toString() == TypeName(JSTYPE_FUNCTION, names)) {
        if (!typeOf->inputMaybeCallableOrEmulatesUndefined()) {
            *result = (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE);
            return true;
        }
    }

    return false;
}

bool
MCompare::tryFold(bool* result)
{
    JSOp op = jsop();

    if (tryFoldEqualOperands(result))
        return true;

    if (tryFoldTypeOf(result))
        return true;

    if (compareType_ == Compare_Null || compareType_ == Compare_Undefined) {
        // The LHS is the value we want to test against null or undefined.
        if (op == JSOP_STRICTEQ || op == JSOP_STRICTNE) {
            if (lhs()->type() == inputType()) {
                *result = (op == JSOP_STRICTEQ);
                return true;
            }
            if (!lhs()->mightBeType(inputType())) {
                *result = (op == JSOP_STRICTNE);
                return true;
            }
        } else {
            MOZ_ASSERT(op == JSOP_EQ || op == JSOP_NE);
            if (IsNullOrUndefined(lhs()->type())) {
                *result = (op == JSOP_EQ);
                return true;
            }
            if (!lhs()->mightBeType(MIRType_Null) &&
                !lhs()->mightBeType(MIRType_Undefined) &&
                !(lhs()->mightBeType(MIRType_Object) && operandMightEmulateUndefined()))
            {
                *result = (op == JSOP_NE);
                return true;
            }
        }
        return false;
    }

    if (compareType_ == Compare_Boolean) {
        MOZ_ASSERT(op == JSOP_STRICTEQ || op == JSOP_STRICTNE);
        MOZ_ASSERT(rhs()->type() == MIRType_Boolean);
        MOZ_ASSERT(lhs()->type() != MIRType_Boolean, "Should use Int32 comparison");

        if (!lhs()->mightBeType(MIRType_Boolean)) {
            *result = (op == JSOP_STRICTNE);
            return true;
        }
        return false;
    }

    if (compareType_ == Compare_StrictString) {
        MOZ_ASSERT(op == JSOP_STRICTEQ || op == JSOP_STRICTNE);
        MOZ_ASSERT(rhs()->type() == MIRType_String);
        MOZ_ASSERT(lhs()->type() != MIRType_String, "Should use String comparison");

        if (!lhs()->mightBeType(MIRType_String)) {
            *result = (op == JSOP_STRICTNE);
            return true;
        }
        return false;
    }

    return false;
}

bool
MCompare::evaluateConstantOperands(TempAllocator& alloc, bool* result)
{
    if (type() != MIRType_Boolean && type() != MIRType_Int32)
        return false;

    MDefinition* left = getOperand(0);
    MDefinition* right = getOperand(1);

    if (compareType() == Compare_Double) {
        // Optimize "MCompare MConstant (MToDouble SomethingInInt32Range).
        // In most cases the MToDouble was added, because the constant is
        // a double.
        // e.g. v < 9007199254740991, where v is an int32 is always true.
        if (!lhs()->isConstant() && !rhs()->isConstant())
            return false;

        MDefinition* operand = left->isConstant() ? right : left;
        MConstant* constant = left->isConstant() ? left->toConstant() : right->toConstant();
        MOZ_ASSERT(constant->value().isDouble());
        double cte = constant->value().toDouble();

        if (operand->isToDouble() && operand->getOperand(0)->type() == MIRType_Int32) {
            bool replaced = false;
            switch (jsop_) {
              case JSOP_LT:
                if (cte > INT32_MAX || cte < INT32_MIN) {
                    *result = !((constant == lhs()) ^ (cte < INT32_MIN));
                    replaced = true;
                }
                break;
              case JSOP_LE:
                if (constant == lhs()) {
                    if (cte > INT32_MAX || cte <= INT32_MIN) {
                        *result = (cte <= INT32_MIN);
                        replaced = true;
                    }
                } else {
                    if (cte >= INT32_MAX || cte < INT32_MIN) {
                        *result = (cte >= INT32_MIN);
                        replaced = true;
                    }
                }
                break;
              case JSOP_GT:
                if (cte > INT32_MAX || cte < INT32_MIN) {
                    *result = !((constant == rhs()) ^ (cte < INT32_MIN));
                    replaced = true;
                }
                break;
              case JSOP_GE:
                if (constant == lhs()) {
                    if (cte >= INT32_MAX || cte < INT32_MIN) {
                        *result = (cte >= INT32_MAX);
                        replaced = true;
                    }
                } else {
                    if (cte > INT32_MAX || cte <= INT32_MIN) {
                        *result = (cte <= INT32_MIN);
                        replaced = true;
                    }
                }
                break;
              case JSOP_STRICTEQ: // Fall through.
              case JSOP_EQ:
                if (cte > INT32_MAX || cte < INT32_MIN) {
                    *result = false;
                    replaced = true;
                }
                break;
              case JSOP_STRICTNE: // Fall through.
              case JSOP_NE:
                if (cte > INT32_MAX || cte < INT32_MIN) {
                    *result = true;
                    replaced = true;
                }
                break;
              default:
                MOZ_CRASH("Unexpected op.");
            }
            if (replaced) {
                MLimitedTruncate* limit =
                    MLimitedTruncate::New(alloc, operand->getOperand(0), MDefinition::NoTruncate);
                limit->setGuardUnchecked();
                block()->insertBefore(this, limit);
                return true;
            }
        }
    }

    if (!left->isConstant() || !right->isConstant())
        return false;

    Value lhs = left->toConstant()->value();
    Value rhs = right->toConstant()->value();

    // Fold away some String equality comparisons.
    if (lhs.isString() && rhs.isString()) {
        int32_t comp = 0; // Default to equal.
        if (left != right)
            comp = CompareAtoms(&lhs.toString()->asAtom(), &rhs.toString()->asAtom());

        switch (jsop_) {
          case JSOP_LT:
            *result = (comp < 0);
            break;
          case JSOP_LE:
            *result = (comp <= 0);
            break;
          case JSOP_GT:
            *result = (comp > 0);
            break;
          case JSOP_GE:
            *result = (comp >= 0);
            break;
          case JSOP_STRICTEQ: // Fall through.
          case JSOP_EQ:
            *result = (comp == 0);
            break;
          case JSOP_STRICTNE: // Fall through.
          case JSOP_NE:
            *result = (comp != 0);
            break;
          default:
            MOZ_CRASH("Unexpected op.");
        }

        return true;
    }

    if (compareType_ == Compare_UInt32) {
        uint32_t lhsUint = uint32_t(lhs.toInt32());
        uint32_t rhsUint = uint32_t(rhs.toInt32());

        switch (jsop_) {
          case JSOP_LT:
            *result = (lhsUint < rhsUint);
            break;
          case JSOP_LE:
            *result = (lhsUint <= rhsUint);
            break;
          case JSOP_GT:
            *result = (lhsUint > rhsUint);
            break;
          case JSOP_GE:
            *result = (lhsUint >= rhsUint);
            break;
          case JSOP_STRICTEQ: // Fall through.
          case JSOP_EQ:
            *result = (lhsUint == rhsUint);
            break;
          case JSOP_STRICTNE: // Fall through.
          case JSOP_NE:
            *result = (lhsUint != rhsUint);
            break;
          default:
            MOZ_CRASH("Unexpected op.");
        }

        return true;
    }

    if (!lhs.isNumber() || !rhs.isNumber())
        return false;

    switch (jsop_) {
      case JSOP_LT:
        *result = (lhs.toNumber() < rhs.toNumber());
        break;
      case JSOP_LE:
        *result = (lhs.toNumber() <= rhs.toNumber());
        break;
      case JSOP_GT:
        *result = (lhs.toNumber() > rhs.toNumber());
        break;
      case JSOP_GE:
        *result = (lhs.toNumber() >= rhs.toNumber());
        break;
      case JSOP_STRICTEQ: // Fall through.
      case JSOP_EQ:
        *result = (lhs.toNumber() == rhs.toNumber());
        break;
      case JSOP_STRICTNE: // Fall through.
      case JSOP_NE:
        *result = (lhs.toNumber() != rhs.toNumber());
        break;
      default:
        return false;
    }

    return true;
}

MDefinition*
MCompare::foldsTo(TempAllocator& alloc)
{
    bool result;

    if (tryFold(&result) || evaluateConstantOperands(alloc, &result)) {
        if (type() == MIRType_Int32)
            return MConstant::New(alloc, Int32Value(result));

        MOZ_ASSERT(type() == MIRType_Boolean);
        return MConstant::New(alloc, BooleanValue(result));
    }

    return this;
}

void
MCompare::trySpecializeFloat32(TempAllocator& alloc)
{
    MDefinition* lhs = getOperand(0);
    MDefinition* rhs = getOperand(1);

    if (lhs->canProduceFloat32() && rhs->canProduceFloat32() && compareType_ == Compare_Double) {
        compareType_ = Compare_Float32;
    } else {
        if (lhs->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, lhs, this);
        if (rhs->type() == MIRType_Float32)
            ConvertDefinitionToDouble<1>(alloc, rhs, this);
    }
}

void
MCompare::filtersUndefinedOrNull(bool trueBranch, MDefinition** subject, bool* filtersUndefined,
                                 bool* filtersNull)
{
    *filtersNull = *filtersUndefined = false;
    *subject = nullptr;

    if (compareType() != Compare_Undefined && compareType() != Compare_Null)
        return;

    MOZ_ASSERT(jsop() == JSOP_STRICTNE || jsop() == JSOP_NE ||
               jsop() == JSOP_STRICTEQ || jsop() == JSOP_EQ);

    // JSOP_*NE only removes undefined/null from if/true branch
    if (!trueBranch && (jsop() == JSOP_STRICTNE || jsop() == JSOP_NE))
        return;

    // JSOP_*EQ only removes undefined/null from else/false branch
    if (trueBranch && (jsop() == JSOP_STRICTEQ || jsop() == JSOP_EQ))
        return;

    if (jsop() == JSOP_STRICTEQ || jsop() == JSOP_STRICTNE) {
        *filtersUndefined = compareType() == Compare_Undefined;
        *filtersNull = compareType() == Compare_Null;
    } else {
        *filtersUndefined = *filtersNull = true;
    }

    *subject = lhs();
}

void
MNot::cacheOperandMightEmulateUndefined(CompilerConstraintList* constraints)
{
    MOZ_ASSERT(operandMightEmulateUndefined());

    if (!getOperand(0)->maybeEmulatesUndefined(constraints))
        markNoOperandEmulatesUndefined();
}

MDefinition*
MNot::foldsTo(TempAllocator& alloc)
{
    // Fold if the input is constant
    if (input()->isConstantValue() && !input()->constantValue().isMagic()) {
        bool result = input()->constantToBoolean();
        if (type() == MIRType_Int32)
            return MConstant::New(alloc, Int32Value(!result));

        // ToBoolean can't cause side effects, so this is safe.
        return MConstant::New(alloc, BooleanValue(!result));
    }

    // If the operand of the Not is itself a Not, they cancel out. But we can't
    // always convert Not(Not(x)) to x because that may loose the conversion to
    // boolean. We can simplify Not(Not(Not(x))) to Not(x) though.
    MDefinition* op = getOperand(0);
    if (op->isNot()) {
        MDefinition* opop = op->getOperand(0);
        if (opop->isNot())
            return opop;
    }

    // NOT of an undefined or null value is always true
    if (input()->type() == MIRType_Undefined || input()->type() == MIRType_Null)
        return MConstant::New(alloc, BooleanValue(true));

    // NOT of a symbol is always false.
    if (input()->type() == MIRType_Symbol)
        return MConstant::New(alloc, BooleanValue(false));

    // NOT of an object that can't emulate undefined is always false.
    if (input()->type() == MIRType_Object && !operandMightEmulateUndefined())
        return MConstant::New(alloc, BooleanValue(false));

    return this;
}

void
MNot::trySpecializeFloat32(TempAllocator& alloc)
{
    MDefinition* in = input();
    if (!in->canProduceFloat32() && in->type() == MIRType_Float32)
        ConvertDefinitionToDouble<0>(alloc, in, this);
}

void
MBeta::printOpcode(GenericPrinter& out) const
{
    MDefinition::printOpcode(out);

    out.printf(" ");
    comparison_->dump(out);
}

bool
MNewObject::shouldUseVM() const
{
    if (JSObject* obj = templateObject())
        return obj->is<PlainObject>() && obj->as<PlainObject>().hasDynamicSlots();
    return true;
}

bool
MCreateThisWithTemplate::canRecoverOnBailout() const
{
    MOZ_ASSERT(templateObject()->is<PlainObject>() || templateObject()->is<UnboxedPlainObject>());
    MOZ_ASSERT_IF(templateObject()->is<PlainObject>(),
                  !templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
    return true;
}

bool
OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject)
{
    const UnboxedLayout& layout =
        templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();

    // 0 is used as an error code.
    const UnboxedLayout::PropertyVector& properties = layout.properties();
    MOZ_ASSERT(properties.length() < 255);

    // Allocate an array of indexes, where the top of each field correspond to
    // the index of the operand in the MObjectState instance.
    if (!map.init(alloc, layout.size()))
        return false;

    // Reset all indexes to 0, which is an error code.
    for (size_t i = 0; i < map.length(); i++)
        map[i] = 0;

    // Map the property offsets to the indexes of MObjectState operands.
    uint8_t index = 1;
    for (size_t i = 0; i < properties.length(); i++, index++)
        map[properties[i].offset] = index;

    return true;
}

MObjectState::MObjectState(MObjectState* state)
  : numSlots_(state->numSlots_),
    numFixedSlots_(state->numFixedSlots_),
    operandIndex_(state->operandIndex_)
{
    // This instruction is only used as a summary for bailout paths.
    setResultType(MIRType_Object);
    setRecoveredOnBailout();
}

MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandIndex)
{
    // This instruction is only used as a summary for bailout paths.
    setResultType(MIRType_Object);
    setRecoveredOnBailout();

    if (templateObject->is<NativeObject>()) {
        NativeObject* nativeObject = &templateObject->as<NativeObject>();
        numSlots_ = nativeObject->slotSpan();
        numFixedSlots_ = nativeObject->numFixedSlots();
    } else {
        const UnboxedLayout& layout =
            templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
        // Same as UnboxedLayout::makeNativeGroup
        numSlots_ = layout.properties().length();
        numFixedSlots_ = gc::GetGCKindSlots(layout.getAllocKind());
    }

    operandIndex_ = operandIndex;
}

JSObject*
MObjectState::templateObjectOf(MDefinition* obj)
{
    if (obj->isNewObject())
        return obj->toNewObject()->templateObject();
    else if (obj->isCreateThisWithTemplate())
        return obj->toCreateThisWithTemplate()->templateObject();
    else
        return obj->toNewCallObject()->templateObject();

    return nullptr;
}

bool
MObjectState::init(TempAllocator& alloc, MDefinition* obj)
{
    if (!MVariadicInstruction::init(alloc, numSlots() + 1))
        return false;
    // +1, for the Object.
    initOperand(0, obj);
    return true;
}

MObjectState*
MObjectState::New(TempAllocator& alloc, MDefinition* obj, MDefinition* undefinedVal)
{
    JSObject* templateObject = templateObjectOf(obj);
    MOZ_ASSERT(templateObject, "Unexpected object creation.");

    OperandIndexMap* operandIndex = nullptr;
    if (templateObject->is<UnboxedPlainObject>()) {
        operandIndex = new(alloc) OperandIndexMap;
        if (!operandIndex || !operandIndex->init(alloc, templateObject))
            return nullptr;
    }

    MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex);
    if (!res || !res->init(alloc, obj))
        return nullptr;
    for (size_t i = 0; i < res->numSlots(); i++)
        res->initSlot(i, undefinedVal);
    return res;
}

MObjectState*
MObjectState::Copy(TempAllocator& alloc, MObjectState* state)
{
    MObjectState* res = new(alloc) MObjectState(state);
    if (!res || !res->init(alloc, state->object()))
        return nullptr;
    for (size_t i = 0; i < res->numSlots(); i++)
        res->initSlot(i, state->getSlot(i));
    return res;
}

MArrayState::MArrayState(MDefinition* arr)
{
    // This instruction is only used as a summary for bailout paths.
    setResultType(MIRType_Object);
    setRecoveredOnBailout();
    numElements_ = arr->toNewArray()->length();
}

bool
MArrayState::init(TempAllocator& alloc, MDefinition* obj, MDefinition* len)
{
    if (!MVariadicInstruction::init(alloc, numElements() + 2))
        return false;
    // +1, for the Array object.
    initOperand(0, obj);
    // +1, for the length value of the array.
    initOperand(1, len);
    return true;
}

MArrayState*
MArrayState::New(TempAllocator& alloc, MDefinition* arr, MDefinition* undefinedVal,
                 MDefinition* initLength)
{
    MArrayState* res = new(alloc) MArrayState(arr);
    if (!res || !res->init(alloc, arr, initLength))
        return nullptr;
    for (size_t i = 0; i < res->numElements(); i++)
        res->initElement(i, undefinedVal);
    return res;
}

MArrayState*
MArrayState::Copy(TempAllocator& alloc, MArrayState* state)
{
    MDefinition* arr = state->array();
    MDefinition* len = state->initializedLength();
    MArrayState* res = new(alloc) MArrayState(arr);
    if (!res || !res->init(alloc, arr, len))
        return nullptr;
    for (size_t i = 0; i < res->numElements(); i++)
        res->initElement(i, state->getElement(i));
    return res;
}

MNewArray::MNewArray(CompilerConstraintList* constraints, uint32_t length, MConstant* templateConst,
                     gc::InitialHeap initialHeap, jsbytecode* pc)
  : MUnaryInstruction(templateConst),
    length_(length),
    initialHeap_(initialHeap),
    convertDoubleElements_(false),
    pc_(pc)
{
    setResultType(MIRType_Object);
    if (templateObject()) {
        if (TemporaryTypeSet* types = MakeSingletonTypeSet(constraints, templateObject())) {
            setResultTypeSet(types);
            if (types->convertDoubleElements(constraints) == TemporaryTypeSet::AlwaysConvertToDoubles)
                convertDoubleElements_ = true;
        }
    }
}

bool
MNewArray::shouldUseVM() const
{
    if (!templateObject())
        return true;

    if (templateObject()->is<UnboxedArrayObject>()) {
        MOZ_ASSERT(templateObject()->as<UnboxedArrayObject>().capacity() >= length());
        return !templateObject()->as<UnboxedArrayObject>().hasInlineElements();
    }

    MOZ_ASSERT(length() <= NativeObject::MAX_DENSE_ELEMENTS_COUNT);

    size_t arraySlots =
        gc::GetGCKindSlots(templateObject()->asTenured().getAllocKind()) - ObjectElements::VALUES_PER_HEADER;

    return length() > arraySlots;
}

bool
MLoadFixedSlot::mightAlias(const MDefinition* store) const
{
    if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
        return false;
    return true;
}

bool
MLoadFixedSlotAndUnbox::mightAlias(const MDefinition* store) const
{
    if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
        return false;
    return true;
}

MDefinition*
MLoadFixedSlot::foldsTo(TempAllocator& alloc)
{
    if (!dependency() || !dependency()->isStoreFixedSlot())
        return this;

    MStoreFixedSlot* store = dependency()->toStoreFixedSlot();
    if (!store->block()->dominates(block()))
        return this;

    if (store->object() != object())
        return this;

    if (store->slot() != slot())
        return this;

    return foldsToStoredValue(alloc, store->value());
}

bool
MAsmJSLoadHeap::mightAlias(const MDefinition* def) const
{
    if (def->isAsmJSStoreHeap()) {
        const MAsmJSStoreHeap* store = def->toAsmJSStoreHeap();
        if (store->accessType() != accessType())
            return true;
        if (!ptr()->isConstant() || !store->ptr()->isConstant())
            return true;
        const MConstant* otherPtr = store->ptr()->toConstant();
        return ptr()->toConstant()->value() == otherPtr->value();
    }
    return true;
}

bool
MAsmJSLoadHeap::congruentTo(const MDefinition* ins) const
{
    if (!ins->isAsmJSLoadHeap())
        return false;
    const MAsmJSLoadHeap* load = ins->toAsmJSLoadHeap();
    return load->accessType() == accessType() && congruentIfOperandsEqual(load);
}

bool
MAsmJSLoadGlobalVar::mightAlias(const MDefinition* def) const
{
    if (def->isAsmJSStoreGlobalVar()) {
        const MAsmJSStoreGlobalVar* store = def->toAsmJSStoreGlobalVar();
        return store->globalDataOffset() == globalDataOffset_;
    }
    return true;
}

HashNumber
MAsmJSLoadGlobalVar::valueHash() const
{
    HashNumber hash = MDefinition::valueHash();
    hash = addU32ToHash(hash, globalDataOffset_);
    return hash;
}

bool
MAsmJSLoadGlobalVar::congruentTo(const MDefinition* ins) const
{
    if (ins->isAsmJSLoadGlobalVar()) {
        const MAsmJSLoadGlobalVar* load = ins->toAsmJSLoadGlobalVar();
        return globalDataOffset_ == load->globalDataOffset_;
    }
    return false;
}

MDefinition*
MAsmJSLoadGlobalVar::foldsTo(TempAllocator& alloc)
{
    if (!dependency() || !dependency()->isAsmJSStoreGlobalVar())
        return this;

    MAsmJSStoreGlobalVar* store = dependency()->toAsmJSStoreGlobalVar();
    if (!store->block()->dominates(block()))
        return this;

    if (store->globalDataOffset() != globalDataOffset())
        return this;

    if (store->value()->type() != type())
        return this;

    return store->value();
}

HashNumber
MAsmJSLoadFuncPtr::valueHash() const
{
    HashNumber hash = MDefinition::valueHash();
    hash = addU32ToHash(hash, globalDataOffset_);
    return hash;
}

bool
MAsmJSLoadFuncPtr::congruentTo(const MDefinition* ins) const
{
    if (ins->isAsmJSLoadFuncPtr()) {
        const MAsmJSLoadFuncPtr* load = ins->toAsmJSLoadFuncPtr();
        return globalDataOffset_ == load->globalDataOffset_;
    }
    return false;
}

HashNumber
MAsmJSLoadFFIFunc::valueHash() const
{
    HashNumber hash = MDefinition::valueHash();
    hash = addU32ToHash(hash, globalDataOffset_);
    return hash;
}

bool
MAsmJSLoadFFIFunc::congruentTo(const MDefinition* ins) const
{
    if (ins->isAsmJSLoadFFIFunc()) {
        const MAsmJSLoadFFIFunc* load = ins->toAsmJSLoadFFIFunc();
        return globalDataOffset_ == load->globalDataOffset_;
    }
    return false;
}

bool
MLoadSlot::mightAlias(const MDefinition* store) const
{
    if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot())
        return false;
    return true;
}

HashNumber
MLoadSlot::valueHash() const
{
    HashNumber hash = MDefinition::valueHash();
    hash = addU32ToHash(hash, slot_);
    return hash;
}

MDefinition*
MLoadSlot::foldsTo(TempAllocator& alloc)
{
    if (!dependency() || !dependency()->isStoreSlot())
        return this;

    MStoreSlot* store = dependency()->toStoreSlot();
    if (!store->block()->dominates(block()))
        return this;

    if (store->slots() != slots())
        return this;

    return foldsToStoredValue(alloc, store->value());
}

MDefinition*
MFunctionEnvironment::foldsTo(TempAllocator& alloc)
{
    if (!input()->isLambda())
        return this;

    return input()->toLambda()->scopeChain();
}

MDefinition*
MLoadElement::foldsTo(TempAllocator& alloc)
{
    if (!dependency() || !dependency()->isStoreElement())
        return this;

    MStoreElement* store = dependency()->toStoreElement();
    if (!store->block()->dominates(block()))
        return this;

    if (store->elements() != elements())
        return this;

    if (store->index() != index())
        return this;

    return foldsToStoredValue(alloc, store->value());
}

// Gets the MDefinition* representing the source/target object's storage.
// Usually this is just an MElements*, but sometimes there are layers
// of indirection or inlining, which are handled elsewhere.
static inline const MElements*
MaybeUnwrapElements(const MDefinition* elementsOrObj)
{
    // Sometimes there is a level of indirection for conversion.
    if (elementsOrObj->isConvertElementsToDoubles())
        return MaybeUnwrapElements(elementsOrObj->toConvertElementsToDoubles()->elements());

    // For inline elements, the object may be passed directly, for example as MUnbox.
    if (elementsOrObj->type() == MIRType_Object)
        return nullptr;

    // MTypedArrayElements and MTypedObjectElements aren't handled.
    if (!elementsOrObj->isElements())
        return nullptr;

    return elementsOrObj->toElements();
}

static inline const MDefinition*
GetElementsObject(const MDefinition* elementsOrObj)
{
    if (elementsOrObj->type() == MIRType_Object)
        return elementsOrObj;

    const MDefinition* elements = MaybeUnwrapElements(elementsOrObj);
    if (elements)
        return elements->toElements()->input();

    return nullptr;
}

// Gets the MDefinition of the target Object for the given store operation.
static inline const MDefinition*
GetStoreObject(const MDefinition* store)
{
    switch (store->op()) {
      case MDefinition::Op_StoreElement:
        return GetElementsObject(store->toStoreElement()->elements());

      case MDefinition::Op_StoreElementHole:
        return store->toStoreElementHole()->object();

      case MDefinition::Op_StoreUnboxedObjectOrNull:
        return GetElementsObject(store->toStoreUnboxedObjectOrNull()->elements());

      case MDefinition::Op_StoreUnboxedString:
        return GetElementsObject(store->toStoreUnboxedString()->elements());

      case MDefinition::Op_StoreUnboxedScalar:
        return GetElementsObject(store->toStoreUnboxedScalar()->elements());

      default:
        return nullptr;
    }
}

// Implements mightAlias() logic common to all load operations.
static bool
GenericLoadMightAlias(const MDefinition* elementsOrObj, const MDefinition* store)
{
    const MElements* elements = MaybeUnwrapElements(elementsOrObj);
    if (elements)
        return elements->mightAlias(store);

    // Unhandled Elements kind.
    if (elementsOrObj->type() != MIRType_Object)
        return true;

    // Inline storage for objects.
    // Refer to IsValidElementsType().
    const MDefinition* object = elementsOrObj;
    MOZ_ASSERT(object->type() == MIRType_Object);
    if (!object->resultTypeSet())
        return true;

    const MDefinition* storeObject = GetStoreObject(store);
    if (!storeObject)
        return true;
    if (!storeObject->resultTypeSet())
        return true;

    return object->resultTypeSet()->objectsIntersect(storeObject->resultTypeSet());
}

bool
MElements::mightAlias(const MDefinition* store) const
{
    if (!input()->resultTypeSet())
        return true;

    const MDefinition* storeObj = GetStoreObject(store);
    if (!storeObj)
        return true;
    if (!storeObj->resultTypeSet())
        return true;

    return input()->resultTypeSet()->objectsIntersect(storeObj->resultTypeSet());
}

bool
MLoadElement::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(elements(), store);
}

bool
MInitializedLength::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(elements(), store);
}

bool
MLoadUnboxedObjectOrNull::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(elements(), store);
}

bool
MLoadUnboxedString::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(elements(), store);
}

bool
MLoadUnboxedScalar::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(elements(), store);
}

bool
MUnboxedArrayInitializedLength::mightAlias(const MDefinition* store) const
{
    return GenericLoadMightAlias(object(), store);
}

bool
MGuardReceiverPolymorphic::congruentTo(const MDefinition* ins) const
{
    if (!ins->isGuardReceiverPolymorphic())
        return false;

    const MGuardReceiverPolymorphic* other = ins->toGuardReceiverPolymorphic();

    if (numReceivers() != other->numReceivers())
        return false;
    for (size_t i = 0; i < numReceivers(); i++) {
        if (receiver(i) != other->receiver(i))
            return false;
    }

    return congruentIfOperandsEqual(ins);
}

void
InlinePropertyTable::trimTo(const ObjectVector& targets, const BoolVector& choiceSet)
{
    for (size_t i = 0; i < targets.length(); i++) {
        // If the target was inlined, don't erase the entry.
        if (choiceSet[i])
            continue;

        JSFunction* target = &targets[i]->as<JSFunction>();

        // Eliminate all entries containing the vetoed function from the map.
        size_t j = 0;
        while (j < numEntries()) {
            if (entries_[j]->func == target)
                entries_.erase(&entries_[j]);
            else
                j++;
        }
    }
}

void
InlinePropertyTable::trimToTargets(const ObjectVector& targets)
{
    JitSpew(JitSpew_Inlining, "Got inlineable property cache with %d cases",
            (int)numEntries());

    size_t i = 0;
    while (i < numEntries()) {
        bool foundFunc = false;
        for (size_t j = 0; j < targets.length(); j++) {
            if (entries_[i]->func == targets[j]) {
                foundFunc = true;
                break;
            }
        }
        if (!foundFunc)
            entries_.erase(&(entries_[i]));
        else
            i++;
    }

    JitSpew(JitSpew_Inlining, "%d inlineable cases left after trimming to %d targets",
            (int)numEntries(), (int)targets.length());
}

bool
InlinePropertyTable::hasFunction(JSFunction* func) const
{
    for (size_t i = 0; i < numEntries(); i++) {
        if (entries_[i]->func == func)
            return true;
    }
    return false;
}

bool
InlinePropertyTable::hasObjectGroup(ObjectGroup* group) const
{
    for (size_t i = 0; i < numEntries(); i++) {
        if (entries_[i]->group == group)
            return true;
    }
    return false;
}

TemporaryTypeSet*
InlinePropertyTable::buildTypeSetForFunction(JSFunction* func) const
{
    LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();
    TemporaryTypeSet* types = alloc->new_<TemporaryTypeSet>();
    if (!types)
        return nullptr;
    for (size_t i = 0; i < numEntries(); i++) {
        if (entries_[i]->func == func)
            types->addType(TypeSet::ObjectType(entries_[i]->group), alloc);
    }
    return types;
}

SharedMem<void*>
MLoadTypedArrayElementStatic::base() const
{
    return AnyTypedArrayViewData(someTypedArray_);
}

size_t
MLoadTypedArrayElementStatic::length() const
{
    return AnyTypedArrayByteLength(someTypedArray_);
}

bool
MLoadTypedArrayElementStatic::congruentTo(const MDefinition* ins) const
{
    if (!ins->isLoadTypedArrayElementStatic())
        return false;
    const MLoadTypedArrayElementStatic* other = ins->toLoadTypedArrayElementStatic();
    if (offset() != other->offset())
        return false;
    if (needsBoundsCheck() != other->needsBoundsCheck())
        return false;
    if (accessType() != other->accessType())
        return false;
    if (base() != other->base())
        return false;
    return congruentIfOperandsEqual(other);
}

SharedMem<void*>
MStoreTypedArrayElementStatic::base() const
{
    return AnyTypedArrayViewData(someTypedArray_);
}

bool
MGetPropertyCache::allowDoubleResult() const
{
    if (!resultTypeSet())
        return true;

    return resultTypeSet()->hasType(TypeSet::DoubleType());
}

size_t
MStoreTypedArrayElementStatic::length() const
{
    return AnyTypedArrayByteLength(someTypedArray_);
}

bool
MGetPropertyPolymorphic::mightAlias(const MDefinition* store) const
{
    // Allow hoisting this instruction if the store does not write to a
    // slot read by this instruction.

    if (!store->isStoreFixedSlot() && !store->isStoreSlot())
        return true;

    for (size_t i = 0; i < numReceivers(); i++) {
        const Shape* shape = this->shape(i);
        if (!shape)
            continue;
        if (shape->slot() < shape->numFixedSlots()) {
            // Fixed slot.
            uint32_t slot = shape->slot();
            if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot)
                continue;
            if (store->isStoreSlot())
                continue;
        } else {
            // Dynamic slot.
            uint32_t slot = shape->slot() - shape->numFixedSlots();
            if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot)
                continue;
            if (store->isStoreFixedSlot())
                continue;
        }

        return true;
    }

    return false;
}

void
MGetPropertyCache::setBlock(MBasicBlock* block)
{
    MDefinition::setBlock(block);
    // Track where we started.
    if (!location_.pc) {
        location_.pc = block->trackedPc();
        location_.script = block->info().script();
    }
}

bool
MGetPropertyCache::updateForReplacement(MDefinition* ins)
{
    MGetPropertyCache* other = ins->toGetPropertyCache();
    location_.append(&other->location_);
    return true;
}

MDefinition*
MAsmJSUnsignedToDouble::foldsTo(TempAllocator& alloc)
{
    if (input()->isConstantValue()) {
        const Value& v = input()->constantValue();
        if (v.isInt32())
            return MConstant::New(alloc, DoubleValue(uint32_t(v.toInt32())));
    }

    return this;
}

MDefinition*
MAsmJSUnsignedToFloat32::foldsTo(TempAllocator& alloc)
{
    if (input()->isConstantValue()) {
        const Value& v = input()->constantValue();
        if (v.isInt32()) {
            double dval = double(uint32_t(v.toInt32()));
            if (IsFloat32Representable(dval))
                return MConstant::NewAsmJS(alloc, JS::Float32Value(float(dval)), MIRType_Float32);
        }
    }

    return this;
}

MAsmJSCall*
MAsmJSCall::New(TempAllocator& alloc, const wasm::CallSiteDesc& desc, Callee callee,
                const Args& args, MIRType resultType, size_t spIncrement)
{
    MAsmJSCall* call = new(alloc) MAsmJSCall(desc, callee, spIncrement);
    call->setResultType(resultType);

    if (!call->argRegs_.init(alloc, args.length()))
        return nullptr;
    for (size_t i = 0; i < call->argRegs_.length(); i++)
        call->argRegs_[i] = args[i].reg;

    if (!call->init(alloc, call->argRegs_.length() + (callee.which() == Callee::Dynamic ? 1 : 0)))
        return nullptr;
    // FixedList doesn't initialize its elements, so do an unchecked init.
    for (size_t i = 0; i < call->argRegs_.length(); i++)
        call->initOperand(i, args[i].def);
    if (callee.which() == Callee::Dynamic)
        call->initOperand(call->argRegs_.length(), callee.dynamic());

    return call;
}

void
MSqrt::trySpecializeFloat32(TempAllocator& alloc) {
    if (!input()->canProduceFloat32() || !CheckUsesAreFloat32Consumers(this)) {
        if (input()->type() == MIRType_Float32)
            ConvertDefinitionToDouble<0>(alloc, input(), this);
        return;
    }

    setResultType(MIRType_Float32);
    specialization_ = MIRType_Float32;
}

MDefinition*
MClz::foldsTo(TempAllocator& alloc)
{
    if (num()->isConstantValue()) {
        int32_t n = num()->constantValue().toInt32();
        if (n == 0)
            return MConstant::New(alloc, Int32Value(32));
        return MConstant::New(alloc, Int32Value(mozilla::CountLeadingZeroes32(n)));
    }

    return this;
}

MDefinition*
MBoundsCheck::foldsTo(TempAllocator& alloc)
{
    if (index()->isConstantValue() && length()->isConstantValue()) {
       uint32_t len = length()->constantValue().toInt32();
       uint32_t idx = index()->constantValue().toInt32();
       if (idx + uint32_t(minimum()) < len && idx + uint32_t(maximum()) < len)
           return index();
    }

    return this;
}

MDefinition*
MTableSwitch::foldsTo(TempAllocator& alloc)
{
    MDefinition* op = getOperand(0);

    // If we only have one successor, convert to a plain goto to the only
    // successor. TableSwitch indices are numeric; other types will always go to
    // the only successor.
    if (numSuccessors() == 1 || (op->type() != MIRType_Value && !IsNumberType(op->type())))
        return MGoto::New(alloc, getDefault());

    return this;
}

MDefinition*
MArrayJoin::foldsTo(TempAllocator& alloc)
{
    // :TODO: Enable this optimization after fixing Bug 977966 test cases.
    return this;

    MDefinition* arr = array();

    if (!arr->isStringSplit())
        return this;

    this->setRecoveredOnBailout();
    if (arr->hasLiveDefUses()) {
        this->setNotRecoveredOnBailout();
        return this;
    }

    // We're replacing foo.split(bar).join(baz) by
    // foo.replace(bar, baz).  MStringSplit could be recovered by
    // a bailout.  As we are removing its last use, and its result
    // could be captured by a resume point, this MStringSplit will
    // be executed on the bailout path.
    MDefinition* string = arr->toStringSplit()->string();
    MDefinition* pattern = arr->toStringSplit()->separator();
    MDefinition* replacement = sep();

    setNotRecoveredOnBailout();
    return MStringReplace::New(alloc, string, pattern, replacement);
}

MConvertUnboxedObjectToNative*
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
{
    MConvertUnboxedObjectToNative* res = new(alloc) MConvertUnboxedObjectToNative(obj, group);

    ObjectGroup* nativeGroup = group->unboxedLayout().nativeGroup();

    // Make a new type set for the result of this instruction which replaces
    // the input group with the native group we will convert it to.
    TemporaryTypeSet* types = obj->resultTypeSet();
    if (types && !types->unknownObject()) {
        TemporaryTypeSet* newTypes = types->cloneWithoutObjects(alloc.lifoAlloc());
        if (newTypes) {
            for (size_t i = 0; i < types->getObjectCount(); i++) {
                TypeSet::ObjectKey* key = types->getObject(i);
                if (!key)
                    continue;
                if (key->unknownProperties() || !key->isGroup() || key->group() != group)
                    newTypes->addType(TypeSet::ObjectType(key), alloc.lifoAlloc());
                else
                    newTypes->addType(TypeSet::ObjectType(nativeGroup), alloc.lifoAlloc());
            }
            res->setResultTypeSet(newTypes);
        }
    }

    return res;
}

bool
jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
                                MDefinition* obj, MDefinition* id)
{
    if (obj->mightBeType(MIRType_String))
        return false;

    if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
        return false;

    TemporaryTypeSet* types = obj->resultTypeSet();
    if (!types)
        return false;

    // Typed arrays are native classes but do not have dense elements.
    const Class* clasp = types->getKnownClass(constraints);
    return clasp && clasp->isNative() && !IsAnyTypedArrayClass(clasp);
}

JSValueType
jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* obj,
                             MDefinition* id)
{
    if (obj->mightBeType(MIRType_String))
        return JSVAL_TYPE_MAGIC;

    if (id && id->type() != MIRType_Int32 && id->type() != MIRType_Double)
        return JSVAL_TYPE_MAGIC;

    TemporaryTypeSet* types = obj->resultTypeSet();
    if (!types || types->unknownObject())
        return JSVAL_TYPE_MAGIC;

    JSValueType elementType = JSVAL_TYPE_MAGIC;
    for (unsigned i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key)
            continue;

        if (key->unknownProperties() || !key->isGroup())
            return JSVAL_TYPE_MAGIC;

        if (key->clasp() != &UnboxedArrayObject::class_)
            return JSVAL_TYPE_MAGIC;

        const UnboxedLayout &layout = key->group()->unboxedLayout();

        if (layout.nativeGroup())
            return JSVAL_TYPE_MAGIC;

        if (elementType == layout.elementType() || elementType == JSVAL_TYPE_MAGIC)
            elementType = layout.elementType();
        else
            return JSVAL_TYPE_MAGIC;

        key->watchStateChangeForUnboxedConvertedToNative(constraints);
    }

    return elementType;
}

bool
jit::ElementAccessIsAnyTypedArray(CompilerConstraintList* constraints,
                                  MDefinition* obj, MDefinition* id,
                                  Scalar::Type* arrayType)
{
    if (obj->mightBeType(MIRType_String))
        return false;

    if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
        return false;

    TemporaryTypeSet* types = obj->resultTypeSet();
    if (!types)
        return false;

    *arrayType = types->getTypedArrayType(constraints);
    return *arrayType != Scalar::MaxTypedArrayViewType;
}

bool
jit::ElementAccessIsPacked(CompilerConstraintList* constraints, MDefinition* obj)
{
    TemporaryTypeSet* types = obj->resultTypeSet();
    return types && !types->hasObjectFlags(constraints, OBJECT_FLAG_NON_PACKED);
}

bool
jit::ElementAccessMightBeCopyOnWrite(CompilerConstraintList* constraints, MDefinition* obj)
{
    TemporaryTypeSet* types = obj->resultTypeSet();
    return !types || types->hasObjectFlags(constraints, OBJECT_FLAG_COPY_ON_WRITE);
}

bool
jit::ElementAccessHasExtraIndexedProperty(IonBuilder* builder, MDefinition* obj)
{
    TemporaryTypeSet* types = obj->resultTypeSet();

    if (!types || types->hasObjectFlags(builder->constraints(), OBJECT_FLAG_LENGTH_OVERFLOW))
        return true;

    return TypeCanHaveExtraIndexedProperties(builder, types);
}

MIRType
jit::DenseNativeElementType(CompilerConstraintList* constraints, MDefinition* obj)
{
    TemporaryTypeSet* types = obj->resultTypeSet();
    MIRType elementType = MIRType_None;
    unsigned count = types->getObjectCount();

    for (unsigned i = 0; i < count; i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key)
            continue;

        if (key->unknownProperties())
            return MIRType_None;

        HeapTypeSetKey elementTypes = key->property(JSID_VOID);

        MIRType type = elementTypes.knownMIRType(constraints);
        if (type == MIRType_None)
            return MIRType_None;

        if (elementType == MIRType_None)
            elementType = type;
        else if (elementType != type)
            return MIRType_None;
    }

    return elementType;
}

static BarrierKind
PropertyReadNeedsTypeBarrier(CompilerConstraintList* constraints,
                             TypeSet::ObjectKey* key, PropertyName* name,
                             TypeSet* observed)
{
    // If the object being read from has types for the property which haven't
    // been observed at this access site, the read could produce a new type and
    // a barrier is needed. Note that this only covers reads from properties
    // which are accounted for by type information, i.e. native data properties
    // and elements.
    //
    // We also need a barrier if the object is a proxy, because then all bets
    // are off, just as if it has unknown properties.
    if (key->unknownProperties() || observed->empty() ||
        key->clasp()->isProxy())
    {
        return BarrierKind::TypeSet;
    }

    jsid id = name ? NameToId(name) : JSID_VOID;
    HeapTypeSetKey property = key->property(id);
    if (property.maybeTypes()) {
        if (!TypeSetIncludes(observed, MIRType_Value, property.maybeTypes())) {
            // If all possible objects have been observed, we don't have to
            // guard on the specific object types.
            if (property.maybeTypes()->objectsAreSubset(observed)) {
                property.freeze(constraints);
                return BarrierKind::TypeTagOnly;
            }
            return BarrierKind::TypeSet;
        }
    }

    // Type information for global objects is not required to reflect the
    // initial 'undefined' value for properties, in particular global
    // variables declared with 'var'. Until the property is assigned a value
    // other than undefined, a barrier is required.
    if (key->isSingleton()) {
        JSObject* obj = key->singleton();
        if (name && CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
            (!property.maybeTypes() || property.maybeTypes()->empty()))
        {
            return BarrierKind::TypeSet;
        }
    }

    property.freeze(constraints);
    return BarrierKind::NoBarrier;
}

static bool
ObjectSubsumes(TypeSet::ObjectKey* first, TypeSet::ObjectKey* second)
{
    if (first->isSingleton() ||
        second->isSingleton() ||
        first->clasp() != second->clasp() ||
        first->unknownProperties() ||
        second->unknownProperties())
    {
        return false;
    }

    if (first->clasp() == &ArrayObject::class_) {
        HeapTypeSetKey firstElements = first->property(JSID_VOID);
        HeapTypeSetKey secondElements = second->property(JSID_VOID);

        return firstElements.maybeTypes() && secondElements.maybeTypes() &&
               firstElements.maybeTypes()->equals(secondElements.maybeTypes());
    }

    if (first->clasp() == &UnboxedArrayObject::class_) {
        return first->group()->unboxedLayout().elementType() ==
               second->group()->unboxedLayout().elementType();
    }

    return false;
}

BarrierKind
jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
                                  CompilerConstraintList* constraints,
                                  TypeSet::ObjectKey* key, PropertyName* name,
                                  TemporaryTypeSet* observed, bool updateObserved)
{
    if (!updateObserved)
        return PropertyReadNeedsTypeBarrier(constraints, key, name, observed);

    // If this access has never executed, try to add types to the observed set
    // according to any property which exists on the object or its prototype.
    if (observed->empty() && name) {
        JSObject* obj;
        if (key->isSingleton())
            obj = key->singleton();
        else
            obj = key->proto().isLazy() ? nullptr : key->proto().toObjectOrNull();

        while (obj) {
            if (!obj->getClass()->isNative())
                break;

            TypeSet::ObjectKey* key = TypeSet::ObjectKey::get(obj);
            if (propertycx)
                key->ensureTrackedProperty(propertycx, NameToId(name));

            if (!key->unknownProperties()) {
                HeapTypeSetKey property = key->property(NameToId(name));
                if (property.maybeTypes()) {
                    TypeSet::TypeList types;
                    if (!property.maybeTypes()->enumerateTypes(&types))
                        break;
                    if (types.length()) {
                        // Note: the return value here is ignored.
                        observed->addType(types[0], GetJitContext()->temp->lifoAlloc());
                        break;
                    }
                }
            }

            obj = obj->getProto();
        }
    }

    // If any objects which could be observed are similar to ones that have
    // already been observed, add them to the observed type set.
    if (!key->unknownProperties()) {
        HeapTypeSetKey property = key->property(name ? NameToId(name) : JSID_VOID);

        if (property.maybeTypes() && !property.maybeTypes()->unknownObject()) {
            for (size_t i = 0; i < property.maybeTypes()->getObjectCount(); i++) {
                TypeSet::ObjectKey* key = property.maybeTypes()->getObject(i);
                if (!key || observed->unknownObject())
                    continue;

                for (size_t j = 0; j < observed->getObjectCount(); j++) {
                    TypeSet::ObjectKey* observedKey = observed->getObject(j);
                    if (observedKey && ObjectSubsumes(observedKey, key)) {
                        // Note: the return value here is ignored.
                        observed->addType(TypeSet::ObjectType(key),
                                          GetJitContext()->temp->lifoAlloc());
                        break;
                    }
                }
            }
        }
    }

    return PropertyReadNeedsTypeBarrier(constraints, key, name, observed);
}

BarrierKind
jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
                                  CompilerConstraintList* constraints,
                                  MDefinition* obj, PropertyName* name,
                                  TemporaryTypeSet* observed)
{
    if (observed->unknown())
        return BarrierKind::NoBarrier;

    TypeSet* types = obj->resultTypeSet();
    if (!types || types->unknownObject())
        return BarrierKind::TypeSet;

    BarrierKind res = BarrierKind::NoBarrier;

    bool updateObserved = types->getObjectCount() == 1;
    for (size_t i = 0; i < types->getObjectCount(); i++) {
        if (TypeSet::ObjectKey* key = types->getObject(i)) {
            BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, key, name,
                                                            observed, updateObserved);
            if (kind == BarrierKind::TypeSet)
                return BarrierKind::TypeSet;

            if (kind == BarrierKind::TypeTagOnly) {
                MOZ_ASSERT(res == BarrierKind::NoBarrier || res == BarrierKind::TypeTagOnly);
                res = BarrierKind::TypeTagOnly;
            } else {
                MOZ_ASSERT(kind == BarrierKind::NoBarrier);
            }
        }
    }

    return res;
}

BarrierKind
jit::PropertyReadOnPrototypeNeedsTypeBarrier(IonBuilder* builder,
                                             MDefinition* obj, PropertyName* name,
                                             TemporaryTypeSet* observed)
{
    if (observed->unknown())
        return BarrierKind::NoBarrier;

    TypeSet* types = obj->resultTypeSet();
    if (!types || types->unknownObject())
        return BarrierKind::TypeSet;

    BarrierKind res = BarrierKind::NoBarrier;

    for (size_t i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key)
            continue;
        while (true) {
            if (!key->hasStableClassAndProto(builder->constraints()))
                return BarrierKind::TypeSet;
            if (!key->proto().isObject())
                break;
            JSObject* proto = builder->checkNurseryObject(key->proto().toObject());
            key = TypeSet::ObjectKey::get(proto);
            BarrierKind kind = PropertyReadNeedsTypeBarrier(builder->constraints(),
                                                            key, name, observed);
            if (kind == BarrierKind::TypeSet)
                return BarrierKind::TypeSet;

            if (kind == BarrierKind::TypeTagOnly) {
                MOZ_ASSERT(res == BarrierKind::NoBarrier || res == BarrierKind::TypeTagOnly);
                res = BarrierKind::TypeTagOnly;
            } else {
                MOZ_ASSERT(kind == BarrierKind::NoBarrier);
            }
        }
    }

    return res;
}

bool
jit::PropertyReadIsIdempotent(CompilerConstraintList* constraints,
                              MDefinition* obj, PropertyName* name)
{
    // Determine if reading a property from obj is likely to be idempotent.

    TypeSet* types = obj->resultTypeSet();
    if (!types || types->unknownObject())
        return false;

    for (size_t i = 0; i < types->getObjectCount(); i++) {
        if (TypeSet::ObjectKey* key = types->getObject(i)) {
            if (key->unknownProperties())
                return false;

            // Check if the property has been reconfigured or is a getter.
            HeapTypeSetKey property = key->property(NameToId(name));
            if (property.nonData(constraints))
                return false;
        }
    }

    return true;
}

void
jit::AddObjectsForPropertyRead(MDefinition* obj, PropertyName* name,
                               TemporaryTypeSet* observed)
{
    // Add objects to observed which *could* be observed by reading name from obj,
    // to hopefully avoid unnecessary type barriers and code invalidations.

    LifoAlloc* alloc = GetJitContext()->temp->lifoAlloc();

    TemporaryTypeSet* types = obj->resultTypeSet();
    if (!types || types->unknownObject()) {
        observed->addType(TypeSet::AnyObjectType(), alloc);
        return;
    }

    for (size_t i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key)
            continue;

        if (key->unknownProperties()) {
            observed->addType(TypeSet::AnyObjectType(), alloc);
            return;
        }

        jsid id = name ? NameToId(name) : JSID_VOID;
        HeapTypeSetKey property = key->property(id);
        HeapTypeSet* types = property.maybeTypes();
        if (!types)
            continue;

        if (types->unknownObject()) {
            observed->addType(TypeSet::AnyObjectType(), alloc);
            return;
        }

        for (size_t i = 0; i < types->getObjectCount(); i++) {
            if (TypeSet::ObjectKey* key = types->getObject(i))
                observed->addType(TypeSet::ObjectType(key), alloc);
        }
    }
}

static bool
PrototypeHasIndexedProperty(IonBuilder* builder, JSObject* obj)
{
    do {
        TypeSet::ObjectKey* key = TypeSet::ObjectKey::get(builder->checkNurseryObject(obj));
        if (ClassCanHaveExtraProperties(key->clasp()))
            return true;
        if (key->unknownProperties())
            return true;
        HeapTypeSetKey index = key->property(JSID_VOID);
        if (index.nonData(builder->constraints()) || index.isOwnProperty(builder->constraints()))
            return true;
        obj = obj->getProto();
    } while (obj);

    return false;
}

// Whether Array.prototype, or an object on its proto chain, has an indexed property.
bool
jit::ArrayPrototypeHasIndexedProperty(IonBuilder* builder, JSScript* script)
{
    if (JSObject* proto = script->global().maybeGetArrayPrototype())
        return PrototypeHasIndexedProperty(builder, proto);
    return true;
}

// Whether obj or any of its prototypes have an indexed property.
bool
jit::TypeCanHaveExtraIndexedProperties(IonBuilder* builder, TemporaryTypeSet* types)
{
    const Class* clasp = types->getKnownClass(builder->constraints());

    // Note: typed arrays have indexed properties not accounted for by type
    // information, though these are all in bounds and will be accounted for
    // by JIT paths.
    if (!clasp || (ClassCanHaveExtraProperties(clasp) && !IsAnyTypedArrayClass(clasp)))
        return true;

    if (types->hasObjectFlags(builder->constraints(), OBJECT_FLAG_SPARSE_INDEXES))
        return true;

    JSObject* proto;
    if (!types->getCommonPrototype(builder->constraints(), &proto))
        return true;

    if (!proto)
        return false;

    return PrototypeHasIndexedProperty(builder, proto);
}

static bool
PropertyTypeIncludes(TempAllocator& alloc, HeapTypeSetKey property,
                     MDefinition* value, MIRType implicitType)
{
    // If implicitType is not MIRType_None, it is an additional type which the
    // property implicitly includes. In this case, make a new type set which
    // explicitly contains the type.
    TypeSet* types = property.maybeTypes();
    if (implicitType != MIRType_None) {
        TypeSet::Type newType = TypeSet::PrimitiveType(ValueTypeFromMIRType(implicitType));
        if (types)
            types = types->clone(alloc.lifoAlloc());
        else
            types = alloc.lifoAlloc()->new_<TemporaryTypeSet>();
        types->addType(newType, alloc.lifoAlloc());
    }

    return TypeSetIncludes(types, value->type(), value->resultTypeSet());
}

static bool
TryAddTypeBarrierForWrite(TempAllocator& alloc, CompilerConstraintList* constraints,
                          MBasicBlock* current, TemporaryTypeSet* objTypes,
                          PropertyName* name, MDefinition** pvalue, MIRType implicitType)
{
    // Return whether pvalue was modified to include a type barrier ensuring
    // that writing the value to objTypes/id will not require changing type
    // information.

    // All objects in the set must have the same types for name. Otherwise, we
    // could bail out without subsequently triggering a type change that
    // invalidates the compiled code.
    Maybe<HeapTypeSetKey> aggregateProperty;

    for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = objTypes->getObject(i);
        if (!key)
            continue;

        if (key->unknownProperties())
            return false;

        jsid id = name ? NameToId(name) : JSID_VOID;
        HeapTypeSetKey property = key->property(id);
        if (!property.maybeTypes() || property.couldBeConstant(constraints))
            return false;

        if (PropertyTypeIncludes(alloc, property, *pvalue, implicitType))
            return false;

        // This freeze is not required for correctness, but ensures that we
        // will recompile if the property types change and the barrier can
        // potentially be removed.
        property.freeze(constraints);

        if (!aggregateProperty) {
            aggregateProperty.emplace(property);
        } else {
            if (!aggregateProperty->maybeTypes()->equals(property.maybeTypes()))
                return false;
        }
    }

    MOZ_ASSERT(aggregateProperty);

    MIRType propertyType = aggregateProperty->knownMIRType(constraints);
    switch (propertyType) {
      case MIRType_Boolean:
      case MIRType_Int32:
      case MIRType_Double:
      case MIRType_String:
      case MIRType_Symbol: {
        // The property is a particular primitive type, guard by unboxing the
        // value before the write.
        if (!(*pvalue)->mightBeType(propertyType)) {
            // The value's type does not match the property type. Just do a VM
            // call as it will always trigger invalidation of the compiled code.
            MOZ_ASSERT_IF((*pvalue)->type() != MIRType_Value, (*pvalue)->type() != propertyType);
            return false;
        }
        MInstruction* ins = MUnbox::New(alloc, *pvalue, propertyType, MUnbox::Fallible);
        current->add(ins);
        *pvalue = ins;
        return true;
      }
      default:;
    }

    if ((*pvalue)->type() != MIRType_Value)
        return false;

    TemporaryTypeSet* types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
    if (!types)
        return false;

    // If all possible objects can be stored without a barrier, we don't have to
    // guard on the specific object types.
    BarrierKind kind = BarrierKind::TypeSet;
    if ((*pvalue)->resultTypeSet() && (*pvalue)->resultTypeSet()->objectsAreSubset(types))
        kind = BarrierKind::TypeTagOnly;

    MInstruction* ins = MMonitorTypes::New(alloc, *pvalue, types, kind);
    current->add(ins);
    return true;
}

static MInstruction*
AddGroupGuard(TempAllocator& alloc, MBasicBlock* current, MDefinition* obj,
              TypeSet::ObjectKey* key, bool bailOnEquality)
{
    MInstruction* guard;

    if (key->isGroup()) {
        guard = MGuardObjectGroup::New(alloc, obj, key->group(), bailOnEquality,
                                       Bailout_ObjectIdentityOrTypeGuard);
    } else {
        MConstant* singletonConst = MConstant::NewConstraintlessObject(alloc, key->singleton());
        current->add(singletonConst);
        guard = MGuardObjectIdentity::New(alloc, obj, singletonConst, bailOnEquality);
    }

    current->add(guard);

    // For now, never move object group / identity guards.
    guard->setNotMovable();

    return guard;
}

// Whether value can be written to property without changing type information.
bool
jit::CanWriteProperty(TempAllocator& alloc, CompilerConstraintList* constraints,
                      HeapTypeSetKey property, MDefinition* value,
                      MIRType implicitType /* = MIRType_None */)
{
    if (property.couldBeConstant(constraints))
        return false;
    return PropertyTypeIncludes(alloc, property, value, implicitType);
}

bool
jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList* constraints,
                                   MBasicBlock* current, MDefinition** pobj,
                                   PropertyName* name, MDefinition** pvalue,
                                   bool canModify, MIRType implicitType)
{
    // If any value being written is not reflected in the type information for
    // objects which obj could represent, a type barrier is needed when writing
    // the value. As for propertyReadNeedsTypeBarrier, this only applies for
    // properties that are accounted for by type information, i.e. normal data
    // properties and elements.

    TemporaryTypeSet* types = (*pobj)->resultTypeSet();
    if (!types || types->unknownObject())
        return true;

    // If all of the objects being written to have property types which already
    // reflect the value, no barrier at all is needed. Additionally, if all
    // objects being written to have the same types for the property, and those
    // types do *not* reflect the value, add a type barrier for the value.

    bool success = true;
    for (size_t i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key || key->unknownProperties())
            continue;

        // TI doesn't track TypedArray indexes and should never insert a type
        // barrier for them.
        if (!name && IsAnyTypedArrayClass(key->clasp()))
            continue;

        jsid id = name ? NameToId(name) : JSID_VOID;
        HeapTypeSetKey property = key->property(id);
        if (!CanWriteProperty(alloc, constraints, property, *pvalue, implicitType)) {
            // Either pobj or pvalue needs to be modified to filter out the
            // types which the value could have but are not in the property,
            // or a VM call is required. A VM call is always required if pobj
            // and pvalue cannot be modified.
            if (!canModify)
                return true;
            success = TryAddTypeBarrierForWrite(alloc, constraints, current, types, name, pvalue,
                                                implicitType);
            break;
        }
    }

    // Perform additional filtering to make sure that any unboxed property
    // being written can accommodate the value.
    for (size_t i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (key && key->isGroup() && key->group()->maybeUnboxedLayout()) {
            const UnboxedLayout& layout = key->group()->unboxedLayout();
            if (name) {
                const UnboxedLayout::Property* property = layout.lookup(name);
                if (property && !CanStoreUnboxedType(alloc, property->type, *pvalue))
                    return true;
            } else {
                if (layout.isArray() && !CanStoreUnboxedType(alloc, layout.elementType(), *pvalue))
                    return true;
            }
        }
    }

    if (success)
        return false;

    // If all of the objects except one have property types which reflect the
    // value, and the remaining object has no types at all for the property,
    // add a guard that the object does not have that remaining object's type.

    if (types->getObjectCount() <= 1)
        return true;

    TypeSet::ObjectKey* excluded = nullptr;
    for (size_t i = 0; i < types->getObjectCount(); i++) {
        TypeSet::ObjectKey* key = types->getObject(i);
        if (!key || key->unknownProperties())
            continue;
        if (!name && IsAnyTypedArrayClass(key->clasp()))
            continue;

        jsid id = name ? NameToId(name) : JSID_VOID;
        HeapTypeSetKey property = key->property(id);
        if (CanWriteProperty(alloc, constraints, property, *pvalue, implicitType))
            continue;

        if ((property.maybeTypes() && !property.maybeTypes()->empty()) || excluded)
            return true;
        excluded = key;
    }

    MOZ_ASSERT(excluded);

    // If the excluded object is a group with an unboxed layout, make sure it
    // does not have a corresponding native group. Objects with the native
    // group might appear even though they are not in the type set.
    if (excluded->isGroup()) {
        if (UnboxedLayout* layout = excluded->group()->maybeUnboxedLayout()) {
            if (layout->nativeGroup())
                return true;
            excluded->watchStateChangeForUnboxedConvertedToNative(constraints);
        }
    }

    *pobj = AddGroupGuard(alloc, current, *pobj, excluded, /* bailOnEquality = */ true);
    return false;
}
