// Copyright (c) 2013, 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/deopt_instructions.h"

#include "vm/assembler.h"
#include "vm/code_patcher.h"
#include "vm/intermediate_language.h"
#include "vm/locations.h"
#include "vm/parser.h"
#include "vm/stack_frame.h"

namespace dart {

DEFINE_FLAG(bool, compress_deopt_info, true,
            "Compress the size of the deoptimization info for optimized code.");
DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, trace_deoptimization_verbose);


DeoptContext::DeoptContext(const StackFrame* frame,
                           const Code& code,
                           DestFrameOptions dest_options,
                           fpu_register_t* fpu_registers,
                           intptr_t* cpu_registers)
    : code_(code.raw()),
      object_table_(Array::null()),
      deopt_info_(DeoptInfo::null()),
      dest_frame_is_allocated_(false),
      dest_frame_(NULL),
      dest_frame_size_(0),
      source_frame_is_allocated_(false),
      source_frame_(NULL),
      source_frame_size_(0),
      cpu_registers_(cpu_registers),
      fpu_registers_(fpu_registers),
      num_args_(0),
      deopt_reason_(ICData::kDeoptUnknown),
      isolate_(Isolate::Current()),
      deferred_boxes_(NULL),
      deferred_object_refs_(NULL),
      deferred_objects_count_(0),
      deferred_objects_(NULL) {
  object_table_ = code.object_table();

  ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown;
  const DeoptInfo& deopt_info =
      DeoptInfo::Handle(code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason));
  ASSERT(!deopt_info.IsNull());
  deopt_info_ = deopt_info.raw();
  deopt_reason_ = deopt_reason;

  const Function& function = Function::Handle(code.function());

  // Do not include incoming arguments if there are optional arguments
  // (they are copied into local space at method entry).
  num_args_ =
      function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();

  // The fixed size section of the (fake) Dart frame called via a stub by the
  // optimized function contains FP, PP (ARM and MIPS only), PC-marker and
  // return-address. This section is copied as well, so that its contained
  // values can be updated before returning to the deoptimized function.
  source_frame_size_ =
      + kDartFrameFixedSize  // For saved values below sp.
      + ((frame->fp() - frame->sp()) / kWordSize)  // For frame size incl. sp.
      + 1  // For fp.
      + kParamEndSlotFromFp  // For saved values above fp.
      + num_args_;  // For arguments.
  source_frame_ = reinterpret_cast<intptr_t*>(
      frame->sp() - (kDartFrameFixedSize * kWordSize));

  if (dest_options == kDestIsOriginalFrame) {
    // Work from a copy of the source frame.
    intptr_t* original_frame = source_frame_;
    source_frame_ = new intptr_t[source_frame_size_];
    ASSERT(source_frame_ != NULL);
    for (intptr_t i = 0; i < source_frame_size_; i++) {
      source_frame_[i] = original_frame[i];
    }
    source_frame_is_allocated_ = true;
  }
  caller_fp_ = GetSourceFp();

  dest_frame_size_ = deopt_info.FrameSize();

  if (dest_options == kDestIsAllocated) {
    dest_frame_ = new intptr_t[dest_frame_size_];
    ASSERT(source_frame_ != NULL);
    for (intptr_t i = 0; i < dest_frame_size_; i++) {
      dest_frame_[i] = 0;
    }
    dest_frame_is_allocated_ = true;
  }

  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
    OS::PrintErr(
        "Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
        deopt_reason,
        DeoptReasonToCString(deopt_reason_),
        frame->pc(),
        function.ToFullyQualifiedCString(),
        function.deoptimization_counter());
  }
}


DeoptContext::~DeoptContext() {
  // Delete memory for source frame and registers.
  if (source_frame_is_allocated_) {
    delete[] source_frame_;
  }
  source_frame_ = NULL;
  delete[] fpu_registers_;
  delete[] cpu_registers_;
  fpu_registers_ = NULL;
  cpu_registers_ = NULL;
  if (dest_frame_is_allocated_) {
    delete[] dest_frame_;
  }
  dest_frame_ = NULL;

  // Delete all deferred objects.
  for (intptr_t i = 0; i < deferred_objects_count_; i++) {
    delete deferred_objects_[i];
  }
  delete[] deferred_objects_;
  deferred_objects_ = NULL;
  deferred_objects_count_ = 0;
}


void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_table_));
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&deopt_info_));

  // Visit any object pointers on the destination stack.
  if (dest_frame_is_allocated_) {
    for (intptr_t i = 0; i < dest_frame_size_; i++) {
      if (dest_frame_[i] != 0) {
        visitor->VisitPointer(reinterpret_cast<RawObject**>(&dest_frame_[i]));
      }
    }
  }
}


intptr_t DeoptContext::DestStackAdjustment() const {
  return (dest_frame_size_
          - kDartFrameFixedSize
          - num_args_
          - kParamEndSlotFromFp
          - 1);  // For fp.
}


intptr_t DeoptContext::GetSourceFp() const {
  return source_frame_[source_frame_size_ - 1 - num_args_ -
                       kParamEndSlotFromFp];
}


intptr_t DeoptContext::GetSourcePp() const {
  return source_frame_[source_frame_size_ - 1 - num_args_ -
                       kParamEndSlotFromFp +
                       StackFrame::SavedCallerPpSlotFromFp()];
}


intptr_t DeoptContext::GetSourcePc() const {
  return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp];
}


intptr_t DeoptContext::GetCallerFp() const {
  return caller_fp_;
}


void DeoptContext::SetCallerFp(intptr_t caller_fp) {
  caller_fp_ = caller_fp;
}


