// Copyright 2011 Google Inc. All Rights Reserved.

#include "dex_verifier.h"

#include <iostream>

#include "class_linker.h"
#include "dex_file.h"
#include "dex_instruction.h"
#include "dex_instruction_visitor.h"
#include "dex_verifier.h"
#include "logging.h"
#include "runtime.h"
#include "stringpiece.h"

namespace art {

#define k_  kRegTypeUnknown
#define kU  kRegTypeUninit
#define kX  kRegTypeConflict
#define k0  kRegTypeZero
#define k1  kRegTypeOne
#define kZ  kRegTypeBoolean
#define ky  kRegTypeConstPosByte
#define kY  kRegTypeConstByte
#define kh  kRegTypeConstPosShort
#define kH  kRegTypeConstShort
#define kc  kRegTypeConstChar
#define ki  kRegTypeConstInteger
#define kb  kRegTypePosByte
#define kB  kRegTypeByte
#define ks  kRegTypePosShort
#define kS  kRegTypeShort
#define kC  kRegTypeChar
#define kI  kRegTypeInteger
#define kF  kRegTypeFloat
#define kN  kRegTypeConstLo
#define kn  kRegTypeConstHi
#define kJ  kRegTypeLongLo
#define kj  kRegTypeLongHi
#define kD  kRegTypeDoubleLo
#define kd  kRegTypeDoubleHi

const char DexVerifier::merge_table_[kRegTypeMAX][kRegTypeMAX] =
  {
    /* chk:  _  U  X  0  1  Z  y  Y  h  H  c  i  b  B  s  S  C  I  F  N  n  J  j  D  d */
    { /*_*/ k_,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
    { /*U*/ kX,kU,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
    { /*X*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
    { /*0*/ kX,kX,kX,k0,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*1*/ kX,kX,kX,kZ,k1,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*Z*/ kX,kX,kX,kZ,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*y*/ kX,kX,kX,ky,ky,ky,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*Y*/ kX,kX,kX,kY,kY,kY,kY,kY,kh,kH,kc,ki,kB,kB,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*h*/ kX,kX,kX,kh,kh,kh,kh,kh,kh,kH,kc,ki,ks,kS,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*H*/ kX,kX,kX,kH,kH,kH,kH,kH,kH,kH,kc,ki,kS,kS,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*c*/ kX,kX,kX,kc,kc,kc,kc,kc,kc,kc,kc,ki,kC,kI,kC,kI,kC,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*i*/ kX,kX,kX,ki,ki,ki,ki,ki,ki,ki,ki,ki,kI,kI,kI,kI,kI,kI,kF,kX,kX,kX,kX,kX,kX },
    { /*b*/ kX,kX,kX,kb,kb,kb,kb,kB,ks,kS,kC,kI,kb,kB,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*B*/ kX,kX,kX,kB,kB,kB,kB,kB,kS,kS,kI,kI,kB,kB,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*s*/ kX,kX,kX,ks,ks,ks,ks,kS,ks,kS,kC,kI,ks,kS,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*S*/ kX,kX,kX,kS,kS,kS,kS,kS,kS,kS,kI,kI,kS,kS,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*C*/ kX,kX,kX,kC,kC,kC,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*I*/ kX,kX,kX,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kX,kX,kX,kX,kX,kX,kX },
    { /*F*/ kX,kX,kX,kF,kF,kF,kF,kF,kF,kF,kF,kF,kX,kX,kX,kX,kX,kX,kF,kX,kX,kX,kX,kX,kX },
    { /*N*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kN,kX,kJ,kX,kD,kX },
    { /*n*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kn,kX,kj,kX,kd },
    { /*J*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kJ,kX,kJ,kX,kX,kX },
    { /*j*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kj,kX,kj,kX,kX },
    { /*D*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kD,kX,kX,kX,kD,kX },
    { /*d*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kd,kX,kX,kX,kd },
  };

#undef k_
#undef kU
#undef kX
#undef k0
#undef k1
#undef kZ
#undef ky
#undef kY
#undef kh
#undef kH
#undef kc
#undef ki
#undef kb
#undef kB
#undef ks
#undef kS
#undef kC
#undef kI
#undef kF
#undef kN
#undef kn
#undef kJ
#undef kj
#undef kD
#undef kd

bool DexVerifier::VerifyClass(Class* klass) {
  if (klass->IsVerified()) {
    return true;
  }
  for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
    Method* method = klass->GetDirectMethod(i);
    if (!VerifyMethod(method)) {
        LOG(ERROR) << "Verifier rejected class "
                   << klass->GetDescriptor()->ToModifiedUtf8();
      return false;
    }
  }
  for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
    Method* method = klass->GetVirtualMethod(i);
    if (!VerifyMethod(method)) {
        LOG(ERROR) << "Verifier rejected class "
                   << klass->GetDescriptor()->ToModifiedUtf8();
      return false;
    }
  }
  return true;
}

bool DexVerifier::VerifyMethod(Method* method) {
  const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
  const DexFile::CodeItem* code_item =
      dex_file.GetCodeItem(method->GetCodeItemOffset());

  /*
   * Construct the verifier state container object.
   */
  VerifierData vdata(method, &dex_file, code_item);

  /*
   * If there aren't any instructions, make sure that's expected, then
   * exit successfully.
   */
  if (code_item == NULL) {
    if (!method->IsNative() && !method->IsAbstract()) {
      LOG(ERROR) << "VFY: zero-length code in concrete non-native method";
      return false;
    }
    return true;
  }

  /*
   * Sanity-check the register counts. ins + locals = registers, so make
   * sure that ins <= registers.
   */
  if (code_item->ins_size_ > code_item->registers_size_) {
    LOG(ERROR) << "VFY: bad register counts (ins=" << code_item->ins_size_
               << " regs=" << code_item->registers_size_;
    return false;
  }

  /*
   * Allocate and initialize an array to hold instruction data.
   */
  vdata.insn_flags_.reset(new InsnFlags[code_item->insns_size_]());

  /*
   * Run through the instructions and see if the width checks out.
   */
  if (!ComputeWidthsAndCountOps(&vdata)) {
    return false;
  }

  /*
   * Flag instructions guarded by a "try" block and check exception handlers.
   */
  if (!ScanTryCatchBlocks(&vdata)) {
    return false;
  }

  /*
   * Perform static instruction verification.
   */
  if (!VerifyInstructions(&vdata)) {
    return false;
  }

  /*
   * Perform code flow analysis.
   */
  if (!VerifyCodeFlow(&vdata)) {
    return false;
  }

  return true;
}

bool DexVerifier::VerifyInstructions(VerifierData* vdata) {
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
  const Instruction* inst = Instruction::At(ptr);

  /* Flag the start of the method as a branch target. */
  InsnSetBranchTarget(insn_flags, 0);

  uint32_t width = 0;
  uint32_t insns_size = code_item->insns_size_;

  while (width < insns_size) {
    if (!VerifyInstruction(vdata, inst, width)) {
      LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
                 << (int) inst->Opcode() << " at 0x" << width << std::dec;
      return false;
    }

    /* Flag instructions that are garbage collection points */
    if (inst->IsBranch() || inst->IsSwitch() || inst->IsThrow() ||
        inst->IsReturn()) {
      InsnSetGcPoint(insn_flags, width);
    }

    width += inst->Size();
    inst = inst->Next();
  }
  return true;
}

bool DexVerifier::VerifyInstruction(VerifierData* vdata,
    const Instruction* inst, uint32_t code_offset) {
  const DexFile* dex_file = vdata->dex_file_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  Instruction::DecodedInstruction dec_insn(inst);
  bool result = true;

  int argumentA = inst->GetVerifyTypeArgumentA();
  int argumentB = inst->GetVerifyTypeArgumentB();
  int argumentC = inst->GetVerifyTypeArgumentC();
  int extra_flags = inst->GetVerifyExtraFlags();

  switch (argumentA) {
    case Instruction::kVerifyRegA:
      result &= CheckRegisterIndex(code_item, dec_insn.vA_);
      break;
    case Instruction::kVerifyRegAWide:
      result &= CheckWideRegisterIndex(code_item, dec_insn.vA_);
      break;
  }

  switch (argumentB) {
    case Instruction::kVerifyRegB:
      result &= CheckRegisterIndex(code_item, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBField:
      result &= CheckFieldIndex(dex_file, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBMethod:
      result &= CheckMethodIndex(dex_file, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBNewInstance:
      result &= CheckNewInstance(dex_file, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBString:
      result &= CheckStringIndex(dex_file, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBType:
      result &= CheckTypeIndex(dex_file, dec_insn.vB_);
      break;
    case Instruction::kVerifyRegBWide:
      result &= CheckWideRegisterIndex(code_item, dec_insn.vB_);
      break;
  }

  switch (argumentC) {
    case Instruction::kVerifyRegC:
      result &= CheckRegisterIndex(code_item, dec_insn.vC_);
      break;
    case Instruction::kVerifyRegCField:
      result &= CheckFieldIndex(dex_file, dec_insn.vC_);
      break;
    case Instruction::kVerifyRegCNewArray:
      result &= CheckNewArray(dex_file, dec_insn.vC_);
      break;
    case Instruction::kVerifyRegCType:
      result &= CheckTypeIndex(dex_file, dec_insn.vC_);
      break;
    case Instruction::kVerifyRegCWide:
      result &= CheckWideRegisterIndex(code_item, dec_insn.vC_);
      break;
  }

  switch (extra_flags) {
    case Instruction::kVerifyArrayData:
      result &= CheckArrayData(code_item, code_offset);
      break;
    case Instruction::kVerifyBranchTarget:
      result &= CheckBranchTarget(code_item, insn_flags, code_offset);
      break;
    case Instruction::kVerifySwitchTargets:
      result &= CheckSwitchTargets(code_item, insn_flags, code_offset);
      break;
    case Instruction::kVerifyVarArg:
      result &= CheckVarArgRegs(code_item, dec_insn.vA_, dec_insn.arg_);
      break;
    case Instruction::kVerifyVarArgRange:
      result &= CheckVarArgRangeRegs(code_item, dec_insn.vA_, dec_insn.vC_);
      break;
    case Instruction::kVerifyError:
      LOG(ERROR) << "VFY: unexpected opcode " << std::hex
                 << (int) dec_insn.opcode_ << std::dec;
      result = false;
      break;
  }

  return result;
}

bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) {
  Method* method = vdata->method_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  uint16_t registers_size = code_item->registers_size_;
  uint32_t insns_size = code_item->insns_size_;
  bool generate_register_map = true;
  RegisterTable reg_table;

  if (registers_size * insns_size > 4*1024*1024) {
    LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
               << " insns_size=" << insns_size << ")";
  }

  /* Create and initialize register lists. */
  if (!InitRegisterTable(vdata, &reg_table,
      generate_register_map ? kTrackRegsGcPoints : kTrackRegsBranches)) {
    return false;
  }

  vdata->register_lines_ = reg_table.register_lines_.get();

  /* Allocate a map to hold the classes of uninitialized instances. */
  vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));

  /* Initialize register types of method arguments. */
  if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
    LOG(ERROR) << "VFY: bad signature '"
               << method->GetSignature()->ToModifiedUtf8() << "' for "
               << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
               << "." << method->GetName()->ToModifiedUtf8();
    return false;
  }

  /* Perform code flow verification. */
  if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
    return false;
  }

  /* Generate a register map. */
  if (generate_register_map) {
    RegisterMap* map = GenerateRegisterMapV(vdata);
    /*
     * Tuck the map into the Method. It will either get used directly or, if
     * we're in dexopt, will be packed up and appended to the DEX file.
     */
    // TODO: Put the map somewhere...
    delete map;
  }

  return true;
}

bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
  const uint16_t* insns = vdata->code_item_->insns_;
  uint32_t insns_size = vdata->code_item_->insns_size_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  const byte* ptr = reinterpret_cast<const byte*>(insns);
  const Instruction* inst = Instruction::At(ptr);
  size_t new_instance_count = 0;
  size_t monitor_enter_count = 0;
  size_t width = 0;

  while (width < insns_size) {
    Instruction::Code opcode = inst->Opcode();
    if (opcode == Instruction::NEW_INSTANCE) {
      new_instance_count++;
    } else if (opcode == Instruction::MONITOR_ENTER) {
      monitor_enter_count++;
    }

    insn_flags[width] |= inst->Size();
    width += inst->Size();
    inst = inst->Next();
  }

  if (width != insns_size) {
    LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
               << insns_size << ")";
    return false;
  }

  vdata->new_instance_count_ = new_instance_count;
  vdata->monitor_enter_count_ = monitor_enter_count;
  return true;
}

bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  uint32_t insns_size = code_item->insns_size_;
  uint32_t tries_size = code_item->tries_size_;

  if (tries_size == 0) {
    return true;
  }

  const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);

  for (uint32_t idx = 0; idx < tries_size; idx++) {
    const DexFile::TryItem* try_item = &tries[idx];
    uint32_t start = try_item->start_addr_;
    uint32_t end = start + try_item->insn_count_;

    if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
      LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
                 << " endAddr=" << end << " (size=" << insns_size << ")";
      return false;
    }

    if (InsnGetWidth(insn_flags, start) == 0) {
      LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
                 << start << ")";
      return false;
    }

    uint32_t addr;
    for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
      InsnSetInTry(insn_flags, addr);
    }
  }

  /* Iterate over each of the handlers to verify target addresses. */
  const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
  for (uint32_t idx = 0; idx < handlers_size; idx++) {
    DexFile::CatchHandlerIterator iterator(handlers_ptr);

    for (; !iterator.HasNext(); iterator.Next()) {
      uint32_t addr = iterator.Get().address_;
      if (InsnGetWidth(insn_flags, addr) == 0) {
        LOG(ERROR) << "VFY: exception handler starts at bad address ("
                   << addr << ")";
        return false;
      }

      InsnSetBranchTarget(insn_flags, addr);
    }

    handlers_ptr = iterator.GetData();
  }

  return true;
}

bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
    const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
    bool* pConditional, bool* selfOkay) {
  const uint16_t* insns = code_item->insns_ + cur_offset;

  switch (*insns & 0xff) {
    case Instruction::GOTO:
      *pOffset = ((int16_t) *insns) >> 8;
      *pConditional = false;
      *selfOkay = false;
      break;
    case Instruction::GOTO_32:
      *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
      *pConditional = false;
      *selfOkay = true;
      break;
    case Instruction::GOTO_16:
      *pOffset = (int16_t) insns[1];
      *pConditional = false;
      *selfOkay = false;
      break;
    case Instruction::IF_EQ:
    case Instruction::IF_NE:
    case Instruction::IF_LT:
    case Instruction::IF_GE:
    case Instruction::IF_GT:
    case Instruction::IF_LE:
    case Instruction::IF_EQZ:
    case Instruction::IF_NEZ:
    case Instruction::IF_LTZ:
    case Instruction::IF_GEZ:
    case Instruction::IF_GTZ:
    case Instruction::IF_LEZ:
      *pOffset = (int16_t) insns[1];
      *pConditional = true;
      *selfOkay = false;
      break;
    default:
      return false;
      break;
  }

  return true;
}

bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
    uint32_t cur_offset) {
  const uint32_t insn_count = code_item->insns_size_;
  const uint16_t* insns = code_item->insns_ + cur_offset;
  const uint16_t* array_data;
  int32_t array_data_offset;

  assert(cur_offset < insn_count);

  /* make sure the start of the array data table is in range */
  array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
  if ((int32_t) cur_offset + array_data_offset < 0 ||
      cur_offset + array_data_offset + 2 >= insn_count)
  {
    LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
               << ", data offset " << array_data_offset << ", count "
               << insn_count;
    return false;
  }

  /* offset to array data table is a relative branch-style offset */
  array_data = insns + array_data_offset;

  /* make sure the table is 32-bit aligned */
  if ((((uint32_t) array_data) & 0x03) != 0) {
    LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
               << ", data offset " << array_data_offset;
    return false;
  }

  uint32_t value_width = array_data[1];
  uint32_t value_count = *(uint32_t*) (&array_data[2]);
  uint32_t table_size = 4 + (value_width * value_count + 1) / 2;

  /* make sure the end of the switch is in range */
  if (cur_offset + array_data_offset + table_size > insn_count) {
    LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
               << ", data offset " << array_data_offset << ", end "
               << cur_offset + array_data_offset + table_size << ", count "
               << insn_count;
    return false;
  }

  return true;
}

bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().type_ids_size_) {
    LOG(ERROR) << "VFY: bad type index " << idx << " (max "
               << dex_file->GetHeader().type_ids_size_ << ")";
    return false;
  }

  const char* descriptor = dex_file->dexStringByTypeIdx(idx);
  if (descriptor[0] != 'L') {
    LOG(ERROR) << "VFY: can't call new-instance on type '"
               << descriptor << "'";
    return false;
  }

  return true;
}

bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().type_ids_size_) {
    LOG(ERROR) << "VFY: bad type index " << idx << " (max "
               << dex_file->GetHeader().type_ids_size_ << ")";
    return false;
  }

  int bracket_count = 0;
  const char* descriptor = dex_file->dexStringByTypeIdx(idx);
  const char* cp = descriptor;
  while (*cp++ == '[')
    bracket_count++;

  if (bracket_count == 0) {
    /* The given class must be an array type. */
    LOG(ERROR) << "VFY: can't new-array class '" << descriptor
               << "' (not an array)";
    return false;
  } else if (bracket_count > 255) {
    /* It is illegal to create an array of more than 255 dimensions. */
    LOG(ERROR) << "VFY: can't new-array class '" << descriptor
               << "' (exceeds limit)";
    return false;
  }

  return true;
}

bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().type_ids_size_) {
    LOG(ERROR) << "VFY: bad type index " << idx << " (max "
               << dex_file->GetHeader().type_ids_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().field_ids_size_) {
    LOG(ERROR) << "VFY: bad field index " << idx << " (max "
               << dex_file->GetHeader().field_ids_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().method_ids_size_) {
    LOG(ERROR) << "VFY: bad method index " << idx << " (max "
               << dex_file->GetHeader().method_ids_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
  if (idx >= dex_file->GetHeader().string_ids_size_) {
    LOG(ERROR) << "VFY: bad string index " << idx << " (max "
               << dex_file->GetHeader().string_ids_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
    uint32_t idx) {
  if (idx >= code_item->registers_size_) {
    LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
               << code_item->registers_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
    uint32_t idx) {
  if (idx + 1 >= code_item->registers_size_) {
    LOG(ERROR) << "VFY: wide register index out of range (" << idx
               << "+1 >= " << code_item->registers_size_ << ")";
    return false;
  }
  return true;
}

bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
    uint32_t vA, uint32_t arg[]) {
  uint16_t registers_size = code_item->registers_size_;
  uint32_t idx;

  if (vA > 5) {
    LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
    return false;
  }

  for (idx = 0; idx < vA; idx++) {
    if (arg[idx] > registers_size) {
      LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
                 << ") in non-range invoke (> " << registers_size << ")";
      return false;
    }
  }

  return true;
}

bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
    uint32_t vA, uint32_t vC) {
  uint16_t registers_size = code_item->registers_size_;

  /*
   * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
   * so there's no risk of integer overflow when adding them here.
   */
  if (vA + vC > registers_size) {
    LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
               << " in range invoke (> " << registers_size << ")";
    return false;
  }

  return true;
}

bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
    InsnFlags insn_flags[], uint32_t cur_offset) {
  const uint32_t insn_count = code_item->insns_size_;
  const uint16_t* insns = code_item->insns_ + cur_offset;
  const uint16_t* switch_insns;
  uint16_t expected_signature;
  uint32_t switch_count, table_size;
  int32_t switch_offset, keys_offset, targets_offset;
  int32_t offset, abs_offset;
  uint32_t targ;

  /* make sure the start of the switch is in range */
  switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
  if ((int32_t) cur_offset + switch_offset < 0 ||
      cur_offset + switch_offset + 2 >= insn_count) {
    LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
               << ", switch offset " << switch_offset << ", count "
               << insn_count;
    return false;
  }

  /* offset to switch table is a relative branch-style offset */
  switch_insns = insns + switch_offset;

  /* make sure the table is 32-bit aligned */
  if ((((uint32_t) switch_insns) & 0x03) != 0) {
    LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
               << ", switch offset " << switch_offset;
    return false;
  }

  switch_count = switch_insns[1];

  if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
    /* 0=sig, 1=count, 2/3=firstKey */
    targets_offset = 4;
    keys_offset = -1;
    expected_signature = Instruction::kPackedSwitchSignature;
  } else {
    /* 0=sig, 1=count, 2..count*2 = keys */
    keys_offset = 2;
    targets_offset = 2 + 2 * switch_count;
    expected_signature = Instruction::kSparseSwitchSignature;
  }
  table_size = targets_offset + switch_count * 2;

  if (switch_insns[0] != expected_signature) {
    LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
               << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
               << std::dec;
    return false;
  }

  /* make sure the end of the switch is in range */
  if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
      LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
                 << ", switch offset " << switch_offset << ", end "
                 << cur_offset + switch_offset + table_size << ", count "
                 << insn_count;
    return false;
  }

  /* for a sparse switch, verify the keys are in ascending order */
  if (keys_offset > 0 && switch_count > 1) {
    int32_t last_key;

    last_key = switch_insns[keys_offset] |
               (switch_insns[keys_offset + 1] << 16);
    for (targ = 1; targ < switch_count; targ++) {
      int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
                    (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
      if (key <= last_key) {
        LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
                   << ", this=" << key;
        return false;
      }

      last_key = key;
    }
  }

  /* verify each switch target */
  for (targ = 0; targ < switch_count; targ++) {
    offset = (int32_t) switch_insns[targets_offset + targ * 2] |
             (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
    abs_offset = cur_offset + offset;

    if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
        !InsnIsOpcode(insn_flags, abs_offset)) {
      LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
                 << std::hex << abs_offset << ") at " << cur_offset << std::dec
                 << "[" << targ << "]";
      return false;
    }
    InsnSetBranchTarget(insn_flags, abs_offset);
  }

  return true;
}

bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
    InsnFlags insn_flags[], uint32_t cur_offset) {
  const uint32_t insn_count = code_item->insns_size_;
  int32_t offset, abs_offset;
  bool isConditional, selfOkay;

  if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
                       &isConditional, &selfOkay))
    return false;

  if (!selfOkay && offset == 0) {
    LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
               << cur_offset << std::dec;
    return false;
  }

  /*
   * Check for 32-bit overflow. This isn't strictly necessary if we can
   * depend on the VM to have identical "wrap-around" behavior, but
   * it's unwise to depend on that.
   */
  if (((int64_t) cur_offset + (int64_t) offset) !=
      (int64_t) (cur_offset + offset)) {
    LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
               << std::dec << " +" << offset;
    return false;
  }
  abs_offset = cur_offset + offset;
  if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
      !InsnIsOpcode(insn_flags, abs_offset))
  {
    LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
               << std::hex << abs_offset << ") at " << cur_offset << std::dec;
    return false;
  }
  InsnSetBranchTarget(insn_flags, abs_offset);

  return true;
}

bool DexVerifier::InitRegisterTable(VerifierData* vdata,
    RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  uint16_t registers_size = code_item->registers_size_;
  uint32_t insns_size = code_item->insns_size_;
  uint32_t i;

  /*
   * Every address gets a RegisterLine struct. This is wasteful, but
   * not so much that it's worth chasing through an extra level of
   * indirection.
   */
  reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
  reg_table->register_lines_.reset(new RegisterLine[insns_size]());

  assert(insns_size > 0);

  bool track_monitors;
  //if (gDvm.monitorVerification) {
    //track_monitors = (vdata->monitor_enter_count_ != 0);
  //} else {
    track_monitors = false;
  //}

  /*
   * Allocate entries in the sparse register line table.
   *
   * There is a RegisterLine associated with every address, but not
   * every RegisterLine has non-NULL pointers to storage for its fields.
   */
  for (i = 0; i < insns_size; i++) {
    bool interesting;

    switch (track_regs_for) {
      case kTrackRegsAll:
        interesting = InsnIsOpcode(insn_flags, i);
        break;
      case kTrackRegsGcPoints:
        interesting = InsnIsGcPoint(insn_flags, i) ||
                      InsnIsBranchTarget(insn_flags, i);
        break;
      case kTrackRegsBranches:
        interesting = InsnIsBranchTarget(insn_flags, i);
        break;
      default:
        return false;
    }

    if (interesting) {
      reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
          track_monitors);
    }
  }

  /*
   * Allocate space for our "temporary" register lines.
   */
  reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
  reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);

  return true;
}

DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
    VerifierData* vdata) {
  Method* method = vdata->method_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  size_t new_instance_count = vdata->new_instance_count_;

  if (IsInitMethod(method)) {
    new_instance_count++;
  }

  /*
   * Allocate the header and map as a single unit.
   *
   * TODO: consider having a static instance so we can avoid allocations.
   * I don't think the verifier is guaranteed to be single-threaded when
   * running in the VM (rather than dexopt), so that must be taken into
   * account.
   */
  UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);

  size_t idx = 0;
  if (IsInitMethod(method)) {
    uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
  }

  /*
   * Run through and find the new-instance instructions.
   */
  uint32_t addr = 0;
  uint32_t insns_size = code_item->insns_size_;
  const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
  const Instruction* inst = Instruction::At(ptr);
  while (addr < insns_size) {
    Instruction::Code opcode = inst->Opcode();
    if (opcode == Instruction::NEW_INSTANCE) {
      uninit_map->map_[idx++].addr_ = addr;
    }

    addr += inst->Size();
    inst = inst->Next();
  }

  assert(idx == new_instance_count);
  return uninit_map;
}

bool DexVerifier::IsInitMethod(const Method* method) {
  return (method->GetName()->Equals("<init>"));
}

Class* DexVerifier::LookupClassByDescriptor(const Method* method,
    const char* descriptor, VerifyError* failure) {
  /*
   * The compiler occasionally puts references to nonexistent classes in
   * signatures. For example, if you have a non-static inner class with no
   * constructor, the compiler provides a private <init> for you.
   * Constructing the class requires <init>(parent), but the outer class can't
   * call that because the method is private. So the compiler generates a
   * package-scope <init>(parent,bogus) method that just calls the regular
   * <init> (the "bogus" part being necessary to distinguish the signature of
   * the synthetic method). Treating the bogus class as an instance of
   * java.lang.Object allows the verifier to process the class successfully.
   */
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  const ClassLoader* class_loader =
      method->GetDeclaringClass()->GetClassLoader();
  Class* klass = class_linker->FindClass(descriptor, class_loader);

  if (klass == NULL) {
    Thread::Current()->ClearException();
    if (strchr(descriptor, '$') != NULL) {
      LOG(INFO) << "VFY: unable to find class referenced in signature ("
                << descriptor << ")";
    } else {
      LOG(ERROR) << "VFY: unable to find class referenced in signature ("
                 << descriptor << ")";
    }

    /* Check if the descriptor is an array. */
    if (descriptor[0] == '[') {
      /*
       * There should never be a problem loading primitive arrays.
       */
      if (descriptor[1] != 'L' && descriptor[1] != '[') {
        LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
                   << "'";
        *failure = VERIFY_ERROR_GENERIC;
      }

      /*
       * Try to continue with base array type. This will let us pass basic
       * stuff (e.g. get array len) that wouldn't fly with an Object. This
       * is NOT correct if the missing type is a primitive array, but we
       * should never have a problem loading those. (I'm not convinced this
       * is correct or even useful. Just use Object here?)
       */
      klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
    } else if (descriptor[0] == 'L') {
      /*
       * We are looking at a non-array reference descriptor;
       * try to continue with base reference type.
       */
      klass = class_linker->FindSystemClass("Ljava/lang/Object;");
    } else {
      /* We are looking at a primitive type. */
      LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
      *failure = VERIFY_ERROR_GENERIC;
    }

    if (klass == NULL) {
      *failure = VERIFY_ERROR_GENERIC;
    }
  }

  if (klass->IsPrimitive()) {
    LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
    *failure = VERIFY_ERROR_GENERIC;
    klass = NULL;
  }

  return klass;
}

Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
    VerifyError* failure) {
  assert(sig[0] == 'L');
  size_t end = sig.find(';');

  if (end == std::string::npos) {
    LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
    *failure = VERIFY_ERROR_GENERIC;
    return NULL;
  }

  return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
      failure);
}

Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
    std::string sig, VerifyError* failure) {
  assert(sig[0] == '[');
  size_t end = 0;

  while (sig[end] == '[')
    end++;

  if (sig[end] == 'L') {
    end = sig.find(';');
    if (end == std::string::npos) {
      LOG(ERROR) << "VFY: bad signature component '" << sig
                 << "' (missing ';')";
      *failure = VERIFY_ERROR_GENERIC;
      return NULL;
    }
  }

  return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
      failure);
}

bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
{
  Method* method = vdata->method_;
  const DexFile* dex_file = vdata->dex_file_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();

  int arg_start = code_item->registers_size_ - code_item->ins_size_;
  int expected_args = code_item->ins_size_;   /* long/double count as two */
  int actual_args = 0;

  assert(arg_start >= 0);      /* should have been verified earlier */

  /*
   * Include the "this" pointer.
   */
  if (!method->IsStatic()) {
    /*
     * If this is a constructor for a class other than java.lang.Object,
     * mark the first ("this") argument as uninitialized. This restricts
     * field access until the superclass constructor is called.
     */
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
    if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
      int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
          method->GetDeclaringClass());
      assert(idx == 0);
      reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
    } else {
      reg_types[arg_start + actual_args] =
          RegTypeFromClass(method->GetDeclaringClass());
    }
    actual_args++;
  }

  const DexFile::ProtoId& proto_id =
      dex_file->GetProtoId(method->GetProtoIdx());
  DexFile::ParameterIterator iterator(*dex_file, proto_id);
  VerifyError failure = VERIFY_ERROR_NONE;

  for (; iterator.HasNext(); iterator.Next()) {
    const char* descriptor = iterator.GetDescriptor();

    if (descriptor == NULL) {
      break;
    }

    if (actual_args >= expected_args) {
      LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
                 << descriptor << ")";
      return false;
    }

    switch (*descriptor) {
      case 'L':
      case '[':
        /*
         * We assume that reference arguments are initialized. The only way
         * it could be otherwise (assuming the caller was verified) is if
         * the current method is <init>, but in that case it's effectively
         * considered initialized the instant we reach here (in the sense
         * that we can return without doing anything or call virtual methods).
         */
        {
          Class* klass =
              LookupClassByDescriptor(method, descriptor, &failure);
          if (failure != VERIFY_ERROR_NONE)
            return false;
          reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
        }
        actual_args++;
        break;
      case 'Z':
        reg_types[arg_start + actual_args] = kRegTypeBoolean;
        actual_args++;
        break;
      case 'C':
        reg_types[arg_start + actual_args] = kRegTypeChar;
        actual_args++;
        break;
      case 'B':
        reg_types[arg_start + actual_args] = kRegTypeByte;
        actual_args++;
        break;
      case 'I':
        reg_types[arg_start + actual_args] = kRegTypeInteger;
        actual_args++;
        break;
      case 'S':
        reg_types[arg_start + actual_args] = kRegTypeShort;
        actual_args++;
        break;
      case 'F':
        reg_types[arg_start + actual_args] = kRegTypeFloat;
        actual_args++;
        break;
      case 'D':
        reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
        reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
        actual_args += 2;
        break;
      case 'J':
        reg_types[arg_start + actual_args] = kRegTypeLongLo;
        reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
        actual_args += 2;
        break;
      default:
        LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
                   << "'";
        return false;
    }
  }

  if (actual_args != expected_args) {
    LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
               << actual_args;
    return false;
  }

  const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);

  /*
   * Validate return type. We don't do the type lookup; just want to make
   * sure that it has the right format. Only major difference from the
   * method argument format is that 'V' is supported.
   */
  switch (*descriptor) {
    case 'I':
    case 'C':
    case 'S':
    case 'B':
    case 'Z':
    case 'V':
    case 'F':
    case 'D':
    case 'J':
      if (*(descriptor + 1) != '\0')
        return false;
      break;
    case '[':
      /* single/multi, object/primitive */
      while (*++descriptor == '[')
        ;
      if (*descriptor == 'L') {
        while (*++descriptor != ';' && *descriptor != '\0')
          ;
        if (*descriptor != ';')
          return false;
      } else {
        if (*(descriptor+1) != '\0')
          return false;
      }
      break;
    case 'L':
      /* could be more thorough here, but shouldn't be required */
      while (*++descriptor != ';' && *descriptor != '\0')
        ;
      if (*descriptor != ';')
        return false;
      break;
    default:
      return false;
  }

  return true;
}

int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
    Class* klass) {
  int idx;
  assert(klass != NULL);

  /* TODO: binary search when num_entries > 8 */
  for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
    if (uninit_map->map_[idx].addr_ == addr) {
      if (uninit_map->map_[idx].klass_ != NULL &&
          uninit_map->map_[idx].klass_ != klass) {
        LOG(ERROR) << "VFY: addr " << addr << " already set to "
                   << (int) uninit_map->map_[idx].klass_ << ", not setting to "
                   << (int) klass;
        return -1;          // already set to something else??
      }
      uninit_map->map_[idx].klass_ = klass;
      return idx;
    }
  }

  LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
  assert(false);      // shouldn't happen
  return -1;
}

bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
    RegisterTable* reg_table) {
  const Method* method = vdata->method_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  const uint16_t* insns = code_item->insns_;
  uint32_t insns_size = code_item->insns_size_;
  size_t insn_idx, start_guess;

  /* Begin by marking the first instruction as "changed". */
  InsnSetChanged(insn_flags, 0, true);

  start_guess = 0;

  /* Continue until no instructions are marked "changed". */
  while (true) {
    /*
     * Find the first marked one. Use "start_guess" as a way to find
     * one quickly.
     */
    for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
      if (InsnIsChanged(insn_flags, insn_idx))
        break;
    }

    if (insn_idx == insns_size) {
      if (start_guess != 0) {
        /* try again, starting from the top */
        start_guess = 0;
        continue;
      } else {
        /* all flags are clear */
        break;
      }
    }

    /*
     * We carry the working set of registers from instruction to instruction.
     * If this address can be the target of a branch (or throw) instruction,
     * or if we're skipping around chasing "changed" flags, we need to load
     * the set of registers from the table.
     *
     * Because we always prefer to continue on to the next instruction, we
     * should never have a situation where we have a stray "changed" flag set
     * on an instruction that isn't a branch target.
     */
    if (InsnIsBranchTarget(insn_flags, insn_idx)) {
      RegisterLine* work_line = &reg_table->work_line_;
      CopyLineFromTable(work_line, reg_table, insn_idx);
    } else {
#ifndef NDEBUG
      /*
       * Sanity check: retrieve the stored register line (assuming
       * a full table) and make sure it actually matches.
       */
      RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
      if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
          insn_idx, &reg_table->work_line_) != 0) {
        Class* klass = method->GetDeclaringClass();
        LOG(ERROR) << "HUH? work_line diverged in "
                   << klass->GetDescriptor()->ToModifiedUtf8() << "."
                   << method->GetName()->ToModifiedUtf8() << " "
                   << method->GetSignature()->ToModifiedUtf8();
      }
#endif
    }

    if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
      Class* klass = method->GetDeclaringClass();
      LOG(ERROR) << "VFY: failure to verify "
                 << klass->GetDescriptor()->ToModifiedUtf8() << "."
                << method->GetName()->ToModifiedUtf8() << " "
                << method->GetSignature()->ToModifiedUtf8();
      return false;
    }

    /* Clear "changed" and mark as visited. */
    InsnSetVisited(insn_flags, insn_idx, true);
    InsnSetChanged(insn_flags, insn_idx, false);
  }

  if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
    /*
     * Scan for dead code. There's nothing "evil" about dead code
     * (besides the wasted space), but it indicates a flaw somewhere
     * down the line, possibly in the verifier.
     *
     * If we've substituted "always throw" instructions into the stream,
     * we are almost certainly going to have some dead code.
     */
    int dead_start = -1;
    for (insn_idx = 0; insn_idx < insns_size;
         insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
      /*
       * Switch-statement data doesn't get "visited" by scanner. It
       * may or may not be preceded by a padding NOP (for alignment).
       */
      if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
          insns[insn_idx] == Instruction::kSparseSwitchSignature ||
          insns[insn_idx] == Instruction::kArrayDataSignature ||
          (insns[insn_idx] == Instruction::NOP &&
           (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
            insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
            insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
        InsnSetVisited(insn_flags, insn_idx, true);
      }

      if (!InsnIsVisited(insn_flags, insn_idx)) {
        if (dead_start < 0)
          dead_start = insn_idx;
      } else if (dead_start >= 0) {
        Class* klass = method->GetDeclaringClass();
        LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
                  << insn_idx - 1 << std::dec << " in "
                  << klass->GetDescriptor()->ToModifiedUtf8() << "."
                  << method->GetName()->ToModifiedUtf8() << " "
                  << method->GetSignature()->ToModifiedUtf8();
        dead_start = -1;
      }
    }
    if (dead_start >= 0) {
      Class* klass = method->GetDeclaringClass();
      LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
                << insn_idx - 1 << std::dec << " in "
                << klass->GetDescriptor()->ToModifiedUtf8() << "."
                << method->GetName()->ToModifiedUtf8() << " "
                << method->GetSignature()->ToModifiedUtf8();
    }
  }

  return true;
}

bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
    RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
  const Method* method = vdata->method_;
  Class* klass = method->GetDeclaringClass();
  const DexFile::CodeItem* code_item = vdata->code_item_;
  InsnFlags* insn_flags = vdata->insn_flags_.get();
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
  const uint16_t* insns = code_item->insns_ + insn_idx;
  uint32_t insns_size = code_item->insns_size_;
  uint32_t registers_size = code_item->registers_size_;

#ifdef VERIFIER_STATS
  if (InsnIsVisited(insn_flags, insn_idx)) {
    gDvm.verifierStats.instrsReexamined++;
  } else {
    gDvm.verifierStats.instrsExamined++;
  }
#endif

  /*
   * Once we finish decoding the instruction, we need to figure out where
   * we can go from here. There are three possible ways to transfer
   * control to another statement:
   *
   * (1) Continue to the next instruction. Applies to all but
   *     unconditional branches, method returns, and exception throws.
   * (2) Branch to one or more possible locations. Applies to branches
   *     and switch statements.
   * (3) Exception handlers. Applies to any instruction that can
   *     throw an exception that is handled by an encompassing "try"
   *     block.
   *
   * We can also return, in which case there is no successor instruction
   * from this point.
   *
   * The behavior can be determined from the OpcodeFlags.
   */
  RegisterLine* work_line = &reg_table->work_line_;
  const DexFile* dex_file = vdata->dex_file_;
  const byte* ptr = reinterpret_cast<const byte*>(insns);
  const Instruction* inst = Instruction::At(ptr);
  Instruction::DecodedInstruction dec_insn(inst);
  int opcode_flag = inst->Flag();

  Class* res_class;
  int32_t branch_target = 0;
  RegType tmp_type;
  bool just_set_result = false;
  VerifyError failure = VERIFY_ERROR_NONE;

  /*
   * Make a copy of the previous register state. If the instruction
   * can throw an exception, we will copy/merge this into the "catch"
   * address rather than work_line, because we don't want the result
   * from the "successful" code path (e.g. a check-cast that "improves"
   * a type) to be visible to the exception handler.
   */
  if ((opcode_flag & Instruction::kThrow) != 0 &&
      InsnIsInTry(insn_flags, insn_idx)) {
    CopyRegisterLine(&reg_table->saved_line_, work_line,
        reg_table->insn_reg_count_plus_);
  } else {
#ifndef NDEBUG
    memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
        reg_table->insn_reg_count_plus_ * sizeof(RegType));
