// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
#if defined(TARGET_ARCH_DBC)

#include "vm/compiler/backend/il.h"

#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/backend/range_analysis.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"

#define __ compiler->assembler()->

namespace dart {

DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(int, optimization_counter_threshold);

// List of instructions that are still unimplemented by DBC backend.
#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M)                                  \
  M(BinaryInt32Op)                                                             \
  M(BinaryUint32Op)                                                            \
  M(CheckCondition)                                                            \
  M(DoubleToInteger)                                                           \
  M(ExtractNthOutput)                                                          \
  M(GuardFieldClass)                                                           \
  M(GuardFieldLength)                                                          \
  M(GuardFieldType)                                                            \
  M(IfThenElse)                                                                \
  M(Int32ToDouble)                                                             \
  M(LoadCodeUnits)                                                             \
  M(ShiftUint32Op)                                                             \
  M(SpeculativeShiftUint32Op)                                                  \
  M(TruncDivMod)                                                               \
  M(UnaryUint32Op)                                                             \
  M(IntConverter)

// List of instructions that are not used by DBC.
// Things we aren't planning to implement for DBC:
// - Unboxed SIMD,
// - Unboxed Mint,
// - Optimized RegExps,
// - Precompilation.
#define FOR_EACH_UNREACHABLE_INSTRUCTION(M)                                    \
  M(CaseInsensitiveCompare)                                                    \
  M(GenericCheckBound)                                                         \
  M(IndirectGoto)                                                              \
  M(Int64ToDouble)                                                             \
  M(BinaryInt64Op)                                                             \
  M(ShiftInt64Op)                                                              \
  M(SpeculativeShiftInt64Op)                                                   \
  M(UnaryInt64Op)                                                              \
  M(CheckedSmiOp)                                                              \
  M(CheckedSmiComparison)                                                      \
  M(SimdOp)

// Location summaries actually are not used by the unoptimizing DBC compiler
// because we don't allocate any registers.
static LocationSummary* CreateLocationSummary(
    Zone* zone,
    intptr_t num_inputs,
    Location output = Location::NoLocation(),
    LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall,
    intptr_t num_temps = 0) {
  LocationSummary* locs =
      new (zone) LocationSummary(zone, num_inputs, num_temps, contains_call);
  for (intptr_t i = 0; i < num_inputs; i++) {
    locs->set_in(i, (contains_call == LocationSummary::kNoCall)
                        ? Location::RequiresRegister()
                        : Location::RegisterLocation(i));
  }
  for (intptr_t i = 0; i < num_temps; i++) {
    locs->set_temp(i, Location::RequiresRegister());
  }
  if (!output.IsInvalid()) {
    // For instructions that call we default to returning result in R0.
    locs->set_out(0, output);
  }
  return locs;
}

#define DEFINE_MAKE_LOCATION_SUMMARY(Name, ...)                                \
  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
      const {                                                                  \
    return CreateLocationSummary(zone, __VA_ARGS__);                           \
  }

#define EMIT_NATIVE_CODE(Name, ...)                                            \
  DEFINE_MAKE_LOCATION_SUMMARY(Name, __VA_ARGS__);                             \
  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler)

#define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                       \
  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
      const {                                                                  \
    if (!opt) UNIMPLEMENTED();                                                 \
    return NULL;                                                               \
  }

#define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                         \
  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
      const {                                                                  \
    UNREACHABLE();                                                             \
    return NULL;                                                               \
  }

#define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)                            \
  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
    UNIMPLEMENTED();                                                           \
  }

#define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)                              \
  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
    UNREACHABLE();                                                             \
  }

#define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name)                            \
  void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) {         \
    UNIMPLEMENTED();                                                           \
  }                                                                            \
  Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*,                \
                                            BranchLabels) {                    \
    UNIMPLEMENTED();                                                           \
    return NEXT_IS_TRUE;                                                       \
  }

#define DEFINE_UNIMPLEMENTED(Name)                                             \
  DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                             \
  DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)

FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED)

#undef DEFINE_UNIMPLEMENTED

#define DEFINE_UNREACHABLE(Name)                                               \
  DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                               \
  DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)

FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE)

#undef DEFINE_UNREACHABLE

// Only used in AOT compilation.
DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(CheckedSmiComparison)

EMIT_NATIVE_CODE(InstanceOf,
                 3,
                 Location::SameAsFirstInput(),
                 LocationSummary::kCall) {
  SubtypeTestCache& test_cache = SubtypeTestCache::Handle();
  if (!type().IsVoidType() && type().IsInstantiated()) {
    test_cache = SubtypeTestCache::New();
  }

  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());  // Value.
    __ Push(locs()->in(1).reg());  // Instantiator type arguments.
    __ Push(locs()->in(2).reg());  // Function type arguments.
  }

  __ PushConstant(type());
  __ PushConstant(test_cache);
  __ InstanceOf();
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable,
                             3,
                             Location::SameAsFirstInput(),
                             LocationSummary::kCall);

DEFINE_MAKE_LOCATION_SUMMARY(AssertSubtype,
                             2,
                             Location::NoLocation(),
                             LocationSummary::kCall);

EMIT_NATIVE_CODE(AssertBoolean,
                 1,
                 Location::SameAsFirstInput(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
  }
  __ AssertBoolean(0);
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
  if (compiler->is_optimizing()) {
    __ Drop1();
  }
}

EMIT_NATIVE_CODE(PolymorphicInstanceCall,
                 0,
                 Location::RegisterLocation(0),
                 LocationSummary::kCall) {
  const Array& arguments_descriptor =
      Array::Handle(instance_call()->GetArgumentsDescriptor());
  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);

  // Push the target onto the stack.
  const intptr_t length = targets_.length();
  if (!Utils::IsUint(8, length)) {
    Unsupported(compiler);
    UNREACHABLE();
  }
  bool using_ranges = false;
  for (intptr_t i = 0; i < length; i++) {
    if (!targets_[i].IsSingleCid()) {
      using_ranges = true;
      break;
    }
  }

  if (using_ranges) {
    __ PushPolymorphicInstanceCallByRange(
        instance_call()->ArgumentCountWithoutTypeArgs(), length);
  } else {
    __ PushPolymorphicInstanceCall(
        instance_call()->ArgumentCountWithoutTypeArgs(), length);
  }
  for (intptr_t i = 0; i < length; i++) {
    const Function& target = *targets_.TargetAt(i)->target;

    __ Nop(compiler->ToEmbeddableCid(targets_[i].cid_start, this));
    if (using_ranges) {
      __ Nop(compiler->ToEmbeddableCid(1 + targets_[i].Extent(), this));
    }
    __ Nop(__ AddConstant(target));
  }
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail,
                      0);

  // Call the function.
  __ StaticCall(instance_call()->ArgumentCount(), argdesc_kidx);
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 instance_call()->token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
  __ PopLocal(locs()->out(0).reg());
}

EMIT_NATIVE_CODE(LoadIndexedUnsafe, 1, Location::RegisterLocation(0)) {
  ASSERT(base_reg() == FPREG);

  ASSERT(offset_ % kWordSize == 0);
  const intptr_t slot_offset = offset_ / kWordSize;
  ASSERT(Utils::IsInt(8, slot_offset));

  if (compiler->is_optimizing()) {
    const Register index = locs()->in(0).reg();
    const Register result = locs()->out(0).reg();
    __ LoadFpRelativeSlotOpt(result, index, slot_offset);
  } else {
    __ LoadFpRelativeSlot(slot_offset);
  }
}

EMIT_NATIVE_CODE(StoreIndexedUnsafe, 2, Location::RegisterLocation(0)) {
  ASSERT(base_reg() == FPREG);

  ASSERT(offset_ % kWordSize == 0);
  const intptr_t slot_offset = offset_ / kWordSize;
  ASSERT(Utils::IsInt(8, slot_offset));

  if (compiler->is_optimizing()) {
    const Register index = locs()->in(kIndexPos).reg();
    const Register value = locs()->in(kValuePos).reg();
    __ StoreFpRelativeSlotOpt(value, index, slot_offset);
  } else {
    __ StoreFpRelativeSlot(slot_offset);
  }
}