static bool IsObjectInstruction(DeoptInstr::Kind kind) {
  switch (kind) {
    case DeoptInstr::kConstant:
    case DeoptInstr::kStackSlot:
    case DeoptInstr::kDoubleStackSlot:
    case DeoptInstr::kInt64StackSlot:
    case DeoptInstr::kInt64StackSlotPair:
    case DeoptInstr::kFloat32x4StackSlot:
    case DeoptInstr::kInt32x4StackSlot:
    case DeoptInstr::kFloat64x2StackSlot:
    case DeoptInstr::kPp:
    case DeoptInstr::kCallerPp:
    case DeoptInstr::kMaterializedObjectRef:
      return true;

    case DeoptInstr::kRegister:
    case DeoptInstr::kFpuRegister:
    case DeoptInstr::kInt64RegisterPair:
    case DeoptInstr::kInt64StackSlotRegister:
    case DeoptInstr::kFloat32x4FpuRegister:
    case DeoptInstr::kInt32x4FpuRegister:
    case DeoptInstr::kFloat64x2FpuRegister:
      // TODO(turnidge): Sometimes we encounter a deopt instruction
      // with a register source while deoptimizing frames during
      // debugging but we haven't saved our register set.  This
      // happens specifically when using the VMService to inspect the
      // stack.  In that case, the register values will have been
      // saved before the StackOverflow runtime call but we do not
      // actually keep track of which registers were saved and
      // restored.
      //
      // It is possible to save this information at the point of the
      // StackOverflow runtime call but would require a bit of magic
      // to either make sure that the registers are pushed on the
      // stack in a predictable fashion or that we save enough
      // information to recover them after the fact.
      //
      // For now, we punt on these instructions.
      return false;

    case DeoptInstr::kRetAddress:
    case DeoptInstr::kPcMarker:
    case DeoptInstr::kCallerFp:
    case DeoptInstr::kCallerPc:
      return false;

    case DeoptInstr::kSuffix:
    case DeoptInstr::kMaterializeObject:
    default:
      // We should not encounter these instructions when filling stack slots.
      UNREACHABLE();
      return false;
  }
  UNREACHABLE();
  return false;
}


void DeoptContext::FillDestFrame() {
  const Code& code = Code::Handle(code_);
  const DeoptInfo& deopt_info = DeoptInfo::Handle(deopt_info_);

  const intptr_t len = deopt_info.TranslationLength();
  GrowableArray<DeoptInstr*> deopt_instructions(len);
  const Array& deopt_table = Array::Handle(code.deopt_info_array());
  ASSERT(!deopt_table.IsNull());
  deopt_info.ToInstructions(deopt_table, &deopt_instructions);

  const intptr_t frame_size = deopt_info.FrameSize();

  // For now, we never place non-objects in the deoptimized frame if
  // the destination frame is a copy.  This allows us to copy the
  // deoptimized frame into an Array.
  const bool objects_only = dest_frame_is_allocated_;

  // All kMaterializeObject instructions are emitted before the instructions
  // that describe stack frames. Skip them and defer materialization of
  // objects until the frame is fully reconstructed and it is safe to perform
  // GC.
  // Arguments (class of the instance to allocate and field-value pairs) are
  // described as part of the expression stack for the bottom-most deoptimized
  // frame. They will be used during materialization and removed from the stack
  // right before control switches to the unoptimized code.
  const intptr_t num_materializations = deopt_info.NumMaterializations();
  PrepareForDeferredMaterialization(num_materializations);
  for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
       from_index < num_materializations;
       from_index++) {
    const intptr_t field_count =
        DeoptInstr::GetFieldCount(deopt_instructions[from_index]);
    intptr_t* args = GetDestFrameAddressAt(to_index);
    DeferredObject* obj = new DeferredObject(field_count, args);
    SetDeferredObjectAt(from_index, obj);
    to_index += obj->ArgumentCount();
  }

  // Populate stack frames.
  for (intptr_t to_index = frame_size - 1, from_index = len - 1;
       to_index >= 0;
       to_index--, from_index--) {
    intptr_t* to_addr = GetDestFrameAddressAt(to_index);
    DeoptInstr* instr = deopt_instructions[from_index];
    if (!objects_only || IsObjectInstruction(instr->kind())) {
      instr->Execute(this, to_addr);
    } else {
      *reinterpret_cast<RawObject**>(to_addr) = Object::null();
    }
  }

  if (FLAG_trace_deoptimization_verbose) {
    intptr_t* start = dest_frame_;
    for (intptr_t i = 0; i < frame_size; i++) {
      OS::PrintErr("*%" Pd ". [%" Px "] %#014" Px " [%s]\n",
                   i,
                   reinterpret_cast<uword>(&start[i]),
                   start[i],
                   deopt_instructions[i + (len - frame_size)]->ToCString());
    }
  }
}


static void FillDeferredSlots(DeoptContext* deopt_context,
                              DeferredSlot** slot_list) {
  DeferredSlot* slot = *slot_list;
  *slot_list = NULL;

  while (slot != NULL) {
    DeferredSlot* current = slot;
    slot = slot->next();

    current->Materialize(deopt_context);

    delete current;
  }
}


// Materializes all deferred objects.  Returns the total number of
// artificial arguments used during deoptimization.
intptr_t DeoptContext::MaterializeDeferredObjects() {
  // First materialize all unboxed "primitive" values (doubles, mints, simd)
  // then materialize objects. The order is important: objects might be
  // referencing boxes allocated on the first step. At the same time
  // objects can't be referencing other deferred objects because storing
  // an object into a field is always conservatively treated as escaping by
  // allocation sinking and load forwarding.
  FillDeferredSlots(this, &deferred_boxes_);
  FillDeferredSlots(this, &deferred_object_refs_);

  // Compute total number of artificial arguments used during deoptimization.
  intptr_t deopt_arg_count = 0;
  for (intptr_t i = 0; i < DeferredObjectsCount(); i++) {
    deopt_arg_count += GetDeferredObject(i)->ArgumentCount();
  }

  // Since this is the only step where GC can occur during deoptimization,
  // use it to report the source line where deoptimization occured.
  if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
    DartFrameIterator iterator;
    StackFrame* top_frame = iterator.NextFrame();
    ASSERT(top_frame != NULL);
    const Code& code = Code::Handle(top_frame->LookupDartCode());
    const Function& top_function = Function::Handle(code.function());
    const Script& script = Script::Handle(top_function.script());
    const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc());
    intptr_t line, column;
    script.GetTokenLocation(token_pos, &line, &column);
    String& line_string = String::Handle(script.GetLine(line));
    OS::PrintErr("  Function: %s\n", top_function.ToFullyQualifiedCString());
    OS::PrintErr("  Line %" Pd ": '%s'\n", line, line_string.ToCString());
    OS::PrintErr("  Deopt args: %" Pd "\n", deopt_arg_count);
  }

  return deopt_arg_count;
}


RawArray* DeoptContext::DestFrameAsArray() {
  ASSERT(dest_frame_ != NULL && dest_frame_is_allocated_);
  const Array& dest_array =
      Array::Handle(Array::New(dest_frame_size_));
  Object& obj = Object::Handle();
  for (intptr_t i = 0; i < dest_frame_size_; i++) {
    obj = reinterpret_cast<RawObject*>(dest_frame_[i]);
    dest_array.SetAt(i, obj);
  }
  return dest_array.raw();
}