#endif
  }

  switch (dec_insn.opcode_) {
    case Instruction::NOP:
      /*
       * A "pure" NOP has no effect on anything. Data tables start with
       * a signature that looks like a NOP; if we see one of these in
       * the course of executing code then we have a problem.
       */
      if (dec_insn.vA_ != 0) {
        LOG(ERROR) << "VFY: encountered data table in instruction stream";
        failure = VERIFY_ERROR_GENERIC;
      }
      break;

    case Instruction::MOVE:
    case Instruction::MOVE_FROM16:
    case Instruction::MOVE_16:
      CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
          &failure);
      break;
    case Instruction::MOVE_WIDE:
    case Instruction::MOVE_WIDE_FROM16:
    case Instruction::MOVE_WIDE_16:
      CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
      break;
    case Instruction::MOVE_OBJECT:
    case Instruction::MOVE_OBJECT_FROM16:
    case Instruction::MOVE_OBJECT_16:
      CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
          &failure);
      break;

    /*
     * The move-result instructions copy data out of a "pseudo-register"
     * with the results from the last method invocation. In practice we
     * might want to hold the result in an actual CPU register, so the
     * Dalvik spec requires that these only appear immediately after an
     * invoke or filled-new-array.
     *
     * These calls invalidate the "result" register. (This is now
     * redundant with the reset done below, but it can make the debug info
     * easier to read in some cases.)
     */
    case Instruction::MOVE_RESULT:
      CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
          kTypeCategory1nr, &failure);
      break;
    case Instruction::MOVE_RESULT_WIDE:
      CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
      break;
    case Instruction::MOVE_RESULT_OBJECT:
      CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
          kTypeCategoryRef, &failure);
      break;

    case Instruction::MOVE_EXCEPTION:
      /*
       * This statement can only appear as the first instruction in an
       * exception handler (though not all exception handlers need to
       * have one of these). We verify that as part of extracting the
       * exception type from the catch block list.
       *
       * "res_class" will hold the closest common superclass of all
       * exceptions that can be handled here.
       */
      res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
      if (res_class == NULL) {
        assert(failure != VERIFY_ERROR_NONE);
      } else {
        SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
      }
      break;

    case Instruction::RETURN_VOID:
      if (!CheckConstructorReturn(method, work_line, registers_size)) {
        failure = VERIFY_ERROR_GENERIC;
      } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
        LOG(ERROR) << "VFY: return-void not expected";
        failure = VERIFY_ERROR_GENERIC;
      }
      break;
    case Instruction::RETURN:
      if (!CheckConstructorReturn(method, work_line, registers_size)) {
        failure = VERIFY_ERROR_GENERIC;
      } else {
        /* check the method signature */
        RegType return_type = GetMethodReturnType(dex_file, method);
        CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
        if (failure != VERIFY_ERROR_NONE)
          LOG(ERROR) << "VFY: return-1nr not expected";

        /*
         * compiler may generate synthetic functions that write byte
         * values into boolean fields. Also, it may use integer values
         * for boolean, byte, short, and character return types.
         */
        RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
        if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
           ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
             return_type == kRegTypeShort || return_type == kRegTypeChar) &&
             src_type == kRegTypeInteger))
          return_type = src_type;

        /* check the register contents */
        VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
        if (failure != VERIFY_ERROR_NONE) {
          LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
        }
      }
      break;
    case Instruction::RETURN_WIDE:
      if (!CheckConstructorReturn(method, work_line, registers_size)) {
        failure = VERIFY_ERROR_GENERIC;
      } else {
        RegType return_type;

        /* check the method signature */
        return_type = GetMethodReturnType(dex_file, method);
        CheckTypeCategory(return_type, kTypeCategory2, &failure);
        if (failure != VERIFY_ERROR_NONE)
          LOG(ERROR) << "VFY: return-wide not expected";

        /* check the register contents */
        VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
        if (failure != VERIFY_ERROR_NONE) {
          LOG(ERROR) << "VFY: return-wide on invalid register pair v"
                     << dec_insn.vA_;
        }
      }
      break;
    case Instruction::RETURN_OBJECT:
      if (!CheckConstructorReturn(method, work_line, registers_size)) {
        failure = VERIFY_ERROR_GENERIC;
      } else {
        RegType return_type = GetMethodReturnType(dex_file, method);
        CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
        if (failure != VERIFY_ERROR_NONE) {
          LOG(ERROR) << "VFY: return-object not expected";
          break;
        }

        /* return_type is the *expected* return type, not register value */
        assert(return_type != kRegTypeZero);
        assert(!RegTypeIsUninitReference(return_type));

        /*
         * Verify that the reference in vAA is an instance of the type
         * in "return_type". The Zero type is allowed here. If the
         * method is declared to return an interface, then any
         * initialized reference is acceptable.
         *
         * Note GetClassFromRegister fails if the register holds an
         * uninitialized reference, so we do not allow them to be
         * returned.
         */
        Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
        res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        if (res_class != NULL) {
          if (!decl_class->IsInterface() &&
              //!res_class->InstanceOf(decl_class)) {
              !decl_class->IsAssignableFrom(res_class)) {
            LOG(ERROR) << "VFY: returning " << std::hex
                       << res_class->GetDescriptor()->ToModifiedUtf8()
                       << " (cl=0x" << (int) res_class->GetClassLoader()
                       << "), declared "
                       << decl_class->GetDescriptor()->ToModifiedUtf8()
                       << " (cl=0x" << (int) decl_class->GetClassLoader()
                       << ")" << std::dec;
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
        }
      }
      break;

    case Instruction::CONST_4:
    case Instruction::CONST_16:
    case Instruction::CONST:
      /* could be boolean, int, float, or a null reference */
      SetRegisterType(work_line, dec_insn.vA_,
          DetermineCat1Const((int32_t) dec_insn.vB_));
      break;
    case Instruction::CONST_HIGH16:
      /* could be boolean, int, float, or a null reference */
      SetRegisterType(work_line, dec_insn.vA_,
          DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
      break;
    case Instruction::CONST_WIDE_16:
    case Instruction::CONST_WIDE_32:
    case Instruction::CONST_WIDE:
    case Instruction::CONST_WIDE_HIGH16:
      /* could be long or double; resolved upon use */
      SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
      break;
    case Instruction::CONST_STRING:
    case Instruction::CONST_STRING_JUMBO:
      SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
          class_linker->FindSystemClass("Ljava/lang/String;")));
      break;
    case Instruction::CONST_CLASS:
      /* make sure we can resolve the class; access check is important */
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
        LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else {
        SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
            class_linker->FindSystemClass("Ljava/lang/Class;")));
      }
      break;

    case Instruction::MONITOR_ENTER:
      HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
      break;
    case Instruction::MONITOR_EXIT:
      /*
       * monitor-exit instructions are odd. They can throw exceptions,
       * but when they do they act as if they succeeded and the PC is
       * pointing to the following instruction. (This behavior goes back
       * to the need to handle asynchronous exceptions, a now-deprecated
       * feature that Dalvik doesn't support.)
       *
       * In practice we don't need to worry about this. The only
       * exceptions that can be thrown from monitor-exit are for a
       * null reference and -exit without a matching -enter. If the
       * structured locking checks are working, the former would have
       * failed on the -enter instruction, and the latter is impossible.
       *
       * This is fortunate, because issue 3221411 prevents us from
       * chasing the "can throw" path when monitor verification is
       * enabled. If we can fully verify the locking we can ignore
       * some catch blocks (which will show up as "dead" code when
       * we skip them here); if we can't, then the code path could be
       * "live" so we still need to check it.
       */
      if (work_line->monitor_entries_.get() != NULL)
        opcode_flag &= ~Instruction::kThrow;
      HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
      break;

    case Instruction::CHECK_CAST:
      /*
       * If this instruction succeeds, we will promote register vA to
       * the type in vB. (This could be a demotion -- not expected, so
       * we don't try to address it.)
       *
       * If it fails, an exception is thrown, which we deal with later
       * by ignoring the update to dec_insn.vA_ when branching to a handler.
       */
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
        LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else {
        RegType orig_type;

        orig_type = GetRegisterType(work_line, dec_insn.vA_);
        if (!RegTypeIsReference(orig_type)) {
          LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
        SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
      }
      break;
    case Instruction::INSTANCE_OF:
      /* make sure we're checking a reference type */
      tmp_type = GetRegisterType(work_line, dec_insn.vB_);
      if (!RegTypeIsReference(tmp_type)) {
        LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
        failure = VERIFY_ERROR_GENERIC;
        break;
      }

      /* make sure we can resolve the class; access check is important */
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vC_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
        LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else {
        /* result is boolean */
        SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
      }
      break;

    case Instruction::ARRAY_LENGTH:
      res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;
      if (res_class != NULL && !res_class->IsArrayClass()) {
        LOG(ERROR) << "VFY: array-length on non-array";
        failure = VERIFY_ERROR_GENERIC;
        break;
      }
      SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
      break;

    case Instruction::NEW_INSTANCE:
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
        LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else {
        RegType uninit_type;

        /* can't create an instance of an interface or abstract class */
        if (res_class->IsAbstract() || res_class->IsInterface()) {
          LOG(ERROR) << "VFY: new-instance on interface or abstract class"
                     << res_class->GetDescriptor()->ToModifiedUtf8();
          failure = VERIFY_ERROR_INSTANTIATION;
          break;
        }

        /* add resolved class to uninit map if not already there */
        int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
        assert(uidx >= 0);
        uninit_type = RegTypeFromUninitIndex(uidx);

        /*
         * Any registers holding previous allocations from this address
         * that have not yet been initialized must be marked invalid.
         */
        MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
            uninit_type);

        /* add the new uninitialized reference to the register ste */
        SetRegisterType(work_line, dec_insn.vA_, uninit_type);
      }
      break;
   case Instruction::NEW_ARRAY:
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vC_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
        LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else if (!res_class->IsArrayClass()) {
        LOG(ERROR) << "VFY: new-array on non-array class";
        failure = VERIFY_ERROR_GENERIC;
      } else {
        /* make sure "size" register is valid type */
        VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
        /* set register type to array class */
        SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
      }
      break;
    case Instruction::FILLED_NEW_ARRAY:
    case Instruction::FILLED_NEW_ARRAY_RANGE:
      res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
      if (res_class == NULL) {
        const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
        LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
                   << " (" << bad_class_desc << ") in "
                   << klass->GetDescriptor()->ToModifiedUtf8();
        assert(failure != VERIFY_ERROR_GENERIC);
      } else if (!res_class->IsArrayClass()) {
        LOG(ERROR) << "VFY: filled-new-array on non-array class";
        failure = VERIFY_ERROR_GENERIC;
      } else {
        bool is_range = (dec_insn.opcode_ ==
            Instruction::FILLED_NEW_ARRAY_RANGE);

        /* check the arguments to the instruction */
        VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
            is_range, &failure);
        /* filled-array result goes into "result" register */
        SetResultRegisterType(work_line, registers_size,
            RegTypeFromClass(res_class));
        just_set_result = true;
      }
      break;

    case Instruction::CMPL_FLOAT:
    case Instruction::CMPG_FLOAT:
      VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
      VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
      SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
      break;
    case Instruction::CMPL_DOUBLE:
    case Instruction::CMPG_DOUBLE:
      VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
      VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
      SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
      break;
    case Instruction::CMP_LONG:
      VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
      VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
      SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
      break;

    case Instruction::THROW:
      res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
      if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
        Class* throwable_class =
            class_linker->FindSystemClass("Ljava/lang/Throwable;");
        if (!throwable_class->IsAssignableFrom(res_class)) {
          LOG(ERROR) << "VFY: thrown class "
                     << res_class->GetDescriptor()->ToModifiedUtf8()
                     << " not instanceof Throwable",
          failure = VERIFY_ERROR_GENERIC;
        }
      }
      break;

    case Instruction::GOTO:
    case Instruction::GOTO_16:
    case Instruction::GOTO_32:
      /* no effect on or use of registers */
      break;

    case Instruction::PACKED_SWITCH:
    case Instruction::SPARSE_SWITCH:
      /* verify that vAA is an integer, or can be converted to one */
      VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
      break;

    case Instruction::FILL_ARRAY_DATA:
      {
        RegType value_type;
        const uint16_t *array_data;
        uint16_t elem_width;

        /* Similar to the verification done for APUT */
        res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /* res_class can be null if the reg type is Zero */
        if (res_class == NULL)
          break;

        Class::PrimitiveType prim_type =
            res_class->GetComponentType()->GetPrimitiveType();
        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
            prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
          LOG(ERROR) << "VFY: invalid fill-array-data on " <<
                res_class->GetDescriptor()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        value_type = PrimitiveTypeToRegType(prim_type);
        assert(value_type != kRegTypeUnknown);

        /*
         * Now verify if the element width in the table matches the element
         * width declared in the array
         */
        array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
        if (array_data[0] != Instruction::kArrayDataSignature) {
          LOG(ERROR) << "VFY: invalid magic for array-data";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        switch (prim_type) {
          case Class::kPrimBoolean:
          case Class::kPrimByte:
            elem_width = 1;
            break;
          case Class::kPrimChar:
          case Class::kPrimShort:
            elem_width = 2;
            break;
          case Class::kPrimFloat:
          case Class::kPrimInt:
            elem_width = 4;
            break;
          case Class::kPrimDouble:
          case Class::kPrimLong:
            elem_width = 8;
            break;
          default:
            elem_width = 0;
            break;
        }

        /*
         * Since we don't compress the data in Dex, expect to see equal
         * width of data stored in the table and expected from the array
         * class.
         */
        if (array_data[1] != elem_width) {
          LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
                     << " vs " << elem_width << ")";
          failure = VERIFY_ERROR_GENERIC;
        }
      }
      break;

    case Instruction::IF_EQ:
    case Instruction::IF_NE:
      {
        RegType type1, type2;

        type1 = GetRegisterType(work_line, dec_insn.vA_);
        type2 = GetRegisterType(work_line, dec_insn.vB_);

        /* both references? */
        if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
          break;

        /* both category-1nr? */
        CheckTypeCategory(type1, kTypeCategory1nr, &failure);
        CheckTypeCategory(type2, kTypeCategory1nr, &failure);
        if (failure != VERIFY_ERROR_NONE) {
          LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
          break;
        }
      }
      break;
    case Instruction::IF_LT:
    case Instruction::IF_GE:
    case Instruction::IF_GT:
    case Instruction::IF_LE:
      tmp_type = GetRegisterType(work_line, dec_insn.vA_);
      CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
      if (failure != VERIFY_ERROR_NONE) {
        LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
        break;
      }
      tmp_type = GetRegisterType(work_line, dec_insn.vB_);
      CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
      if (failure != VERIFY_ERROR_NONE) {
        LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
        break;
      }
      break;
    case Instruction::IF_EQZ:
    case Instruction::IF_NEZ:
      tmp_type = GetRegisterType(work_line, dec_insn.vA_);
      if (RegTypeIsReference(tmp_type))
        break;
      CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
      if (failure != VERIFY_ERROR_NONE)
        LOG(ERROR) << "VFY: expected cat-1 arg to if";
      break;
    case Instruction::IF_LTZ:
    case Instruction::IF_GEZ:
    case Instruction::IF_GTZ:
    case Instruction::IF_LEZ:
      tmp_type = GetRegisterType(work_line, dec_insn.vA_);
      CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
      if (failure != VERIFY_ERROR_NONE)
        LOG(ERROR) << "VFY: expected cat-1 arg to if";
      break;

    case Instruction::AGET:
      tmp_type = kRegTypeConstInteger;
      goto aget_1nr_common;
    case Instruction::AGET_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto aget_1nr_common;
    case Instruction::AGET_BYTE:
      tmp_type = kRegTypeByte;
      goto aget_1nr_common;
    case Instruction::AGET_CHAR:
      tmp_type = kRegTypeChar;
      goto aget_1nr_common;
    case Instruction::AGET_SHORT:
      tmp_type = kRegTypeShort;
      goto aget_1nr_common;
aget_1nr_common:
      {
        RegType src_type, index_type;

        index_type = GetRegisterType(work_line, dec_insn.vC_);
        CheckArrayIndexType(method, index_type, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        if (res_class != NULL) {
          /* verify the class */
          Class::PrimitiveType prim_type =
              res_class->GetComponentType()->GetPrimitiveType();
          if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
              prim_type == Class::kPrimNot) {
            LOG(ERROR) << "VFY: invalid aget-1nr target "
                       << res_class->GetDescriptor()->ToModifiedUtf8();
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /* make sure array type matches instruction */
          src_type = PrimitiveTypeToRegType(prim_type);

          /* differentiate between float and int */
          if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
            tmp_type = src_type;

          if (tmp_type != src_type) {
            LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
                       << " with inst type=" << tmp_type << " (on "
                       << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

        }
        SetRegisterType(work_line, dec_insn.vA_, tmp_type);
      }
      break;

    case Instruction::AGET_WIDE:
      {
        RegType dst_type, index_type;

        index_type = GetRegisterType(work_line, dec_insn.vC_);
        CheckArrayIndexType(method, index_type, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        if (res_class != NULL) {
          /* verify the class */
          Class::PrimitiveType prim_type =
              res_class->GetComponentType()->GetPrimitiveType();
          if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
              prim_type == Class::kPrimNot) {
            LOG(ERROR) << "VFY: invalid aget-wide target "
                       << res_class->GetDescriptor()->ToModifiedUtf8();
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /* try to refine "dst_type" */
          switch (prim_type) {
            case Class::kPrimLong:
              dst_type = kRegTypeLongLo;
              break;
            case Class::kPrimDouble:
              dst_type = kRegTypeDoubleLo;
              break;
            default:
              LOG(ERROR) << "VFY: invalid aget-wide on "
                         << res_class->GetDescriptor()->ToModifiedUtf8();
              dst_type = kRegTypeUnknown;
              failure = VERIFY_ERROR_GENERIC;
              break;
          }
        } else {
          /*
           * Null array ref; this code path will fail at runtime. We
           * know this is either long or double, so label it const.
           */
          dst_type = kRegTypeConstLo;
        }
        SetRegisterType(work_line, dec_insn.vA_, dst_type);
      }
      break;

    case Instruction::AGET_OBJECT:
      {
        RegType dst_type, index_type;

        index_type = GetRegisterType(work_line, dec_insn.vC_);
        CheckArrayIndexType(method, index_type, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /* get the class of the array we're pulling an object from */
        res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        if (res_class != NULL) {
          Class* element_class;

          assert(res_class != NULL);
          if (!res_class->IsArrayClass()) {
            LOG(ERROR) << "VFY: aget-object on non-array class";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
          assert(res_class->GetComponentType() != NULL);

          /*
           * Find the element class. res_class->GetComponentType() indicates
           * the basic type, which won't be what we want for a
           * multi-dimensional array.
           */
          if (res_class->GetDescriptor()->CharAt(1) == '[') {
            assert(res_class->GetArrayRank() > 1);
            std::string descriptor =
                res_class->GetDescriptor()->ToModifiedUtf8();
            element_class = class_linker->FindClass(descriptor.c_str() + 1,
                           res_class->GetClassLoader());
          } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
            assert(res_class->GetArrayRank() == 1);
            element_class = res_class->GetComponentType();
          } else {
            LOG(ERROR) << "VFY: aget-object on non-ref array class ("
                       << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          dst_type = RegTypeFromClass(element_class);
        } else {
          /*
           * The array reference is NULL, so the current code path will
           * throw an exception. For proper merging with later code
           * paths, and correct handling of "if-eqz" tests on the
           * result of the array get, we want to treat this as a null
           * reference.
           */
          dst_type = kRegTypeZero;
        }
      SetRegisterType(work_line, dec_insn.vA_, dst_type);
      }
      break;
    case Instruction::APUT:
      tmp_type = kRegTypeInteger;
      goto aput_1nr_common;
    case Instruction::APUT_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto aput_1nr_common;
    case Instruction::APUT_BYTE:
      tmp_type = kRegTypeByte;
      goto aput_1nr_common;
    case Instruction::APUT_CHAR:
      tmp_type = kRegTypeChar;
      goto aput_1nr_common;
    case Instruction::APUT_SHORT:
      tmp_type = kRegTypeShort;
      goto aput_1nr_common;
aput_1nr_common:
      {
        RegType src_type, dst_type, index_type;

        index_type = GetRegisterType(work_line, dec_insn.vC_);
        CheckArrayIndexType(method, index_type, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /* res_class can be null if the reg type is Zero */
        if (res_class == NULL)
          break;

        Class::PrimitiveType prim_type =
            res_class->GetComponentType()->GetPrimitiveType();
        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
            prim_type == Class::kPrimNot) {
          LOG(ERROR) << "VFY: invalid aput-1nr on "
                     << res_class->GetDescriptor()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        /* verify that instruction matches array */
        dst_type = PrimitiveTypeToRegType(prim_type);

        /* correct if float */
        if (dst_type == kRegTypeFloat)
          tmp_type = kRegTypeFloat;

        /* make sure the source register has the correct type */
        src_type = GetRegisterType(work_line, dec_insn.vA_);
        if (!CanConvertTo1nr(src_type, tmp_type)) {
          LOG(ERROR) << "VFY: invalid reg type " << src_type
                     << " on aput instr (need " << tmp_type << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);

        if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
          tmp_type != dst_type) {
          LOG(ERROR) << "VFY: invalid aput-1nr on "
                     << res_class->GetDescriptor()->ToModifiedUtf8()
                     << " (inst=" << tmp_type << " dst=" << dst_type << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
      }
      break;
    case Instruction::APUT_WIDE:
      tmp_type = GetRegisterType(work_line, dec_insn.vC_);
      CheckArrayIndexType(method, tmp_type, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;

      res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;
      if (res_class != NULL) {
        Class::PrimitiveType prim_type =
            res_class->GetComponentType()->GetPrimitiveType();
        /* verify the class and try to refine "dst_type" */
        if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
            prim_type == Class::kPrimNot)
        {
          LOG(ERROR) << "VFY: invalid aput-wide on "
                     << res_class->GetDescriptor()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        switch (prim_type) {
          case Class::kPrimLong:
            VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
                &failure);
            break;
          case Class::kPrimDouble:
            VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
                &failure);
            break;
          default:
            LOG(ERROR) << "VFY: invalid aput-wide on "
                       << res_class->GetDescriptor()->ToModifiedUtf8();
            failure = VERIFY_ERROR_GENERIC;
            break;
        }
      }
      break;
    case Instruction::APUT_OBJECT:
      tmp_type = GetRegisterType(work_line, dec_insn.vC_);
      CheckArrayIndexType(method, tmp_type, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;

      /* get the ref we're storing; Zero is okay, Uninit is not */
      res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;
      if (res_class != NULL) {
        Class* array_class;
        Class* element_class;

        /*
         * Get the array class. If the array ref is null, we won't
         * have type information (and we'll crash at runtime with a
         * null pointer exception).
         */
        array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);

        if (array_class != NULL) {
          /* see if the array holds a compatible type */
          if (!array_class->IsArrayClass()) {
            LOG(ERROR) << "VFY: invalid aput-object on "
                       << array_class->GetDescriptor()->ToModifiedUtf8();
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /*
           * Find the element class. res_class->GetComponentType() indicates
           * the basic type, which won't be what we want for a
           * multi-dimensional array.
           *
           * All we want to check here is that the element type is a
           * reference class. We *don't* check instanceof here, because
           * you can still put a String into a String[] after the latter
           * has been cast to an Object[].
           */
          if (array_class->GetDescriptor()->CharAt(1) == '[') {
            assert(array_class->GetArrayRank() > 1);
            std::string descriptor =
                array_class->GetDescriptor()->ToModifiedUtf8();
            element_class = class_linker->FindClass(descriptor.c_str() + 1,
                           array_class->GetClassLoader());
          } else {
            assert(array_class->GetArrayRank() == 1);
            element_class = array_class->GetComponentType();
          }
          if (element_class->GetPrimitiveType() != Class::kPrimNot) {
            LOG(ERROR) << "VFY: invalid aput-object of "
                       << res_class->GetDescriptor()->ToModifiedUtf8()
                       << " into "
                       << array_class->GetDescriptor()->ToModifiedUtf8();
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
        }
      }
      break;

    case Instruction::IGET:
      tmp_type = kRegTypeInteger;
      goto iget_1nr_common;
    case Instruction::IGET_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto iget_1nr_common;
    case Instruction::IGET_BYTE:
      tmp_type = kRegTypeByte;
      goto iget_1nr_common;
    case Instruction::IGET_CHAR:
      tmp_type = kRegTypeChar;
      goto iget_1nr_common;
    case Instruction::IGET_SHORT:
      tmp_type = kRegTypeShort;
      goto iget_1nr_common;
iget_1nr_common:
      {
        Field* inst_field;
        RegType obj_type, field_type;

        obj_type = GetRegisterType(work_line, dec_insn.vB_);
        inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /* make sure the field's type is compatible with expectation */
        field_type =
            PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());

        /* correct if float */
        if (field_type == kRegTypeFloat)
          tmp_type = kRegTypeFloat;

        if (field_type == kRegTypeUnknown || tmp_type != field_type) {
          Class* inst_field_class = inst_field->GetDeclaringClass();
          LOG(ERROR) << "VFY: invalid iget-1nr of "
                     << inst_field_class->GetDescriptor()->ToModifiedUtf8()
                     << "." << inst_field->GetName()->ToModifiedUtf8()
                     << " (inst=" << tmp_type << " field=" << field_type << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        SetRegisterType(work_line, dec_insn.vA_, tmp_type);
      }
      break;
    case Instruction::IGET_WIDE:
      {
        RegType dst_type;
        Field* inst_field;
        RegType obj_type;

        obj_type = GetRegisterType(work_line, dec_insn.vB_);
        inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
        Class* inst_field_class = inst_field->GetDeclaringClass();
        if (failure != VERIFY_ERROR_NONE)
          break;
        /* check the type, which should be prim */
        switch (inst_field->GetType()->GetPrimitiveType()) {
          case Class::kPrimDouble:
            dst_type = kRegTypeDoubleLo;
            break;
          case Class::kPrimLong:
            dst_type = kRegTypeLongLo;
            break;
          default:
            LOG(ERROR) << "VFY: invalid iget-wide of "
                       << inst_field_class->GetDescriptor()->ToModifiedUtf8()
                       << "." << inst_field->GetName()->ToModifiedUtf8();
            dst_type = kRegTypeUnknown;
            failure = VERIFY_ERROR_GENERIC;
            break;
        }
        if (failure == VERIFY_ERROR_NONE) {
          SetRegisterType(work_line, dec_insn.vA_, dst_type);
        }
      }
      break;
    case Instruction::IGET_OBJECT:
      {
        Class* field_class;
        Field* inst_field;
        RegType obj_type;

        obj_type = GetRegisterType(work_line, dec_insn.vB_);
        inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        field_class = inst_field->GetType();
        if (field_class == NULL) {
          /* class not found or primitive type */
          LOG(ERROR) << "VFY: unable to recover field class from "
                     << inst_field->GetName()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
        if (failure == VERIFY_ERROR_NONE) {
          assert(!field_class->IsPrimitive());
          SetRegisterType(work_line, dec_insn.vA_,
              RegTypeFromClass(field_class));
        }
      }
      break;
    case Instruction::IPUT:
      tmp_type = kRegTypeInteger;
      goto iput_1nr_common;
    case Instruction::IPUT_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto iput_1nr_common;
    case Instruction::IPUT_BYTE:
      tmp_type = kRegTypeByte;
      goto iput_1nr_common;
    case Instruction::IPUT_CHAR:
      tmp_type = kRegTypeChar;
      goto iput_1nr_common;
    case Instruction::IPUT_SHORT:
      tmp_type = kRegTypeShort;
      goto iput_1nr_common;
iput_1nr_common:
      {
        RegType src_type, field_type, obj_type;
        Field* inst_field;

        obj_type = GetRegisterType(work_line, dec_insn.vB_);
        inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        CheckFinalFieldAccess(method, inst_field, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /* get type of field we're storing into */
        field_type =
            PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
        src_type = GetRegisterType(work_line, dec_insn.vA_);

        /* correct if float */
        if (field_type == kRegTypeFloat)
          tmp_type = kRegTypeFloat;

        /*
         * compiler can generate synthetic functions that write byte values
         * into boolean fields.
         */
        if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
          tmp_type = kRegTypeByte;
        if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
          field_type = kRegTypeByte;

        /* make sure the source register has the correct type */
        if (!CanConvertTo1nr(src_type, tmp_type)) {
          LOG(ERROR) << "VFY: invalid reg type " << src_type
                     << " on iput instr (need " << tmp_type << ")",
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);

        if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
            tmp_type != field_type) {
          Class* inst_field_class = inst_field->GetDeclaringClass();
          LOG(ERROR) << "VFY: invalid iput-1nr of "
                     << inst_field_class->GetDescriptor()->ToModifiedUtf8()
                     << "." << inst_field->GetName()->ToModifiedUtf8()
                     << " (inst=" << tmp_type << " field=" << field_type << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
      }
      break;
    case Instruction::IPUT_WIDE:
      Field* inst_field;
      RegType obj_type;

      obj_type = GetRegisterType(work_line, dec_insn.vB_);
      inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;
      CheckFinalFieldAccess(method, inst_field, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;

      /* check the type, which should be prim */
      switch (inst_field->GetType()->GetPrimitiveType()) {
        case Class::kPrimDouble:
          VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
              &failure);
          break;
        case Class::kPrimLong:
          VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
          break;
        default:
          LOG(ERROR) << "VFY: invalid iput-wide of "
                     << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                     << "." << inst_field->GetName()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
      break;
    case Instruction::IPUT_OBJECT:
      {
        Class* field_class;
        Class* value_class;
        Field* inst_field;
        RegType obj_type, value_type;

        obj_type = GetRegisterType(work_line, dec_insn.vB_);
        inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        CheckFinalFieldAccess(method, inst_field, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        field_class = inst_field->GetType();
        if (field_class == NULL) {
          LOG(ERROR) << "VFY: unable to recover field class from '"
                     << inst_field->GetName()->ToModifiedUtf8() << "'";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        value_type = GetRegisterType(work_line, dec_insn.vA_);
        if (!RegTypeIsReference(value_type)) {
          LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
                     << " into ref field '"
                     << inst_field->GetName()->ToModifiedUtf8() << "' ("
                     << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
        if (value_type != kRegTypeZero) {
          value_class = RegTypeInitializedReferenceToClass(value_type);
          if (value_class == NULL) {
            LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
                       << " into ref field";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
          /* allow if field is any interface or field is base class */
          if (!field_class->IsInterface() &&
              !field_class->IsAssignableFrom(value_class)) {
            Class* inst_field_class = inst_field->GetDeclaringClass();
            LOG(ERROR) << "VFY: storing type '"
                       << value_class->GetDescriptor()->ToModifiedUtf8()
                       << "' into field type '"
                       << field_class->GetDescriptor()->ToModifiedUtf8()
                       << "' ("
                       << inst_field_class->GetDescriptor()->ToModifiedUtf8()
                       << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
        }
      }
      break;

    case Instruction::SGET:
      tmp_type = kRegTypeInteger;
      goto sget_1nr_common;
    case Instruction::SGET_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto sget_1nr_common;
    case Instruction::SGET_BYTE:
      tmp_type = kRegTypeByte;
      goto sget_1nr_common;
    case Instruction::SGET_CHAR:
      tmp_type = kRegTypeChar;
      goto sget_1nr_common;
    case Instruction::SGET_SHORT:
      tmp_type = kRegTypeShort;
      goto sget_1nr_common;
sget_1nr_common:
      {
        Field* static_field;
        RegType field_type;

        static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /*
         * Make sure the field's type is compatible with expectation.
         * We can get ourselves into trouble if we mix & match loads
         * and stores with different widths, so rather than just checking
         * "CanConvertTo1nr" we require that the field types have equal
         * widths.
         */
        field_type =
            PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());

        /* correct if float */
        if (field_type == kRegTypeFloat)
          tmp_type = kRegTypeFloat;

        if (tmp_type != field_type) {
          Class* static_field_class = static_field->GetDeclaringClass();
          LOG(ERROR) << "VFY: invalid sget-1nr of "
                     << static_field_class->GetDescriptor()->ToModifiedUtf8()
                     << "." << static_field->GetName()->ToModifiedUtf8()
                     << " (inst=" << tmp_type << " actual=" << field_type
                     << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        SetRegisterType(work_line, dec_insn.vA_, tmp_type);
      }
      break;
    case Instruction::SGET_WIDE:
      {
        Field* static_field;
        RegType dst_type;

        static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
        Class* static_field_class = static_field->GetDeclaringClass();
        if (failure != VERIFY_ERROR_NONE)
          break;
        /* check the type, which should be prim */
        switch (static_field->GetType()->GetPrimitiveType()) {
          case Class::kPrimDouble:
            dst_type = kRegTypeDoubleLo;
            break;
          case Class::kPrimLong:
            dst_type = kRegTypeLongLo;
            break;
          default:
            LOG(ERROR) << "VFY: invalid sget-wide of "
                       << static_field_class->GetDescriptor()->ToModifiedUtf8()
                       << "." << static_field->GetName()->ToModifiedUtf8();
            dst_type = kRegTypeUnknown;
            failure = VERIFY_ERROR_GENERIC;
            break;
        }
        if (failure == VERIFY_ERROR_NONE) {
          SetRegisterType(work_line, dec_insn.vA_, dst_type);
        }
      }
      break;
    case Instruction::SGET_OBJECT:
      {
        Field* static_field;
        Class* field_class;

        static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        field_class = static_field->GetType();
        if (field_class == NULL) {
          LOG(ERROR) << "VFY: unable to recover field class from '"
                     << static_field->GetName()->ToModifiedUtf8() << "'";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
        if (field_class->IsPrimitive()) {
          LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
      SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
      }
      break;
    case Instruction::SPUT:
      tmp_type = kRegTypeInteger;
      goto sput_1nr_common;
    case Instruction::SPUT_BOOLEAN:
      tmp_type = kRegTypeBoolean;
      goto sput_1nr_common;
    case Instruction::SPUT_BYTE:
      tmp_type = kRegTypeByte;
      goto sput_1nr_common;
    case Instruction::SPUT_CHAR:
      tmp_type = kRegTypeChar;
      goto sput_1nr_common;
    case Instruction::SPUT_SHORT:
      tmp_type = kRegTypeShort;
      goto sput_1nr_common;
sput_1nr_common:
      {
        RegType src_type, field_type;
        Field* static_field;

        static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        CheckFinalFieldAccess(method, static_field, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /*
         * Get type of field we're storing into. We know that the
         * contents of the register match the instruction, but we also
         * need to ensure that the instruction matches the field type.
         * Using e.g. sput-short to write into a 32-bit integer field
         * can lead to trouble if we do 16-bit writes.
         */
        field_type =
            PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
        src_type = GetRegisterType(work_line, dec_insn.vA_);

        /* correct if float */
        if (field_type == kRegTypeFloat)
          tmp_type = kRegTypeFloat;

        /*
         * compiler can generate synthetic functions that write byte values
         * into boolean fields.
         */
        if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
          tmp_type = kRegTypeByte;
        if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
          field_type = kRegTypeByte;

        /* make sure the source register has the correct type */
        if (!CanConvertTo1nr(src_type, tmp_type)) {
          LOG(ERROR) << "VFY: invalid reg type " << src_type
                     << " on sput instr (need " << tmp_type << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);

        if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
            tmp_type != field_type) {
          Class* static_field_class = static_field->GetDeclaringClass();
          LOG(ERROR) << "VFY: invalid sput-1nr of "
                     << static_field_class->GetDescriptor()->ToModifiedUtf8()
                     << "." << static_field->GetName()->ToModifiedUtf8()
                     << " (inst=" << tmp_type << " actual=" << field_type
                     << ")";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
      }
      break;
    case Instruction::SPUT_WIDE:
      Field* static_field;

      static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;
      CheckFinalFieldAccess(method, static_field, &failure);
      if (failure != VERIFY_ERROR_NONE)
        break;

      /* check the type, which should be prim */
      switch (static_field->GetType()->GetPrimitiveType()) {
        case Class::kPrimDouble:
          VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
              &failure);
          break;
        case Class::kPrimLong:
          VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
          break;
        default:
          LOG(ERROR) << "VFY: invalid sput-wide of "
                     << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                     << "." << static_field->GetName()->ToModifiedUtf8();
          failure = VERIFY_ERROR_GENERIC;
          break;
      }
      break;
    case Instruction::SPUT_OBJECT:
      {
        Class* field_class;
        Class* value_class;
        Field* static_field;
        RegType value_type;

        static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;
        CheckFinalFieldAccess(method, static_field, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        field_class = static_field->GetType();
        if (field_class == NULL) {
          LOG(ERROR) << "VFY: unable to recover field class from '"
                     << static_field->GetName()->ToModifiedUtf8() << "'";
          failure = VERIFY_ERROR_GENERIC;
          break;
        }

        value_type = GetRegisterType(work_line, dec_insn.vA_);
        if (!RegTypeIsReference(value_type)) {
          LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
                     << " into ref field '"
                     << static_field->GetName()->ToModifiedUtf8() << "' ("
                     << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
          failure = VERIFY_ERROR_GENERIC;
          break;
        }
        if (value_type != kRegTypeZero) {
          value_class = RegTypeInitializedReferenceToClass(value_type);
          if (value_class == NULL) {
            LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
                       << " into ref field";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
          /* allow if field is any interface or field is base class */
          if (!field_class->IsInterface() &&
              !field_class->IsAssignableFrom(value_class)) {
            Class* static_field_class = static_field->GetDeclaringClass();
            LOG(ERROR) << "VFY: storing type '"
                       << value_class->GetDescriptor()->ToModifiedUtf8()
                       << "' into field type '"
                       << field_class->GetDescriptor()->ToModifiedUtf8()
                       << "' ("
                       << static_field_class->GetDescriptor()->ToModifiedUtf8()
                       << "." << static_field->GetName()->ToModifiedUtf8()
                       << ")",
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
        }
      }
      break;

    case Instruction::INVOKE_VIRTUAL:
    case Instruction::INVOKE_VIRTUAL_RANGE:
    case Instruction::INVOKE_SUPER:
    case Instruction::INVOKE_SUPER_RANGE:
      {
        Method* called_method;
        RegType return_type;
        bool is_range;
        bool is_super;

        is_range =  (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
                     dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
        is_super =  (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
                     dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);

        called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
            &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
        if (failure != VERIFY_ERROR_NONE)
            break;
        return_type = GetMethodReturnType(dex_file, called_method);
        SetResultRegisterType(work_line, registers_size, return_type);
        just_set_result = true;
      }
      break;
    case Instruction::INVOKE_DIRECT:
    case Instruction::INVOKE_DIRECT_RANGE:
      {
        RegType return_type;
        Method* called_method;
        bool is_range;

        is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
        called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
            &dec_insn, METHOD_DIRECT, is_range, false, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        /*
         * Some additional checks when calling <init>. We know from
         * the invocation arg check that the "this" argument is an
         * instance of called_method->klass. Now we further restrict
         * that to require that called_method->klass is the same as
         * this->klass or this->super, allowing the latter only if
         * the "this" argument is the same as the "this" argument to
         * this method (which implies that we're in <init> ourselves).
         */
        if (IsInitMethod(called_method)) {
          RegType this_type;
          this_type = GetInvocationThis(work_line, &dec_insn, &failure);
          if (failure != VERIFY_ERROR_NONE)
            break;

          /* no null refs allowed (?) */
          if (this_type == kRegTypeZero) {
            LOG(ERROR) << "VFY: unable to initialize null ref";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          Class* this_class;

          this_class = RegTypeReferenceToClass(this_type, uninit_map);
          assert(this_class != NULL);

          /* must be in same class or in superclass */
          if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
          {
            if (this_class != method->GetDeclaringClass()) {
              LOG(ERROR) << "VFY: invoke-direct <init> on super only "
                         << "allowed for 'this' in <init>";
              failure = VERIFY_ERROR_GENERIC;
              break;
            }
          }  else if (called_method->GetDeclaringClass() != this_class) {
            LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
                       << "class or super";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /* arg must be an uninitialized reference */
          if (!RegTypeIsUninitReference(this_type)) {
            LOG(ERROR) << "VFY: can only initialize the uninitialized";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /*
           * Replace the uninitialized reference with an initialized
           * one, and clear the entry in the uninit map. We need to
           * do this for all registers that have the same object
           * instance in them, not just the "this" register.
           */
          MarkRefsAsInitialized(work_line, registers_size, uninit_map,
              this_type, &failure);
          if (failure != VERIFY_ERROR_NONE)
            break;
          }
        return_type = GetMethodReturnType(dex_file, called_method);
        SetResultRegisterType(work_line, registers_size, return_type);
        just_set_result = true;
      }
      break;
    case Instruction::INVOKE_STATIC:
    case Instruction::INVOKE_STATIC_RANGE:
      {
        RegType return_type;
        Method* called_method;
        bool is_range;

        is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
        called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
            &dec_insn, METHOD_STATIC, is_range, false, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        return_type = GetMethodReturnType(dex_file, called_method);
        SetResultRegisterType(work_line, registers_size, return_type);
        just_set_result = true;
      }
      break;
    case Instruction::INVOKE_INTERFACE:
    case Instruction::INVOKE_INTERFACE_RANGE:
      {
        RegType /*this_type,*/ return_type;
        Method* abs_method;
        bool is_range;

        is_range =  (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
        abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
            &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

#if 0   /* can't do this here, fails on dalvik test 052-verifier-fun */
        /*
         * Get the type of the "this" arg, which should always be an
         * interface class. Because we don't do a full merge on
         * interface classes, this might have reduced to Object.
         */
        this_type = GetInvocationThis(work_line, &dec_insn, &failure);
        if (failure != VERIFY_ERROR_NONE)
          break;

        if (this_type == kRegTypeZero) {
          /* null pointer always passes (and always fails at runtime) */
        } else {
          Class* this_class;

          this_class = RegTypeInitializedReferenceToClass(this_type);
          if (this_class == NULL) {
            LOG(ERROR) << "VFY: interface call on uninitialized";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }

          /*
           * Either "this_class" needs to be the interface class that
           * defined abs_method, or abs_method's class needs to be one
           * of the interfaces implemented by "this_class". (Or, if
           * we couldn't complete the merge, this will be Object.)
           */
          if (this_class != abs_method->GetDeclaringClass() &&
              this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
              !this_class->Implements(abs_method->GetDeclaringClass())) {
            LOG(ERROR) << "VFY: unable to match abs_method '"
                       << abs_method->GetName()->ToModifiedUtf8() << "' with "
                       << this_class->GetDescriptor()->ToModifiedUtf8()
                       << " interfaces";
            failure = VERIFY_ERROR_GENERIC;
            break;
          }
        }
#endif

        /*
         * We don't have an object instance, so we can't find the
         * concrete method. However, all of the type information is
         * in the abstract method, so we're good.
         */
        return_type = GetMethodReturnType(dex_file, abs_method);
        SetResultRegisterType(work_line, registers_size, return_type);
        just_set_result = true;
      }
      break;

    case Instruction::NEG_INT:
    case Instruction::NOT_INT:
      CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          &failure);
      break;
    case Instruction::NEG_LONG:
    case Instruction::NOT_LONG:
      CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
      break;
    case Instruction::NEG_FLOAT:
      CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
      break;
    case Instruction::NEG_DOUBLE:
      CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
          &failure);
      break;
    case Instruction::INT_TO_LONG:
      CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
          &failure);
      break;
    case Instruction::INT_TO_FLOAT:
      CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
      break;
    case Instruction::INT_TO_DOUBLE:
      CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
          &failure);
      break;
    case Instruction::LONG_TO_INT:
      CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
          &failure);
      break;
    case Instruction::LONG_TO_FLOAT:
      CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
      break;
    case Instruction::LONG_TO_DOUBLE:
      CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
          &failure);
      break;
    case Instruction::FLOAT_TO_INT:
      CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
      break;
    case Instruction::FLOAT_TO_LONG:
      CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
      break;
    case Instruction::FLOAT_TO_DOUBLE:
      CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
          &failure);
      break;
    case Instruction::DOUBLE_TO_INT:
      CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
          &failure);
      break;
    case Instruction::DOUBLE_TO_LONG:
      CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
          &failure);
      break;
    case Instruction::DOUBLE_TO_FLOAT:
      CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
          &failure);
      break;
    case Instruction::INT_TO_BYTE:
      CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
      break;
    case Instruction::INT_TO_CHAR:
      CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
      break;
    case Instruction::INT_TO_SHORT:
      CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
      break;

    case Instruction::ADD_INT:
    case Instruction::SUB_INT:
    case Instruction::MUL_INT:
    case Instruction::REM_INT:
    case Instruction::DIV_INT:
    case Instruction::SHL_INT:
    case Instruction::SHR_INT:
    case Instruction::USHR_INT:
      CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          kRegTypeInteger, false, &failure);
      break;
    case Instruction::AND_INT:
    case Instruction::OR_INT:
    case Instruction::XOR_INT:
      CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          kRegTypeInteger, true, &failure);
      break;
    case Instruction::ADD_LONG:
    case Instruction::SUB_LONG:
    case Instruction::MUL_LONG:
    case Instruction::DIV_LONG:
    case Instruction::REM_LONG:
    case Instruction::AND_LONG:
    case Instruction::OR_LONG:
    case Instruction::XOR_LONG:
      CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
          kRegTypeLongLo, false, &failure);
      break;
    case Instruction::SHL_LONG:
    case Instruction::SHR_LONG:
    case Instruction::USHR_LONG:
      /* shift distance is Int, making these different from other binops */
      CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
          kRegTypeInteger, false, &failure);
      break;
    case Instruction::ADD_FLOAT:
    case Instruction::SUB_FLOAT:
    case Instruction::MUL_FLOAT:
    case Instruction::DIV_FLOAT:
    case Instruction::REM_FLOAT:
      CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
          kRegTypeFloat, false, &failure);
      break;
    case Instruction::ADD_DOUBLE:
    case Instruction::SUB_DOUBLE:
    case Instruction::MUL_DOUBLE:
    case Instruction::DIV_DOUBLE:
    case Instruction::REM_DOUBLE:
      CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
          kRegTypeDoubleLo, false, &failure);
      break;
    case Instruction::ADD_INT_2ADDR:
    case Instruction::SUB_INT_2ADDR:
    case Instruction::MUL_INT_2ADDR:
    case Instruction::REM_INT_2ADDR:
    case Instruction::SHL_INT_2ADDR:
    case Instruction::SHR_INT_2ADDR:
    case Instruction::USHR_INT_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          kRegTypeInteger, false, &failure);
      break;
    case Instruction::AND_INT_2ADDR:
    case Instruction::OR_INT_2ADDR:
    case Instruction::XOR_INT_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          kRegTypeInteger, true, &failure);
      break;
    case Instruction::DIV_INT_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
          kRegTypeInteger, false, &failure);
      break;
    case Instruction::ADD_LONG_2ADDR:
    case Instruction::SUB_LONG_2ADDR:
    case Instruction::MUL_LONG_2ADDR:
    case Instruction::DIV_LONG_2ADDR:
    case Instruction::REM_LONG_2ADDR:
    case Instruction::AND_LONG_2ADDR:
    case Instruction::OR_LONG_2ADDR:
    case Instruction::XOR_LONG_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
          kRegTypeLongLo, false, &failure);
      break;
    case Instruction::SHL_LONG_2ADDR:
    case Instruction::SHR_LONG_2ADDR:
    case Instruction::USHR_LONG_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
          kRegTypeInteger, false, &failure);
      break;
    case Instruction::ADD_FLOAT_2ADDR:
    case Instruction::SUB_FLOAT_2ADDR:
    case Instruction::MUL_FLOAT_2ADDR:
    case Instruction::DIV_FLOAT_2ADDR:
    case Instruction::REM_FLOAT_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
          kRegTypeFloat, false, &failure);
      break;
    case Instruction::ADD_DOUBLE_2ADDR:
    case Instruction::SUB_DOUBLE_2ADDR:
    case Instruction::MUL_DOUBLE_2ADDR:
    case Instruction::DIV_DOUBLE_2ADDR:
    case Instruction::REM_DOUBLE_2ADDR:
      CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
          kRegTypeDoubleLo, false, &failure);
      break;
    case Instruction::ADD_INT_LIT16:
    case Instruction::RSUB_INT:
    case Instruction::MUL_INT_LIT16:
    case Instruction::DIV_INT_LIT16:
    case Instruction::REM_INT_LIT16:
      CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
          &failure);
      break;
    case Instruction::AND_INT_LIT16:
    case Instruction::OR_INT_LIT16:
    case Instruction::XOR_INT_LIT16:
      CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
          &failure);
      break;
    case Instruction::ADD_INT_LIT8:
    case Instruction::RSUB_INT_LIT8:
    case Instruction::MUL_INT_LIT8:
    case Instruction::DIV_INT_LIT8:
    case Instruction::REM_INT_LIT8:
    case Instruction::SHL_INT_LIT8:
      CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
          &failure);
      break;
    case Instruction::SHR_INT_LIT8:
      tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
          false, &failure);
      CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
          &failure);
      break;
    case Instruction::USHR_INT_LIT8:
      tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
          true, &failure);
      CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
          &failure);
      break;
    case Instruction::AND_INT_LIT8:
    case Instruction::OR_INT_LIT8:
    case Instruction::XOR_INT_LIT8:
      CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
          &failure);
      break;

    /*
     * This falls into the general category of "optimized" instructions,
     * which don't generally appear during verification. Because it's
     * inserted in the course of verification, we can expect to see it here.
     */
    //case Instruction::THROW_VERIFICATION_ERROR:
    case Instruction::UNUSED_ED:
      break;

    /*
     * Verifying "quickened" instructions is tricky, because we have
     * discarded the original field/method information. The byte offsets
     * and vtable indices only have meaning in the context of an object
     * instance.
     *
     * If a piece of code declares a local reference variable, assigns
     * null to it, and then issues a virtual method call on it, we
     * cannot evaluate the method call during verification. This situation
     * isn't hard to handle, since we know the call will always result in an
     * NPE, and the arguments and return value don't matter. Any code that
     * depends on the result of the method call is inaccessible, so the
     * fact that we can't fully verify anything that comes after the bad
     * call is not a problem.
     *
     * We must also consider the case of multiple code paths, only some of
     * which involve a null reference. We can completely verify the method
     * if we sidestep the results of executing with a null reference.
     * For example, if on the first pass through the code we try to do a
     * virtual method invocation through a null ref, we have to skip the
     * method checks and have the method return a "wildcard" type (which
     * merges with anything to become that other thing). The move-result
     * will tell us if it's a reference, single-word numeric, or double-word
     * value. We continue to perform the verification, and at the end of
     * the function any invocations that were never fully exercised are
     * marked as null-only.
     *
     * We would do something similar for the field accesses. The field's
     * type, once known, can be used to recover the width of short integers.
     * If the object reference was null, the field-get returns the "wildcard"
     * type, which is acceptable for any operation.
     */
    case Instruction::UNUSED_EE:
    case Instruction::UNUSED_EF:
    case Instruction::UNUSED_F2:
    case Instruction::UNUSED_F3:
    case Instruction::UNUSED_F4:
    case Instruction::UNUSED_F5:
    case Instruction::UNUSED_F6:
    case Instruction::UNUSED_F7:
    case Instruction::UNUSED_F8:
    case Instruction::UNUSED_F9:
    case Instruction::UNUSED_FA:
    case Instruction::UNUSED_FB:
    //case Instruction::EXECUTE_INLINE:
    //case Instruction::EXECUTE_INLINE_RANGE:
    //case Instruction::IGET_QUICK:
    //case Instruction::IGET_WIDE_QUICK:
    //case Instruction::IGET_OBJECT_QUICK:
    //case Instruction::IPUT_QUICK:
    //case Instruction::IPUT_WIDE_QUICK:
    //case Instruction::IPUT_OBJECT_QUICK:
    //case Instruction::INVOKE_VIRTUAL_QUICK:
    //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
    //case Instruction::INVOKE_SUPER_QUICK:
    //case Instruction::INVOKE_SUPER_QUICK_RANGE:
      /* fall through to failure */

    /*
     * These instructions are equivalent (from the verifier's point of view)
     * to the original form. The change was made for correctness rather
     * than improved performance (except for invoke-object-init, which
     * provides both). The substitution takes place after verification
     * completes, though, so we don't expect to see them here.
     */
    case Instruction::UNUSED_F0:
    case Instruction::UNUSED_F1:
    case Instruction::UNUSED_E3:
    case Instruction::UNUSED_E8:
    case Instruction::UNUSED_E7:
    case Instruction::UNUSED_E4:
    case Instruction::UNUSED_E9:
    case Instruction::UNUSED_FC:
    case Instruction::UNUSED_E5:
    case Instruction::UNUSED_EA:
    case Instruction::UNUSED_FD:
    case Instruction::UNUSED_E6:
    case Instruction::UNUSED_EB:
    case Instruction::UNUSED_FE:
    //case Instruction::INVOKE_OBJECT_INIT_RANGE:
    //case Instruction::RETURN_VOID_BARRIER:
    //case Instruction::IGET_VOLATILE:
    //case Instruction::IGET_WIDE_VOLATILE:
    //case Instruction::IGET_OBJECT_VOLATILE:
    //case Instruction::IPUT_VOLATILE:
    //case Instruction::IPUT_WIDE_VOLATILE:
    //case Instruction::IPUT_OBJECT_VOLATILE:
    //case Instruction::SGET_VOLATILE:
    //case Instruction::SGET_WIDE_VOLATILE:
    //case Instruction::SGET_OBJECT_VOLATILE:
    //case Instruction::SPUT_VOLATILE:
    //case Instruction::SPUT_WIDE_VOLATILE:
    //case Instruction::SPUT_OBJECT_VOLATILE:
      /* fall through to failure */

    /* These should never appear during verification. */
    case Instruction::UNUSED_3E:
    case Instruction::UNUSED_3F:
    case Instruction::UNUSED_40:
    case Instruction::UNUSED_41:
    case Instruction::UNUSED_42:
    case Instruction::UNUSED_43:
    case Instruction::UNUSED_73:
    case Instruction::UNUSED_79:
    case Instruction::UNUSED_7A:
    case Instruction::UNUSED_EC:
    case Instruction::UNUSED_FF:
    //case Instruction::BREAKPOINT:
    //case Instruction::DISPATCH_FF:
      failure = VERIFY_ERROR_GENERIC;
      break;

    /*
     * DO NOT add a "default" clause here. Without it the compiler will
     * complain if an instruction is missing (which is desirable).
     */
    }

  if (failure != VERIFY_ERROR_NONE) {
    //if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing)
    if (failure == VERIFY_ERROR_GENERIC) {
      /* immediate failure, reject class */
      LOG(ERROR) << "VFY:  rejecting opcode 0x" << std::hex
                 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
      return false;
    } else {
      /* replace opcode and continue on */
      LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
                 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
      if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
      {
        LOG(ERROR) << "VFY:  rejecting opcode 0x" << std::hex
                   << (int) dec_insn.opcode_ << " at 0x" << insn_idx
                   << std::dec;
        return false;
      }
      /* IMPORTANT: method->insns may have been changed */
      insns = code_item->insns_ + insn_idx;

      /* continue on as if we just handled a throw-verification-error */
      failure = VERIFY_ERROR_NONE;
      opcode_flag = Instruction::kThrow;
    }
  }

  /*
   * If we didn't just set the result register, clear it out. This
   * ensures that you can only use "move-result" immediately after the
   * result is set. (We could check this statically, but it's not
   * expensive and it makes our debugging output cleaner.)
   */
  if (!just_set_result) {
    int reg = RESULT_REGISTER(registers_size);
    SetRegisterType(work_line, reg, kRegTypeUnknown);
    SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
  }

  /*
   * Handle "continue". Tag the next consecutive instruction.
   */
  if ((opcode_flag & Instruction::kContinue) != 0) {
    size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
    if (insn_idx + insn_width >= insns_size) {
      LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
                 << std::hex << insn_idx << std::dec << ")";
      return false;
    }

    /*
     * The only way to get to a move-exception instruction is to get
     * thrown there. Make sure the next instruction isn't one.
     */
    if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
      return false;

    if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
      /*
       * Merge registers into what we have for the next instruction,
       * and set the "changed" flag if needed.
       */
      if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
          work_line))
        return false;
    } else {
      /*
       * We're not recording register data for the next instruction,
       * so we don't know what the prior state was. We have to
       * assume that something has changed and re-evaluate it.
       */
      InsnSetChanged(insn_flags, insn_idx + insn_width, true);
    }
  }

  /*
   * Handle "branch". Tag the branch target.
   *
   * NOTE: instructions like Instruction::EQZ provide information about the
   * state of the register when the branch is taken or not taken. For example,
   * somebody could get a reference field, check it for zero, and if the
   * branch is taken immediately store that register in a boolean field
   * since the value is known to be zero. We do not currently account for
   * that, and will reject the code.
   *
   * TODO: avoid re-fetching the branch target
   */
  if ((opcode_flag & Instruction::kBranch) != 0) {
    bool isConditional, selfOkay;

    if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
        &isConditional, &selfOkay)) {
      /* should never happen after static verification */
      LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
      return false;
    }
    assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
    assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);

    if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
      return false;

    /* update branch target, set "changed" if appropriate */
    if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
        work_line))
      return false;
  }

  /*
   * Handle "switch". Tag all possible branch targets.
   *
   * We've already verified that the table is structurally sound, so we
   * just need to walk through and tag the targets.
   */
  if ((opcode_flag & Instruction::kSwitch) != 0) {
    int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
    const uint16_t* switch_insns = insns + offset_to_switch;
    int switch_count = switch_insns[1];
    int offset_to_targets, targ;

    if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
      /* 0 = sig, 1 = count, 2/3 = first key */
      offset_to_targets = 4;
    } else {
      /* 0 = sig, 1 = count, 2..count * 2 = keys */
      assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
      offset_to_targets = 2 + 2 * switch_count;
    }

    /* verify each switch target */
    for (targ = 0; targ < switch_count; targ++) {
      int offset;
      uint32_t abs_offset;

      /* offsets are 32-bit, and only partly endian-swapped */
      offset = switch_insns[offset_to_targets + targ * 2] |
         (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
      abs_offset = insn_idx + offset;

      assert(abs_offset < insns_size);

      if (!CheckMoveException(code_item->insns_, abs_offset))
        return false;

      if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
        return false;
    }
  }

  /*
   * Handle instructions that can throw and that are sitting in a
   * "try" block. (If they're not in a "try" block when they throw,
   * control transfers out of the method.)
   */
  if ((opcode_flag & Instruction::kThrow) != 0 &&
      InsnIsInTry(insn_flags, insn_idx)) {
    bool has_catch_all = false;
    DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
        *code_item, insn_idx);

    for (; !iterator.HasNext(); iterator.Next()) {
      if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
        has_catch_all = true;

      /*
       * Merge registers into the "catch" block. We want to use the
       * "savedRegs" rather than "work_regs", because at runtime the
       * exception will be thrown before the instruction modifies any
       * registers.
       */
      if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
          &reg_table->saved_line_))
        return false;
    }

    /*
     * If the monitor stack depth is nonzero, there must be a "catch all"
     * handler for this instruction. This does apply to monitor-exit
     * because of async exception handling.
     */
    if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
      /*
       * The state in work_line reflects the post-execution state.
       * If the current instruction is a monitor-enter and the monitor
       * stack was empty, we don't need a catch-all (if it throws,
       * it will do so before grabbing the lock).
       */
      if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
          work_line->monitor_stack_top_ == 1))
      {
        LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
                   << insn_idx << std::dec;
        return false;
      }
    }
  }

  /* If we're returning from the method, make sure monitor stack is empty. */
  if ((opcode_flag & Instruction::kReturn) != 0 &&
      work_line->monitor_stack_top_ != 0) {
    LOG(ERROR) << "VFY: return with stack depth="
               << work_line->monitor_stack_top_ << " at 0x" << std::hex
               << insn_idx << std::dec;
    return false;
  }

  /*
   * Update start_guess. Advance to the next instruction of that's
   * possible, otherwise use the branch target if one was found. If
   * neither of those exists we're in a return or throw; leave start_guess
   * alone and let the caller sort it out.
   */
  if ((opcode_flag & Instruction::kContinue) != 0) {
    *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
  } else if ((opcode_flag & Instruction::kBranch) != 0) {
    /* we're still okay if branch_target is zero */
    *start_guess = insn_idx + branch_target;
  }

  assert(*start_guess < insns_size &&
      InsnGetWidth(insn_flags, *start_guess) != 0);

  return true;
}

bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
    InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
  const uint16_t* insns = code_item->insns_ + insn_idx;
  const byte* ptr = reinterpret_cast<const byte*>(insns);
  const Instruction* inst = Instruction::At(ptr);
  Instruction::Code opcode = inst->Opcode();
  VerifyErrorRefType ref_type;

  /*
   * Generate the new instruction out of the old.
   *
   * First, make sure this is an instruction we're expecting to stomp on.
   */
  switch (opcode) {
    case Instruction::CONST_CLASS:            // insn[1] == class ref, 2 bytes
    case Instruction::CHECK_CAST:
    case Instruction::INSTANCE_OF:
    case Instruction::NEW_INSTANCE:
    case Instruction::NEW_ARRAY:
    case Instruction::FILLED_NEW_ARRAY:       // insn[1] == class ref, 3 bytes
    case Instruction::FILLED_NEW_ARRAY_RANGE:
      ref_type = VERIFY_ERROR_REF_CLASS;
      break;

    case Instruction::IGET:                   // insn[1] == field ref, 2 bytes
    case Instruction::IGET_BOOLEAN:
    case Instruction::IGET_BYTE:
    case Instruction::IGET_CHAR:
    case Instruction::IGET_SHORT:
    case Instruction::IGET_WIDE:
    case Instruction::IGET_OBJECT:
    case Instruction::IPUT:
    case Instruction::IPUT_BOOLEAN:
    case Instruction::IPUT_BYTE:
    case Instruction::IPUT_CHAR:
    case Instruction::IPUT_SHORT:
    case Instruction::IPUT_WIDE:
    case Instruction::IPUT_OBJECT:
    case Instruction::SGET:
    case Instruction::SGET_BOOLEAN:
    case Instruction::SGET_BYTE:
    case Instruction::SGET_CHAR:
    case Instruction::SGET_SHORT:
    case Instruction::SGET_WIDE:
    case Instruction::SGET_OBJECT:
    case Instruction::SPUT:
    case Instruction::SPUT_BOOLEAN:
    case Instruction::SPUT_BYTE:
    case Instruction::SPUT_CHAR:
    case Instruction::SPUT_SHORT:
    case Instruction::SPUT_WIDE:
    case Instruction::SPUT_OBJECT:
      ref_type = VERIFY_ERROR_REF_FIELD;
      break;

    case Instruction::INVOKE_VIRTUAL:         // insn[1] == method ref, 3 bytes
    case Instruction::INVOKE_VIRTUAL_RANGE:
    case Instruction::INVOKE_SUPER:
    case Instruction::INVOKE_SUPER_RANGE:
    case Instruction::INVOKE_DIRECT:
    case Instruction::INVOKE_DIRECT_RANGE:
    case Instruction::INVOKE_STATIC:
    case Instruction::INVOKE_STATIC_RANGE:
    case Instruction::INVOKE_INTERFACE:
    case Instruction::INVOKE_INTERFACE_RANGE:
      ref_type = VERIFY_ERROR_REF_METHOD;
      break;

    default:
      /* could handle this in a generic way, but this is probably safer */
      LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
                 << (int) opcode << std::dec;
      return false;
  }

  assert(inst->IsThrow());

  /* write a NOP over the third code unit, if necessary */
  int width = InsnGetWidth(insn_flags, insn_idx);
  switch (width) {
    case 2:
      /* nothing to do */
      break;
    case 3:
      // TODO: Add this functionality
      //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
      break;
    default:
      /* whoops */
      LOG(FATAL) << "ERROR: stomped a " << width
                 << "-unit instruction with a verifier error";
  }

  /* encode the opcode, with the failure code in the high byte */
  // TODO: REPLACE FAILING OPCODES
  //assert(width == 2 || width == 3);
  //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
      //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
  //UpdateCodeUnit(method, insns, new_val);

  return true;
}