EMIT_NATIVE_CODE(TailCall,
                 1,
                 Location::NoLocation(),
                 LocationSummary::kNoCall,
                 1) {
  if (compiler->is_optimizing()) {
    const Register arg_desc = locs()->in(0).reg();
    const Register temp = locs()->temp(0).reg();
    __ LoadConstant(temp, code());
    __ TailCallOpt(arg_desc, temp);
  } else {
    __ PushConstant(code());
    __ TailCall();
  }
}

EMIT_NATIVE_CODE(Stop, 0) {
  __ Stop(message());
}

EMIT_NATIVE_CODE(CheckStackOverflow,
                 0,
                 Location::NoLocation(),
                 LocationSummary::kCall) {
  if (compiler->ForceSlowPathForStackOverflow()) {
    __ CheckStackAlwaysExit();
  } else {
    __ CheckStack();
  }
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
}

EMIT_NATIVE_CODE(PushArgument, 1) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
  }
}

EMIT_NATIVE_CODE(LoadLocal, 0) {
  ASSERT(!compiler->is_optimizing());
  const intptr_t slot_index =
      compiler::target::frame_layout.FrameSlotForVariable(&local());
  __ Push(LocalVarIndex(0, slot_index));
}

EMIT_NATIVE_CODE(StoreLocal, 0) {
  ASSERT(!compiler->is_optimizing());
  const intptr_t slot_index =
      compiler::target::frame_layout.FrameSlotForVariable(&local());
  if (HasTemp()) {
    __ StoreLocal(LocalVarIndex(0, slot_index));
  } else {
    __ PopLocal(LocalVarIndex(0, slot_index));
  }
}

EMIT_NATIVE_CODE(LoadClassId, 1, Location::RequiresRegister()) {
  if (compiler->is_optimizing()) {
    __ LoadClassId(locs()->out(0).reg(), locs()->in(0).reg());
  } else {
    __ LoadClassIdTOS();
  }
}

EMIT_NATIVE_CODE(Constant, 0, Location::RequiresRegister()) {
  if (compiler->is_optimizing()) {
    if (locs()->out(0).IsRegister()) {
      __ LoadConstant(locs()->out(0).reg(), value());
    }
  } else {
    __ PushConstant(value());
  }
}

EMIT_NATIVE_CODE(UnboxedConstant, 0, Location::RequiresRegister()) {
  // The register allocator drops constant definitions that have no uses.
  if (locs()->out(0).IsInvalid()) {
    return;
  }
  if (representation_ != kUnboxedDouble) {
    Unsupported(compiler);
    UNREACHABLE();
  }
  const Register result = locs()->out(0).reg();
  if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
    __ BitXor(result, result, result);
  } else {
    __ LoadConstant(result, value());
    __ UnboxDouble(result, result);
  }
}

EMIT_NATIVE_CODE(Return, 1) {
  if (compiler->is_optimizing()) {
    __ Return(locs()->in(0).reg());
  } else {
    __ ReturnTOS();
  }
}

LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(

    Zone* zone,
    bool opt) const {
  const intptr_t kNumInputs = 1;
  const intptr_t kNumTemps = 1;
  LocationSummary* locs = new (zone)
      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
  for (intptr_t i = 0; i < kNumInputs; i++) {
    locs->set_in(i, Location::RequiresRegister());
  }
  for (intptr_t i = 0; i < kNumTemps; i++) {
    locs->set_temp(i, Location::RequiresRegister());
  }
  return locs;
}

void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
  if (compiler->is_optimizing()) {
    __ LoadConstant(locs()->temp(0).reg(),
                    Field::ZoneHandle(field().Original()));
    __ StoreField(locs()->temp(0).reg(),
                  Field::static_value_offset() / kWordSize,
                  locs()->in(0).reg());
  } else {
    const intptr_t kidx = __ AddConstant(field());
    __ StoreStaticTOS(kidx);
  }
}

EMIT_NATIVE_CODE(LoadStaticField, 1, Location::RequiresRegister()) {
  if (compiler->is_optimizing()) {
    __ LoadField(locs()->out(0).reg(), locs()->in(0).reg(),
                 Field::static_value_offset() / kWordSize);
  } else {
    const intptr_t kidx = __ AddConstant(StaticField());
    __ PushStatic(kidx);
  }
}

EMIT_NATIVE_CODE(InitStaticField,
                 1,
                 Location::NoLocation(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
    __ InitStaticTOS();
  } else {
    __ InitStaticTOS();
  }
  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
}

EMIT_NATIVE_CODE(ClosureCall,
                 1,
                 Location::RegisterLocation(0),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
  }

  const Array& arguments_descriptor =
      Array::ZoneHandle(GetArgumentsDescriptor());
  const intptr_t argdesc_kidx =
      compiler->assembler()->AddConstant(arguments_descriptor);
  __ StaticCall(ArgumentCount(), argdesc_kidx);
  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
                                  Condition true_condition,
                                  BranchLabels labels) {
  if (true_condition == NEXT_IS_TRUE) {
    // NEXT_IS_TRUE indicates that the preceeding test expects the true case
    // to be in the subsequent instruction, which it skips if the test fails.
    __ Jump(labels.true_label);
    if (labels.fall_through != labels.false_label) {
      // The preceeding Jump instruction will be skipped if the test fails.
      // If we aren't falling through to the false case, then we have to do
      // a Jump to it here.
      __ Jump(labels.false_label);
    }
  } else {
    ASSERT(true_condition == NEXT_IS_FALSE);
    // NEXT_IS_FALSE indicates that the preceeding test has been flipped and
    // expects the false case to be in the subsequent instruction, which it
    // skips if the test succeeds.
    __ Jump(labels.false_label);
    if (labels.fall_through != labels.true_label) {
      // The preceeding Jump instruction will be skipped if the test succeeds.
      // If we aren't falling through to the true case, then we have to do
      // a Jump to it here.
      __ Jump(labels.true_label);
    }
  }
}

Condition StrictCompareInstr::GetNextInstructionCondition(
    FlowGraphCompiler* compiler,
    BranchLabels labels) {
  return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE
                                                     : NEXT_IS_FALSE;
}

Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                                 BranchLabels labels) {
  ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT));

  Token::Kind comparison;
  Condition condition;
  if (labels.fall_through == labels.false_label) {
    condition = NEXT_IS_TRUE;
    comparison = kind();
  } else {
    // Flip comparison to save a jump.
    condition = NEXT_IS_FALSE;
    comparison =
        (kind() == Token::kEQ_STRICT) ? Token::kNE_STRICT : Token::kEQ_STRICT;
  }

  if (!compiler->is_optimizing()) {
    const SimulatorBytecode::Opcode eq_op =
        needs_number_check() ? SimulatorBytecode::kIfEqStrictNumTOS
                             : SimulatorBytecode::kIfEqStrictTOS;
    const SimulatorBytecode::Opcode ne_op =
        needs_number_check() ? SimulatorBytecode::kIfNeStrictNumTOS
                             : SimulatorBytecode::kIfNeStrictTOS;
    __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op);
  } else {
    const SimulatorBytecode::Opcode eq_op =
        needs_number_check() ? SimulatorBytecode::kIfEqStrictNum
                             : SimulatorBytecode::kIfEqStrict;
    const SimulatorBytecode::Opcode ne_op =
        needs_number_check() ? SimulatorBytecode::kIfNeStrictNum
                             : SimulatorBytecode::kIfNeStrict;
    __ Emit(SimulatorBytecode::Encode(
        (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, locs()->in(0).reg(),
        locs()->in(1).reg()));
  }

  if (needs_number_check() && token_pos().IsReal()) {
    compiler->RecordSafepoint(locs());
    compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id_,
                                   token_pos());
  }

  return condition;
}

DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare,
                             2,
                             Location::RequiresRegister(),
                             needs_number_check() ? LocationSummary::kCall
                                                  : LocationSummary::kNoCall)

void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                     BranchInstr* branch) {
  BranchLabels labels = compiler->CreateBranchLabels(branch);
  Condition true_condition = EmitComparisonCode(compiler, labels);
  if (true_condition != INVALID_CONDITION) {
    EmitBranchOnCondition(compiler, true_condition, labels);
  }
}

