// 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::kMintStackSlotPair:
    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::kMintRegisterPair:
    case DeoptInstr::kMintStackSlotRegister:
    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 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_,
                                                RawPcDescriptors::kDeopt);
    ASSERT(continue_at_pc != 0);
    *dest_addr = continue_at_pc;

    uword pc = code.GetPcForDeoptId(deopt_id_, RawPcDescriptors::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 DeoptMintRegisterPairInstr: public DeoptInstr {
 public:
  DeoptMintRegisterPairInstr(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 kMintRegisterPair; }

  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::IsValid(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(DeoptMintRegisterPairInstr);
};


class DeoptMintStackSlotPairInstr: public DeoptInstr {
 public:
  DeoptMintStackSlotPairInstr(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 kMintStackSlotPair; }

  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::IsValid(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(DeoptMintStackSlotPairInstr);
};


class DeoptMintStackSlotRegisterInstr : public DeoptInstr {
 public:
  DeoptMintStackSlotRegisterInstr(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 kMintStackSlotRegister; }

  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::IsValid(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(DeoptMintStackSlotRegisterInstr);
};


// 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(),
                                    RawPcDescriptors::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 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 kMintRegisterPair: {
      intptr_t lo_reg_as_int =
          DeoptMintRegisterPairInstr::LoRegister::decode(source_index);
      intptr_t hi_reg_as_int =
          DeoptMintRegisterPairInstr::HiRegister::decode(source_index);
      return new DeoptMintRegisterPairInstr(lo_reg_as_int, hi_reg_as_int);
    }
    case kMintStackSlotPair: {
      intptr_t lo_slot =
          DeoptMintStackSlotPairInstr::LoSlot::decode(source_index);
      intptr_t hi_slot =
          DeoptMintStackSlotPairInstr::HiSlot::decode(source_index);
      return new DeoptMintStackSlotPairInstr(lo_slot, hi_slot);
    }
    case kMintStackSlotRegister: {
      intptr_t slot =
          DeoptMintStackSlotRegisterInstr::Slot::decode(source_index);
      intptr_t reg_as_int =
          DeoptMintStackSlotRegisterInstr::Reg::decode(source_index);
      bool flip = DeoptMintStackSlotRegisterInstr::Flip::decode(source_index);
      return new DeoptMintStackSlotRegisterInstr(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(Isolate* isolate, const intptr_t num_args)
    : isolate_(isolate),
      instructions_(),
      object_table_(GrowableObjectArray::Handle(
          GrowableObjectArray::New(Heap::kOld))),
      num_args_(num_args),
      trie_root_(new(isolate) 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, RawPcDescriptors::kDeopt) != 0));
#endif
  const intptr_t object_table_index = FindOrAddObjectInTable(code);
  ASSERT(dest_index == FrameSize());
  instructions_.Add(
      new(isolate()) 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(isolate()) 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(isolate()) 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(isolate()) DeoptConstantInstr(object_table_index);
  } else if (source_loc.IsRegister()) {
    ASSERT(value->definition()->representation() == kTagged);
    deopt_instr = new(isolate()) DeoptRegisterInstr(source_loc.reg());
  } else if (source_loc.IsFpuRegister()) {
    if (value->definition()->representation() == kUnboxedDouble) {
      deopt_instr = new(isolate()) DeoptFpuRegisterInstr(source_loc.fpu_reg());
    } else if (value->definition()->representation() == kUnboxedFloat32x4) {
      deopt_instr =
          new(isolate()) DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg());
    } else if (value->definition()->representation() == kUnboxedInt32x4) {
      deopt_instr =
          new(isolate()) DeoptInt32x4FpuRegisterInstr(source_loc.fpu_reg());
    } else {
      ASSERT(value->definition()->representation() == kUnboxedFloat64x2);
      deopt_instr =
          new(isolate()) 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(isolate()) DeoptStackSlotInstr(source_index);
  } else if (source_loc.IsDoubleStackSlot()) {
    ASSERT(value->definition()->representation() == kUnboxedDouble);
    intptr_t source_index = CalculateStackIndex(source_loc);
    deopt_instr = new(isolate()) DeoptDoubleStackSlotInstr(source_index);
  } else if (source_loc.IsQuadStackSlot()) {
    intptr_t source_index = CalculateStackIndex(source_loc);
    if (value->definition()->representation() == kUnboxedFloat32x4) {
      deopt_instr = new(isolate()) DeoptFloat32x4StackSlotInstr(source_index);
    } else if (value->definition()->representation() == kUnboxedInt32x4) {
      deopt_instr = new(isolate()) DeoptInt32x4StackSlotInstr(source_index);
    } else {
      ASSERT(value->definition()->representation() == kUnboxedFloat64x2);
      deopt_instr = new(isolate()) 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(isolate()) DeoptMintRegisterPairInstr(pair->At(0).reg(),
                                                    pair->At(1).reg());
    } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) {
      deopt_instr = new(isolate()) DeoptMintStackSlotPairInstr(
          CalculateStackIndex(pair->At(0)),
          CalculateStackIndex(pair->At(1)));
    } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) {
      deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr(
          CalculateStackIndex(pair->At(1)),
          pair->At(0).reg(),
          true);
    } else {
      ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister());
      deopt_instr = new(isolate()) DeoptMintStackSlotRegisterInstr(
          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(isolate()) 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(isolate()) DeoptCallerFpInstr());
}


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


void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) {
  ASSERT(dest_index == FrameSize());
  instructions_.Add(new(isolate()) 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(isolate()) 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(isolate()) 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(isolate(), 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(isolate()) TrieNode(instr, current_info_number_);
    node->AddChild(child);
  }

  if (suffix_length > 1) {
    suffix->AddChild(node);
    DeoptInstr* instr =
        new(isolate()) 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