// Deoptimization instruction moving value from optimized frame at
// 'source_index' to specified slots in the unoptimized frame.
// 'source_index' represents the slot index of the frame (0 being
// first argument) and accounts for saved return address, frame
// pointer, pool pointer and pc marker.
class DeoptStackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptStackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kStackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "s%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    intptr_t* source_addr =
        deopt_context->GetSourceFrameAddressAt(source_index);
    *dest_addr = *source_addr;
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr);
};


class DeoptDoubleStackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptDoubleStackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "ds%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    double* source_addr = reinterpret_cast<double*>(
        deopt_context->GetSourceFrameAddressAt(source_index));
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferDoubleMaterialization(
        *source_addr, reinterpret_cast<RawDouble**>(dest_addr));
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptDoubleStackSlotInstr);
};


class DeoptInt64StackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptInt64StackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "int64 stack slot:%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    int64_t* source_addr = reinterpret_cast<int64_t*>(
        deopt_context->GetSourceFrameAddressAt(source_index));
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    if (Smi::IsValid64(*source_addr)) {
      *dest_addr = reinterpret_cast<intptr_t>(
          Smi::New(static_cast<intptr_t>(*source_addr)));
    } else {
      deopt_context->DeferMintMaterialization(
          *source_addr, reinterpret_cast<RawMint**>(dest_addr));
    }
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotInstr);
};


class DeoptFloat32x4StackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptFloat32x4StackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "f32x4s%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>(
        deopt_context->GetSourceFrameAddressAt(source_index));
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferFloat32x4Materialization(
        *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr));
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4StackSlotInstr);
};


class DeoptFloat64x2StackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptFloat64x2StackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kFloat64x2StackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "f64x2s%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>(
        deopt_context->GetSourceFrameAddressAt(source_index));
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferFloat64x2Materialization(
        *source_addr, reinterpret_cast<RawFloat64x2**>(dest_addr));
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptFloat64x2StackSlotInstr);
};


class DeoptInt32x4StackSlotInstr : public DeoptInstr {
 public:
  explicit DeoptInt32x4StackSlotInstr(intptr_t source_index)
      : stack_slot_index_(source_index) {
    ASSERT(stack_slot_index_ >= 0);
  }

  virtual intptr_t source_index() const { return stack_slot_index_; }
  virtual DeoptInstr::Kind kind() const { return kInt32x4StackSlot; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "ui32x4s%" Pd "", stack_slot_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t source_index =
       deopt_context->source_frame_size() - stack_slot_index_ - 1;
    simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>(
        deopt_context->GetSourceFrameAddressAt(source_index));
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferInt32x4Materialization(
        *source_addr, reinterpret_cast<RawInt32x4**>(dest_addr));
  }

 private:
  const intptr_t stack_slot_index_;  // First argument is 0, always >= 0.

  DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4StackSlotInstr);
};


// Deoptimization instruction creating return address using function and
// deopt-id stored at 'object_table_index'.
class DeoptRetAddressInstr : public DeoptInstr {
 public:
  DeoptRetAddressInstr(intptr_t object_table_index, intptr_t deopt_id)
      : object_table_index_(object_table_index), deopt_id_(deopt_id) {
    ASSERT(object_table_index >= 0);
    ASSERT(deopt_id >= 0);
  }

  explicit DeoptRetAddressInstr(intptr_t source_index)
      : object_table_index_(ObjectTableIndex::decode(source_index)),
        deopt_id_(DeoptId::decode(source_index)) {
  }

  virtual intptr_t source_index() const {
    return ObjectTableIndex::encode(object_table_index_) |
        DeoptId::encode(deopt_id_);
  }

  virtual DeoptInstr::Kind kind() const { return kRetAddress; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    Code& code = Code::Handle(deopt_context->isolate());
    code ^= deopt_context->ObjectAt(object_table_index_);
    ASSERT(!code.IsNull());
    uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
                                                PcDescriptors::kDeopt);
    ASSERT(continue_at_pc != 0);
    *dest_addr = continue_at_pc;

    uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall);
    if (pc != 0) {
      // If the deoptimization happened at an IC call, update the IC data
      // to avoid repeated deoptimization at the same site next time around.
      ICData& ic_data = ICData::Handle();
      CodePatcher::GetInstanceCallAt(pc, code, &ic_data);
      if (!ic_data.IsNull()) {
        ic_data.AddDeoptReason(deopt_context->deopt_reason());
      }
    } else if (deopt_context->deopt_reason() ==
               ICData::kDeoptHoistedCheckClass) {
      // Prevent excessive deoptimization.
      Function::Handle(code.function()).set_allows_hoisting_check_class(false);
    }
  }

  intptr_t object_table_index() const { return object_table_index_; }
  intptr_t deopt_id() const { return deopt_id_; }

 private:
  static const intptr_t kFieldWidth = kBitsPerWord / 2;
  class ObjectTableIndex : public BitField<intptr_t, 0, kFieldWidth> { };
  class DeoptId : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };

  const intptr_t object_table_index_;
  const intptr_t deopt_id_;

  DISALLOW_COPY_AND_ASSIGN(DeoptRetAddressInstr);
};


// Deoptimization instruction moving a constant stored at 'object_table_index'.
class DeoptConstantInstr : public DeoptInstr {
 public:
  explicit DeoptConstantInstr(intptr_t object_table_index)
      : object_table_index_(object_table_index) {
    ASSERT(object_table_index >= 0);
  }

  virtual intptr_t source_index() const { return object_table_index_; }
  virtual DeoptInstr::Kind kind() const { return kConstant; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "const oti:%" Pd "", object_table_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    const Object& obj = Object::Handle(
        deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_));
    *reinterpret_cast<RawObject**>(dest_addr) = obj.raw();
  }

 private:
  const intptr_t object_table_index_;

  DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr);
};


// Deoptimization instruction moving a CPU register.
class DeoptRegisterInstr: public DeoptInstr {
 public:
  explicit DeoptRegisterInstr(intptr_t reg_as_int)
      : reg_(static_cast<Register>(reg_as_int)) {}

  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
  virtual DeoptInstr::Kind kind() const { return kRegister; }

  virtual const char* ToCString() const {
    return Assembler::RegisterName(reg_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    *dest_addr = deopt_context->RegisterValue(reg_);
  }

 private:
  const Register reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr);
};