void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
  Label is_true, is_false;
  BranchLabels labels = {&is_true, &is_false, &is_false};
  Condition true_condition =
      this->GetNextInstructionCondition(compiler, labels);
  if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() ||
      is_true.IsLinked() || is_false.IsLinked()) {
    Condition actual_condition = EmitComparisonCode(compiler, labels);
    ASSERT(actual_condition == true_condition);
    if (true_condition != INVALID_CONDITION) {
      EmitBranchOnCondition(compiler, true_condition, labels);
    }
    Label done;
    __ Bind(&is_false);
    __ PushConstant(Bool::False());
    __ Jump(&done);
    __ Bind(&is_true);
    __ PushConstant(Bool::True());
    __ Bind(&done);
  } else {
    const Register result = this->locs()->out(0).reg();
    bool next_is_true = true_condition == NEXT_IS_TRUE;
    __ LoadConstant(result, Bool::Get(!next_is_true));
    Condition actual_condition = EmitComparisonCode(compiler, labels);
    ASSERT(actual_condition == true_condition);
    // Although we have a condition to branch on, the comparison code may also
    // have contained a direct branch to one of the labels, so they may need to
    // be bound.
    if (next_is_true && is_true.IsLinked()) {
      __ Bind(&is_true);
    } else if (!next_is_true && is_false.IsLinked()) {
      __ Bind(&is_false);
    }
    // This instruction is conditionally skipped by EmitComparisonCode.
    __ LoadConstant(result, Bool::Get(next_is_true));
    // If the other label is linked we need to bind it and emit code that loads
    // the correct boolean.
    if ((next_is_true && is_false.IsLinked()) ||
        (!next_is_true && is_true.IsLinked())) {
      Label done;
      __ Jump(&done);
      __ Bind(next_is_true ? &is_false : &is_true);
      __ LoadConstant(result, Bool::Get(!next_is_true));
      __ Bind(&done);
    }
  }
}

LocationSummary* BranchInstr::MakeLocationSummary(

    Zone* zone,
    bool opt) const {
  comparison()->InitializeLocationSummary(zone, opt);
  if (!comparison()->HasLocs()) {
    return NULL;
  }
  // Branches don't produce a result.
  comparison()->locs()->set_out(0, Location::NoLocation());
  return comparison()->locs();
}

void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
  comparison()->EmitBranchCode(compiler, this);
}

EMIT_NATIVE_CODE(Goto, 0) {
  if (!compiler->is_optimizing()) {
    // Add a deoptimization descriptor for deoptimizing instructions that
    // may be inserted before this instruction.
    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
                                   TokenPosition::kNoSource);
  }
  if (HasParallelMove()) {
    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
  }
  // We can fall through if the successor is the next block in the list.
  // Otherwise, we need a jump.
  if (!compiler->CanFallThroughTo(successor())) {
    __ Jump(compiler->GetJumpLabel(successor()));
  }
}

Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler,
                                                    BranchLabels labels) {
  ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
  return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
}

Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                           BranchLabels labels) {
  ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
  Register left = locs()->in(0).reg();
  Register right = locs()->in(1).reg();
  __ TestSmi(left, right);
  return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
}

DEFINE_MAKE_LOCATION_SUMMARY(TestSmi,
                             2,
                             Location::RequiresRegister(),
                             LocationSummary::kNoCall)

Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                            BranchLabels labels) {
  ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
  const Register value = locs()->in(0).reg();
  const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;

  const ZoneGrowableArray<intptr_t>& data = cid_results();
  const intptr_t num_cases = data.length() / 2;
  ASSERT(num_cases <= 255);
  __ TestCids(value, num_cases);

  bool result = false;
  for (intptr_t i = 0; i < data.length(); i += 2) {
    const intptr_t test_cid = data[i];
    result = data[i + 1] == true_result;
    __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this));
  }

  // No match found, deoptimize or default action.
  if (CanDeoptimize()) {
    compiler->EmitDeopt(deopt_id(), ICData::kDeoptTestCids,
                        licm_hoisted_ ? ICData::kHoisted : 0);
  } else {
    // If the cid is not in the list, jump to the opposite label from the cids
    // that are in the list.  These must be all the same (see asserts in the
    // constructor).
    Label* target = result ? labels.false_label : labels.true_label;
    __ Jump(target);
  }

  return NEXT_IS_TRUE;
}

Condition TestCidsInstr::GetNextInstructionCondition(
    FlowGraphCompiler* compiler,
    BranchLabels labels) {
  return NEXT_IS_TRUE;
}

DEFINE_MAKE_LOCATION_SUMMARY(TestCids,
                             1,
                             Location::RequiresRegister(),
                             LocationSummary::kNoCall)

EMIT_NATIVE_CODE(CreateArray,
                 2,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    const Register length = locs()->in(kLengthPos).reg();
    const Register type_arguments = locs()->in(kElementTypePos).reg();
    const Register out = locs()->out(0).reg();
    __ CreateArrayOpt(out, length, type_arguments);
    __ Push(type_arguments);
    __ Push(length);
    __ CreateArrayTOS();
    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
    __ PopLocal(out);
  } else {
    __ CreateArrayTOS();
    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
  }
}