/* Handle a monitor-enter instruction. */
void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
    uint32_t insn_idx, VerifyError* failure) {
  if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
    LOG(ERROR) << "VFY: monitor-enter on non-object";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }

  if (work_line->monitor_entries_.get() == NULL) {
    return;
  }

  if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
    LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
               << ")";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }

  /*
   * Push an entry on the stack, and set a bit in the register flags to
   * indicate that it's associated with this register.
   */
  work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
  work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
}

/* Handle a monitor-exit instruction. */
void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
    uint32_t insn_idx, VerifyError* failure) {
  if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
    LOG(ERROR) << "VFY: monitor-exit on non-object";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }

  if (work_line->monitor_entries_.get() == NULL) {
    return;
  }

  if (work_line->monitor_stack_top_ == 0) {
    LOG(ERROR) << "VFY: monitor-exit stack underflow";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }

  /*
   * Confirm that the entry at the top of the stack is associated with
   * the register. Pop the top entry off.
   */
  work_line->monitor_stack_top_--;
#ifdef BUG_3215458_FIXED
  /*
   * TODO: This code can safely be enabled if know we are working on
   * a dex file of format version 036 or later. (That is, we'll need to
   * add a check for the version number.)
   */
  if ((work_line->monitor_entries_[reg_idx] &
      (1 << work_line->monitor_stack_top_)) == 0) {
    LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
               << " not set: addr=0x" << std::hex << insn_idx << std::dec
               << " (bits[" << reg_idx << "]=" << std::hex
               << work_line->monitor_entries_[reg_idx] << std::dec << ")";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }
#endif
  work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;

  /* Clear the bit from the register flags. */
  work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
}

Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
    int field_idx, VerifyError* failure) {
  Method* method = vdata->method_;
  const DexFile* dex_file = vdata->dex_file_;
  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
  const ClassLoader* class_loader =
      method->GetDeclaringClass()->GetClassLoader();
  Field* field = NULL;
  Class* obj_class;
  bool must_be_local = false;

  if (!RegTypeIsReference(obj_type)) {
    LOG(ERROR) << "VFY: attempt to access field in non-reference type "
               << obj_type;
    *failure = VERIFY_ERROR_GENERIC;
    return field;
  }

  field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
      class_loader, false);
  if (field == NULL) {
    LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
    return field;
  }

  if (obj_type == kRegTypeZero)
    return field;

  /*
   * Access to fields in uninitialized objects is allowed if this is
   * the <init> method for the object and the field in question is
   * declared by this class.
   */
  obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
  assert(obj_class != NULL);
  if (RegTypeIsUninitReference(obj_type)) {
    if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
      LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
      *failure = VERIFY_ERROR_GENERIC;
      return field;
    }
    must_be_local = true;
  }

  if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
    LOG(ERROR) << "VFY: invalid field access (field "
               << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
               << "." << field->GetName()->ToModifiedUtf8() << ", through "
               << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
    *failure = VERIFY_ERROR_NO_FIELD;
    return field;
  }

  if (must_be_local) {
    bool found = false;
    /* for uninit ref, make sure it's defined by this class, not super */
    for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
      found |= (field == obj_class->GetInstanceField(i));
    }
    if (!found) {
      LOG(ERROR) << "VFY: invalid constructor field access (field "
                 << field->GetName()->ToModifiedUtf8() << " in "
                 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
      *failure = VERIFY_ERROR_GENERIC;
      return field;
    }
  }

  return field;
}

Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
    VerifyError* failure) {
  Method* method = vdata->method_;
  const DexFile* dex_file = vdata->dex_file_;
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
  const ClassLoader* class_loader =
      method->GetDeclaringClass()->GetClassLoader();
  Field* field;

  field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
      class_loader, true);
  if (field == NULL) {
    //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);

    //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
               //<< dex_file->GetFieldName(field_id) << ") in "
               //<< dex_file->GetFieldClassDescriptor(field_id);
    LOG(ERROR) << "VFY: unable to resolve static field";
  }

  return field;
}

Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
    VerifyError* failure) {
  const DexFile* dex_file = vdata->dex_file_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  Method* method = vdata->method_;
  Class* common_super = NULL;
  uint32_t handlers_size;
  const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);

  if (code_item->tries_size_ != 0) {
    handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
  } else {
    handlers_size = 0;
  }

  for (uint32_t i = 0; i < handlers_size; i++) {
    DexFile::CatchHandlerIterator iterator(handlers_ptr);

    for (; !iterator.HasNext(); iterator.Next()) {
      DexFile::CatchHandlerItem handler = iterator.Get();
      if (handler.address_ == (uint32_t) insn_idx) {
        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
        Class* klass;

        if (handler.type_idx_ == DexFile::kDexNoIndex) {
          klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
        } else {
          klass = class_linker->ResolveType(*dex_file, handler.type_idx_,
              method->GetDeclaringClass());
        }

        if (klass == NULL) {
          LOG(ERROR) << "VFY: unable to resolve exception class "
                     << handler.type_idx_ << " ("
                     << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
          /* TODO: do we want to keep going?  If we don't fail this we run
           * the risk of having a non-Throwable introduced at runtime.
           * However, that won't pass an instanceof test, so is essentially
           * harmless.
           */
        } else {
          if (common_super == NULL)
            common_super = klass;
          else
            common_super = FindCommonSuperclass(klass, common_super);
        }
      }
    }

    handlers_ptr = iterator.GetData();
  }

  if (common_super == NULL) {
    /* no catch blocks, or no catches with classes we can find */
    LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
               << insn_idx << std::dec;
    *failure = VERIFY_ERROR_GENERIC;
  }

  return common_super;
}

DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
    const Method* method) {
  Class* klass = method->GetReturnType();
  if (klass->IsPrimitive())
    return PrimitiveTypeToRegType(klass->GetPrimitiveType());
  else
    return RegTypeFromClass(klass);
}

Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
    uint32_t vsrc, VerifyError* failure) {
  /* get the element type of the array held in vsrc */
  RegType type = GetRegisterType(register_line, vsrc);

  /* if "always zero", we allow it to fail at runtime */
  if (type == kRegTypeZero)
    return NULL;

  if (!RegTypeIsReference(type)) {
    LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
               << " (type=" << type << ")",
    *failure = VERIFY_ERROR_GENERIC;
    return NULL;
  }
  if (RegTypeIsUninitReference(type)) {
    LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
    *failure = VERIFY_ERROR_GENERIC;
    return NULL;
  }

  return RegTypeInitializedReferenceToClass(type);
}

DexVerifier::RegType DexVerifier::GetInvocationThis(
    const RegisterLine* register_line,
    const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
  if (dec_insn->vA_ < 1) {
    LOG(ERROR) << "VFY: invoke lacks 'this'";
    *failure = VERIFY_ERROR_GENERIC;
    return kRegTypeUnknown;
  }

  /* get the element type of the array held in vsrc */
  RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
  if (!RegTypeIsReference(this_type)) {
    LOG(ERROR) << "VFY: tried to get class from non-ref register v"
               << dec_insn->vC_ << " (type=" << this_type << ")";
    *failure = VERIFY_ERROR_GENERIC;
    return kRegTypeUnknown;
  }

  return this_type;
}

void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
    RegType new_type) {
  RegType* insn_regs = register_line->reg_types_.get();

  switch (new_type) {
    case kRegTypeUnknown:
    case kRegTypeBoolean:
    case kRegTypeOne:
    case kRegTypeConstByte:
    case kRegTypeConstPosByte:
    case kRegTypeConstShort:
    case kRegTypeConstPosShort:
    case kRegTypeConstChar:
    case kRegTypeConstInteger:
    case kRegTypeByte:
    case kRegTypePosByte:
    case kRegTypeShort:
    case kRegTypePosShort:
    case kRegTypeChar:
    case kRegTypeInteger:
    case kRegTypeFloat:
    case kRegTypeZero:
    case kRegTypeUninit:
      insn_regs[vdst] = new_type;
      break;
    case kRegTypeConstLo:
    case kRegTypeLongLo:
    case kRegTypeDoubleLo:
      insn_regs[vdst] = new_type;
      insn_regs[vdst + 1] = new_type + 1;
      break;
    case kRegTypeConstHi:
    case kRegTypeLongHi:
    case kRegTypeDoubleHi:
      /* should never set these explicitly */
      LOG(FATAL) << "BUG: explicit set of high register type";
      break;

    default:
      /* can't switch for ref types, so we check explicitly */
      if (RegTypeIsReference(new_type)) {
        insn_regs[vdst] = new_type;

        /*
         * In most circumstances we won't see a reference to a primitive
         * class here (e.g. "D"), since that would mean the object in the
         * register is actually a primitive type. It can happen as the
         * result of an assumed-successful check-cast instruction in
         * which the second argument refers to a primitive class. (In
         * practice, such an instruction will always throw an exception.)
         *
         * This is not an issue for instructions like const-class, where
         * the object in the register is a java.lang.Class instance.
         */
        break;
      }
      /* bad type - fall through */

    case kRegTypeConflict:      // should only be set during a merge
      LOG(FATAL) << "BUG: set register to unknown type " << new_type;
      break;
  }

  /*
   * Clear the monitor entry bits for this register.
   */
  if (register_line->monitor_entries_.get() != NULL)
    register_line->monitor_entries_[vdst] = 0;
}

void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
    RegType check_type, VerifyError* failure) {
  const RegType* insn_regs = register_line->reg_types_.get();
  RegType src_type = insn_regs[vsrc];

  switch (check_type) {
    case kRegTypeFloat:
    case kRegTypeBoolean:
    case kRegTypePosByte:
    case kRegTypeByte:
    case kRegTypePosShort:
    case kRegTypeShort:
    case kRegTypeChar:
    case kRegTypeInteger:
      if (!CanConvertTo1nr(src_type, check_type)) {
        LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
                   << ", wanted " << check_type;
        *failure = VERIFY_ERROR_GENERIC;
      }
      /* Update type if result is float */
      if (check_type == kRegTypeFloat) {
        SetRegisterType(register_line, vsrc, check_type);
      } else {
        /* Update const type to actual type after use */
        SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
      }
      break;
    case kRegTypeLongLo:
    case kRegTypeDoubleLo:
      if (insn_regs[vsrc + 1] != src_type + 1) {
        LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
                   << " values " << insn_regs[vsrc] << ","
                   << insn_regs[vsrc + 1];
        *failure = VERIFY_ERROR_GENERIC;
      } else if (!CanConvertTo2(src_type, check_type)) {
        LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
                   << ", wanted " << check_type;
        *failure = VERIFY_ERROR_GENERIC;
      }
      /* Update type if source is from const */
      if (src_type == kRegTypeConstLo) {
        SetRegisterType(register_line, vsrc, check_type);
      }
      break;
    case kRegTypeConstLo:
    case kRegTypeConstHi:
    case kRegTypeLongHi:
    case kRegTypeDoubleHi:
    case kRegTypeZero:
    case kRegTypeOne:
    case kRegTypeUnknown:
    case kRegTypeConflict:
      /* should never be checking for these explicitly */
      assert(false);
      *failure = VERIFY_ERROR_GENERIC;
      return;
    case kRegTypeUninit:
    default:
      /* make sure check_type is initialized reference */
      if (!RegTypeIsReference(check_type)) {
        LOG(ERROR) << "VFY: unexpected check type " << check_type;
        assert(false);
        *failure = VERIFY_ERROR_GENERIC;
        break;
      }
      if (RegTypeIsUninitReference(check_type)) {
        LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
        *failure = VERIFY_ERROR_GENERIC;
        break;
      }
      /* make sure src_type is initialized reference or always-NULL */
      if (!RegTypeIsReference(src_type)) {
        LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
                   << ", wanted ref";
        *failure = VERIFY_ERROR_GENERIC;
        break;
      }
      if (RegTypeIsUninitReference(src_type)) {
        LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
        *failure = VERIFY_ERROR_GENERIC;
        break;
      }
      /* if the register isn't Zero, make sure it's an instance of check */
      if (src_type != kRegTypeZero) {
        Class* src_class = RegTypeInitializedReferenceToClass(src_type);
        Class* check_class = RegTypeInitializedReferenceToClass(check_type);
        assert(src_class != NULL);
        assert(check_class != NULL);

        if (!check_class->IsAssignableFrom(src_class)) {
          LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
                     << " is not instance of "
                     << check_class->GetDescriptor()->ToModifiedUtf8();
          *failure = VERIFY_ERROR_GENERIC;
        }
      }
      break;
  }
}

void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
    const int insn_reg_count, RegType new_type) {
  SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
}

void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
    int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
    VerifyError* failure) {
  RegType* insn_regs = register_line->reg_types_.get();
  Class* klass = GetUninitInstance(uninit_map,
      RegTypeToUninitIndex(uninit_type));

  if (klass == NULL) {
    LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
               << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
               << ")";
    *failure = VERIFY_ERROR_GENERIC;
    return;
  }

  RegType init_type = RegTypeFromClass(klass);
  int changed = 0;
  for (int i = 0; i < insn_reg_count; i++) {
    if (insn_regs[i] == uninit_type) {
      insn_regs[i] = init_type;
      changed++;
    }
  }
  assert(changed > 0);

  return;
}

void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
    int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
  RegType* insn_regs = register_line->reg_types_.get();

  for (int i = 0; i < insn_reg_count; i++) {
    if (insn_regs[i] == uninit_type) {
      insn_regs[i] = kRegTypeConflict;
      if (register_line->monitor_entries_.get() != NULL)
        register_line->monitor_entries_[i] = 0;
    }
  }
}

void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
    uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
  assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
  RegType type = GetRegisterType(register_line, vsrc);
  CheckTypeCategory(type, cat, failure);
  if (*failure != VERIFY_ERROR_NONE) {
    LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
               << " cat=" << (int) cat;
  } else {
    SetRegisterType(register_line, vdst, type);
    if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
      register_line->monitor_entries_[vdst] =
          register_line->monitor_entries_[vsrc];
    }
  }
}

void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
    uint32_t vsrc, VerifyError* failure) {
  RegType type_l = GetRegisterType(register_line, vsrc);
  RegType type_h = GetRegisterType(register_line, vsrc + 1);

  CheckTypeCategory(type_l, kTypeCategory2, failure);
  CheckWidePair(type_l, type_h, failure);
  if (*failure != VERIFY_ERROR_NONE) {
    LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
               << "/" << type_h;
  } else {
    SetRegisterType(register_line, vdst, type_l);
  }
}

void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
    const int insn_reg_count, uint32_t vdst, TypeCategory cat,
    VerifyError* failure) {
  assert(vdst < (uint32_t) insn_reg_count);

  uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
  RegType type = GetRegisterType(register_line, vsrc);
  CheckTypeCategory(type, cat, failure);
  if (*failure != VERIFY_ERROR_NONE) {
    LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
               << (int) cat << " type=" << type;
  } else {
    SetRegisterType(register_line, vdst, type);
    SetRegisterType(register_line, vsrc, kRegTypeUnknown);
  }
}

/*
 * Implement "move-result-wide". Copy the category-2 value from the result
 * register to another register, and reset the result register.
 */
void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
    const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
  assert(vdst < (uint32_t) insn_reg_count);

  uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
  RegType type_l = GetRegisterType(register_line, vsrc);
  RegType type_h = GetRegisterType(register_line, vsrc + 1);
  CheckTypeCategory(type_l, kTypeCategory2, failure);
  CheckWidePair(type_l, type_h, failure);
  if (*failure != VERIFY_ERROR_NONE) {
    LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
               << type_l << "/" << type_h;
  } else {
    SetRegisterType(register_line, vdst, type_l);
    SetRegisterType(register_line, vsrc, kRegTypeUnknown);
    SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
  }
}