// Deoptimization instruction moving an XMM register.
class DeoptFpuRegisterInstr: public DeoptInstr {
 public:
  explicit DeoptFpuRegisterInstr(intptr_t reg_as_int)
      : reg_(static_cast<FpuRegister>(reg_as_int)) {}

  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
  virtual DeoptInstr::Kind kind() const { return kFpuRegister; }

  virtual const char* ToCString() const {
    return Assembler::FpuRegisterName(reg_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    double value = deopt_context->FpuRegisterValue(reg_);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferDoubleMaterialization(
        value, reinterpret_cast<RawDouble**>(dest_addr));
  }

 private:
  const FpuRegister reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptFpuRegisterInstr);
};


class DeoptInt64RegisterPairInstr: public DeoptInstr {
 public:
  DeoptInt64RegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int)
      : lo_reg_(static_cast<Register>(lo_reg_as_int)),
        hi_reg_(static_cast<Register>(hi_reg_as_int)) {}

  virtual intptr_t source_index() const {
    return EncodeRegisters(static_cast<intptr_t>(lo_reg_),
                           static_cast<intptr_t>(hi_reg_));
  }
  virtual DeoptInstr::Kind kind() const { return kInt64RegisterPair; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "int64 register pair: %s,%s", Assembler::RegisterName(hi_reg_),
                                      Assembler::RegisterName(lo_reg_));
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    uint32_t lo_value = deopt_context->RegisterValue(lo_reg_);
    int32_t hi_value = deopt_context->RegisterValue(hi_reg_);
    int64_t value = Utils::LowHighTo64Bits(lo_value, hi_value);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    if (Smi::IsValid64(value)) {
      *dest_addr = reinterpret_cast<intptr_t>(
          Smi::New(static_cast<intptr_t>(value)));
    } else {
      deopt_context->DeferMintMaterialization(
          value, reinterpret_cast<RawMint**>(dest_addr));
    }
  }

  static const intptr_t kFieldWidth = kBitsPerWord / 2;
  class LoRegister : public BitField<intptr_t, 0, kFieldWidth> { };
  class HiRegister : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
  static intptr_t EncodeRegisters(intptr_t lo_reg_as_int,
                                  intptr_t hi_reg_as_int) {
    return LoRegister::encode(lo_reg_as_int) |
           HiRegister::encode(hi_reg_as_int);
  }

  static intptr_t DecodeLoRegister(intptr_t v) {
    return LoRegister::decode(v);
  }

  static intptr_t DecodeHiRegister(intptr_t v) {
    return HiRegister::decode(v);
  }

 private:
  const Register lo_reg_;
  const Register hi_reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptInt64RegisterPairInstr);
};


class DeoptInt64StackSlotPairInstr: public DeoptInstr {
 public:
  DeoptInt64StackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot)
      : lo_slot_(static_cast<Register>(lo_slot)),
        hi_slot_(static_cast<Register>(hi_slot)) {}

  virtual intptr_t source_index() const {
    return EncodeSlots(static_cast<intptr_t>(lo_slot_),
                       static_cast<intptr_t>(hi_slot_));
  }
  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotPair; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "int64 stack slots: %" Pd", %" Pd "", lo_slot_, hi_slot_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t lo_source_index =
        deopt_context->source_frame_size() - lo_slot_ - 1;
    int32_t* lo_source_addr = reinterpret_cast<int32_t*>(
        deopt_context->GetSourceFrameAddressAt(lo_source_index));
    intptr_t hi_source_index =
       deopt_context->source_frame_size() - hi_slot_ - 1;
    int32_t* hi_source_addr = reinterpret_cast<int32_t*>(
        deopt_context->GetSourceFrameAddressAt(hi_source_index));
    int64_t value = Utils::LowHighTo64Bits(*lo_source_addr, *hi_source_addr);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    if (Smi::IsValid64(value)) {
      *dest_addr = reinterpret_cast<intptr_t>(
          Smi::New(static_cast<intptr_t>(value)));
    } else {
      deopt_context->DeferMintMaterialization(
          value, reinterpret_cast<RawMint**>(dest_addr));
    }
  }

  static const intptr_t kFieldWidth = kBitsPerWord / 2;
  class LoSlot : public BitField<intptr_t, 0, kFieldWidth> { };
  class HiSlot : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
  static intptr_t EncodeSlots(intptr_t lo_slot,
                              intptr_t hi_slot) {
    return LoSlot::encode(lo_slot) |
           HiSlot::encode(hi_slot);
  }

  static intptr_t DecodeLoSlot(intptr_t v) {
    return LoSlot::decode(v);
  }

  static intptr_t DecodeHiSlot(intptr_t v) {
    return HiSlot::decode(v);
  }

 private:
  const intptr_t lo_slot_;
  const intptr_t hi_slot_;

  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotPairInstr);
};


class DeoptInt64StackSlotRegisterInstr : public DeoptInstr {
 public:
  DeoptInt64StackSlotRegisterInstr(intptr_t source_index,
                                   intptr_t reg_as_int,
                                   bool flip)
      : slot_(source_index),
        reg_(static_cast<Register>(reg_as_int)),
        flip_(flip) {
    // when flip_ is false, stack slot is low bits and reg is high bits.
    // when flip_ is true, stack slot is high bits and reg is low bits.
  }