EMIT_NATIVE_CODE(StoreIndexed,
                 3,
                 Location::NoLocation(),
                 LocationSummary::kNoCall,
                 1) {
  if (!compiler->is_optimizing()) {
    ASSERT(class_id() == kArrayCid);
    __ StoreIndexedTOS();
    return;
  }
  const Register array = locs()->in(kArrayPos).reg();
  const Register index = locs()->in(kIndexPos).reg();
  const Register value = locs()->in(kValuePos).reg();
  const Register temp = locs()->temp(0).reg();
  switch (class_id()) {
    case kArrayCid:
      __ StoreIndexed(array, index, value);
      break;
    case kTypedDataUint8ArrayCid:
    case kTypedDataInt8ArrayCid:
    case kExternalOneByteStringCid:
    case kExternalTypedDataUint8ArrayCid:
      ASSERT(index_scale() == 1);
      if (IsExternal()) {
        __ StoreIndexedUntaggedUint8(array, index, value);
      } else {
        __ StoreIndexedUint8(array, index, value);
      }
      break;
    case kOneByteStringCid:
      ASSERT(index_scale() == 1);
      __ StoreIndexedOneByteString(array, index, value);
      break;
    case kTypedDataInt32ArrayCid:
    case kTypedDataUint32ArrayCid: {
      if (IsExternal()) {
        if (index_scale() == 1) {
          __ StoreIndexedUntaggedUint32(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedUntaggedUint32(array, temp, value);
        }
      } else {
        if (index_scale() == 1) {
          __ StoreIndexedUint32(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedUint32(array, temp, value);
        }
      }
      break;
    }
    case kTypedDataFloat32ArrayCid:
      if (IsExternal()) {
        if (index_scale() == 1) {
          __ StoreIndexedUntaggedFloat32(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedUntaggedFloat32(array, temp, value);
        }
      } else {
        if (index_scale() == 1) {
          __ StoreIndexedFloat32(array, index, value);
        } else if (index_scale() == 4) {
          __ StoreIndexed4Float32(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedFloat32(array, temp, value);
        }
      }
      break;
    case kTypedDataFloat64ArrayCid:
      if (IsExternal()) {
        if (index_scale() == 1) {
          __ StoreIndexedUntaggedFloat64(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedUntaggedFloat64(array, temp, value);
        }
      } else {
        if (index_scale() == 1) {
          __ StoreIndexedFloat64(array, index, value);
        } else if (index_scale() == 8) {
          __ StoreIndexed8Float64(array, index, value);
        } else {
          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
          __ StoreIndexedFloat64(array, temp, value);
        }
      }
      break;
    default:
      Unsupported(compiler);
      UNREACHABLE();
      break;
  }
}

EMIT_NATIVE_CODE(LoadIndexed,
                 2,
                 Location::RequiresRegister(),
                 LocationSummary::kNoCall,
                 1) {
  if (compiler->is_optimizing()) {
    ASSERT(compiler->is_optimizing());
    const Register array = locs()->in(0).reg();
    const Register index = locs()->in(1).reg();
    const Register temp = locs()->temp(0).reg();
    const Register result = locs()->out(0).reg();
    switch (class_id()) {
      case kArrayCid:
      case kImmutableArrayCid:
        __ LoadIndexed(result, array, index);
        break;
      case kTypedDataUint8ArrayCid:
      case kTypedDataUint8ClampedArrayCid:
      case kExternalOneByteStringCid:
      case kExternalTypedDataUint8ArrayCid:
      case kExternalTypedDataUint8ClampedArrayCid:
        ASSERT(index_scale() == 1);
        if (IsExternal()) {
          __ LoadIndexedUntaggedUint8(result, array, index);
        } else {
          __ LoadIndexedUint8(result, array, index);
        }
        break;
      case kTypedDataInt8ArrayCid:
        ASSERT(index_scale() == 1);
        if (IsExternal()) {
          __ LoadIndexedUntaggedInt8(result, array, index);
        } else {
          __ LoadIndexedInt8(result, array, index);
        }
        break;
      case kOneByteStringCid:
        ASSERT(index_scale() == 1);
        __ LoadIndexedOneByteString(result, array, index);
        break;
      case kTwoByteStringCid:
        if (index_scale() != 2) {
          // TODO(zra): Fix-up index.
          Unsupported(compiler);
          UNREACHABLE();
        }
        if (IsExternal()) {
          Unsupported(compiler);
          UNREACHABLE();
        }
        __ LoadIndexedTwoByteString(result, array, index);
        break;
      case kTypedDataInt32ArrayCid:
        ASSERT(representation() == kUnboxedInt32);
        if (IsExternal()) {
          if (index_scale() == 1) {
            __ LoadIndexedUntaggedInt32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedUntaggedInt32(result, array, temp);
          }
        } else {
          if (index_scale() == 1) {
            __ LoadIndexedInt32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedInt32(result, array, temp);
          }
        }
        break;
      case kTypedDataUint32ArrayCid:
        ASSERT(representation() == kUnboxedUint32);
        if (IsExternal()) {
          if (index_scale() == 1) {
            __ LoadIndexedUntaggedUint32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedUntaggedUint32(result, array, temp);
          }
        } else {
          if (index_scale() == 1) {
            __ LoadIndexedUint32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedUint32(result, array, temp);
          }
        }
        break;
      case kTypedDataFloat32ArrayCid:
        if (IsExternal()) {
          if (index_scale() == 1) {
            __ LoadIndexedUntaggedFloat32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedUntaggedFloat32(result, array, temp);
          }
        } else {
          if (index_scale() == 1) {
            __ LoadIndexedFloat32(result, array, index);
          } else if (index_scale() == 4) {
            __ LoadIndexed4Float32(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedFloat32(result, array, temp);
          }
        }
        break;
      case kTypedDataFloat64ArrayCid:
        if (IsExternal()) {
          if (index_scale() == 1) {
            __ LoadIndexedUntaggedFloat64(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedUntaggedFloat64(result, array, temp);
          }
        } else {
          if (index_scale() == 1) {
            __ LoadIndexedFloat64(result, array, index);
          } else if (index_scale() == 8) {
            __ LoadIndexed8Float64(result, array, index);
          } else {
            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
            __ LoadIndexedFloat64(result, array, temp);
          }
        }
        break;
      default:
        Unsupported(compiler);
        UNREACHABLE();
        break;
    }
  } else {
    switch (class_id()) {
      case kArrayCid:
      case kImmutableArrayCid:
        __ LoadIndexedTOS();
        break;
      default:
        Unsupported(compiler);
        UNREACHABLE();
        break;
    }
  }
}

EMIT_NATIVE_CODE(StringInterpolate,
                 1,
                 Location::RegisterLocation(0),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
  }
  const intptr_t kTypeArgsLen = 0;
  const intptr_t kArgumentCount = 1;
  const Array& arguments_descriptor = Array::Handle(ArgumentsDescriptor::New(
      kTypeArgsLen, kArgumentCount, Object::null_array()));
  __ PushConstant(CallFunction());
  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
  __ StaticCall(kArgumentCount, argdesc_kidx);
  // Note: can't use RecordAfterCall here because
  // StringInterpolateInstr::ArgumentCount() is 0. However
  // internally it does a call with 1 argument which needs to
  // be reflected in the lazy deoptimization environment.
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), kArgumentCount,
                                  FlowGraphCompiler::kHasResult, locs());
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
  const Representation result_rep =
      compiler::ffi::ResultHostRepresentation(signature_);
  // TODO(36809): In 32 bit we'll need a result location as well.
  const TypedData& signature_descriptor =
      TypedData::Handle(compiler::ffi::FfiSignatureDescriptor::New(
          *arg_host_locations_, result_rep));

  const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor);

  __ FfiCall(sigdesc_kidx);
}

EMIT_NATIVE_CODE(NativeCall,
                 0,
                 Location::NoLocation(),
                 LocationSummary::kCall) {
  SetupNative();

  const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());

  NativeFunctionWrapper trampoline;
  NativeFunction function;
  if (link_lazily()) {
    trampoline = &NativeEntry::BootstrapNativeCallWrapper;
    function = reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
  } else {
    if (is_bootstrap_native()) {
      trampoline = &NativeEntry::BootstrapNativeCallWrapper;
    } else if (is_auto_scope()) {
      trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
    } else {
      trampoline = &NativeEntry::NoScopeNativeCallWrapper;
    }
    function = native_c_function();
  }

  const ExternalLabel trampoline_label(reinterpret_cast<uword>(trampoline));
  const intptr_t trampoline_kidx =
      __ object_pool_builder().FindNativeFunctionWrapper(
          &trampoline_label, ObjectPool::Patchability::kPatchable);
  const ExternalLabel label(reinterpret_cast<uword>(function));
  const intptr_t target_kidx = __ object_pool_builder().FindNativeFunction(
      &label, ObjectPool::Patchability::kPatchable);
  const intptr_t argc_tag_kidx =
      __ object_pool_builder().FindImmediate(static_cast<uword>(argc_tag));
  __ NativeCall(trampoline_kidx, target_kidx, argc_tag_kidx);
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                 token_pos());
}

EMIT_NATIVE_CODE(OneByteStringFromCharCode,
                 1,
                 Location::RequiresRegister(),
                 LocationSummary::kNoCall) {
  ASSERT(compiler->is_optimizing());
  const Register char_code = locs()->in(0).reg();  // Char code is a smi.
  const Register result = locs()->out(0).reg();
  __ OneByteStringFromCharCode(result, char_code);
}

EMIT_NATIVE_CODE(StringToCharCode,
                 1,
                 Location::RequiresRegister(),
                 LocationSummary::kNoCall) {
  ASSERT(cid_ == kOneByteStringCid);
  const Register str = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();  // Result char code is a smi.
  __ StringToCharCode(result, str);
}

EMIT_NATIVE_CODE(AllocateObject,
                 0,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  if (ArgumentCount() == 1) {
    // Allocate with type arguments.
    if (compiler->is_optimizing()) {
      // If we're optimizing, try a streamlined fastpath.
      const intptr_t instance_size = cls().instance_size();
      Isolate* isolate = Isolate::Current();
      if (Heap::IsAllocatableInNewSpace(instance_size) &&
          !cls().TraceAllocation(isolate)) {
        uint32_t tags = 0;
        tags = RawObject::SizeTag::update(instance_size, tags);
        ASSERT(cls().id() != kIllegalCid);
        tags = RawObject::ClassIdTag::update(cls().id(), tags);
        if (Smi::IsValid(tags)) {
          const intptr_t tags_kidx =
              __ AddConstant(Smi::Handle(Smi::New(tags)));
          __ AllocateTOpt(locs()->out(0).reg(), tags_kidx);
          __ Nop(cls().type_arguments_field_offset());
        }
      }
      __ PushConstant(cls());
      __ AllocateT();
      compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                     token_pos());
      compiler->RecordSafepoint(locs());
      __ PopLocal(locs()->out(0).reg());
    } else {
      __ PushConstant(cls());
      __ AllocateT();
      compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                     token_pos());
      compiler->RecordSafepoint(locs());
    }
  } else if (compiler->is_optimizing()) {
    // If we're optimizing, try a streamlined fastpath.
    const intptr_t instance_size = cls().instance_size();
    Isolate* isolate = Isolate::Current();
    if (Heap::IsAllocatableInNewSpace(instance_size) &&
        !cls().TraceAllocation(isolate)) {
      uword tags = 0;
      tags = RawObject::SizeTag::update(instance_size, tags);
      ASSERT(cls().id() != kIllegalCid);
      tags = RawObject::ClassIdTag::update(cls().id(), tags);
      // tags also has the initial zero hash code on 64 bit.
      if (Smi::IsValid(tags)) {
        const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
        __ AllocateOpt(locs()->out(0).reg(), tags_kidx);
      }
    }
    const intptr_t kidx = __ AddConstant(cls());
    __ Allocate(kidx);
    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                   token_pos());
    compiler->RecordSafepoint(locs());
    __ PopLocal(locs()->out(0).reg());
  } else {
    const intptr_t kidx = __ AddConstant(cls());
    __ Allocate(kidx);
    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                   token_pos());
    compiler->RecordSafepoint(locs());
  }
}