int DexVerifier::GetClassDepth(Class* klass) {
  int depth = 0;
  while (klass->GetSuperClass() != NULL) {
    klass = klass->GetSuperClass();
    depth++;
  }
  return depth;
}

Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
  int depth1, depth2;

  depth1 = GetClassDepth(c1);
  depth2 = GetClassDepth(c2);

  /* pull the deepest one up */
  if (depth1 > depth2) {
    while (depth1 > depth2) {
      c1 = c1->GetSuperClass();
      depth1--;
    }
  } else {
    while (depth2 > depth1) {
      c2 = c2->GetSuperClass();
      depth2--;
    }
  }

  /* walk up in lock-step */
  while (c1 != c2) {
    c1 = c1->GetSuperClass();
    c2 = c2->GetSuperClass();

    assert(c1 != NULL && c2 != NULL);
  }

  return c1;
}

Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
  Class* array_class = NULL;
  Class* common_elem;
  int array_dim1, array_dim2;
  int i, num_dims;
  bool has_primitive = false;

  array_dim1 = c1->GetArrayRank();
  array_dim2 = c2->GetArrayRank();
  assert(c1->GetArrayRank() > 0);
  assert(c2->GetArrayRank() > 0);

  if (c1->GetComponentType()->IsPrimitive()) {
    array_dim1--;
    has_primitive = true;
  }
  if (c2->GetComponentType()->IsPrimitive()) {
    array_dim2--;
    has_primitive = true;
  }

  if (!has_primitive && array_dim1 == array_dim2) {
    /*
     * Two arrays of reference types with equal dimensions. Try to
     * find a good match.
     */
    common_elem = FindCommonSuperclass(c1->GetComponentType(),
        c2->GetComponentType());
    num_dims = array_dim1;
  } else {
    /*
     * Mismatched array depths and/or array(s) of primitives. We want
     * Object, or an Object array with appropriate dimensions.
     *
     * We initialize array_class to Object here, because it's possible
     * for us to set num_dims=0.
     */
    if (array_dim1 < array_dim2)
      num_dims = array_dim1;
    else
      num_dims = array_dim2;
    array_class = common_elem = c1->GetSuperClass();  // == java.lang.Object
  }

  /*
   * Find an appropriately-dimensioned array class. This is easiest
   * to do iteratively, using the array class found by the current round
   * as the element type for the next round.
   */
  for (i = 0; i < num_dims; i++) {
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    const ClassLoader* class_loader = c1->GetClassLoader();
    std::string descriptor = "[" +
        common_elem->GetDescriptor()->ToModifiedUtf8();
    array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
    common_elem = array_class;
  }
  assert(array_class != NULL);

  return array_class;
}

Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
  assert(!c1->IsPrimitive() && !c2->IsPrimitive());

  if (c1 == c2)
    return c1;

  if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
    return c1;
  }
  if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
    return c2;
  }
  if (c1->IsArrayClass() && c2->IsArrayClass()) {
    return FindCommonArraySuperclass(c1, c2);
  }

  return DigForSuperclass(c1, c2);
}

DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
    bool* changed) {
  RegType result;

  /*
   * Check for trivial case so we don't have to hit memory.
   */
  if (type1 == type2)
    return type1;

  /*
   * Use the table if we can, and reject any attempts to merge something
   * from the table with a reference type.
   *
   * Uninitialized references are composed of the enum ORed with an
   * index value. The uninitialized table entry at index zero *will*
   * show up as a simple kRegTypeUninit value. Since this cannot be
   * merged with anything but itself, the rules do the right thing.
   */
  if (type1 < kRegTypeMAX) {
    if (type2 < kRegTypeMAX) {
      result = merge_table_[type1][type2];
    } else {
      /* simple + reference == conflict, usually */
      if (type1 == kRegTypeZero)
        result = type2;
      else
        result = kRegTypeConflict;
    }
  } else {
    if (type2 < kRegTypeMAX) {
      /* reference + simple == conflict, usually */
      if (type2 == kRegTypeZero)
        result = type1;
      else
        result = kRegTypeConflict;
    } else {
      /* merging two references */
      if (RegTypeIsUninitReference(type1) ||
          RegTypeIsUninitReference(type2))
      {
        /* can't merge uninit with anything but self */
        result = kRegTypeConflict;
      } else {
        Class* klass1 = RegTypeInitializedReferenceToClass(type1);
        Class* klass2 = RegTypeInitializedReferenceToClass(type2);
        Class* merged_class = FindCommonSuperclass(klass1, klass2);
        assert(merged_class != NULL);
        result = RegTypeFromClass(merged_class);
      }
    }
  }

  if (result != type1)
    *changed = true;
  return result;
}

DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
    MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
  MonitorEntries result = ents1 & ents2;
  if (result != ents1)
    *changed = true;
  return result;
}

bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
    RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
  const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
  assert(work_line != NULL);
  const RegType* work_regs = work_line->reg_types_.get();

  if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
    /*
     * We haven't processed this instruction before, and we haven't
     * touched the registers here, so there's nothing to "merge". Copy
     * the registers over and mark it as changed. (This is the only
     * way a register can transition out of "unknown", so this is not
     * just an optimization.)
     */
    CopyLineToTable(reg_table, next_insn, work_line);
    InsnSetChanged(insn_flags, next_insn, true);
  } else {
    /* Merge registers, set Changed only if different */
    RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
    RegType* target_regs = target_line->reg_types_.get();
    MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
    MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
    bool changed = false;
    unsigned int idx;

    assert(target_regs != NULL);
    if (target_mon_ents != NULL) {
      /* Monitor stacks must be identical. */
      if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
        LOG(ERROR) << "VFY: mismatched stack depth "
                   << target_line->monitor_stack_top_ << " vs. "
                   << work_line->monitor_stack_top_ << " at 0x"
                   << std::hex << next_insn << std::dec;
        return false;
      }
      if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
                 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
         LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
                    << next_insn << std::dec;
         return false;
      }
    }

    for (idx = 0; idx < insn_reg_count_plus; idx++) {
      target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);

      if (target_mon_ents != NULL) {
        target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
             work_mon_ents[idx], &changed);
      }
    }

    if (changed) {
      InsnSetChanged(insn_flags, next_insn, true);
    }
  }

  return true;
}

bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
  static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
                            [kRegType1nrEND - kRegType1nrSTART + 1] =
  {
    /* chk: 0  1  Z  y  Y  h  H  c  i  b  B  s  S  C  I  F */
    { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
    { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
    { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
    { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
    { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
    { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
    { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
    { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
    { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
    { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
    { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
    { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
    { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
  };

  assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);

  if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
    return (bool) conv_tab[src_type - kRegType1nrSTART]
                          [check_type - kRegType1nrSTART];

  return false;
}

bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
  return ((src_type == kRegTypeConstLo || src_type == check_type) &&
          (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
}

DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
    Class::PrimitiveType prim_type) {
  switch (prim_type) {
    case Class::kPrimBoolean: return kRegTypeBoolean;
    case Class::kPrimByte:    return kRegTypeByte;
    case Class::kPrimShort:   return kRegTypeShort;
    case Class::kPrimChar:    return kRegTypeChar;
    case Class::kPrimInt:     return kRegTypeInteger;
    case Class::kPrimLong:    return kRegTypeLongLo;
    case Class::kPrimFloat:   return kRegTypeFloat;
    case Class::kPrimDouble:  return kRegTypeDoubleLo;
    case Class::kPrimVoid:
    default: {
      return kRegTypeUnknown;
    }
  }
}

DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
  switch (const_type) {
    case kRegTypeConstPosByte: return kRegTypePosByte;
    case kRegTypeConstByte: return kRegTypeByte;
    case kRegTypeConstPosShort: return kRegTypePosShort;
    case kRegTypeConstShort: return kRegTypeShort;
    case kRegTypeConstChar: return kRegTypeChar;
    case kRegTypeConstInteger: return kRegTypeInteger;
    default: {
      return const_type;
    }
  }
}

char DexVerifier::DetermineCat1Const(int32_t value) {
  if (value < -32768)
    return kRegTypeConstInteger;
  else if (value < -128)
    return kRegTypeConstShort;
  else if (value < 0)
    return kRegTypeConstByte;
  else if (value == 0)
    return kRegTypeZero;
  else if (value == 1)
    return kRegTypeOne;
  else if (value < 128)
    return kRegTypeConstPosByte;
  else if (value < 32768)
    return kRegTypeConstPosShort;
  else if (value < 65536)
    return kRegTypeConstChar;
  else
    return kRegTypeConstInteger;
}

void DexVerifier::CheckFinalFieldAccess(const Method* method,
    const Field* field, VerifyError* failure) {
  if (!field->IsFinal())
    return;

  /* make sure we're in the same class */
  if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
    LOG(ERROR) << "VFY: can't modify final field "
               << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
               << "." << field->GetName()->ToModifiedUtf8();
    *failure = VERIFY_ERROR_ACCESS_FIELD;
    return;
  }
}

void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
    VerifyError* failure) {
  if (*failure == VERIFY_ERROR_NONE) {
    /*
     * The 1nr types are interchangeable at this level. We could
     * do something special if we can definitively identify it as a
     * float, but there's no real value in doing so.
     */
    CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
    if (*failure != VERIFY_ERROR_NONE) {
      LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
    }
  }
}

bool DexVerifier::CheckConstructorReturn(const Method* method,
    const RegisterLine* register_line, const int insn_reg_count) {
  const RegType* insn_regs = register_line->reg_types_.get();

  if (!IsInitMethod(method))
    return true;

  RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);

  for (int i = 0; i < insn_reg_count; i++) {
    if (insn_regs[i] == uninit_this) {
      LOG(ERROR) << "VFY: <init> returning without calling superclass init";
      return false;
    }
  }
  return true;
}

bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
  if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
    LOG(ERROR) << "VFY: invalid use of move-exception";
    return false;
  }
  return true;
}

void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
    VerifyError* failure) {
  switch (cat) {
    case kTypeCategory1nr:
      switch (type) {
        case kRegTypeZero:
        case kRegTypeOne:
        case kRegTypeBoolean:
        case kRegTypeConstPosByte:
        case kRegTypeConstByte:
        case kRegTypeConstPosShort:
        case kRegTypeConstShort:
        case kRegTypeConstChar:
        case kRegTypeConstInteger:
        case kRegTypePosByte:
        case kRegTypeByte:
        case kRegTypePosShort:
        case kRegTypeShort:
        case kRegTypeChar:
        case kRegTypeInteger:
        case kRegTypeFloat:
          break;
        default:
          *failure = VERIFY_ERROR_GENERIC;
          break;
      }
      break;
    case kTypeCategory2:
      switch (type) {
        case kRegTypeConstLo:
        case kRegTypeLongLo:
        case kRegTypeDoubleLo:
          break;
        default:
          *failure = VERIFY_ERROR_GENERIC;
         break;
      }
      break;
    case kTypeCategoryRef:
      if (type != kRegTypeZero && !RegTypeIsReference(type))
        *failure = VERIFY_ERROR_GENERIC;
      break;
    default:
      assert(false);
      *failure = VERIFY_ERROR_GENERIC;
      break;
  }
}

void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
    VerifyError* failure) {
  if ((type_h != type_l + 1))
    *failure = VERIFY_ERROR_GENERIC;
}

void DexVerifier::CheckUnop(RegisterLine* register_line,
    Instruction::DecodedInstruction* dec_insn, RegType dst_type,
    RegType src_type, VerifyError* failure) {
  VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
  SetRegisterType(register_line, dec_insn->vA_, dst_type);
}

bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
    uint32_t reg2) {
  RegType type1, type2;

  type1 = GetRegisterType(register_line, reg1);
  type2 = GetRegisterType(register_line, reg2);

  if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
      (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
    return true;
  }
  return false;
}

void DexVerifier::CheckLitop(RegisterLine* register_line,
    Instruction::DecodedInstruction* dec_insn, RegType dst_type,
    RegType src_type, bool check_boolean_op, VerifyError* failure) {
  VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);

  if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
    assert(dst_type == kRegTypeInteger);

    /* check vB with the call, then check the constant manually */
    if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
        && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
      dst_type = kRegTypeBoolean;
    }
  }

  SetRegisterType(register_line, dec_insn->vA_, dst_type);
}

void DexVerifier::CheckBinop(RegisterLine* register_line,
    Instruction::DecodedInstruction* dec_insn, RegType dst_type,
    RegType src_type1, RegType src_type2, bool check_boolean_op,
    VerifyError* failure) {
  VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
  VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);

  if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
    assert(dst_type == kRegTypeInteger);
    if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
      dst_type = kRegTypeBoolean;
  }

  SetRegisterType(register_line, dec_insn->vA_, dst_type);
}

void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
    Instruction::DecodedInstruction* dec_insn, RegType dst_type,
    RegType src_type1, RegType src_type2, bool check_boolean_op,
    VerifyError* failure) {
  VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
  VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);

  if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
    assert(dst_type == kRegTypeInteger);
    if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
      dst_type = kRegTypeBoolean;
  }

  SetRegisterType(register_line, dec_insn->vA_, dst_type);
}

DexVerifier::RegType DexVerifier::AdjustForRightShift(
    RegisterLine* register_line, int reg, unsigned int shift_count,
    bool is_unsigned_shift, VerifyError* failure) {
  RegType src_type = GetRegisterType(register_line, reg);
  RegType new_type;

  /* convert const derived types to their actual types */
  src_type = ConstTypeToRegType(src_type);

  /* no-op */
  if (shift_count == 0)
    return src_type;

  /* safe defaults */
  if (is_unsigned_shift)
    new_type = kRegTypeInteger;
  else
    new_type = src_type;

  if (shift_count >= 32) {
    LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
    /* fail? */
    return new_type;
  }

  switch (src_type) {
    case kRegTypeInteger:               /* 32-bit signed value */
      if (is_unsigned_shift) {
        if (shift_count > 24)
          new_type = kRegTypePosByte;
        else if (shift_count >= 16)
          new_type = kRegTypeChar;
      } else {
        if (shift_count >= 24)
          new_type = kRegTypeByte;
        else if (shift_count >= 16)
          new_type = kRegTypeShort;
      }
      break;
    case kRegTypeShort:                 /* 16-bit signed value */
      if (is_unsigned_shift) {
        /* default (kRegTypeInteger) is correct */
      } else {
        if (shift_count >= 8)
          new_type = kRegTypeByte;
      }
      break;
    case kRegTypePosShort:              /* 15-bit unsigned value */
      if (shift_count >= 8)
        new_type = kRegTypePosByte;
      break;
    case kRegTypeChar:                  /* 16-bit unsigned value */
      if (shift_count > 8)
        new_type = kRegTypePosByte;
      break;
    case kRegTypeByte:                  /* 8-bit signed value */
      /* defaults (u=kRegTypeInteger / s=src_type) are correct */
      break;
    case kRegTypePosByte:               /* 7-bit unsigned value */
      /* always use new_type=src_type */
      new_type = src_type;
      break;
    case kRegTypeZero:                  /* 1-bit unsigned value */
    case kRegTypeOne:
    case kRegTypeBoolean:
      /* unnecessary? */
      new_type = kRegTypeZero;
      break;
    default:
      /* long, double, references; shouldn't be here! */
      assert(false);
      break;
  }

  return new_type;
}

void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
    RegisterLine* register_line,
    const Instruction::DecodedInstruction* dec_insn, Class* res_class,
    bool is_range, VerifyError* failure) {
  uint32_t arg_count = dec_insn->vA_;
  RegType expected_type;
  Class::PrimitiveType elem_type;
  unsigned int ui;

  assert(res_class->IsArrayClass());
  elem_type = res_class->GetComponentType()->GetPrimitiveType();
  if (elem_type == Class::kPrimNot) {
    expected_type = RegTypeFromClass(res_class->GetComponentType());
  } else {
    expected_type = PrimitiveTypeToRegType(elem_type);
  }

  /*
   * Verify each register. If "arg_count" is bad, VerifyRegisterType()
   * will run off the end of the list and fail. It's legal, if silly,
   * for arg_count to be zero.
   */
  for (ui = 0; ui < arg_count; ui++) {
    uint32_t get_reg;

    if (is_range)
      get_reg = dec_insn->vC_ + ui;
    else
      get_reg = dec_insn->arg_[ui];

    VerifyRegisterType(register_line, get_reg, expected_type, failure);
    if (*failure != VERIFY_ERROR_NONE) {
      LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
                 << ") not valid";
      return;
    }
  }
}

bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
    Method* res_method) {
  switch (method_type) {
    case METHOD_DIRECT:
      return res_method->IsDirect();
    case METHOD_STATIC:
      return res_method->IsStatic();
    case METHOD_VIRTUAL:
    case METHOD_INTERFACE:
      return !res_method->IsDirect();
    default:
      return false;
  }
}

Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
    RegisterLine* register_line, const int insn_reg_count,
    const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
    bool is_range, bool is_super, VerifyError* failure) {
  Method* method = vdata->method_;
  const DexFile* dex_file = vdata->dex_file_;
  const DexFile::CodeItem* code_item = vdata->code_item_;
  UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
  const ClassLoader* class_loader =
      method->GetDeclaringClass()->GetClassLoader();

  Method* res_method;
  std::string sig;
  size_t sig_offset;
  int expected_args;
  int actual_args;

  /*
   * Resolve the method. This could be an abstract or concrete method
   * depending on what sort of call we're making.
   */
  res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
      class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));

  /* Scan all implemented interfaces for the method */
  if (method_type == METHOD_INTERFACE && res_method == NULL) {

  }

  if (res_method == NULL) {
    LOG(ERROR) << "VFY: unable to resolve called method";
    *failure = VERIFY_ERROR_NO_METHOD;
    return NULL;
  }
  Class* res_class = res_method->GetDeclaringClass();

  /*
   * Only time you can explicitly call a method starting with '<' is when
   * making a "direct" invocation on "<init>". There are additional
   * restrictions but we don't enforce them here.
   */
  if (res_method->GetName()->Equals("<init>")) {
    if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
      LOG(ERROR) << "VFY: invalid call to "
                 << res_class->GetDescriptor()->ToModifiedUtf8()
                 << "." << res_method->GetName();
      goto bad_sig;
    }
  }

  /*
   * See if the method type implied by the invoke instruction matches the
   * access flags for the target method.
   */
  if (!IsCorrectInvokeKind(method_type, res_method)) {
    LOG(ERROR) << "VFY: invoke type does not match method type of "
               << res_class->GetDescriptor()->ToModifiedUtf8()
               << "." << res_method->GetName()->ToModifiedUtf8();

    *failure = VERIFY_ERROR_GENERIC;
    return NULL;
  }

  /*
   * If we're using invoke-super(method), make sure that the executing
   * method's class' superclass has a vtable entry for the target method.
   */
  if (is_super) {
    assert(method_type == METHOD_VIRTUAL);
    Class* super = method->GetDeclaringClass()->GetSuperClass();
    if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
      if (super == NULL) {
        LOG(ERROR) << "VFY: invalid invoke-super from "
                   << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                   << "." << method->GetName()->ToModifiedUtf8() << " to super -."
                   << res_method->GetName()->ToModifiedUtf8()
                   << " " << res_method->GetSignature()->ToModifiedUtf8();
      } else {
        LOG(ERROR) << "VFY: invalid invoke-super from "
                   << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                   << "." << method->GetName()->ToModifiedUtf8() << " to super "
                   << super->GetDescriptor()->ToModifiedUtf8()
                   << "." << res_method->GetName()->ToModifiedUtf8()
                   << " " << res_method->GetSignature()->ToModifiedUtf8();
      }
      *failure = VERIFY_ERROR_NO_METHOD;
      return NULL;
    }
  }

  /*
   * We use vAA as our expected arg count, rather than res_method->insSize,
   * because we need to match the call to the signature. Also, we might
   * might be calling through an abstract method definition (which doesn't
   * have register count values).
   */
  expected_args = dec_insn->vA_;
  actual_args = 0;

  /* caught by static verifier */
  assert(is_range || expected_args <= 5);

  if (expected_args > code_item->outs_size_) {
    LOG(ERROR) << "VFY: invalid arg count (" << expected_args
               << ") exceeds outsSize (" << code_item->outs_size_ << ")";
    *failure = VERIFY_ERROR_GENERIC;
    return NULL;
  }

  sig = res_method->GetSignature()->ToModifiedUtf8();
  if (sig[0] != '(') {
    LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
    goto bad_sig;
  }

  /*
   * Check the "this" argument, which must be an instance of the class
   * that declared the method. For an interface class, we don't do the
   * full interface merge, so we can't do a rigorous check here (which
   * is okay since we have to do it at runtime).
   */
  if (!res_method->IsStatic()) {
    Class* actual_this_ref;
    RegType actual_arg_type;

    actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
    if (*failure != VERIFY_ERROR_NONE)
      return NULL;

    if (RegTypeIsUninitReference(actual_arg_type) &&
        !res_method->GetName()->Equals("<init>")) {
      LOG(ERROR) << "VFY: 'this' arg must be initialized";
      *failure = VERIFY_ERROR_GENERIC;
      return NULL;
    }
    if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
      actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
      if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
        LOG(ERROR) << "VFY: 'this' arg '"
                   << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
                   << "' not instance of '"
                   << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                   << "'";
        *failure = VERIFY_ERROR_GENERIC;
        return NULL;
      }
    }
    actual_args++;
  }

  /*
   * Process the target method's signature. This signature may or may not
   * have been verified, so we can't assume it's properly formed.
   */
  for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
    if (sig[sig_offset] == ')')
      break;

    if (actual_args >= expected_args) {
      LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
                 << sig.substr(sig_offset) << ")";
      goto bad_sig;
    }

    uint32_t get_reg;
    if (is_range)
      get_reg = dec_insn->vC_ + actual_args;
    else
      get_reg = dec_insn->arg_[actual_args];

    switch (sig[sig_offset]) {
      case 'L':
        {
          Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
              failure);
          if (*failure != VERIFY_ERROR_NONE)
            goto bad_sig;
          VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
              failure);
          if (*failure != VERIFY_ERROR_NONE) {
            LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
                       << klass->GetDescriptor()->ToModifiedUtf8() << ")";
            goto bad_sig;
          }
          sig_offset += sig.substr(sig_offset).find(';');
        }
        actual_args++;
        break;
      case '[':
        {
          Class* klass = LookupSignatureArrayClass(method,
              sig.substr(sig_offset), failure);
          if (*failure != VERIFY_ERROR_NONE)
            goto bad_sig;
          VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
              failure);
          if (*failure != VERIFY_ERROR_NONE) {
            LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
                       << klass->GetDescriptor()->ToModifiedUtf8() << ")";
            goto bad_sig;
          }
          while (sig[sig_offset] == '[')
            sig_offset++;
          if (sig[sig_offset] == 'L')
            sig_offset += sig.substr(sig_offset).find(';');
        }
        actual_args++;
        break;
      case 'Z':
        VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
        actual_args++;
        break;
      case 'C':
        VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
        actual_args++;
        break;
      case 'B':
        VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
        actual_args++;
        break;
      case 'I':
        VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
        actual_args++;
        break;
      case 'S':
        VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
        actual_args++;
        break;
      case 'F':
        VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
        actual_args++;
        break;
      case 'D':
        VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
        actual_args += 2;
        break;
      case 'J':
        VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
        actual_args += 2;
        break;
      default:
        LOG(ERROR) << "VFY: invocation target: bad signature type char '"
                   << sig << "'";
        goto bad_sig;
    }
  }
  if (sig[sig_offset] != ')') {
    LOG(ERROR) << "VFY: invocation target: bad signature '"
               << res_method->GetSignature()->ToModifiedUtf8() << "'";
    goto bad_sig;
  }

  if (actual_args != expected_args) {
    LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
               << actual_args;
    goto bad_sig;
  }

  return res_method;