  virtual intptr_t source_index() const {
    return Encode(static_cast<intptr_t>(slot_),
                  static_cast<intptr_t>(reg_),
                  flip_ ? 1 : 0);
  }
  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotRegister; }

  virtual const char* ToCString() const {
    if (flip_) {
      return Isolate::Current()->current_zone()->PrintToString(
          "int64 reg: %s, stack slot:  %" Pd "", Assembler::RegisterName(reg_),
                                                 slot_);
    } else {
      return Isolate::Current()->current_zone()->PrintToString(
          "int64 stack slot: %" Pd", reg: %s", slot_,
                                               Assembler::RegisterName(reg_));
    }
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    intptr_t slot_source_index =
        deopt_context->source_frame_size() - slot_ - 1;
    int32_t* slot_source_addr = reinterpret_cast<int32_t*>(
        deopt_context->GetSourceFrameAddressAt(slot_source_index));
    int32_t slot_value = *slot_source_addr;
    int32_t reg_value = deopt_context->RegisterValue(reg_);
    int64_t value;
    if (flip_) {
      value = Utils::LowHighTo64Bits(reg_value, slot_value);
    } else {
      value = Utils::LowHighTo64Bits(slot_value, reg_value);
    }
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    if (Smi::IsValid64(value)) {
      *dest_addr = reinterpret_cast<intptr_t>(
          Smi::New(static_cast<intptr_t>(value)));
    } else {
      deopt_context->DeferMintMaterialization(
          value, reinterpret_cast<RawMint**>(dest_addr));
    }
  }

  static const intptr_t kFieldWidth = kBitsPerWord / 2;
  class Slot : public BitField<intptr_t, 0, kFieldWidth> { };
  class Reg : public BitField<intptr_t, kFieldWidth, kFieldWidth - 1> { };
  // 1 bit for the flip.
  class Flip : public BitField<intptr_t, kFieldWidth * 2 - 1, 1> { };

  static intptr_t Encode(intptr_t slot,
                         intptr_t reg_as_int,
                         bool flip) {
    return Slot::encode(slot) |
           Reg::encode(reg_as_int) |
           Flip::encode(flip ? 1 : 0);
  }

  static intptr_t DecodeSlot(intptr_t v) {
    return Slot::decode(v);
  }

  static intptr_t DecodeReg(intptr_t v) {
    return Reg::decode(v);
  }

  static bool DecodeFlip(intptr_t v) {
    return Flip::decode(v);
  }

 private:
  const intptr_t slot_;
  const Register reg_;
  const bool flip_;
  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotRegisterInstr);
};


// Deoptimization instruction moving an XMM register.
class DeoptFloat32x4FpuRegisterInstr: public DeoptInstr {
 public:
  explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int)
      : reg_(static_cast<FpuRegister>(reg_as_int)) {}

  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
  virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "%s(f32x4)", Assembler::FpuRegisterName(reg_));
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferFloat32x4Materialization(
        value, reinterpret_cast<RawFloat32x4**>(dest_addr));
  }

 private:
  const FpuRegister reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptFloat32x4FpuRegisterInstr);
};


class DeoptFloat64x2FpuRegisterInstr: public DeoptInstr {
 public:
  explicit DeoptFloat64x2FpuRegisterInstr(intptr_t reg_as_int)
      : reg_(static_cast<FpuRegister>(reg_as_int)) {}

  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
  virtual DeoptInstr::Kind kind() const { return kFloat64x2FpuRegister; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "%s(f64x2)", Assembler::FpuRegisterName(reg_));
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferFloat64x2Materialization(
        value, reinterpret_cast<RawFloat64x2**>(dest_addr));
  }

 private:
  const FpuRegister reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptFloat64x2FpuRegisterInstr);
};


// Deoptimization instruction moving an XMM register.
class DeoptInt32x4FpuRegisterInstr: public DeoptInstr {
 public:
  explicit DeoptInt32x4FpuRegisterInstr(intptr_t reg_as_int)
      : reg_(static_cast<FpuRegister>(reg_as_int)) {}

  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
  virtual DeoptInstr::Kind kind() const { return kInt32x4FpuRegister; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "%s(f32x4)", Assembler::FpuRegisterName(reg_));
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_);
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferInt32x4Materialization(
        value, reinterpret_cast<RawInt32x4**>(dest_addr));
  }

 private:
  const FpuRegister reg_;

  DISALLOW_COPY_AND_ASSIGN(DeoptInt32x4FpuRegisterInstr);
};


// Deoptimization instruction creating a PC marker for the code of
// function at 'object_table_index'.
class DeoptPcMarkerInstr : public DeoptInstr {
 public:
  explicit DeoptPcMarkerInstr(intptr_t object_table_index)
      : object_table_index_(object_table_index) {
    ASSERT(object_table_index >= 0);
  }

  virtual intptr_t source_index() const { return object_table_index_; }
  virtual DeoptInstr::Kind kind() const { return kPcMarker; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "pcmark oti:%" Pd "", object_table_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    Code& code = Code::Handle(deopt_context->isolate());
    code ^= deopt_context->ObjectAt(object_table_index_);
    if (code.IsNull()) {
      // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0.
      *dest_addr = 0;
      return;
    }
    const Function& function =
        Function::Handle(deopt_context->isolate(), code.function());
    ASSERT(function.HasCode());
    const intptr_t pc_marker =
        code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset;
    *dest_addr = pc_marker;
    // Increment the deoptimization counter. This effectively increments each
    // function occurring in the optimized frame.
    function.set_deoptimization_counter(function.deoptimization_counter() + 1);
    if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
      OS::PrintErr("Deoptimizing %s (count %d)\n",
          function.ToFullyQualifiedCString(),
          function.deoptimization_counter());
    }
    // Clear invocation counter so that hopefully the function gets reoptimized
    // only after more feedback has been collected.
    function.set_usage_counter(0);
    if (function.HasOptimizedCode()) {
      function.SwitchToUnoptimizedCode();
    }
  }

 private:
  intptr_t object_table_index_;

  DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr);
};


// Deoptimization instruction creating a pool pointer for the code of
// function at 'object_table_index'.
class DeoptPpInstr : public DeoptInstr {
 public:
  explicit DeoptPpInstr(intptr_t object_table_index)
      : object_table_index_(object_table_index) {
    ASSERT(object_table_index >= 0);
  }

  virtual intptr_t source_index() const { return object_table_index_; }
  virtual DeoptInstr::Kind kind() const { return kPp; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "pp oti:%" Pd "", object_table_index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    Code& code = Code::Handle(deopt_context->isolate());
    code ^= deopt_context->ObjectAt(object_table_index_);
    ASSERT(!code.IsNull());
    const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool());
    *dest_addr = pp;
  }

 private:
  intptr_t object_table_index_;

  DISALLOW_COPY_AND_ASSIGN(DeoptPpInstr);
};


// Deoptimization instruction copying the caller saved FP from optimized frame.
class DeoptCallerFpInstr : public DeoptInstr {
 public:
  DeoptCallerFpInstr() {}

  virtual intptr_t source_index() const { return 0; }
  virtual DeoptInstr::Kind kind() const { return kCallerFp; }

  virtual const char* ToCString() const {
    return "callerfp";
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    *dest_addr = deopt_context->GetCallerFp();
    deopt_context->SetCallerFp(reinterpret_cast<intptr_t>(
        dest_addr - (kSavedCallerFpSlotFromFp * kWordSize)));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr);
};


// Deoptimization instruction copying the caller saved PP from optimized frame.
class DeoptCallerPpInstr : public DeoptInstr {
 public:
  DeoptCallerPpInstr() {}

  virtual intptr_t source_index() const { return 0; }
  virtual DeoptInstr::Kind kind() const { return kCallerPp; }