EMIT_NATIVE_CODE(StoreInstanceField, 2) {
  ASSERT(OffsetInBytes() % kWordSize == 0);
  if (compiler->is_optimizing()) {
    const Register value = locs()->in(1).reg();
    const Register instance = locs()->in(0).reg();
    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
      __ StoreField(instance, OffsetInBytes() / kWordSize, value);
    } else {
      __ StoreFieldExt(instance, value);
      __ Nop(OffsetInBytes() / kWordSize);
    }
  } else {
    __ StoreFieldTOS(OffsetInBytes() / kWordSize);
  }
}

EMIT_NATIVE_CODE(LoadField, 1, Location::RequiresRegister()) {
  ASSERT(OffsetInBytes() % kWordSize == 0);
  if (compiler->is_optimizing()) {
    const Register result = locs()->out(0).reg();
    const Register instance = locs()->in(0).reg();
    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
      __ LoadField(result, instance, OffsetInBytes() / kWordSize);
    } else {
      __ LoadFieldExt(result, instance);
      __ Nop(OffsetInBytes() / kWordSize);
    }
  } else {
    __ LoadFieldTOS(OffsetInBytes() / kWordSize);
  }
}

EMIT_NATIVE_CODE(LoadUntagged, 1, Location::RequiresRegister()) {
  const Register obj = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  if (object()->definition()->representation() == kUntagged) {
    __ LoadUntagged(result, obj, offset() / kWordSize);
  } else {
    ASSERT(object()->definition()->representation() == kTagged);
    __ LoadField(result, obj, offset() / kWordSize);
  }
}

EMIT_NATIVE_CODE(StoreUntagged, 1, Location::RequiresRegister()) {
  const Register obj = locs()->in(0).reg();
  const Register value = locs()->out(0).reg();
  const auto offset_in_words = offset() / kWordSize;
  if (object()->definition()->representation() == kUntagged) {
    __ StoreUntagged(obj, offset_in_words, value);
  } else {
    ASSERT(object()->definition()->representation() == kTagged);
    __ StoreField(obj, offset_in_words, value);
  }
}

EMIT_NATIVE_CODE(BooleanNegate, 1, Location::RequiresRegister()) {
  if (compiler->is_optimizing()) {
    __ BooleanNegate(locs()->out(0).reg(), locs()->in(0).reg());
  } else {
    __ BooleanNegateTOS();
  }
}

EMIT_NATIVE_CODE(AllocateContext,
                 0,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  ASSERT(!compiler->is_optimizing());
  __ AllocateContext(num_context_variables());
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                 token_pos());
}

EMIT_NATIVE_CODE(AllocateUninitializedContext,
                 0,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  ASSERT(compiler->is_optimizing());
  __ AllocateUninitializedContext(locs()->out(0).reg(),
                                  num_context_variables());
  __ AllocateContext(num_context_variables());
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                 token_pos());
  __ PopLocal(locs()->out(0).reg());
}

EMIT_NATIVE_CODE(CloneContext,
                 1,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());
  }
  __ CloneContext();
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                 token_pos());
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

EMIT_NATIVE_CODE(CatchBlockEntry, 0) {
  __ Bind(compiler->GetJumpLabel(this));
  compiler->AddExceptionHandler(catch_try_index(), try_index(),
                                compiler->assembler()->CodeSize(),
                                handler_token_pos(), is_generated(),
                                catch_handler_types_, needs_stacktrace());
  // On lazy deoptimization we patch the optimized code here to enter the
  // deoptimization stub.
  const intptr_t deopt_id = DeoptId::ToDeoptAfter(GetDeoptId());
  if (compiler->is_optimizing()) {
    compiler->AddDeoptIndexAtCall(deopt_id);
  } else {
    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id,
                                   TokenPosition::kNoSource);
  }
  if (HasParallelMove()) {
    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
  }
  __ SetFrame(compiler->StackSize());

  if (!compiler->is_optimizing()) {
    if (raw_exception_var_ != nullptr) {
      __ MoveSpecial(
          LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable(
                               raw_exception_var_)),
          Simulator::kExceptionSpecialIndex);
    }
    if (raw_stacktrace_var_ != nullptr) {
      __ MoveSpecial(
          LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable(
                               raw_stacktrace_var_)),
          Simulator::kStackTraceSpecialIndex);
    }
  }
}

EMIT_NATIVE_CODE(Throw, 0, Location::NoLocation(), LocationSummary::kCall) {
  __ Throw(0);
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
  __ Trap();
}

EMIT_NATIVE_CODE(ReThrow, 0, Location::NoLocation(), LocationSummary::kCall) {
  compiler->SetNeedsStackTrace(catch_try_index());
  __ Throw(1);
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
  __ Trap();
}

EMIT_NATIVE_CODE(InstantiateType,
                 2,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());  // Instantiator type arguments.
    __ Push(locs()->in(1).reg());  // Function type arguments.
  }
  __ InstantiateType(__ AddConstant(type()));
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

EMIT_NATIVE_CODE(InstantiateTypeArguments,
                 2,
                 Location::RequiresRegister(),
                 LocationSummary::kCall) {
  if (compiler->is_optimizing()) {
    __ Push(locs()->in(0).reg());  // Instantiator type arguments.
    __ Push(locs()->in(1).reg());  // Function type arguments.
  }
  __ InstantiateTypeArgumentsTOS(
      type_arguments().IsRawWhenInstantiatedFromRaw(type_arguments().Length()),
      __ AddConstant(type_arguments()));
  compiler->RecordSafepoint(locs());
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
                                 token_pos());
  if (compiler->is_optimizing()) {
    __ PopLocal(locs()->out(0).reg());
  }
}

void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
#ifdef PRODUCT
  UNREACHABLE();
#else
  __ DebugStep();
  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
#endif
}

void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
  BlockEntryInstr* entry = normal_entry();
  if (entry != nullptr) {
    if (!compiler->CanFallThroughTo(entry)) {
      FATAL("Checked function entry must have no offset");
    }
  } else {
    entry = osr_entry();
    if (!compiler->CanFallThroughTo(entry)) {
      __ Jump(compiler->GetJumpLabel(entry));
    }
  }
}

LocationSummary* Instruction::MakeCallSummary(Zone* zone) {
  LocationSummary* result =
      new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
  // TODO(vegorov) support allocating out registers for calls.
  // Currently we require them to be fixed.
  result->set_out(0, Location::RegisterLocation(0));
  return result;
}

CompileType BinaryUint32OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType ShiftUint32OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType SpeculativeShiftUint32OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType UnaryUint32OpInstr::ComputeType() const {
  return CompileType::Int();
}