bad_sig:
  if (res_method != NULL) {
    LOG(ERROR) << "VFY:  rejecting call to "
               << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
               << "." << res_method->GetName()->ToModifiedUtf8() << " "
               << res_method->GetSignature()->ToModifiedUtf8();
  }

  if (*failure == VERIFY_ERROR_NONE)
    *failure = VERIFY_ERROR_GENERIC;
  return NULL;
}

DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
{
  const DexFile::CodeItem* code_item = vdata->code_item_;
  int i, bytes_for_addr, gc_point_count;

  if (code_item->registers_size_ >= 2048) {
    LOG(ERROR) << "ERROR: register map can't handle "
               << code_item->registers_size_ << " registers";
    return NULL;
  }
  uint8_t reg_width = (code_item->registers_size_ + 7) / 8;

  /*
   * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
   * we only need 16 bits if we actually encode an address >= 256 -- if
   * the method has a section at the end without GC points (e.g. array
   * data) we don't need to count it. The situation is unusual, and
   * detecting it requires scanning the entire method, so we don't bother.
   */
  RegisterMapFormat format;
  if (code_item->insns_size_ < 256) {
    format = kRegMapFormatCompact8;
    bytes_for_addr = 1;
  } else {
    format = kRegMapFormatCompact16;
    bytes_for_addr = 2;
  }

  /*
   * Count up the number of GC point instructions.
   *
   * NOTE: this does not automatically include the first instruction,
   * since we don't count method entry as a GC point.
   */
  gc_point_count = 0;
  for (i = 0; i < (int) code_item->insns_size_; i++) {
    if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
      gc_point_count++;
  }
  if (gc_point_count >= 65536) {
    /* We could handle this, but in practice we don't get near this. */
    LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
               << " gc points in one method";
    return NULL;
  }

  /* Calculate size of buffer to hold the map data. */
  uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);

  RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
      true, data_size);

  /* Populate it. */
  uint8_t* map_data = map->data_.get();
  for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
    if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
      assert(vdata->register_lines_[i].reg_types_.get() != NULL);
      if (format == kRegMapFormatCompact8) {
        *map_data++ = i;
      } else /*kRegMapFormatCompact16*/ {
        *map_data++ = i & 0xff;
        *map_data++ = i >> 8;
      }
      OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
          code_item->registers_size_, map_data);
      map_data += reg_width;
    }
  }

  assert((uint32_t) map_data - (uint32_t) map->data_.get() == data_size);

  // TODO: Remove this check when it's really running...
#if 1
  if (!VerifyMap(vdata, map)) {
    LOG(ERROR) << "Map failed to verify";
    return NULL;
  }
#endif

  /* Try to compress the map. */
  RegisterMap* compress_map = CompressMapDifferential(map);
  if (compress_map != NULL) {
    // TODO: Remove this check when it's really running...
#if 1
    /*
     * Expand the compressed map we just created, and compare it
     * to the original. Abort the VM if it doesn't match up.
     */
    UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
    if (uncompressed_map.get() == NULL) {
      LOG(ERROR) << "Map failed to uncompress - "
                 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                 << "." << vdata->method_->GetName()->ToModifiedUtf8();
      delete map;
      delete compress_map;
      /* bad - compression is broken or we're out of memory */
      return NULL;
    } else {
      if (!CompareMaps(map, uncompressed_map.get())) {
        LOG(ERROR) << "Map comparison failed - "
                   << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
                   << "." << vdata->method_->GetName()->ToModifiedUtf8();
        delete map;
        delete compress_map;
        /* bad - compression is broken */
        return NULL;
      }
    }
#endif
    delete map;
    map = compress_map;
  }

  return map;
}

void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
    uint8_t* data) {
  uint8_t val = 0;
  int i;

  for (i = 0; i < insn_reg_count; i++) {
    RegType type = *regs++;
    val >>= 1;
    if (IsReferenceType(type))
      val |= 0x80;        /* set hi bit */

    if ((i & 0x07) == 7)
      *data++ = val;
  }
  if ((i & 0x07) != 0) {
    /* Flush bits from last byte. */
    val >>= 8 - (i & 0x07);
    *data++ = val;
  }
}

bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
  const uint8_t* raw_map = map->data_.get();
  uint8_t format = map->format_;
  const int num_entries = map->num_entries_;
  int ent;

  if ((vdata->code_item_->registers_size_ + 7) / 8 != map->reg_width_) {
    LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
               << ", reg_width=" << map->reg_width_;
    return false;
  }

  for (ent = 0; ent < num_entries; ent++) {
    int addr;

    switch (format) {
      case kRegMapFormatCompact8:
        addr = *raw_map++;
        break;
      case kRegMapFormatCompact16:
        addr = *raw_map++;
        addr |= (*raw_map++) << 8;
        break;
      default:
        LOG(FATAL) << "GLITCH: bad format (" << format << ")";
        return false;
    }

    const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
    if (regs == NULL) {
      LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
      return false;
    }

    uint8_t val = 0;
    int i;

    for (i = 0; i < vdata->code_item_->registers_size_; i++) {
      bool bit_is_ref, reg_is_ref;

      val >>= 1;
      if ((i & 0x07) == 0) {
        /* Load next byte of data. */
        val = *raw_map++;
      }

      bit_is_ref = val & 0x01;

      RegType type = regs[i];
      reg_is_ref = IsReferenceType(type);

      if (bit_is_ref != reg_is_ref) {
        LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
                   << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
        return false;
      }
    }
    /* Raw_map now points to the address field of the next entry. */
  }

  return true;
}

bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
{
  size_t size1, size2;

  size1 = ComputeRegisterMapSize(map1);
  size2 = ComputeRegisterMapSize(map2);
  if (size1 != size2) {
    LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
               << ")";
    return false;
  }

  if (map1->format_ != map2->format_ || map1->reg_width_ != map2->reg_width_ ||
      map1->num_entries_ != map2->num_entries_ ||
      map1->format_on_heap_ != map2->format_on_heap_) {
    LOG(ERROR) << "CompareMaps: fields mismatch";
  }
  if (memcmp(map1->data_.get(), map2->data_.get(), size1) != 0) {
    LOG(ERROR) << "CompareMaps: data mismatch";
    return false;
  }

  return true;
}

size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
  uint8_t format = map->format_;
  uint16_t num_entries = map->num_entries_;

  assert(map != NULL);

  switch (format) {
    case kRegMapFormatNone:
      return 1;
    case kRegMapFormatCompact8:
      return (1 + map->reg_width_) * num_entries;
    case kRegMapFormatCompact16:
      return (2 + map->reg_width_) * num_entries;
    case kRegMapFormatDifferential:
      {
        /* Decoded ULEB128 length. */
        const uint8_t* ptr = map->data_.get();
        return DecodeUnsignedLeb128(&ptr);
      }
    default:
      LOG(FATAL) << "Bad register map format " << format;
      return 0;
  }
}

int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
    int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
    uint8_t* leb_out_buf) {
  int num_bits_changed = 0;
  int first_bit_changed = -1;
  int leb_size = 0;
  int byte_num;

  /*
   * Run through the vectors, first comparing them at the byte level. This
   * will yield a fairly quick result if nothing has changed between them.
   */
  for (byte_num = 0; byte_num < byte_width; byte_num++) {
    uint8_t byte1 = *bits1++;
    uint8_t byte2 = *bits2++;
    if (byte1 != byte2) {
      /* Walk through the byte, identifying the changed bits. */
      int bit_num;
      for (bit_num = 0; bit_num < 8; bit_num++) {
        if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
          int bit_offset = (byte_num << 3) + bit_num;

          if (first_bit_changed < 0)
            first_bit_changed = bit_offset;
          num_bits_changed++;

          if (leb_out_buf == NULL) {
            leb_size += UnsignedLeb128Size(bit_offset);
          } else {
            uint8_t* cur_buf = leb_out_buf;
            leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
            leb_size += leb_out_buf - cur_buf;
          }
        }
      }
    }
  }

  if (num_bits_changed > 0)
    assert(first_bit_changed >= 0);

  if (first_bit_changed_ptr != NULL)
    *first_bit_changed_ptr = first_bit_changed;
  if (num_bits_changed_ptr != NULL)
    *num_bits_changed_ptr = num_bits_changed;

  return leb_size;
}

DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
    const RegisterMap* map) {
  int orig_size = ComputeRegisterMapSize(map);
  uint8_t* tmp_ptr;
  int addr_width;

  uint8_t format = map->format_;
  switch (format) {
    case kRegMapFormatCompact8:
      addr_width = 1;
      break;
    case kRegMapFormatCompact16:
      addr_width = 2;
      break;
    default:
      LOG(ERROR) << "ERROR: can't compress map with format=" << format;
      return NULL;
  }

  int reg_width = map->reg_width_;
  int num_entries = map->num_entries_;

  if (num_entries <= 1) {
    return NULL;
  }

  /*
   * We don't know how large the compressed data will be. It's possible
   * for it to expand and become larger than the original. The header
   * itself is variable-sized, so we generate everything into a temporary
   * buffer and then copy it to form-fitting storage once we know how big
   * it will be (and that it's smaller than the original).
   *
   * If we use a size that is equal to the size of the input map plus
   * a value longer than a single entry can possibly expand to, we need
   * only check for overflow at the end of each entry. The worst case
   * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
   * Addresses are 16 bits, so that's (1 + 3 + reg_width).
   *
   * The initial address offset and bit vector will take up less than
   * or equal to the amount of space required when uncompressed -- large
   * initial offsets are rejected.
   */
  UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);

  tmp_ptr = tmp_buf.get();

  const uint8_t* map_data = map->data_.get();
  const uint8_t* prev_bits;
  uint16_t addr, prev_addr;

  addr = *map_data++;
  if (addr_width > 1)
    addr |= (*map_data++) << 8;

  if (addr >= 128) {
    LOG(ERROR) << "Can't compress map with starting address >= 128";
    return NULL;
  }

  /*
   * Start by writing the initial address and bit vector data. The high
   * bit of the initial address is used to indicate the required address
   * width (which the decoder can't otherwise determine without parsing
   * the compressed data).
   */
  *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
  memcpy(tmp_ptr, map_data, reg_width);

  prev_bits = map_data;
  prev_addr = addr;

  tmp_ptr += reg_width;
  map_data += reg_width;

  /* Loop over all following entries. */
  for (int entry = 1; entry < num_entries; entry++) {
    int addr_diff;
    uint8_t key;

    /* Pull out the address and figure out how to encode it. */
    addr = *map_data++;
    if (addr_width > 1)
      addr |= (*map_data++) << 8;

    addr_diff = addr - prev_addr;
    assert(addr_diff > 0);
    if (addr_diff < 8) {
      /* Small difference, encode in 3 bits. */
      key = addr_diff -1;          /* set 00000AAA */
    } else {
      /* Large difference, output escape code. */
      key = 0x07;                 /* escape code for AAA */
    }

    int num_bits_changed, first_bit_changed, leb_size;

    leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
        &first_bit_changed, &num_bits_changed, NULL);

    if (num_bits_changed == 0) {
      /* set B to 1 and CCCC to zero to indicate no bits were changed */
      key |= 0x08;
    } else if (num_bits_changed == 1 && first_bit_changed < 16) {
      /* set B to 0 and CCCC to the index of the changed bit */
      key |= first_bit_changed << 4;
    } else if (num_bits_changed < 15 && leb_size < reg_width) {
      /* set B to 1 and CCCC to the number of bits */
      key |= 0x08 | (num_bits_changed << 4);
    } else {
      /* set B to 1 and CCCC to 0x0f so we store the entire vector */
      key |= 0x08 | 0xf0;
    }

    /*
     * Encode output. Start with the key, follow with the address
     * diff (if it didn't fit in 3 bits), then the changed bit info.
     */
    *tmp_ptr++ = key;
    if ((key & 0x07) == 0x07)
      tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);

    if ((key & 0x08) != 0) {
      int bit_count = key >> 4;
      if (bit_count == 0) {
        /* nothing changed, no additional output required */
      } else if (bit_count == 15) {
        /* full vector is most compact representation */
        memcpy(tmp_ptr, map_data, reg_width);
        tmp_ptr += reg_width;
      } else {
        /* write bit indices in ULEB128 format */
        (void) ComputeBitDiff(prev_bits, map_data, reg_width,
               NULL, NULL, tmp_ptr);
        tmp_ptr += leb_size;
      }
    } else {
      /* single-bit changed, value encoded in key byte */
    }

    prev_bits = map_data;
    prev_addr = addr;
    map_data += reg_width;

    /* See if we've run past the original size. */
    if (tmp_ptr - tmp_buf.get() >= orig_size) {
      return NULL;
    }
  }

  /*
   * Create a RegisterMap with the contents.
   *
   * TODO: consider using a threshold other than merely ">=". We would
   * get poorer compression but potentially use less native heap space.
   */
  int new_data_size = tmp_ptr - tmp_buf.get();
  int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);

  if (new_map_size >= orig_size) {
    return NULL;
  }

  RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
      num_entries, true, new_map_size);

  tmp_ptr = new_map->data_.get();
  tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
  memcpy(tmp_ptr, tmp_buf.get(), new_data_size);

  return new_map;
}

DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
    const RegisterMap* map) {
  uint8_t format = map->format_;
  RegisterMapFormat new_format;
  int reg_width, num_entries, new_addr_width, new_data_size;

  if (format != kRegMapFormatDifferential) {
    LOG(ERROR) << "Not differential (" << format << ")";
    return NULL;
  }

  reg_width = map->reg_width_;
  num_entries = map->num_entries_;

  /* Get the data size; we can check this at the end. */
  const uint8_t* src_ptr = map->data_.get();
  int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
  const uint8_t* src_start = src_ptr;

  /* Get the initial address and the 16-bit address flag. */
  int addr = *src_ptr & 0x7f;
  if ((*src_ptr & 0x80) == 0) {
    new_format = kRegMapFormatCompact8;
    new_addr_width = 1;
  } else {
    new_format = kRegMapFormatCompact16;
    new_addr_width = 2;
  }
  src_ptr++;

  /* Now we know enough to allocate the new map. */
  new_data_size = (new_addr_width + reg_width) * num_entries;
  RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
      true, new_data_size);

  /* Write the start address and initial bits to the new map. */
  uint8_t* dst_ptr = new_map->data_.get();

  *dst_ptr++ = addr & 0xff;
  if (new_addr_width > 1)
    *dst_ptr++ = (uint8_t) (addr >> 8);

  memcpy(dst_ptr, src_ptr, reg_width);

  int prev_addr = addr;
  const uint8_t* prev_bits = dst_ptr;    /* point at uncompressed data */

  dst_ptr += reg_width;
  src_ptr += reg_width;

  /* Walk through, uncompressing one line at a time. */
  int entry;
  for (entry = 1; entry < num_entries; entry++) {
    int addr_diff;
    uint8_t key;

    key = *src_ptr++;

    /* Get the address. */
    if ((key & 0x07) == 7) {
      /* Address diff follows in ULEB128. */
      addr_diff = DecodeUnsignedLeb128(&src_ptr);
    } else {
      addr_diff = (key & 0x07) +1;
    }

    addr = prev_addr + addr_diff;
    *dst_ptr++ = addr & 0xff;
    if (new_addr_width > 1)
      *dst_ptr++ = (uint8_t) (addr >> 8);

    /* Unpack the bits. */
    if ((key & 0x08) != 0) {
      int bit_count = (key >> 4);
      if (bit_count == 0) {
        /* No bits changed, just copy previous. */
        memcpy(dst_ptr, prev_bits, reg_width);
      } else if (bit_count == 15) {
        /* Full copy of bit vector is present; ignore prev_bits. */
        memcpy(dst_ptr, src_ptr, reg_width);
        src_ptr += reg_width;
      } else {
        /* Copy previous bits and modify listed indices. */
        memcpy(dst_ptr, prev_bits, reg_width);
        while (bit_count--) {
          int bit_index = DecodeUnsignedLeb128(&src_ptr);
          ToggleBit(dst_ptr, bit_index);
        }
      }
    } else {
      /* Copy previous bits and modify the specified one. */
      memcpy(dst_ptr, prev_bits, reg_width);

      /* One bit, from 0-15 inclusive, was changed. */
      ToggleBit(dst_ptr, key >> 4);
    }

    prev_addr = addr;
    prev_bits = dst_ptr;
    dst_ptr += reg_width;
  }

  if (dst_ptr - new_map->data_.get() != new_data_size) {
    LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_.get()
               << " bytes, expected " << new_data_size;
    free(new_map);
    return NULL;
  }

  if (src_ptr - src_start != expected_src_len) {
    LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
               << " bytes, expected " << expected_src_len;
    free(new_map);
    return NULL;
  }

  return new_map;
}

}  // namespace art