  virtual const char* ToCString() const {
    return "callerpp";
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    *dest_addr = deopt_context->GetSourcePp();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DeoptCallerPpInstr);
};


// Deoptimization instruction copying the caller return address from optimized
// frame.
class DeoptCallerPcInstr : public DeoptInstr {
 public:
  DeoptCallerPcInstr() {}

  virtual intptr_t source_index() const { return 0; }
  virtual DeoptInstr::Kind kind() const { return kCallerPc; }

  virtual const char* ToCString() const {
    return "callerpc";
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    *dest_addr = deopt_context->GetSourcePc();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr);
};


// Deoptimization instruction that indicates the rest of this DeoptInfo is a
// suffix of another one.  The suffix contains the info number (0 based
// index in the deopt table of the DeoptInfo to share) and the length of the
// suffix.
class DeoptSuffixInstr : public DeoptInstr {
 public:
  DeoptSuffixInstr(intptr_t info_number, intptr_t suffix_length)
      : info_number_(info_number), suffix_length_(suffix_length) {
    ASSERT(info_number >= 0);
    ASSERT(suffix_length >= 0);
  }

  explicit DeoptSuffixInstr(intptr_t source_index)
      : info_number_(InfoNumber::decode(source_index)),
        suffix_length_(SuffixLength::decode(source_index)) {
  }

  virtual intptr_t source_index() const {
    return InfoNumber::encode(info_number_) |
        SuffixLength::encode(suffix_length_);
  }
  virtual DeoptInstr::Kind kind() const { return kSuffix; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "suffix %" Pd ":%" Pd, info_number_, suffix_length_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    // The deoptimization info is uncompressed by translating away suffixes
    // before executing the instructions.
    UNREACHABLE();
  }

 private:
  // Static decoder functions in DeoptInstr have access to the bitfield
  // definitions.
  friend class DeoptInstr;

  static const intptr_t kFieldWidth = kBitsPerWord / 2;
  class InfoNumber : public BitField<intptr_t, 0, kFieldWidth> { };
  class SuffixLength : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };

  const intptr_t info_number_;
  const intptr_t suffix_length_;

  DISALLOW_COPY_AND_ASSIGN(DeoptSuffixInstr);
};


// Write reference to a materialized object with the given index into the
// stack slot.
class DeoptMaterializedObjectRefInstr : public DeoptInstr {
 public:
  explicit DeoptMaterializedObjectRefInstr(intptr_t index)
      : index_(index) {
    ASSERT(index >= 0);
  }

  virtual intptr_t source_index() const { return index_; }
  virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "mat ref #%" Pd "", index_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
    deopt_context->DeferMaterializedObjectRef(
        index_, dest_addr);
  }

 private:
  intptr_t index_;

  DISALLOW_COPY_AND_ASSIGN(DeoptMaterializedObjectRefInstr);
};


// Materialize object with the given number of fields.
// Arguments for materialization (class and field-value pairs) are pushed
// to the expression stack of the bottom-most frame.
class DeoptMaterializeObjectInstr : public DeoptInstr {
 public:
  explicit DeoptMaterializeObjectInstr(intptr_t field_count)
      : field_count_(field_count) {
    ASSERT(field_count >= 0);
  }

  virtual intptr_t source_index() const { return field_count_; }
  virtual DeoptInstr::Kind kind() const { return kMaterializeObject; }

  virtual const char* ToCString() const {
    return Isolate::Current()->current_zone()->PrintToString(
        "mat obj len:%" Pd "", field_count_);
  }

  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
    // This instructions are executed manually by the DeoptimizeWithDeoptInfo.
    UNREACHABLE();
  }

 private:
  intptr_t field_count_;

  DISALLOW_COPY_AND_ASSIGN(DeoptMaterializeObjectInstr);
};


intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index,
                                  intptr_t* info_number) {
  *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index);
  return DeoptSuffixInstr::SuffixLength::decode(source_index);
}


uword DeoptInstr::GetRetAddress(DeoptInstr* instr,
                                const Array& object_table,
                                Code* code) {
  ASSERT(instr->kind() == kRetAddress);
  DeoptRetAddressInstr* ret_address_instr =
      static_cast<DeoptRetAddressInstr*>(instr);
  // The following assert may trigger when displaying a backtrace
  // from the simulator.
  ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id()));
  ASSERT(!object_table.IsNull());
  ASSERT(code != NULL);
  *code ^= object_table.At(ret_address_instr->object_table_index());
  ASSERT(!code->IsNull());
  uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(),
                                    PcDescriptors::kDeopt);
  ASSERT(res != 0);
  return res;
}


DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) {
  Kind kind = static_cast<Kind>(kind_as_int);
  switch (kind) {
    case kStackSlot: return new DeoptStackSlotInstr(source_index);
    case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index);
    case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index);
    case kFloat32x4StackSlot:
        return new DeoptFloat32x4StackSlotInstr(source_index);
    case kFloat64x2StackSlot:
        return new DeoptFloat64x2StackSlotInstr(source_index);
    case kInt32x4StackSlot:
        return new DeoptInt32x4StackSlotInstr(source_index);
    case kRetAddress: return new DeoptRetAddressInstr(source_index);
    case kConstant: return new DeoptConstantInstr(source_index);
    case kRegister: return new DeoptRegisterInstr(source_index);
    case kFpuRegister: return new DeoptFpuRegisterInstr(source_index);
    case kInt64RegisterPair: {
      intptr_t lo_reg_as_int =
          DeoptInt64RegisterPairInstr::LoRegister::decode(source_index);
      intptr_t hi_reg_as_int =
          DeoptInt64RegisterPairInstr::HiRegister::decode(source_index);
      return new DeoptInt64RegisterPairInstr(lo_reg_as_int, hi_reg_as_int);
    }
    case kInt64StackSlotPair: {
      intptr_t lo_slot =
          DeoptInt64StackSlotPairInstr::LoSlot::decode(source_index);
      intptr_t hi_slot =
          DeoptInt64StackSlotPairInstr::HiSlot::decode(source_index);
      return new DeoptInt64StackSlotPairInstr(lo_slot, hi_slot);
    }
    case kInt64StackSlotRegister: {
      intptr_t slot =
          DeoptInt64StackSlotRegisterInstr::Slot::decode(source_index);
      intptr_t reg_as_int =
          DeoptInt64StackSlotRegisterInstr::Reg::decode(source_index);
      bool flip = DeoptInt64StackSlotRegisterInstr::Flip::decode(source_index);
      return new DeoptInt64StackSlotRegisterInstr(slot, reg_as_int, flip);
    }
    case kFloat32x4FpuRegister:
        return new DeoptFloat32x4FpuRegisterInstr(source_index);
    case kFloat64x2FpuRegister:
        return new DeoptFloat64x2FpuRegisterInstr(source_index);
    case kInt32x4FpuRegister:
        return new DeoptInt32x4FpuRegisterInstr(source_index);
    case kPcMarker: return new DeoptPcMarkerInstr(source_index);
    case kPp: return new DeoptPpInstr(source_index);
    case kCallerFp: return new DeoptCallerFpInstr();
    case kCallerPp: return new DeoptCallerPpInstr();
    case kCallerPc: return new DeoptCallerPcInstr();
    case kSuffix: return new DeoptSuffixInstr(source_index);
    case kMaterializedObjectRef:
        return new DeoptMaterializedObjectRefInstr(source_index);
    case kMaterializeObject:
      return new DeoptMaterializeObjectInstr(source_index);
  }
  UNREACHABLE();
  return NULL;
}