CompileType LoadIndexedInstr::ComputeType() const {
  switch (class_id_) {
    case kArrayCid:
    case kImmutableArrayCid:
      return CompileType::Dynamic();

    case kTypedDataFloat32ArrayCid:
    case kTypedDataFloat64ArrayCid:
      return CompileType::FromCid(kDoubleCid);
    case kTypedDataFloat32x4ArrayCid:
      return CompileType::FromCid(kFloat32x4Cid);
    case kTypedDataInt32x4ArrayCid:
      return CompileType::FromCid(kInt32x4Cid);
    case kTypedDataFloat64x2ArrayCid:
      return CompileType::FromCid(kFloat64x2Cid);

    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ClampedArrayCid:
    case kExternalTypedDataUint8ArrayCid:
    case kExternalTypedDataUint8ClampedArrayCid:

    case kOneByteStringCid:
    case kTwoByteStringCid:
    case kExternalOneByteStringCid:
      return CompileType::FromCid(kSmiCid);

    case kTypedDataInt32ArrayCid:
    case kTypedDataUint32ArrayCid:
      return CompileType::Int();

    // These are unsupported on DBC and will cause a bailout during
    // EmitNativeCode.
    case kTypedDataInt16ArrayCid:
    case kTypedDataUint16ArrayCid:
    case kExternalTwoByteStringCid:
      return CompileType::FromCid(kSmiCid);

    default:
      UNREACHABLE();
      return CompileType::Dynamic();
  }
}

Representation LoadIndexedInstr::representation() const {
  switch (class_id_) {
    case kArrayCid:
    case kImmutableArrayCid:
      return kTagged;
    case kOneByteStringCid:
    case kTwoByteStringCid:
    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ClampedArrayCid:
    case kExternalOneByteStringCid:
    case kExternalTypedDataUint8ArrayCid:
    case kExternalTypedDataUint8ClampedArrayCid:
      return kUnboxedIntPtr;
    case kTypedDataInt32ArrayCid:
      return kUnboxedInt32;
    case kTypedDataUint32ArrayCid:
      return kUnboxedUint32;
    case kTypedDataFloat32ArrayCid:
    case kTypedDataFloat64ArrayCid:
      return kUnboxedDouble;
    case kTypedDataInt32x4ArrayCid:
      return kUnboxedInt32x4;
    case kTypedDataFloat32x4ArrayCid:
      return kUnboxedFloat32x4;
    case kTypedDataFloat64x2ArrayCid:
      return kUnboxedFloat64x2;

    // These are unsupported on DBC and will cause a bailout during
    // EmitNativeCode.
    case kTypedDataInt16ArrayCid:
    case kTypedDataUint16ArrayCid:
    case kExternalTwoByteStringCid:
      return kUnboxedIntPtr;

    default:
      UNREACHABLE();
      return kTagged;
  }
}

Representation StoreIndexedInstr::RequiredInputRepresentation(
    intptr_t idx) const {
  // Array can be a Dart object or a pointer to external data.
  if (idx == 0) {
    return kNoRepresentation;  // Flexible input representation.
  }
  if (idx == 1) {
    return kTagged;  // Index is a smi.
  }
  ASSERT(idx == 2);
  switch (class_id_) {
    case kArrayCid:
      return kTagged;
    case kOneByteStringCid:
    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kExternalOneByteStringCid:
    case kExternalTypedDataUint8ArrayCid:
      return kUnboxedIntPtr;
    case kTypedDataInt32ArrayCid:
      return kUnboxedInt32;
    case kTypedDataUint32ArrayCid:
      return kUnboxedUint32;
    case kTypedDataFloat32ArrayCid:
    case kTypedDataFloat64ArrayCid:
      return kUnboxedDouble;
    case kTypedDataFloat32x4ArrayCid:
      return kUnboxedFloat32x4;
    case kTypedDataInt32x4ArrayCid:
      return kUnboxedInt32x4;
    case kTypedDataFloat64x2ArrayCid:
      return kUnboxedFloat64x2;

    // These are unsupported on DBC and will cause a bailout during
    // EmitNativeCode.
    case kTypedDataUint8ClampedArrayCid:
    case kExternalTypedDataUint8ClampedArrayCid:
    case kTypedDataInt16ArrayCid:
    case kTypedDataUint16ArrayCid:
      return kUnboxedIntPtr;
    default:
      UNREACHABLE();
      return kTagged;
  }
}

void Environment::DropArguments(intptr_t argc) {
#if defined(DEBUG)
  // Check that we are in the backend - register allocation has been run.
  ASSERT(locations_ != NULL);

  // Check that we are only dropping a valid number of instructions from the
  // environment.
  ASSERT(argc <= values_.length());
#endif
  values_.TruncateTo(values_.length() - argc);
}

EMIT_NATIVE_CODE(CheckSmi, 1) {
  __ CheckSmi(locs()->in(0).reg());
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckSmi,
                      licm_hoisted_ ? ICData::kHoisted : 0);
}

EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) {
  const Register left = locs()->in(0).reg();
  const Register right = locs()->in(1).reg();
  __ CheckEitherNonSmi(left, right);
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
                      licm_hoisted_ ? ICData::kHoisted : 0);
}

EMIT_NATIVE_CODE(CheckClassId, 1) {
  if (cids_.IsSingleCid()) {
    __ CheckClassId(locs()->in(0).reg(),
                    compiler->ToEmbeddableCid(cids_.cid_start, this));
  } else {
    __ CheckClassIdRange(locs()->in(0).reg(),
                         compiler->ToEmbeddableCid(cids_.cid_start, this));
    __ Nop(compiler->ToEmbeddableCid(cids_.Extent(), this));
  }
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass);
}

EMIT_NATIVE_CODE(CheckClass, 1) {
  const Register value = locs()->in(0).reg();
  if (IsNullCheck()) {
    ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull());
    if (IsDeoptIfNull()) {
      __ IfEqNull(value);
    } else {
      __ IfNeNull(value);
    }
  } else {
    ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid));
    const intptr_t may_be_smi = cids_.HasClassId(kSmiCid) ? 1 : 0;
    bool is_bit_test = false;
    intptr_t cid_mask = 0;
    if (IsBitTest()) {
      cid_mask = ComputeCidMask();
      is_bit_test = Smi::IsValid(cid_mask);
    }
    if (is_bit_test) {
      intptr_t min = cids_.ComputeLowestCid();
      __ CheckBitTest(value, may_be_smi);
      __ Nop(compiler->ToEmbeddableCid(min, this));
      __ Nop(__ AddConstant(Smi::Handle(Smi::New(cid_mask))));
    } else {
      bool using_ranges = false;
      int smi_adjustment = 0;
      int length = cids_.length();
      for (intptr_t i = 0; i < length; i++) {
        if (!cids_[i].IsSingleCid()) {
          using_ranges = true;
        } else if (cids_[i].cid_start == kSmiCid) {
          ASSERT(cids_[i].cid_end == kSmiCid);  // We are in the else clause.
          ASSERT(smi_adjustment == 0);
          smi_adjustment = 1;
        }
      }

      if (!Utils::IsUint(8, length)) {
        Unsupported(compiler);
        UNREACHABLE();
      }
      if (using_ranges) {
        __ CheckCidsByRange(value, may_be_smi, (length - smi_adjustment) * 2);
      } else {
        __ CheckCids(value, may_be_smi, length - smi_adjustment);
      }
      for (intptr_t i = 0; i < length; i++) {
        intptr_t cid_start = cids_[i].cid_start;
        intptr_t cid_end = cids_[i].cid_end;
        if (cid_start == kSmiCid && cid_end == kSmiCid) {
          ASSERT(smi_adjustment == 1);
          continue;
        }
        __ Nop(compiler->ToEmbeddableCid(cid_start, this));
        if (using_ranges) {
          __ Nop(compiler->ToEmbeddableCid(1 + cids_[i].Extent(), this));
        }
      }
    }
  }
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass,
                      licm_hoisted_ ? ICData::kHoisted : 0);
}

EMIT_NATIVE_CODE(CheckNull, 1) {
  if (compiler->is_optimizing()) {
    const Register value = locs()->in(0).reg();
    __ IfEqNull(value);
  } else {
    __ IfEqNullTOS();
  }
  __ NullError();
  CheckNullInstr::AddMetadataForRuntimeCall(this, compiler);
}

EMIT_NATIVE_CODE(BinarySmiOp, 2, Location::RequiresRegister()) {
  if (compiler->is_optimizing()) {
    const Register left = locs()->in(0).reg();
    const Register right = locs()->in(1).reg();
    const Register out = locs()->out(0).reg();
    const bool can_deopt = CanDeoptimize();
    bool needs_nop = false;
    switch (op_kind()) {
      case Token::kADD:
        __ Add(out, left, right);
        needs_nop = true;
        break;
      case Token::kSUB:
        __ Sub(out, left, right);
        needs_nop = true;
        break;
      case Token::kMUL:
        __ Mul(out, left, right);
        needs_nop = true;
        break;
      case Token::kTRUNCDIV:
        ASSERT(can_deopt);
        __ Div(out, left, right);
        break;
      case Token::kBIT_AND:
        ASSERT(!can_deopt);
        __ BitAnd(out, left, right);
        break;
      case Token::kBIT_OR:
        ASSERT(!can_deopt);
        __ BitOr(out, left, right);
        break;
      case Token::kBIT_XOR:
        ASSERT(!can_deopt);
        __ BitXor(out, left, right);
        break;
      case Token::kMOD:
        __ Mod(out, left, right);
        needs_nop = true;
        break;
      case Token::kSHR:
        __ Shr(out, left, right);
        needs_nop = true;
        break;
      case Token::kSHL:
        __ Shl(out, left, right);
        needs_nop = true;
        break;
      default:
        UNREACHABLE();
    }
    if (can_deopt) {
      compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinarySmiOp);
    } else if (needs_nop) {
      __ Nop(0);
    }
  } else {
    switch (op_kind()) {
      case Token::kADD:
        __ SmiAddTOS();
        break;
      case Token::kSUB:
        __ SmiSubTOS();
        break;
      case Token::kMUL:
        __ SmiMulTOS();
        break;
      case Token::kBIT_AND:
        __ SmiBitAndTOS();
        break;
      default:
        UNIMPLEMENTED();
    }
  }
}

EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) {
  switch (op_kind()) {
    case Token::kNEGATE: {
      __ Neg(locs()->out(0).reg(), locs()->in(0).reg());
      compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp);
      break;
    }
    case Token::kBIT_NOT:
      __ BitNot(locs()->out(0).reg(), locs()->in(0).reg());
      break;
    default:
      UNREACHABLE();
      break;
  }
}

void BoxInstr::EmitAllocateBox(FlowGraphCompiler* compiler) {
  const Register out = locs()->out(0).reg();
  const Class& box_class = compiler->BoxClassFor(from_representation());
  const intptr_t instance_size = box_class.instance_size();
  Isolate* isolate = Isolate::Current();
  ASSERT(Heap::IsAllocatableInNewSpace(instance_size));
  if (!box_class.TraceAllocation(isolate)) {
    uword tags = 0;
    tags = RawObject::SizeTag::update(instance_size, tags);
    tags = RawObject::ClassIdTag::update(box_class.id(), tags);
    // tags also has the initial zero hash code on 64 bit.
    if (Smi::IsValid(tags)) {
      const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
      __ AllocateOpt(out, tags_kidx);
    }
  }
  const intptr_t kidx = __ AddConstant(box_class);
  __ Allocate(kidx);
  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
                                 token_pos());
  compiler->RecordSafepoint(locs());
  __ PopLocal(out);
}

EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
  ASSERT(from_representation() == kUnboxedDouble ||
         from_representation() == kUnboxedFloat);
  const Register value = locs()->in(0).reg();
  const Register out = locs()->out(0).reg();
  if (from_representation() == kUnboxedFloat) {
    __ FloatToDouble(value, value);
  }
  EmitAllocateBox(compiler);
  __ WriteIntoDouble(out, value);
}

EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
  if (representation() == kUnboxedInt64) {
    EmitLoadInt64FromBoxOrSmi(compiler);
    return;
  }
  ASSERT(representation() == kUnboxedDouble ||
         representation() == kUnboxedFloat);
  const intptr_t value_cid = value()->Type()->ToCid();
  const intptr_t box_cid = BoxCid();
  const Register box = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  if (value_cid == box_cid ||
      (speculative_mode() == kNotSpeculative && value_cid != kSmiCid)) {
    __ UnboxDouble(result, box);
  } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
    __ SmiToDouble(result, box);
  } else if ((value()->Type()->ToNullableCid() == box_cid) &&
             value()->Type()->is_nullable()) {
    __ IfEqNull(box);
    ASSERT(CanDeoptimize());
    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
    __ UnboxDouble(result, box);
  } else {
    __ CheckedUnboxDouble(result, box);
    ASSERT(CanDeoptimize());
    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
  }
  if (representation() == kUnboxedFloat) {
    __ DoubleToFloat(result, result);
  }
}

EMIT_NATIVE_CODE(UnboxInteger32, 1, Location::RequiresRegister()) {
#if defined(ARCH_IS_64_BIT)
  const Register out = locs()->out(0).reg();
  const Register value = locs()->in(0).reg();
  const bool may_truncate = is_truncating() || !CanDeoptimize();
  __ UnboxInt32(out, value, may_truncate);
  if (CanDeoptimize()) {
    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptUnboxInteger);
  } else {
    __ Nop(0);
  }
#else
  Unsupported(compiler);
  UNREACHABLE();
#endif  // defined(ARCH_IS_64_BIT)
}

EMIT_NATIVE_CODE(BoxInteger32, 1, Location::RequiresRegister()) {
#if defined(ARCH_IS_64_BIT)
  const Register out = locs()->out(0).reg();
  const Register value = locs()->in(0).reg();
  if (from_representation() == kUnboxedInt32) {
    __ BoxInt32(out, value);
  } else {
    ASSERT(from_representation() == kUnboxedUint32);
    __ BoxUint32(out, value);
  }
#else
  Unsupported(compiler);
  UNREACHABLE();
#endif  // defined(ARCH_IS_64_BIT)
}

EMIT_NATIVE_CODE(BoxInt64, 1, Location::RequiresRegister()) {
#if defined(ARCH_IS_64_BIT)
  Label done;
  const Register value = locs()->in(0).reg();
  const Register out = locs()->out(0).reg();
  __ BoxInt64(out, value);
  __ Jump(&done);
  EmitAllocateBox(compiler);
  __ WriteIntoMint(out, value);
  __ Bind(&done);
#else
  Unsupported(compiler);
  UNREACHABLE();
#endif  // defined(ARCH_IS_64_BIT)
}

void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
#if defined(ARCH_IS_64_BIT)
  const Register out = locs()->out(0).reg();
  const Register value = locs()->in(0).reg();
  __ UnboxInt64(out, value);
#else
  Unsupported(compiler);
  UNREACHABLE();
#endif  // defined(ARCH_IS_64_BIT)
}

EMIT_NATIVE_CODE(UnboxedWidthExtender, 1, Location::RequiresRegister()) {
  const Register out = locs()->out(0).reg();
  const Register value = locs()->in(0).reg();
  __ UnboxedWidthExtender(out, value, from_representation());
}

EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) {
  const Register value = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  __ DoubleToSmi(result, value);
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptDoubleToSmi);
}

EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) {
  const Register value = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  __ SmiToDouble(result, value);
}

EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
  const Register left = locs()->in(0).reg();
  const Register right = locs()->in(1).reg();
  const Register result = locs()->out(0).reg();
  switch (op_kind()) {
    case Token::kADD:
      __ DAdd(result, left, right);
      break;
    case Token::kSUB:
      __ DSub(result, left, right);
      break;
    case Token::kMUL:
      __ DMul(result, left, right);
      break;
    case Token::kDIV:
      __ DDiv(result, left, right);
      break;
    default:
      UNREACHABLE();
  }
}

Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                                BranchLabels labels) {
  ASSERT(compiler->is_optimizing());
  const Register value = locs()->in(0).reg();
  switch (op_kind()) {
    case MethodRecognizer::kDouble_getIsNaN:
      __ DoubleIsNaN(value);
      break;
    case MethodRecognizer::kDouble_getIsInfinite:
      __ DoubleIsInfinite(value);
      break;
    default:
      UNREACHABLE();
  }
  const bool is_negated = kind() != Token::kEQ;
  return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
}