class DeoptInfoBuilder::TrieNode : public ZoneAllocated {
 public:
  // Construct the root node representing the implicit "shared" terminator
  // at the end of each deopt info.
  TrieNode() : instruction_(NULL), info_number_(-1), children_(16) { }

  // Construct a node representing a written instruction.
  TrieNode(DeoptInstr* instruction, intptr_t info_number)
      : instruction_(instruction), info_number_(info_number), children_(4) { }

  intptr_t info_number() const { return info_number_; }

  void AddChild(TrieNode* child) {
    if (child != NULL) children_.Add(child);
  }

  TrieNode* FindChild(const DeoptInstr& instruction) {
    for (intptr_t i = 0; i < children_.length(); ++i) {
      TrieNode* child = children_[i];
      if (child->instruction_->Equals(instruction)) return child;
    }
    return NULL;
  }

 private:
  const DeoptInstr* instruction_;  // Instruction that was written.
  const intptr_t info_number_;  // Index of the deopt info it was written to.

  GrowableArray<TrieNode*> children_;
};


DeoptInfoBuilder::DeoptInfoBuilder(const intptr_t num_args)
    : instructions_(),
      object_table_(GrowableObjectArray::Handle(
          GrowableObjectArray::New(Heap::kOld))),
      num_args_(num_args),
      trie_root_(new TrieNode()),
      current_info_number_(0),
      frame_start_(-1),
      materializations_() {
}


intptr_t DeoptInfoBuilder::FindOrAddObjectInTable(const Object& obj) const {
  for (intptr_t i = 0; i < object_table_.Length(); i++) {
    if (object_table_.At(i) == obj.raw()) {
      return i;
    }
  }
  // Add object.
  const intptr_t result = object_table_.Length();
  object_table_.Add(obj, Heap::kOld);
  return result;
}


intptr_t DeoptInfoBuilder::CalculateStackIndex(
    const Location& source_loc) const {
  return source_loc.stack_index() < 0 ?
            source_loc.stack_index() + num_args_ :
            source_loc.stack_index() + num_args_ + kDartFrameFixedSize;
}


void DeoptInfoBuilder::AddReturnAddress(const Code& code,
                                        intptr_t deopt_id,
                                        intptr_t dest_index) {
  // Check that deopt_id exists.
  // TODO(vegorov): verify after deoptimization targets as well.
#ifdef DEBUG
  ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
         (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
#endif
  const intptr_t object_table_index = FindOrAddObjectInTable(code);
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id));
}


void DeoptInfoBuilder::AddPcMarker(const Code& code,
                                   intptr_t dest_index) {
  intptr_t object_table_index = FindOrAddObjectInTable(code);
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptPcMarkerInstr(object_table_index));
}


void DeoptInfoBuilder::AddPp(const Code& code,
                             intptr_t dest_index) {
  intptr_t object_table_index = FindOrAddObjectInTable(code);
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptPpInstr(object_table_index));
}


void DeoptInfoBuilder::AddCopy(Value* value,
                               const Location& source_loc,
                               const intptr_t dest_index) {
  DeoptInstr* deopt_instr = NULL;
  if (source_loc.IsConstant()) {
    intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant());
    deopt_instr = new DeoptConstantInstr(object_table_index);
  } else if (source_loc.IsRegister()) {
    ASSERT(value->definition()->representation() == kTagged);
    deopt_instr = new DeoptRegisterInstr(source_loc.reg());
  } else if (source_loc.IsFpuRegister()) {
    if (value->definition()->representation() == kUnboxedDouble) {
      deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg());
    } else if (value->definition()->representation() == kUnboxedFloat32x4) {
      deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg());
    } else if (value->definition()->representation() == kUnboxedInt32x4) {
      deopt_instr = new DeoptInt32x4FpuRegisterInstr(source_loc.fpu_reg());
    } else {
      ASSERT(value->definition()->representation() == kUnboxedFloat64x2);
      deopt_instr = new DeoptFloat64x2FpuRegisterInstr(source_loc.fpu_reg());
    }
  } else if (source_loc.IsStackSlot()) {
    ASSERT(value->definition()->representation() == kTagged);
    intptr_t source_index = CalculateStackIndex(source_loc);
    deopt_instr = new DeoptStackSlotInstr(source_index);
  } else if (source_loc.IsDoubleStackSlot()) {
    intptr_t source_index = CalculateStackIndex(source_loc);
    if (value->definition()->representation() == kUnboxedDouble) {
      deopt_instr = new DeoptDoubleStackSlotInstr(source_index);
    } else {
      ASSERT(value->definition()->representation() == kUnboxedMint);
      deopt_instr = new DeoptInt64StackSlotInstr(source_index);
    }
  } else if (source_loc.IsQuadStackSlot()) {
    intptr_t source_index = CalculateStackIndex(source_loc);
    if (value->definition()->representation() == kUnboxedFloat32x4) {
      deopt_instr = new DeoptFloat32x4StackSlotInstr(source_index);
    } else if (value->definition()->representation() == kUnboxedInt32x4) {
      deopt_instr = new DeoptInt32x4StackSlotInstr(source_index);
    } else {
      ASSERT(value->definition()->representation() == kUnboxedFloat64x2);
      deopt_instr = new DeoptFloat64x2StackSlotInstr(source_index);
    }
  } else if (source_loc.IsPairLocation()) {
    ASSERT(value->definition()->representation() == kUnboxedMint);
    // There are four cases to consider here:
    // (R = Register, S = Stack slot).
    // 1) R, R.
    // 2) S, S.
    // 3) R, S.
    // 4) S, R.
    PairLocation* pair = source_loc.AsPairLocation();
    if (pair->At(0).IsRegister() && pair->At(1).IsRegister()) {
      deopt_instr = new DeoptInt64RegisterPairInstr(pair->At(0).reg(),
                                                    pair->At(1).reg());
    } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) {
      deopt_instr = new DeoptInt64StackSlotPairInstr(
          CalculateStackIndex(pair->At(0)),
          CalculateStackIndex(pair->At(1)));
    } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) {
      deopt_instr = new DeoptInt64StackSlotRegisterInstr(
          CalculateStackIndex(pair->At(1)),
          pair->At(0).reg(),
          true);
    } else {
      ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister());
      deopt_instr = new DeoptInt64StackSlotRegisterInstr(
          CalculateStackIndex(pair->At(0)),
          pair->At(1).reg(),
          false);
    }
  } else if (source_loc.IsInvalid() &&
             value->definition()->IsMaterializeObject()) {
    const intptr_t index = FindMaterialization(
        value->definition()->AsMaterializeObject());
    ASSERT(index >= 0);
    deopt_instr = new DeoptMaterializedObjectRefInstr(index);
  } else {
    UNREACHABLE();
  }
  ASSERT(dest_index == FrameSize());
  ASSERT(deopt_instr != NULL);
  instructions_.Add(deopt_instr);
}