Condition DoubleTestOpInstr::GetNextInstructionCondition(
    FlowGraphCompiler* compiler,
    BranchLabels labels) {
  const bool is_negated = kind() != Token::kEQ;
  return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
}

DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister())

EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
  const Register value = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  __ DNeg(result, value);
}

EMIT_NATIVE_CODE(MathUnary, 1, Location::RequiresRegister()) {
  const Register value = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  if (kind() == MathUnaryInstr::kSqrt) {
    __ DSqrt(result, value);
  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
    __ DMul(result, value, value);
  } else {
    Unsupported(compiler);
    UNREACHABLE();
  }
}

EMIT_NATIVE_CODE(DoubleToDouble, 1, Location::RequiresRegister()) {
  const Register in = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  switch (recognized_kind()) {
    case MethodRecognizer::kDoubleTruncate:
      __ DTruncate(result, in);
      break;
    case MethodRecognizer::kDoubleFloor:
      __ DFloor(result, in);
      break;
    case MethodRecognizer::kDoubleCeil:
      __ DCeil(result, in);
      break;
    default:
      UNREACHABLE();
  }
}

EMIT_NATIVE_CODE(DoubleToFloat, 1, Location::RequiresRegister()) {
  const Register in = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  __ DoubleToFloat(result, in);
}

EMIT_NATIVE_CODE(FloatToDouble, 1, Location::RequiresRegister()) {
  const Register in = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  __ FloatToDouble(result, in);
}

EMIT_NATIVE_CODE(InvokeMathCFunction,
                 InputCount(),
                 Location::RequiresRegister()) {
  const Register left = locs()->in(0).reg();
  const Register result = locs()->out(0).reg();
  if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
    const Register right = locs()->in(1).reg();
    __ DPow(result, left, right);
  } else if (recognized_kind() == MethodRecognizer::kDoubleMod) {
    const Register right = locs()->in(1).reg();
    __ DMod(result, left, right);
  } else if (recognized_kind() == MethodRecognizer::kMathSin) {
    __ DSin(result, left);
  } else if (recognized_kind() == MethodRecognizer::kMathCos) {
    __ DCos(result, left);
  } else {
    Unsupported(compiler);
    UNREACHABLE();
  }
}

EMIT_NATIVE_CODE(MathMinMax, 2, Location::RequiresRegister()) {
  ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
         (op_kind() == MethodRecognizer::kMathMax));
  const Register left = locs()->in(0).reg();
  const Register right = locs()->in(1).reg();
  const Register result = locs()->out(0).reg();
  if (result_cid() == kDoubleCid) {
    if (op_kind() == MethodRecognizer::kMathMin) {
      __ DMin(result, left, right);
    } else {
      __ DMax(result, left, right);
    }
  } else {
    ASSERT(result_cid() == kSmiCid);
    if (op_kind() == MethodRecognizer::kMathMin) {
      __ Min(result, left, right);
    } else {
      __ Max(result, left, right);
    }
  }
}

static SimulatorBytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
  switch (kind) {
    case Token::kEQ:
      return SimulatorBytecode::kIfEqStrict;
    case Token::kNE:
      return SimulatorBytecode::kIfNeStrict;
    case Token::kLT:
      return SimulatorBytecode::kIfLt;
    case Token::kGT:
      return SimulatorBytecode::kIfGt;
    case Token::kLTE:
      return SimulatorBytecode::kIfLe;
    case Token::kGTE:
      return SimulatorBytecode::kIfGe;
    default:
      UNREACHABLE();
      return SimulatorBytecode::kTrap;
  }
}

static SimulatorBytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
  switch (kind) {
    case Token::kEQ:
      return SimulatorBytecode::kIfDEq;
    case Token::kNE:
      return SimulatorBytecode::kIfDNe;
    case Token::kLT:
      return SimulatorBytecode::kIfDLt;
    case Token::kGT:
      return SimulatorBytecode::kIfDGt;
    case Token::kLTE:
      return SimulatorBytecode::kIfDLe;
    case Token::kGTE:
      return SimulatorBytecode::kIfDGe;
    default:
      UNREACHABLE();
      return SimulatorBytecode::kTrap;
  }
}

static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
                                     LocationSummary* locs,
                                     Token::Kind kind,
                                     BranchLabels labels) {
  Token::Kind comparison = kind;
  Condition condition = NEXT_IS_TRUE;
  if (labels.fall_through != labels.false_label) {
    // If we aren't falling through to the false label, we can save a Jump
    // instruction in the case that the true case is the fall through by
    // negating the sense of the test such that the instruction following the
    // test is the Jump to the false label.  In the case where both labels are
    // null we don't negate the sense of the test.
    condition = NEXT_IS_FALSE;
    comparison = Token::NegateComparison(kind);
  }
  if (compiler->is_optimizing()) {
    const Register left = locs->in(0).reg();
    const Register right = locs->in(1).reg();
    __ Emit(SimulatorBytecode::Encode(OpcodeForSmiCondition(comparison), left,
                                      right));
    return condition;
  } else {
    switch (kind) {
      case Token::kEQ:
        __ IfEqStrictTOS();
        break;
      case Token::kNE:
        __ IfNeStrictTOS();
        break;
      case Token::kLT:
        __ IfSmiLtTOS();
        break;
      case Token::kLTE:
        __ IfSmiLeTOS();
        break;
      case Token::kGT:
        __ IfSmiGtTOS();
        break;
      case Token::kGTE:
        __ IfSmiGeTOS();
        break;
      default:
        UNIMPLEMENTED();
    }
    return condition;
  }
}

static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
                                        LocationSummary* locs,
                                        Token::Kind kind) {
  const Register left = locs->in(0).reg();
  const Register right = locs->in(1).reg();
  Token::Kind comparison = kind;
  // For double comparisons we can't flip the condition like with smi
  // comparisons because of NaN which will compare false for all except !=
  // operations.
  // TODO(fschneider): Change the block order instead in DBC so that the
  // false block in always the fall-through block.
  Condition condition = NEXT_IS_TRUE;
  __ Emit(SimulatorBytecode::Encode(OpcodeForDoubleCondition(comparison), left,
                                    right));
  return condition;
}

Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                                   BranchLabels labels) {
  if (operation_cid() == kSmiCid) {
    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
  } else {
    ASSERT(operation_cid() == kDoubleCid);
    return EmitDoubleComparisonOp(compiler, locs(), kind());
  }
}

Condition EqualityCompareInstr::GetNextInstructionCondition(
    FlowGraphCompiler* compiler,
    BranchLabels labels) {
  if (operation_cid() == kSmiCid) {
    return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
                                                       : NEXT_IS_TRUE;
  } else {
    ASSERT(operation_cid() == kDoubleCid);
    return NEXT_IS_TRUE;
  }
}

DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister());

Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
                                                BranchLabels labels) {
  if (operation_cid() == kSmiCid) {
    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
  } else {
    ASSERT(operation_cid() == kDoubleCid);
    return EmitDoubleComparisonOp(compiler, locs(), kind());
  }
}

Condition RelationalOpInstr::GetNextInstructionCondition(
    FlowGraphCompiler* compiler,
    BranchLabels labels) {
  if (operation_cid() == kSmiCid) {
    return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
                                                       : NEXT_IS_TRUE;
  } else {
    ASSERT(operation_cid() == kDoubleCid);
    return NEXT_IS_TRUE;
  }
}

DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister())

EMIT_NATIVE_CODE(CheckArrayBound, 2) {
  const Register length = locs()->in(kLengthPos).reg();
  const Register index = locs()->in(kIndexPos).reg();
  const intptr_t index_cid = this->index()->Type()->ToCid();
  if (index_cid != kSmiCid) {
    __ CheckSmi(index);
    compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound,
                        (generalized_ ? ICData::kGeneralized : 0) |
                            (licm_hoisted_ ? ICData::kHoisted : 0));
  }
  __ IfULe(length, index);
  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound,
                      (generalized_ ? ICData::kGeneralized : 0) |
                          (licm_hoisted_ ? ICData::kHoisted : 0));
}

}  // namespace dart

#endif  // defined TARGET_ARCH_DBC