void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) {
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptCallerFpInstr());
}


void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) {
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptCallerPpInstr());
}


void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) {
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new DeoptCallerPcInstr());
}


void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) {
  ASSERT(dest_index == FrameSize());
  intptr_t object_table_index = FindOrAddObjectInTable(obj);
  instructions_.Add(new DeoptConstantInstr(object_table_index));
}


void DeoptInfoBuilder::AddMaterialization(MaterializeObjectInstr* mat) {
  const intptr_t index = FindMaterialization(mat);
  if (index >= 0) {
    return;  // Already added.
  }
  materializations_.Add(mat);

  // Count initialized fields and emit kMaterializeObject instruction.
  // There is no need to write nulls into fields because object is null
  // initialized by default.
  intptr_t non_null_fields = 0;
  for (intptr_t i = 0; i < mat->InputCount(); i++) {
    if (!mat->InputAt(i)->BindsToConstantNull()) {
      non_null_fields++;
    }
  }

  instructions_.Add(new DeoptMaterializeObjectInstr(non_null_fields));
}


intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) {
  ASSERT(dest_index == kDartFrameFixedSize);
  for (intptr_t i = 0; i < materializations_.length(); i++) {
    MaterializeObjectInstr* mat = materializations_[i];
    // Class of the instance to allocate.
    AddConstant(mat->cls(), dest_index++);
    for (intptr_t i = 0; i < mat->InputCount(); i++) {
      if (!mat->InputAt(i)->BindsToConstantNull()) {
        // Emit offset-value pair.
        AddConstant(Smi::Handle(Smi::New(mat->FieldOffsetAt(i))),
                    dest_index++);
        AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++);
      }
    }
  }
  return dest_index;
}


intptr_t DeoptInfoBuilder::FindMaterialization(
    MaterializeObjectInstr* mat) const {
  for (intptr_t i = 0; i < materializations_.length(); i++) {
    if (materializations_[i] == mat) {
      return i;
    }
  }
  return -1;
}


RawDeoptInfo* DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
  // TODO(vegorov): enable compression of deoptimization info containing object
  // materialization instructions.
  const bool disable_compression =
      (instructions_[0]->kind() == DeoptInstr::kMaterializeObject);

  intptr_t length = instructions_.length();

  // Count the number of instructions that are a shared suffix of some deopt
  // info already written.
  TrieNode* suffix = trie_root_;
  intptr_t suffix_length = 0;
  if (FLAG_compress_deopt_info && !disable_compression) {
    for (intptr_t i = length - 1; i >= 0; --i) {
      TrieNode* node = suffix->FindChild(*instructions_[i]);
      if (node == NULL) break;
      suffix = node;
      ++suffix_length;
    }
  }

  // Allocate space for the translation.  If the shared suffix is longer
  // than one instruction, we replace it with a single suffix instruction.
  if (suffix_length > 1) length -= (suffix_length - 1);
  const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(length));

  // Write the unshared instructions and build their sub-tree.
  TrieNode* node = NULL;
  intptr_t write_count = (suffix_length > 1) ? length - 1 : length;
  for (intptr_t i = 0; i < write_count; ++i) {
    DeoptInstr* instr = instructions_[i];
    deopt_info.SetAt(i, instr->kind(), instr->source_index());
    TrieNode* child = node;
    node = new TrieNode(instr, current_info_number_);
    node->AddChild(child);
  }

  if (suffix_length > 1) {
    suffix->AddChild(node);
    DeoptInstr* instr =
        new DeoptSuffixInstr(suffix->info_number(), suffix_length);
    deopt_info.SetAt(length - 1, instr->kind(), instr->source_index());
  } else {
    trie_root_->AddChild(node);
  }

  ASSERT(deopt_info.VerifyDecompression(instructions_, deopt_table));
  instructions_.Clear();
  materializations_.Clear();
  frame_start_ = -1;

  ++current_info_number_;
  return deopt_info.raw();
}


intptr_t DeoptTable::SizeFor(intptr_t length) {
  return length * kEntrySize;
}

void DeoptTable::SetEntry(const Array& table,
                          intptr_t index,
                          const Smi& offset,
                          const DeoptInfo& info,
                          const Smi& reason) {
  ASSERT((table.Length() % kEntrySize) == 0);
  intptr_t i = index * kEntrySize;
  table.SetAt(i, offset);
  table.SetAt(i + 1, info);
  table.SetAt(i + 2, reason);
}


intptr_t DeoptTable::GetLength(const Array& table) {
  ASSERT((table.Length() % kEntrySize) == 0);
  return table.Length() / kEntrySize;
}


void DeoptTable::GetEntry(const Array& table,
                          intptr_t index,
                          Smi* offset,
                          DeoptInfo* info,
                          Smi* reason) {
  intptr_t i = index * kEntrySize;
  *offset ^= table.At(i);
  *info ^= table.At(i + 1);
  *reason ^= table.At(i + 2);
}

}  // namespace dart
