Separate out more of LLVM build. Move verifier.

Move the verifier to its own directory and break out major components.
Avoid compiling unused files as part of the LLVM build, increase the use
of unimplemented for LLVM.

Change-Id: Icd3b1708363fb70ae99417d06ef8669d60446533
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 423bd72..656032b 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -32,7 +32,6 @@
 #include "debugger.h"
 #include "dex_cache.h"
 #include "dex_file.h"
-#include "dex_verifier.h"
 #include "heap.h"
 #include "intern_table.h"
 #include "leb128.h"
@@ -2058,7 +2057,7 @@
   const DexFile& dex_file = FindDexFile(klass->GetDexCache());
   Class::Status oat_file_class_status(Class::kStatusNotReady);
   bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
-  bool verified = preverified || verifier::DexVerifier::VerifyClass(klass, error_msg);
+  bool verified = preverified || verifier::MethodVerifier::VerifyClass(klass, error_msg);
   if (verified) {
     if (!preverified && oat_file_class_status == Class::kStatusError) {
       LOG(FATAL) << "Verification failed hard on class " << PrettyDescriptor(klass)
diff --git a/src/compiler.cc b/src/compiler.cc
index 0a88cff..ce7eb3c 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -25,7 +25,6 @@
 #include "class_linker.h"
 #include "class_loader.h"
 #include "dex_cache.h"
-#include "dex_verifier.h"
 #include "jni_internal.h"
 #include "oat_compilation_unit.h"
 #include "oat_file.h"
@@ -34,6 +33,7 @@
 #include "space.h"
 #include "stl_util.h"
 #include "timing_logger.h"
+#include "verifier/method_verifier.h"
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
@@ -1147,7 +1147,7 @@
      * will be rejected by the verifier and later skipped during compilation in the compiler.
      */
     std::string error_msg;
-    if (!verifier::DexVerifier::VerifyClass(context->GetDexFile(), context->GetDexCache(),
+    if (!verifier::MethodVerifier::VerifyClass(context->GetDexFile(), context->GetDexCache(),
         context->GetClassLoader(), class_def_index, error_msg)) {
       const DexFile::ClassDef& class_def = context->GetDexFile()->GetClassDef(class_def_index);
       LOG(ERROR) << "Verification failed on class "
@@ -1164,7 +1164,7 @@
     CHECK(Thread::Current()->IsExceptionPending());
     Thread::Current()->ClearException();
     art::Compiler::ClassReference ref(context->GetDexFile(), class_def_index);
-    if (!verifier::DexVerifier::IsClassRejected(ref)) {
+    if (!verifier::MethodVerifier::IsClassRejected(ref)) {
       // If the erroneous class wasn't rejected by the verifier, it was a soft error. We want
       // to try verification again at run-time, so move back into the resolved state.
       klass->SetStatus(Class::kStatusResolved);
@@ -1265,7 +1265,7 @@
   }
   ClassReference ref(&dex_file, class_def_index);
   // Skip compiling classes with generic verifier failures since they will still fail at runtime
-  if (verifier::DexVerifier::IsClassRejected(ref)) {
+  if (verifier::MethodVerifier::IsClassRejected(ref)) {
     return;
   }
   const byte* class_data = dex_file.GetClassData(class_def);
@@ -1456,7 +1456,7 @@
   if (compiled_method == NULL) {
     return;
   }
-  const std::vector<uint8_t>* gc_map = verifier::DexVerifier::GetGcMap(ref);
+  const std::vector<uint8_t>* gc_map = verifier::MethodVerifier::GetGcMap(ref);
   if (gc_map == NULL) {
     return;
   }
diff --git a/src/compiler_llvm/inferred_reg_category_map.h b/src/compiler_llvm/inferred_reg_category_map.h
index 14bc052..7b3501b 100644
--- a/src/compiler_llvm/inferred_reg_category_map.h
+++ b/src/compiler_llvm/inferred_reg_category_map.h
@@ -47,7 +47,7 @@
 
     void SetRegCategory(uint16_t reg_idx, RegCategory cat) {
       if (cat != kRegUnknown) {
-        reg_category_line_[reg_idx] = cat;
+        reg_category_line_.Put(reg_idx, cat);
       }
     }
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index e044c54..fc9c4d8 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -19,7 +19,6 @@
 #include "backend_types.h"
 #include "compilation_unit.h"
 #include "compiler.h"
-#include "dex_verifier.h"
 #include "inferred_reg_category_map.h"
 #include "ir_builder.h"
 #include "logging.h"
@@ -32,6 +31,7 @@
 #include "stl_util.h"
 #include "stringprintf.h"
 #include "utils_llvm.h"
+#include "verifier/method_verifier.h"
 
 #include <iomanip>
 
@@ -62,6 +62,7 @@
     module_(cunit->GetModule()),
     context_(cunit->GetLLVMContext()),
     irb_(*cunit->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
+    basic_block_stack_overflow_(NULL),
     basic_block_reg_alloca_(NULL), basic_block_shadow_frame_alloca_(NULL),
     basic_block_reg_zero_init_(NULL), basic_block_reg_arg_init_(NULL),
     basic_blocks_(code_item_->insns_size_in_code_units_),
@@ -2215,7 +2216,7 @@
   Compiler::MethodReference mref(dex_file_, method_idx_);
 
   InferredRegCategoryMap const* map =
-    verifier::DexVerifier::GetInferredRegCategoryMap(mref);
+    verifier::MethodVerifier::GetInferredRegCategoryMap(mref);
 
   CHECK_NE(map, static_cast<InferredRegCategoryMap*>(NULL));
 
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 3db1667..18e4842 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -15,7 +15,6 @@
  */
 
 #include "class_linker.h"
-#include "dex_verifier.h"
 #include "nth_caller_visitor.h"
 #include "object.h"
 #include "object_utils.h"
@@ -26,6 +25,7 @@
 #include "shadow_frame.h"
 #include "thread.h"
 #include "thread_list.h"
+#include "verifier/method_verifier.h"
 
 #include <algorithm>
 #include <cstdarg>
@@ -33,11 +33,6 @@
 
 namespace art {
 
-extern int64_t D2L(double d);
-extern int32_t D2I(double d);
-extern int64_t F2L(float f);
-extern int32_t F2I(float f);
-
 //----------------------------------------------------------------------------
 // Thread
 //----------------------------------------------------------------------------
diff --git a/src/debugger.cc b/src/debugger.cc
index fe9bc49..1ba0c73 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -22,8 +22,10 @@
 
 #include "class_linker.h"
 #include "class_loader.h"
-#include "dex_verifier.h" // For Instruction.
-#include "oat/runtime/context.h"
+#include "dex_instruction.h"
+#if !defined(ART_USE_LLVM_COMPILER)
+#include "oat/runtime/context.h"  // For VmapTable
+#endif
 #include "object_utils.h"
 #include "safe_map.h"
 #include "scoped_thread_list_lock.h"
@@ -1582,11 +1584,15 @@
   Method* m = f.GetMethod();
   uint16_t reg = DemangleSlot(slot, m);
 
+#if defined(ART_USE_LLVM_COMPILER)
+  UNIMPLEMENTED(FATAL);
+#else
   const VmapTable vmap_table(m->GetVmapTableRaw());
   uint32_t vmap_offset;
   if (vmap_table.IsInContext(reg, vmap_offset)) {
     UNIMPLEMENTED(FATAL) << "Don't know how to pull locals from callee save frames: " << vmap_offset;
   }
+#endif
 
   // TODO: check that the tag is compatible with the actual type of the slot!
 
@@ -1679,11 +1685,15 @@
   Method* m = f.GetMethod();
   uint16_t reg = DemangleSlot(slot, m);
 
+#if defined(ART_USE_LLVM_COMPILER)
+  UNIMPLEMENTED(FATAL);
+#else
   const VmapTable vmap_table(m->GetVmapTableRaw());
   uint32_t vmap_offset;
   if (vmap_table.IsInContext(reg, vmap_offset)) {
     UNIMPLEMENTED(FATAL) << "Don't know how to pull locals from callee save frames: " << vmap_offset;
   }
+#endif
 
   // TODO: check that the tag is compatible with the actual type of the slot!
 
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
deleted file mode 100644
index 75de207..0000000
--- a/src/dex_verifier.h
+++ /dev/null
@@ -1,1440 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_SRC_DEX_VERIFY_H_
-#define ART_SRC_DEX_VERIFY_H_
-
-#include <deque>
-#include <limits>
-#include <set>
-#include <vector>
-
-#include "casts.h"
-#include "compiler.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
-#include "macros.h"
-#include "object.h"
-#include "safe_map.h"
-#include "stl_util.h"
-#include "UniquePtr.h"
-
-namespace art {
-
-struct ReferenceMap2Visitor;
-
-#if defined(ART_USE_LLVM_COMPILER)
-namespace compiler_llvm {
-  class InferredRegCategoryMap;
-}  // namespace compiler_llvm
-#endif
-
-namespace verifier {
-
-class DexVerifier;
-class PcToReferenceMap;
-class RegTypeCache;
-
-/*
- * Set this to enable dead code scanning. This is not required, but it's very useful when testing
- * changes to the verifier (to make sure we're not skipping over stuff). The only reason not to do
- * it is that it slightly increases the time required to perform verification.
- */
-#define DEAD_CODE_SCAN kIsDebugBuild
-
-/*
- * RegType holds information about the "type" of data held in a register.
- */
-class RegType {
- public:
-  enum Type {
-    kRegTypeUnknown = 0,    // Initial state.
-    kRegTypeConflict,       // Merge clash makes this reg's type unknowable.
-    kRegTypeBoolean,        // Z.
-    kRegType1nrSTART = kRegTypeBoolean,
-    kRegTypeIntegralSTART = kRegTypeBoolean,
-    kRegTypeByte,           // B.
-    kRegTypeShort,          // S.
-    kRegTypeChar,           // C.
-    kRegTypeInteger,        // I.
-    kRegTypeIntegralEND = kRegTypeInteger,
-    kRegTypeFloat,          // F.
-    kRegType1nrEND = kRegTypeFloat,
-    kRegTypeLongLo,         // J - lower-numbered register; endian-independent.
-    kRegTypeLongHi,
-    kRegTypeDoubleLo,       // D.
-    kRegTypeDoubleHi,
-    kRegTypeConstLo,        // Const derived wide, lower half - could be long or double.
-    kRegTypeConstHi,        // Const derived wide, upper half - could be long or double.
-    kRegTypeLastFixedLocation = kRegTypeConstHi,
-    kRegTypeConst,          // 32-bit constant derived value - could be float or int.
-    kRegTypeUnresolvedReference,        // Reference type that couldn't be resolved.
-    kRegTypeUninitializedReference,     // Freshly allocated reference type.
-    kRegTypeUninitializedThisReference, // Freshly allocated reference passed as "this".
-    kRegTypeUnresolvedAndUninitializedReference, // Freshly allocated unresolved reference type.
-    kRegTypeReference,                  // Reference type.
-  };
-
-  Type GetType() const {
-    return type_;
-  }
-
-  bool IsUnknown() const { return type_ == kRegTypeUnknown; }
-  bool IsConflict() const { return type_ == kRegTypeConflict; }
-  bool IsBoolean() const { return type_ == kRegTypeBoolean; }
-  bool IsByte()    const { return type_ == kRegTypeByte; }
-  bool IsChar()    const { return type_ == kRegTypeChar; }
-  bool IsShort()   const { return type_ == kRegTypeShort; }
-  bool IsInteger() const { return type_ == kRegTypeInteger; }
-  bool IsLong()    const { return type_ == kRegTypeLongLo; }
-  bool IsFloat()   const { return type_ == kRegTypeFloat; }
-  bool IsDouble()  const { return type_ == kRegTypeDoubleLo; }
-  bool IsUnresolvedReference() const { return type_ == kRegTypeUnresolvedReference; }
-  bool IsUninitializedReference() const { return type_ == kRegTypeUninitializedReference; }
-  bool IsUninitializedThisReference() const { return type_ == kRegTypeUninitializedThisReference; }
-  bool IsUnresolvedAndUninitializedReference() const {
-    return type_ == kRegTypeUnresolvedAndUninitializedReference;
-  }
-  bool IsReference() const { return type_ == kRegTypeReference; }
-  bool IsUninitializedTypes() const {
-    return IsUninitializedReference() || IsUninitializedThisReference() ||
-        IsUnresolvedAndUninitializedReference();
-  }
-  bool IsUnresolvedTypes() const {
-    return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference();
-  }
-  bool IsLowHalf() const { return type_ == kRegTypeLongLo ||
-                                  type_ == kRegTypeDoubleLo ||
-                                  type_ == kRegTypeConstLo; }
-  bool IsHighHalf() const { return type_ == kRegTypeLongHi ||
-                                   type_ == kRegTypeDoubleHi ||
-                                   type_ == kRegTypeConstHi; }
-
-  bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
-
-  // Check this is the low half, and that type_h is its matching high-half
-  bool CheckWidePair(const RegType& type_h) const {
-    return IsLowHalf() && (type_h.type_ == type_ + 1);
-  }
-
-  // The high half that corresponds to this low half
-  const RegType& HighHalf(RegTypeCache* cache) const;
-
-  bool IsConstant() const { return type_ == kRegTypeConst; }
-  bool IsLongConstant() const { return type_ == kRegTypeConstLo; }
-  bool IsLongConstantHigh() const { return type_ == kRegTypeConstHi; }
-
-  // If this is a 32-bit constant, what is the value? This value may just
-  // approximate to the actual constant value by virtue of merging.
-  int32_t ConstantValue() const {
-    DCHECK(IsConstant());
-    return allocation_pc_or_constant_;
-  }
-
-  bool IsZero()         const { return IsConstant() && ConstantValue() == 0; }
-  bool IsOne()          const { return IsConstant() && ConstantValue() == 1; }
-  bool IsConstantBoolean() const { return IsZero() || IsOne(); }
-  bool IsConstantByte() const {
-    return IsConstant() &&
-        ConstantValue() >= std::numeric_limits<jbyte>::min() &&
-        ConstantValue() <= std::numeric_limits<jbyte>::max();
-  }
-  bool IsConstantShort() const {
-    return IsConstant() &&
-        ConstantValue() >= std::numeric_limits<jshort>::min() &&
-        ConstantValue() <= std::numeric_limits<jshort>::max();
-  }
-  bool IsConstantChar() const {
-    return IsConstant() && ConstantValue() >= 0 &&
-        ConstantValue() <= std::numeric_limits<jchar>::max();
-  }
-
-  bool IsReferenceTypes() const {
-    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
-        IsUninitializedThisReference() || IsUnresolvedAndUninitializedReference() || IsZero();
-  }
-  bool IsNonZeroReferenceTypes() const {
-    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
-        IsUninitializedThisReference();
-  }
-  bool IsCategory1Types() const {
-    return (type_ >= kRegType1nrSTART && type_ <= kRegType1nrEND) || IsConstant();
-  }
-  bool IsCategory2Types() const {
-    return IsLowHalf();  // Don't expect explicit testing of high halves
-  }
-
-  bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); }
-  bool IsByteTypes() const { return IsByte() || IsBoolean() || IsConstantByte(); }
-  bool IsShortTypes() const { return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); }
-  bool IsCharTypes() const { return IsChar() || IsBooleanTypes() || IsConstantChar(); }
-  bool IsIntegralTypes() const {
-    return (type_ >= kRegTypeIntegralSTART && type_ <= kRegTypeIntegralEND) || IsConstant();
-  }
-  bool IsArrayIndexTypes() const { return IsIntegralTypes(); }
-
-  // Float type may be derived from any constant type
-  bool IsFloatTypes() const { return IsFloat() || IsConstant(); }
-
-  bool IsLongTypes() const {
-    return IsLong() || IsLongConstant();
-  }
-  bool IsLongHighTypes() const {
-    return type_ == kRegTypeLongHi || type_ == kRegTypeConstHi;
-  }
-  bool IsDoubleTypes() const {
-    return IsDouble() || IsLongConstant();
-  }
-  bool IsDoubleHighTypes() const {
-    return type_ == kRegTypeDoubleHi || type_ == kRegTypeConstHi;
-  }
-
-  uint32_t GetAllocationPc() const {
-    DCHECK(IsUninitializedTypes());
-    return allocation_pc_or_constant_;
-  }
-
-  Class* GetClass() const {
-    DCHECK(!IsUnresolvedReference());
-    DCHECK(klass_or_descriptor_ != NULL);
-    DCHECK(klass_or_descriptor_->IsClass());
-    return down_cast<Class*>(klass_or_descriptor_);
-  }
-
-  bool IsJavaLangObject() const {
-    return IsReference() && GetClass()->IsObjectClass();
-  }
-
-  bool IsArrayTypes() const {
-    if (IsUnresolvedTypes()) {
-      return GetDescriptor()->CharAt(0) == '[';
-    } else if (IsReference()) {
-      return GetClass()->IsArrayClass();
-    } else {
-      return false;
-    }
-  }
-
-  bool IsObjectArrayTypes() const {
-    if (IsUnresolvedTypes()) {
-      // Primitive arrays will always resolve
-      DCHECK(GetDescriptor()->CharAt(1) == 'L' || GetDescriptor()->CharAt(1) == '[');
-      return GetDescriptor()->CharAt(0) == '[';
-    } else if (IsReference()) {
-      Class* type = GetClass();
-      return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
-    } else {
-      return false;
-    }
-  }
-
-  Primitive::Type GetPrimitiveType() const {
-    if (IsNonZeroReferenceTypes()) {
-      return Primitive::kPrimNot;
-    } else if (IsBooleanTypes()) {
-      return Primitive::kPrimBoolean;
-    } else if (IsByteTypes()) {
-      return Primitive::kPrimByte;
-    } else if (IsShortTypes()) {
-      return Primitive::kPrimShort;
-    } else if (IsCharTypes()) {
-      return Primitive::kPrimChar;
-    } else if (IsFloat()) {
-      return Primitive::kPrimFloat;
-    } else if (IsIntegralTypes()) {
-      return Primitive::kPrimInt;
-    } else if (IsDouble()) {
-      return Primitive::kPrimDouble;
-    } else {
-      DCHECK(IsLongTypes());
-      return Primitive::kPrimLong;
-    }
-  }
-
-  bool IsJavaLangObjectArray() const {
-    if (IsReference()) {
-      Class* type = GetClass();
-      return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
-    }
-    return false;
-  }
-
-  bool IsInstantiableTypes() const {
-    return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
-  }
-
-  String* GetDescriptor() const {
-    DCHECK(IsUnresolvedTypes());
-    DCHECK(klass_or_descriptor_ != NULL);
-    DCHECK(klass_or_descriptor_->GetClass()->IsStringClass());
-    return down_cast<String*>(klass_or_descriptor_);
-  }
-
-  uint16_t GetId() const {
-    return cache_id_;
-  }
-
-  std::string Dump() const;
-
-  bool IsAssignableFrom(const RegType& src) const;
-
-  const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const;
-
-  bool Equals(const RegType& other) const { return GetId() == other.GetId(); }
-
-  /*
-   * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
-   * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
-   * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
-   * is the deepest (lowest upper bound) parent of S and T).
-   *
-   * This operation applies for regular classes and arrays, however, for interface types there needn't
-   * be a partial ordering on the types. We could solve the problem of a lack of a partial order by
-   * introducing sets of types, however, the only operation permissible on an interface is
-   * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
-   * types until an invoke-interface call on the interface typed reference at runtime and allow
-   * the perversion of Object being assignable to an interface type (note, however, that we don't
-   * allow assignment of Object or Interface to any concrete class and are therefore type safe).
-   *
-   * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
-   */
-  static Class* ClassJoin(Class* s, Class* t);
-
- private:
-  friend class RegTypeCache;
-
-  RegType(Type type, Object* klass_or_descriptor, uint32_t allocation_pc_or_constant, uint16_t cache_id) :
-    type_(type), klass_or_descriptor_(klass_or_descriptor), allocation_pc_or_constant_(allocation_pc_or_constant),
-    cache_id_(cache_id) {
-    DCHECK(IsConstant() || IsUninitializedTypes() || allocation_pc_or_constant == 0);
-    if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUnknown() &&
-        !IsConflict()) {
-      DCHECK(klass_or_descriptor != NULL);
-      DCHECK(IsUnresolvedTypes() || klass_or_descriptor_->IsClass());
-      DCHECK(!IsUnresolvedTypes() || klass_or_descriptor_->GetClass()->IsStringClass());
-    }
-  }
-
-  const Type type_;  // The current type of the register
-
-  // If known the type of the register, else a String for the descriptor
-  Object* klass_or_descriptor_;
-
-  // Overloaded field that:
-  //   - if IsConstant() holds a 32bit constant value
-  //   - is IsReference() holds the allocation_pc or kInitArgAddr for an initialized reference or
-  //     kUninitThisArgAddr for an uninitialized this ptr
-  const uint32_t allocation_pc_or_constant_;
-
-  // A RegType cache densely encodes types, this is the location in the cache for this type
-  const uint16_t cache_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(RegType);
-};
-std::ostream& operator<<(std::ostream& os, const RegType& rhs);
-
-class RegTypeCache {
- public:
-  explicit RegTypeCache() : entries_(RegType::kRegTypeLastFixedLocation + 1) {
-    Unknown();  // ensure Unknown is initialized
-  }
-  ~RegTypeCache() {
-    STLDeleteElements(&entries_);
-  }
-
-  const RegType& GetFromId(uint16_t id) {
-    DCHECK_LT(id, entries_.size());
-    RegType* result = entries_[id];
-    DCHECK(result != NULL);
-    return *result;
-  }
-
-  const RegType& From(RegType::Type type, const ClassLoader* loader, const char* descriptor);
-  const RegType& FromClass(Class* klass);
-  const RegType& FromCat1Const(int32_t value);
-  const RegType& FromDescriptor(const ClassLoader* loader, const char* descriptor);
-  const RegType& FromType(RegType::Type);
-
-  const RegType& Boolean() { return FromType(RegType::kRegTypeBoolean); }
-  const RegType& Byte()    { return FromType(RegType::kRegTypeByte); }
-  const RegType& Char()    { return FromType(RegType::kRegTypeChar); }
-  const RegType& Short()   { return FromType(RegType::kRegTypeShort); }
-  const RegType& Integer() { return FromType(RegType::kRegTypeInteger); }
-  const RegType& Float()   { return FromType(RegType::kRegTypeFloat); }
-  const RegType& Long()    { return FromType(RegType::kRegTypeLongLo); }
-  const RegType& Double()  { return FromType(RegType::kRegTypeDoubleLo); }
-
-  const RegType& JavaLangClass()  { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Class;"); }
-  const RegType& JavaLangObject() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Object;"); }
-  const RegType& JavaLangString() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/String;"); }
-  const RegType& JavaLangThrowable() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Throwable;"); }
-
-  const RegType& Unknown()  { return FromType(RegType::kRegTypeUnknown); }
-  const RegType& Conflict() { return FromType(RegType::kRegTypeConflict); }
-  const RegType& ConstLo()  { return FromType(RegType::kRegTypeConstLo); }
-  const RegType& Zero()     { return FromCat1Const(0); }
-
-  const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc);
-  const RegType& UninitializedThisArgument(Class* klass);
-  const RegType& FromUninitialized(const RegType& uninit_type);
-
-  // Representatives of various constant types. When merging constants we can't infer a type,
-  // (an int may later be used as a float) so we select these representative values meaning future
-  // merges won't know the exact constant value but have some notion of its size.
-  const RegType& ByteConstant() { return FromCat1Const(std::numeric_limits<jbyte>::min()); }
-  const RegType& ShortConstant() { return FromCat1Const(std::numeric_limits<jshort>::min()); }
-  const RegType& IntConstant() { return FromCat1Const(std::numeric_limits<jint>::max()); }
-
-  const RegType& GetComponentType(const RegType& array, const ClassLoader* loader);
- private:
-  // The allocated entries
-  std::vector<RegType*> entries_;
-
-  DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
-};
-
-class InsnFlags {
- public:
-  InsnFlags() : length_(0), flags_(0) {}
-
-  void SetLengthInCodeUnits(size_t length) {
-    CHECK_LT(length, 65536u);
-    length_ = length;
-  }
-  size_t GetLengthInCodeUnits() {
-    return length_;
-  }
-  bool IsOpcode() const {
-    return length_ != 0;
-  }
-
-  void SetInTry() {
-    flags_ |= 1 << kInTry;
-  }
-  void ClearInTry() {
-    flags_ &= ~(1 << kInTry);
-  }
-  bool IsInTry() const {
-    return (flags_ & (1 << kInTry)) != 0;
-  }
-
-  void SetBranchTarget() {
-    flags_ |= 1 << kBranchTarget;
-  }
-  void ClearBranchTarget() {
-    flags_ &= ~(1 << kBranchTarget);
-  }
-  bool IsBranchTarget() const {
-    return (flags_ & (1 << kBranchTarget)) != 0;
-  }
-
-  void SetGcPoint() {
-    flags_ |= 1 << kGcPoint;
-  }
-  void ClearGcPoint() {
-    flags_ &= ~(1 << kGcPoint);
-  }
-  bool IsGcPoint() const {
-    return (flags_ & (1 << kGcPoint)) != 0;
-  }
-
-  void SetVisited() {
-    flags_ |= 1 << kVisited;
-  }
-  void ClearVisited() {
-    flags_ &= ~(1 << kVisited);
-  }
-  bool IsVisited() const {
-    return (flags_ & (1 << kVisited)) != 0;
-  }
-
-  void SetChanged() {
-    flags_ |= 1 << kChanged;
-  }
-  void ClearChanged() {
-    flags_ &= ~(1 << kChanged);
-  }
-  bool IsChanged() const {
-    return (flags_ & (1 << kChanged)) != 0;
-  }
-
-  bool IsVisitedOrChanged() const {
-    return IsVisited() || IsChanged();
-  }
-
-  std::string Dump() {
-    char encoding[6];
-    if (!IsOpcode()) {
-      strncpy(encoding, "XXXXX", sizeof(encoding));
-    } else {
-      strncpy(encoding, "-----", sizeof(encoding));
-      if (IsInTry())        encoding[kInTry] = 'T';
-      if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
-      if (IsGcPoint())      encoding[kGcPoint] = 'G';
-      if (IsVisited())      encoding[kVisited] = 'V';
-      if (IsChanged())      encoding[kChanged] = 'C';
-    }
-    return std::string(encoding);
-  }
- private:
-  enum {
-    kInTry,
-    kBranchTarget,
-    kGcPoint,
-    kVisited,
-    kChanged,
-  };
-
-  // Size of instruction in code units
-  uint16_t length_;
-  uint8_t flags_;
-};
-
-/*
- * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
- * method determines which list we search, and whether we travel up into superclasses.
- *
- * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
- * All others are stored in the "virtual" list.)
- */
-enum MethodType {
-  METHOD_UNKNOWN  = 0,
-  METHOD_DIRECT,      // <init>, private
-  METHOD_STATIC,      // static
-  METHOD_VIRTUAL,     // virtual, super
-  METHOD_INTERFACE    // interface
-};
-
-const int kRegTypeUninitMask = 0xff;
-const int kRegTypeUninitShift = 8;
-
-/*
- * Register type categories, for type checking.
- *
- * The spec says category 1 includes boolean, byte, char, short, int, float, reference, and
- * returnAddress. Category 2 includes long and double.
- *
- * We treat object references separately, so we have "category1nr". We don't support jsr/ret, so
- * there is no "returnAddress" type.
- */
-enum TypeCategory {
-  kTypeCategoryUnknown = 0,
-  kTypeCategory1nr = 1,         // boolean, byte, char, short, int, float
-  kTypeCategory2 = 2,           // long, double
-  kTypeCategoryRef = 3,         // object reference
-};
-
-/*
- * An enumeration of problems that can turn up during verification.
- * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
- * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
- * that can potentially be corrected, and the verifier will try again at runtime.
- * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
- * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
- * to be rewritten to fail at runtime.
- */
-enum VerifyError {
-  VERIFY_ERROR_NONE = 0,       // No error; must be zero.
-  VERIFY_ERROR_BAD_CLASS_HARD, // VerifyError; hard error that skips compilation.
-  VERIFY_ERROR_BAD_CLASS_SOFT, // VerifyError; soft error that verifies again at runtime.
-
-  VERIFY_ERROR_NO_CLASS,       // NoClassDefFoundError.
-  VERIFY_ERROR_NO_FIELD,       // NoSuchFieldError.
-  VERIFY_ERROR_NO_METHOD,      // NoSuchMethodError.
-  VERIFY_ERROR_ACCESS_CLASS,   // IllegalAccessError.
-  VERIFY_ERROR_ACCESS_FIELD,   // IllegalAccessError.
-  VERIFY_ERROR_ACCESS_METHOD,  // IllegalAccessError.
-  VERIFY_ERROR_CLASS_CHANGE,   // IncompatibleClassChangeError.
-  VERIFY_ERROR_INSTANTIATION,  // InstantiationError.
-};
-std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
-
-/*
- * Identifies the type of reference in the instruction that generated the verify error
- * (e.g. VERIFY_ERROR_ACCESS_CLASS could come from a method, field, or class reference).
- *
- * This must fit in two bits.
- */
-enum VerifyErrorRefType {
-  VERIFY_ERROR_REF_CLASS  = 0,
-  VERIFY_ERROR_REF_FIELD  = 1,
-  VERIFY_ERROR_REF_METHOD = 2,
-};
-const int kVerifyErrorRefTypeShift = 6;
-
-/*
- * Format enumeration for RegisterMap data area.
- */
-enum RegisterMapFormat {
-  kRegMapFormatUnknown = 0,
-  kRegMapFormatNone = 1,      // Indicates no map data follows.
-  kRegMapFormatCompact8 = 2,  // Compact layout, 8-bit addresses.
-  kRegMapFormatCompact16 = 3, // Compact layout, 16-bit addresses.
-};
-const int kRegMapFormatShift = 5;
-const uint8_t kRegMapFormatMask = 0x7;
-
-// During verification, we associate one of these with every "interesting" instruction. We track
-// the status of all registers, and (if the method has any monitor-enter instructions) maintain a
-// stack of entered monitors (identified by code unit offset).
-// If live-precise register maps are enabled, the "liveRegs" vector will be populated. Unlike the
-// other lists of registers here, we do not track the liveness of the method result register
-// (which is not visible to the GC).
-class RegisterLine {
- public:
-  RegisterLine(size_t num_regs, DexVerifier* verifier) :
-    line_(new uint16_t[num_regs]), verifier_(verifier), num_regs_(num_regs) {
-    memset(line_.get(), 0, num_regs_ * sizeof(uint16_t));
-    result_[0] = RegType::kRegTypeUnknown;
-    result_[1] = RegType::kRegTypeUnknown;
-  }
-
-  // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
-  void CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat);
-
-  // Implement category-2 "move" instructions. Copy a 64-bit value from "vsrc" to "vdst". This
-  // copies both halves of the register.
-  void CopyRegister2(uint32_t vdst, uint32_t vsrc);
-
-  // Implement "move-result". Copy the category-1 value from the result register to another
-  // register, and reset the result register.
-  void CopyResultRegister1(uint32_t vdst, bool is_reference);
-
-  // Implement "move-result-wide". Copy the category-2 value from the result register to another
-  // register, and reset the result register.
-  void CopyResultRegister2(uint32_t vdst);
-
-  // Set the invisible result register to unknown
-  void SetResultTypeToUnknown();
-
-  // Set the type of register N, verifying that the register is valid.  If "newType" is the "Lo"
-  // part of a 64-bit value, register N+1 will be set to "newType+1".
-  // The register index was validated during the static pass, so we don't need to check it here.
-  bool SetRegisterType(uint32_t vdst, const RegType& new_type);
-
-  /* Set the type of the "result" register. */
-  void SetResultRegisterType(const RegType& new_type);
-
-  // Get the type of register vsrc.
-  const RegType& GetRegisterType(uint32_t vsrc) const;
-
-  bool VerifyRegisterType(uint32_t vsrc, const RegType& check_type);
-
-  void CopyFromLine(const RegisterLine* src) {
-    DCHECK_EQ(num_regs_, src->num_regs_);
-    memcpy(line_.get(), src->line_.get(), num_regs_ * sizeof(uint16_t));
-    monitors_ = src->monitors_;
-    reg_to_lock_depths_ = src->reg_to_lock_depths_;
-  }
-
-  std::string Dump() const {
-    std::string result;
-    for (size_t i = 0; i < num_regs_; i++) {
-      result += StringPrintf("%zd:[", i);
-      result += GetRegisterType(i).Dump();
-      result += "],";
-    }
-    typedef std::deque<uint32_t>::const_iterator It; // TODO: C++0x auto
-    for (It it = monitors_.begin(), end = monitors_.end(); it != end ; ++it) {
-      result += StringPrintf("{%d},", *it);
-    }
-    return result;
-  }
-
-  void FillWithGarbage() {
-    memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t));
-    while (!monitors_.empty()) {
-      monitors_.pop_back();
-    }
-    reg_to_lock_depths_.clear();
-  }
-
-  /*
-   * We're creating a new instance of class C at address A. Any registers holding instances
-   * previously created at address A must be initialized by now. If not, we mark them as "conflict"
-   * to prevent them from being used (otherwise, MarkRefsAsInitialized would mark the old ones and
-   * the new ones at the same time).
-   */
-  void MarkUninitRefsAsInvalid(const RegType& uninit_type);
-
-  /*
-   * Update all registers holding "uninit_type" to instead hold the corresponding initialized
-   * reference type. This is called when an appropriate constructor is invoked -- all copies of
-   * the reference must be marked as initialized.
-   */
-  void MarkRefsAsInitialized(const RegType& uninit_type);
-
-  /*
-   * Check constraints on constructor return. Specifically, make sure that the "this" argument got
-   * initialized.
-   * The "this" argument to <init> uses code offset kUninitThisArgAddr, which puts it at the start
-   * of the list in slot 0. If we see a register with an uninitialized slot 0 reference, we know it
-   * somehow didn't get initialized.
-   */
-  bool CheckConstructorReturn() const;
-
-  // Compare two register lines. Returns 0 if they match.
-  // Using this for a sort is unwise, since the value can change based on machine endianness.
-  int CompareLine(const RegisterLine* line2) const {
-    DCHECK(monitors_ == line2->monitors_);
-    // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_);
-    return memcmp(line_.get(), line2->line_.get(), num_regs_ * sizeof(uint16_t));
-  }
-
-  size_t NumRegs() const {
-    return num_regs_;
-  }
-
-  /*
-   * Get the "this" pointer from a non-static method invocation. This returns the RegType so the
-   * caller can decide whether it needs the reference to be initialized or not. (Can also return
-   * kRegTypeZero if the reference can only be zero at this point.)
-   *
-   * The argument count is in vA, and the first argument is in vC, for both "simple" and "range"
-   * versions. We just need to make sure vA is >= 1 and then return vC.
-   */
-  const RegType& GetInvocationThis(const DecodedInstruction& dec_insn);
-
-  /*
-   * Verify types for a simple two-register instruction (e.g. "neg-int").
-   * "dst_type" is stored into vA, and "src_type" is verified against vB.
-   */
-  void CheckUnaryOp(const DecodedInstruction& dec_insn,
-                    const RegType& dst_type, const RegType& src_type);
-
-  /*
-   * Verify types for a simple three-register instruction (e.g. "add-int").
-   * "dst_type" is stored into vA, and "src_type1"/"src_type2" are verified
-   * against vB/vC.
-   */
-  void CheckBinaryOp(const DecodedInstruction& dec_insn,
-                     const RegType& dst_type, const RegType& src_type1, const RegType& src_type2,
-                     bool check_boolean_op);
-
-  /*
-   * Verify types for a binary "2addr" operation. "src_type1"/"src_type2"
-   * are verified against vA/vB, then "dst_type" is stored into vA.
-   */
-  void CheckBinaryOp2addr(const DecodedInstruction& dec_insn,
-                          const RegType& dst_type,
-                          const RegType& src_type1, const RegType& src_type2,
-                          bool check_boolean_op);
-
-  /*
-   * Verify types for A two-register instruction with a literal constant (e.g. "add-int/lit8").
-   * "dst_type" is stored into vA, and "src_type" is verified against vB.
-   *
-   * If "check_boolean_op" is set, we use the constant value in vC.
-   */
-  void CheckLiteralOp(const DecodedInstruction& dec_insn,
-                      const RegType& dst_type, const RegType& src_type, bool check_boolean_op);
-
-  // Verify/push monitor onto the monitor stack, locking the value in reg_idx at location insn_idx.
-  void PushMonitor(uint32_t reg_idx, int32_t insn_idx);
-
-  // Verify/pop monitor from monitor stack ensuring that we believe the monitor is locked
-  void PopMonitor(uint32_t reg_idx);
-
-  // Stack of currently held monitors and where they were locked
-  size_t MonitorStackDepth() const {
-    return monitors_.size();
-  }
-
-  // We expect no monitors to be held at certain points, such a method returns. Verify the stack
-  // is empty, failing and returning false if not.
-  bool VerifyMonitorStackEmpty();
-
-  bool MergeRegisters(const RegisterLine* incoming_line);
-
-  size_t GetMaxNonZeroReferenceReg(size_t max_ref_reg) {
-    size_t i = static_cast<int>(max_ref_reg) < 0 ? 0 : max_ref_reg;
-    for (; i < num_regs_; i++) {
-      if (GetRegisterType(i).IsNonZeroReferenceTypes()) {
-        max_ref_reg = i;
-      }
-    }
-    return max_ref_reg;
-  }
-
-  // Write a bit at each register location that holds a reference
-  void WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes);
- private:
-
-  void CopyRegToLockDepth(size_t dst, size_t src) {
-    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(src);
-    if (it != reg_to_lock_depths_.end()) {
-      reg_to_lock_depths_.Put(dst, it->second);
-    }
-  }
-
-  bool IsSetLockDepth(size_t reg, size_t depth) {
-    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
-    if (it != reg_to_lock_depths_.end()) {
-      return (it->second & (1 << depth)) != 0;
-    } else {
-      return false;
-    }
-  }
-
-  void SetRegToLockDepth(size_t reg, size_t depth) {
-    CHECK_LT(depth, 32u);
-    DCHECK(!IsSetLockDepth(reg, depth));
-    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
-    if (it == reg_to_lock_depths_.end()) {
-      reg_to_lock_depths_.Put(reg, 1 << depth);
-    } else {
-      it->second |= (1 << depth);
-    }
-  }
-
-  void ClearRegToLockDepth(size_t reg, size_t depth) {
-    CHECK_LT(depth, 32u);
-    DCHECK(IsSetLockDepth(reg, depth));
-    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
-    DCHECK(it != reg_to_lock_depths_.end());
-    uint32_t depths = it->second ^ (1 << depth);
-    if (depths != 0) {
-      it->second = depths;
-    } else {
-      reg_to_lock_depths_.erase(it);
-    }
-  }
-
-  void ClearAllRegToLockDepths(size_t reg) {
-    reg_to_lock_depths_.erase(reg);
-  }
-
-  // Storage for the result register's type, valid after an invocation
-  uint16_t result_[2];
-
-  // An array of RegType Ids associated with each dex register
-  UniquePtr<uint16_t[]> line_;
-
-  // Back link to the verifier
-  DexVerifier* verifier_;
-
-  // Length of reg_types_
-  const size_t num_regs_;
-  // A stack of monitor enter locations
-  std::deque<uint32_t> monitors_;
-  // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
-  // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
-  // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5
-  SafeMap<uint32_t, uint32_t> reg_to_lock_depths_;
-};
-std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs);
-
-// We don't need to store the register data for many instructions, because we either only need
-// it at branch points (for verification) or GC points and branches (for verification +
-// type-precise register analysis).
-enum RegisterTrackingMode {
-  kTrackRegsBranches,
-  kTrackRegsGcPoints,
-  kTrackRegsAll,
-};
-
-class PcToRegisterLineTable {
- public:
-  PcToRegisterLineTable() {}
-  ~PcToRegisterLineTable() {
-    STLDeleteValues(&pc_to_register_line_);
-  }
-
-  // Initialize the RegisterTable. Every instruction address can have a different set of information
-  // about what's in which register, but for verification purposes we only need to store it at
-  // branch target addresses (because we merge into that).
-  void Init(RegisterTrackingMode mode, InsnFlags* flags, uint32_t insns_size,
-            uint16_t registers_size, DexVerifier* verifier);
-
-  RegisterLine* GetLine(size_t idx) {
-    Table::iterator result = pc_to_register_line_.find(idx);  // TODO: C++0x auto
-    if (result == pc_to_register_line_.end()) {
-      return NULL;
-    } else {
-      return result->second;
-    }
-  }
-
- private:
-  // Map from a dex pc to the register status associated with it
-  typedef SafeMap<int32_t, RegisterLine*> Table;
-  Table pc_to_register_line_;
-
-  // Number of registers we track for each instruction. This is equal to the method's declared
-  // "registersSize" plus kExtraRegs (2).
-  size_t insn_reg_count_plus_;
-};
-
-
-
-// The verifier
-class DexVerifier {
- public:
-  /* Verify a class. Returns "true" on success. */
-  static bool VerifyClass(const Class* klass, std::string& error);
-
-  /*
-   * Structurally verify a class. Returns "true" on success. Used at compile time
-   * when the pointer for the method or declaring class can't be resolved.
-   */
-  static bool VerifyClass(const DexFile* dex_file, DexCache* dex_cache,
-      const ClassLoader* class_loader, uint32_t class_def_idx, std::string& error);
-
-  uint8_t EncodePcToReferenceMapData() const;
-
-  uint32_t DexFileVersion() const {
-    return dex_file_->GetVersion();
-  }
-
-  RegTypeCache* GetRegTypeCache() {
-    return &reg_types_;
-  }
-
-  // Verification failed
-  std::ostream& Fail(VerifyError error);
-
-  // Log for verification information
-  std::ostream& LogVerifyInfo() {
-    return info_messages_ << "VFY: " << PrettyMethod(method_)
-                          << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : ";
-  }
-
-  // Dump the state of the verifier, namely each instruction, what flags are set on it, register
-  // information
-  void Dump(std::ostream& os);
-
-  static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref);
-  static void InitGcMaps();
-  static void DeleteGcMaps();
-
-#if defined(ART_USE_LLVM_COMPILER)
-  static const compiler_llvm::InferredRegCategoryMap* GetInferredRegCategoryMap(Compiler::MethodReference ref);
-  static void InitInferredRegCategoryMaps();
-  static void DeleteInferredRegCategoryMaps();
-#endif
-
-  static bool IsClassRejected(Compiler::ClassReference ref);
-
- private:
-
-  explicit DexVerifier(Method* method);
-  explicit DexVerifier(const DexFile* dex_file, DexCache* dex_cache,
-      const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item);
-
-  /*
-   * Perform verification on a single method.
-   *
-   * We do this in three passes:
-   *  (1) Walk through all code units, determining instruction locations,
-   *      widths, and other characteristics.
-   *  (2) Walk through all code units, performing static checks on
-   *      operands.
-   *  (3) Iterate through the method, checking type safety and looking
-   *      for code flow problems.
-   *
-   * Some checks may be bypassed depending on the verification mode. We can't
-   * turn this stuff off completely if we want to do "exact" GC.
-   *
-   * Confirmed here:
-   * - code array must not be empty
-   * Confirmed by ComputeWidthsAndCountOps():
-   * - opcode of first instruction begins at index 0
-   * - only documented instructions may appear
-   * - each instruction follows the last
-   * - last byte of last instruction is at (code_length-1)
-   */
-  static bool VerifyMethod(Method* method);
-  static void VerifyMethodAndDump(Method* method);
-
-  /*
-   * Perform structural verification on a single method. Used at compile time
-   * when the pointer for the method or declaring class can't be resolved.
-   *
-   * We do this in two passes:
-   *  (1) Walk through all code units, determining instruction locations,
-   *      widths, and other characteristics.
-   *  (2) Walk through all code units, performing static checks on
-   *      operands.
-   *
-   * Code flow verification is skipped since a resolved method and class are
-   * necessary to perform all the checks.
-   */
-  static bool VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
-      const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item);
-
-  /* Run both structural and code flow verification on the method. */
-  bool VerifyAll();
-
-  /* Perform structural verification on a single method. */
-  bool VerifyStructure();
-
-  /*
-   * Compute the width of the instruction at each address in the instruction stream, and store it in
-   * insn_flags_. Addresses that are in the middle of an instruction, or that are part of switch
-   * table data, are not touched (so the caller should probably initialize "insn_flags" to zero).
-   *
-   * The "new_instance_count_" and "monitor_enter_count_" fields in vdata are also set.
-   *
-   * Performs some static checks, notably:
-   * - opcode of first instruction begins at index 0
-   * - only documented instructions may appear
-   * - each instruction follows the last
-   * - last byte of last instruction is at (code_length-1)
-   *
-   * Logs an error and returns "false" on failure.
-   */
-  bool ComputeWidthsAndCountOps();
-
-  /*
-   * Set the "in try" flags for all instructions protected by "try" statements. Also sets the
-   * "branch target" flags for exception handlers.
-   *
-   * Call this after widths have been set in "insn_flags".
-   *
-   * Returns "false" if something in the exception table looks fishy, but we're expecting the
-   * exception table to be somewhat sane.
-   */
-  bool ScanTryCatchBlocks();
-
-  /*
-   * Perform static verification on all instructions in a method.
-   *
-   * Walks through instructions in a method calling VerifyInstruction on each.
-   */
-  bool VerifyInstructions();
-
-  /*
-   * Perform static verification on an instruction.
-   *
-   * As a side effect, this sets the "branch target" flags in InsnFlags.
-   *
-   * "(CF)" items are handled during code-flow analysis.
-   *
-   * v3 4.10.1
-   * - target of each jump and branch instruction must be valid
-   * - targets of switch statements must be valid
-   * - operands referencing constant pool entries must be valid
-   * - (CF) operands of getfield, putfield, getstatic, putstatic must be valid
-   * - (CF) operands of method invocation instructions must be valid
-   * - (CF) only invoke-direct can call a method starting with '<'
-   * - (CF) <clinit> must never be called explicitly
-   * - operands of instanceof, checkcast, new (and variants) must be valid
-   * - new-array[-type] limited to 255 dimensions
-   * - can't use "new" on an array class
-   * - (?) limit dimensions in multi-array creation
-   * - local variable load/store register values must be in valid range
-   *
-   * v3 4.11.1.2
-   * - branches must be within the bounds of the code array
-   * - targets of all control-flow instructions are the start of an instruction
-   * - register accesses fall within range of allocated registers
-   * - (N/A) access to constant pool must be of appropriate type
-   * - code does not end in the middle of an instruction
-   * - execution cannot fall off the end of the code
-   * - (earlier) for each exception handler, the "try" area must begin and
-   *   end at the start of an instruction (end can be at the end of the code)
-   * - (earlier) for each exception handler, the handler must start at a valid
-   *   instruction
-   */
-  bool VerifyInstruction(const Instruction* inst, uint32_t code_offset);
-
-  /* Ensure that the register index is valid for this code item. */
-  bool CheckRegisterIndex(uint32_t idx);
-
-  /* Ensure that the wide register index is valid for this code item. */
-  bool CheckWideRegisterIndex(uint32_t idx);
-
-  // Perform static checks on a field get or set instruction. All we do here is ensure that the
-  // field index is in the valid range.
-  bool CheckFieldIndex(uint32_t idx);
-
-  // Perform static checks on a method invocation instruction. All we do here is ensure that the
-  // method index is in the valid range.
-  bool CheckMethodIndex(uint32_t idx);
-
-  // Perform static checks on a "new-instance" instruction. Specifically, make sure the class
-  // reference isn't for an array class.
-  bool CheckNewInstance(uint32_t idx);
-
-  /* Ensure that the string index is in the valid range. */
-  bool CheckStringIndex(uint32_t idx);
-
-  // Perform static checks on an instruction that takes a class constant. Ensure that the class
-  // index is in the valid range.
-  bool CheckTypeIndex(uint32_t idx);
-
-  // Perform static checks on a "new-array" instruction. Specifically, make sure they aren't
-  // creating an array of arrays that causes the number of dimensions to exceed 255.
-  bool CheckNewArray(uint32_t idx);
-
-  // Verify an array data table. "cur_offset" is the offset of the fill-array-data instruction.
-  bool CheckArrayData(uint32_t cur_offset);
-
-  // Verify that the target of a branch instruction is valid. We don't expect code to jump directly
-  // into an exception handler, but it's valid to do so as long as the target isn't a
-  // "move-exception" instruction. We verify that in a later stage.
-  // The dex format forbids certain instructions from branching to themselves.
-  // Updates "insnFlags", setting the "branch target" flag.
-  bool CheckBranchTarget(uint32_t cur_offset);
-
-  // Verify a switch table. "cur_offset" is the offset of the switch instruction.
-  // Updates "insnFlags", setting the "branch target" flag.
-  bool CheckSwitchTargets(uint32_t cur_offset);
-
-  // Check the register indices used in a "vararg" instruction, such as invoke-virtual or
-  // filled-new-array.
-  // - vA holds word count (0-5), args[] have values.
-  // There are some tests we don't do here, e.g. we don't try to verify that invoking a method that
-  // takes a double is done with consecutive registers. This requires parsing the target method
-  // signature, which we will be doing later on during the code flow analysis.
-  bool CheckVarArgRegs(uint32_t vA, uint32_t arg[]);
-
-  // Check the register indices used in a "vararg/range" instruction, such as invoke-virtual/range
-  // or filled-new-array/range.
-  // - vA holds word count, vC holds index of first reg.
-  bool CheckVarArgRangeRegs(uint32_t vA, uint32_t vC);
-
-  // Extract the relative offset from a branch instruction.
-  // Returns "false" on failure (e.g. this isn't a branch instruction).
-  bool GetBranchOffset(uint32_t cur_offset, int32_t* pOffset, bool* pConditional,
-                       bool* selfOkay);
-
-  /* Perform detailed code-flow analysis on a single method. */
-  bool VerifyCodeFlow();
-
-  // Set the register types for the first instruction in the method based on the method signature.
-  // This has the side-effect of validating the signature.
-  bool SetTypesFromSignature();
-
-  /*
-   * Perform code flow on a method.
-   *
-   * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit on the first
-   * instruction, process it (setting additional "changed" bits), and repeat until there are no
-   * more.
-   *
-   * v3 4.11.1.1
-   * - (N/A) operand stack is always the same size
-   * - operand stack [registers] contain the correct types of values
-   * - local variables [registers] contain the correct types of values
-   * - methods are invoked with the appropriate arguments
-   * - fields are assigned using values of appropriate types
-   * - opcodes have the correct type values in operand registers
-   * - there is never an uninitialized class instance in a local variable in code protected by an
-   *   exception handler (operand stack is okay, because the operand stack is discarded when an
-   *   exception is thrown) [can't know what's a local var w/o the debug info -- should fall out of
-   *   register typing]
-   *
-   * v3 4.11.1.2
-   * - execution cannot fall off the end of the code
-   *
-   * (We also do many of the items described in the "static checks" sections, because it's easier to
-   * do them here.)
-   *
-   * We need an array of RegType values, one per register, for every instruction. If the method uses
-   * monitor-enter, we need extra data for every register, and a stack for every "interesting"
-   * instruction. In theory this could become quite large -- up to several megabytes for a monster
-   * function.
-   *
-   * NOTE:
-   * The spec forbids backward branches when there's an uninitialized reference in a register. The
-   * idea is to prevent something like this:
-   *   loop:
-   *     move r1, r0
-   *     new-instance r0, MyClass
-   *     ...
-   *     if-eq rN, loop  // once
-   *   initialize r0
-   *
-   * This leaves us with two different instances, both allocated by the same instruction, but only
-   * one is initialized. The scheme outlined in v3 4.11.1.4 wouldn't catch this, so they work around
-   * it by preventing backward branches. We achieve identical results without restricting code
-   * reordering by specifying that you can't execute the new-instance instruction if a register
-   * contains an uninitialized instance created by that same instruction.
-   */
-  bool CodeFlowVerifyMethod();
-
-  /*
-   * Perform verification for a single instruction.
-   *
-   * This requires fully decoding the instruction to determine the effect it has on registers.
-   *
-   * Finds zero or more following instructions and sets the "changed" flag if execution at that
-   * point needs to be (re-)evaluated. Register changes are merged into "reg_types_" at the target
-   * addresses. Does not set or clear any other flags in "insn_flags_".
-   */
-  bool CodeFlowVerifyInstruction(uint32_t* start_guess);
-
-  // Perform verification of a new array instruction
-  void VerifyNewArray(const DecodedInstruction& dec_insn, bool is_filled,
-                      bool is_range);
-
-  // Perform verification of an aget instruction. The destination register's type will be set to
-  // be that of component type of the array unless the array type is unknown, in which case a
-  // bottom type inferred from the type of instruction is used. is_primitive is false for an
-  // aget-object.
-  void VerifyAGet(const DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
-
-  // Perform verification of an aput instruction.
-  void VerifyAPut(const DecodedInstruction& insn, const RegType& insn_type,
-                  bool is_primitive);
-
-  // Lookup instance field and fail for resolution violations
-  Field* GetInstanceField(const RegType& obj_type, int field_idx);
-
-  // Lookup static field and fail for resolution violations
-  Field* GetStaticField(int field_idx);
-
-  // Perform verification of an iget or sget instruction.
-  void VerifyISGet(const DecodedInstruction& insn, const RegType& insn_type,
-                   bool is_primitive, bool is_static);
-
-  // Perform verification of an iput or sput instruction.
-  void VerifyISPut(const DecodedInstruction& insn, const RegType& insn_type,
-                   bool is_primitive, bool is_static);
-
-  // Resolves a class based on an index and performs access checks to ensure the referrer can
-  // access the resolved class.
-  const RegType& ResolveClassAndCheckAccess(uint32_t class_idx);
-
-  /*
-   * For the "move-exception" instruction at "work_insn_idx_", which must be at an exception handler
-   * address, determine the Join of all exceptions that can land here. Fails if no matching
-   * exception handler can be found or if the Join of exception types fails.
-   */
-  const RegType& GetCaughtExceptionType();
-
-  /*
-   * Resolves a method based on an index and performs access checks to ensure
-   * the referrer can access the resolved method.
-   * Does not throw exceptions.
-   */
-  Method* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type);
-
-  /*
-   * Verify the arguments to a method. We're executing in "method", making
-   * a call to the method reference in vB.
-   *
-   * If this is a "direct" invoke, we allow calls to <init>. For calls to
-   * <init>, the first argument may be an uninitialized reference. Otherwise,
-   * calls to anything starting with '<' will be rejected, as will any
-   * uninitialized reference arguments.
-   *
-   * For non-static method calls, this will verify that the method call is
-   * appropriate for the "this" argument.
-   *
-   * The method reference is in vBBBB. The "is_range" parameter determines
-   * whether we use 0-4 "args" values or a range of registers defined by
-   * vAA and vCCCC.
-   *
-   * Widening conversions on integers and references are allowed, but
-   * narrowing conversions are not.
-   *
-   * Returns the resolved method on success, NULL on failure (with *failure
-   * set appropriately).
-   */
-  Method* VerifyInvocationArgs(const DecodedInstruction& dec_insn,
-                               MethodType method_type, bool is_range, bool is_super);
-
-  /*
-   * Return the register type for the method. We can't just use the already-computed
-   * DalvikJniReturnType, because if it's a reference type we need to do the class lookup.
-   * Returned references are assumed to be initialized. Returns kRegTypeUnknown for "void".
-   */
-  const RegType& GetMethodReturnType();
-
-  /*
-   * Verify that the target instruction is not "move-exception". It's important that the only way
-   * to execute a move-exception is as the first instruction of an exception handler.
-   * Returns "true" if all is well, "false" if the target instruction is move-exception.
-   */
-  bool CheckNotMoveException(const uint16_t* insns, int insn_idx);
-
-  /*
-   * Replace an instruction with "throw-verification-error". This allows us to
-   * defer error reporting until the code path is first used.
-   */
-  void ReplaceFailingInstruction();
-
-  /*
-  * Control can transfer to "next_insn". Merge the registers from merge_line into the table at
-  * next_insn, and set the changed flag on the target address if any of the registers were changed.
-  * Returns "false" if an error is encountered.
-  */
-  bool UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line);
-
-#if defined(ART_USE_LLVM_COMPILER)
-  /*
-   * Generate the inferred register category for LLVM-based code generator.
-   * Returns a pointer to a two-dimension Class array, or NULL on failure.
-   */
-  const compiler_llvm::InferredRegCategoryMap* GenerateInferredRegCategoryMap();
-#endif
-
-  /*
-   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
-   * verification). For type-precise determination we have all the data we need, so we just need to
-   * encode it in some clever fashion.
-   * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
-   */
-  const std::vector<uint8_t>* GenerateGcMap();
-
-  // Verify that the GC map associated with method_ is well formed
-  void VerifyGcMap(const std::vector<uint8_t>& data);
-
-  // Compute sizes for GC map data
-  void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
-
-  InsnFlags CurrentInsnFlags() {
-    return insn_flags_[work_insn_idx_];
-  }
-
-  // All the GC maps that the verifier has created
-  typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable;
-  static Mutex* gc_maps_lock_;
-  static GcMapTable* gc_maps_;
-  static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map);
-
-#if defined(ART_USE_LLVM_COMPILER)
-  // All the inferred register category maps that the verifier has created
-  typedef SafeMap<const Compiler::MethodReference,
-                  const compiler_llvm::InferredRegCategoryMap*> InferredRegCategoryMapTable;
-  static Mutex* inferred_reg_category_maps_lock_;
-  static InferredRegCategoryMapTable* inferred_reg_category_maps_;
-  static void SetInferredRegCategoryMap(Compiler::MethodReference ref,
-                                        const compiler_llvm::InferredRegCategoryMap& m);
-#endif
-
-  static void AddRejectedClass(Compiler::ClassReference ref);
-
-  RegTypeCache reg_types_;
-
-  PcToRegisterLineTable reg_table_;
-
-  // Storage for the register status we're currently working on.
-  UniquePtr<RegisterLine> work_line_;
-
-  // The address of the instruction we're currently working on, note that this is in 2 byte
-  // quantities
-  uint32_t work_insn_idx_;
-
-  // Storage for the register status we're saving for later.
-  UniquePtr<RegisterLine> saved_line_;
-
-  Method* method_;  // The method we're working on.
-  const DexFile* dex_file_;  // The dex file containing the method.
-  DexCache* dex_cache_;  // The dex_cache for the declaring class of the method.
-  const ClassLoader* class_loader_;  // The class loader for the declaring class of the method.
-  uint32_t class_def_idx_;  // The class def index of the declaring class of the method.
-  const DexFile::CodeItem* code_item_;  // The code item containing the code for the method.
-  UniquePtr<InsnFlags[]> insn_flags_;  // Instruction widths and flags, one entry per code unit.
-
-  // The type of any error that occurs
-  VerifyError failure_;
-
-  // Failure message log
-  std::ostringstream fail_messages_;
-  // Info message log
-  std::ostringstream info_messages_;
-
-  // The number of occurrences of specific opcodes.
-  size_t new_instance_count_;
-  size_t monitor_enter_count_;
-
-  friend struct art::ReferenceMap2Visitor; // for VerifyMethodAndDump
-};
-
-// Lightweight wrapper for PC to reference bit maps.
-class PcToReferenceMap {
- public:
-  PcToReferenceMap(const uint8_t* data, size_t data_length) {
-    data_ = data;
-    CHECK(data_ != NULL);
-    // Check the size of the table agrees with the number of entries
-    size_t data_size = data_length - 4;
-    DCHECK_EQ(EntryWidth() * NumEntries(), data_size);
-  }
-
-  // The number of entries in the table
-  size_t NumEntries() const {
-    return GetData()[2] | (GetData()[3] << 8);
-  }
-
-  // Get the PC at the given index
-  uint16_t GetPC(size_t index) const {
-    size_t entry_offset = index * EntryWidth();
-    if (PcWidth() == 1) {
-      return Table()[entry_offset];
-    } else {
-      return Table()[entry_offset] | (Table()[entry_offset + 1] << 8);
-    }
-  }
-
-  // Return address of bitmap encoding what are live references
-  const uint8_t* GetBitMap(size_t index) const {
-    size_t entry_offset = index * EntryWidth();
-    return &Table()[entry_offset + PcWidth()];
-  }
-
-  // Find the bitmap associated with the given dex pc
-  const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const;
-
-  // The number of bytes used to encode registers
-  size_t RegWidth() const {
-    return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift);
-  }
-
- private:
-  // Table of num_entries * (dex pc, bitmap)
-  const uint8_t* Table() const {
-    return GetData() + 4;
-  }
-
-  // The format of the table of the PCs for the table
-  RegisterMapFormat Format() const {
-    return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask);
-  }
-
-  // Number of bytes used to encode a dex pc
-  size_t PcWidth() const {
-    RegisterMapFormat format = Format();
-    switch (format) {
-      case kRegMapFormatCompact8:
-        return 1;
-      case kRegMapFormatCompact16:
-        return 2;
-      default:
-        LOG(FATAL) << "Invalid format " << static_cast<int>(format);
-        return -1;
-    }
-  }
-
-  // The width of an entry in the table
-  size_t EntryWidth() const {
-    return PcWidth() + RegWidth();
-  }
-
-  const uint8_t* GetData() const {
-    return data_;
-  }
-  const uint8_t* data_;  // The header and table data
-};
-
-}  // namespace verifier
-}  // namespace art
-
-#endif  // ART_SRC_DEX_VERIFY_H_
diff --git a/src/oat/runtime/support_math.cc b/src/oat/runtime/support_math.cc
index 80e7d3f..7c6e0b1 100644
--- a/src/oat/runtime/support_math.cc
+++ b/src/oat/runtime/support_math.cc
@@ -62,67 +62,6 @@
   return -1;
 }
 
-/*
- * Float/double conversion requires clamping to min and max of integer form.  If
- * target doesn't support this normally, use these.
- */
-int64_t D2L(double d) {
-  static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
-  static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
-  if (d >= kMaxLong) {
-    return (int64_t) 0x7fffffffffffffffULL;
-  } else if (d <= kMinLong) {
-    return (int64_t) 0x8000000000000000ULL;
-  } else if (d != d)  { // NaN case
-    return 0;
-  } else {
-    return (int64_t) d;
-  }
-}
-
-int64_t F2L(float f) {
-  static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
-  static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
-  if (f >= kMaxLong) {
-    return (int64_t) 0x7fffffffffffffffULL;
-  } else if (f <= kMinLong) {
-    return (int64_t) 0x8000000000000000ULL;
-  } else if (f != f) { // NaN case
-    return 0;
-  } else {
-    return (int64_t) f;
-  }
-}
-
-int32_t D2I(double d) {
-  static const double kMaxInt = (double) (int32_t) 0x7fffffffUL;
-  static const double kMinInt = (double) (int32_t) 0x80000000UL;
-  if (d >= kMaxInt) {
-    return (int32_t) 0x7fffffffUL;
-  } else if (d <= kMinInt) {
-    return (int32_t) 0x80000000UL;
-  } else if (d != d)  { // NaN case
-    return 0;
-  } else {
-    return (int32_t) d;
-  }
-}
-
-int32_t F2I(float f) {
-  static const float kMaxInt = (float) (int32_t) 0x7fffffffUL;
-  static const float kMinInt = (float) (int32_t) 0x80000000UL;
-  if (f >= kMaxInt) {
-    return (int32_t) 0x7fffffffUL;
-  } else if (f <= kMinInt) {
-    return (int32_t) 0x80000000UL;
-  } else if (f != f) { // NaN case
-    return 0;
-  } else {
-    return (int32_t) f;
-  }
-}
-
-
 extern "C" int64_t artLdivFromCode(int64_t a, int64_t b) {
   return a / b;
 }
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index d5820bf..4d4890d 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -15,7 +15,6 @@
  */
 
 #include "callee_save_frame.h"
-#include "dex_verifier.h"
 #include "object.h"
 #include "object_utils.h"
 #include "runtime_support.h"
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 735c231..3fe7640 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -15,6 +15,7 @@
  */
 
 #include "oat/runtime/oat_support_entrypoints.h"
+#include "runtime_support.h"
 
 namespace art {
 
@@ -70,8 +71,6 @@
 extern int32_t CmplDouble(double a, double b);
 extern int32_t CmpgFloat(float a, float b);
 extern int32_t CmplFloat(float a, float b);
-extern int64_t D2L(double d);
-extern int64_t F2L(float f);
 extern "C" int32_t art_idiv_from_code(int32_t, int32_t);
 extern "C" int32_t art_idivmod_from_code(int32_t, int32_t);
 extern "C" int64_t art_ldiv_from_code(int64_t, int64_t);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 93eb9a1..5bcb927 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -24,7 +24,6 @@
 
 #include "class_linker.h"
 #include "dex_instruction.h"
-#include "dex_verifier.h"
 #include "disassembler.h"
 #include "file.h"
 #include "image.h"
@@ -35,6 +34,7 @@
 #include "safe_map.h"
 #include "space.h"
 #include "stringpiece.h"
+#include "verifier/gc_map.h"
 
 namespace art {
 
diff --git a/src/object.cc b/src/object.cc
index 158f0e6..8c101ba 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -591,6 +591,10 @@
   DCHECK(Thread::Current() == self);
   CHECK(IsNative()) << PrettyMethod(this);
   CHECK(native_method != NULL) << PrettyMethod(this);
+#if defined(ART_USE_LLVM_COMPILER)
+  SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+                           native_method, false);
+#else
   if (!self->GetJniEnv()->vm->work_around_app_jni_bugs) {
     SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
                              native_method, false);
@@ -608,6 +612,7 @@
     SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(Method, gc_map_),
         reinterpret_cast<const uint8_t*>(native_method), false);
   }
+#endif
 }
 
 void Method::UnregisterNative(Thread* self) {
diff --git a/src/runtime.cc b/src/runtime.cc
index 06c4020..77c887e 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -29,7 +29,6 @@
 #include "constants_arm.h"
 #include "constants_x86.h"
 #include "debugger.h"
-#include "dex_verifier.h"
 #include "heap.h"
 #include "image.h"
 #include "intern_table.h"
@@ -43,6 +42,7 @@
 #include "thread_list.h"
 #include "trace.h"
 #include "UniquePtr.h"
+#include "verifier/method_verifier.h"
 
 // TODO: this drags in cutil/log.h, which conflicts with our logging.h.
 #include "JniConstants.h"
@@ -72,6 +72,8 @@
       exit_(NULL),
       abort_(NULL),
       stats_enabled_(false),
+      method_trace_(0),
+      method_trace_file_size_(0),
       tracer_(NULL),
       use_compile_time_class_path_(false) {
   for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
@@ -100,9 +102,9 @@
   delete class_linker_;
   delete heap_;
 #if defined(ART_USE_LLVM_COMPILER)
-  verifier::DexVerifier::DeleteInferredRegCategoryMaps();
+  verifier::MethodVerifier::DeleteInferredRegCategoryMaps();
 #endif
-  verifier::DexVerifier::DeleteGcMaps();
+  verifier::MethodVerifier::DeleteGcMaps();
   delete intern_table_;
   delete java_vm_;
   Thread::Shutdown();
@@ -644,10 +646,10 @@
   thread_list_ = new ThreadList;
   intern_table_ = new InternTable;
 
-  verifier::DexVerifier::InitGcMaps();
+  verifier::MethodVerifier::InitGcMaps();
 
 #if defined(ART_USE_LLVM_COMPILER)
-  verifier::DexVerifier::InitInferredRegCategoryMaps();
+  verifier::MethodVerifier::InitInferredRegCategoryMaps();
 #endif
 
   heap_ = new Heap(options->heap_initial_size_,
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 8c2b30c..50f0130 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -20,6 +20,66 @@
 
 namespace art {
 
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+int64_t D2L(double d) {
+  static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
+  static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
+  if (d >= kMaxLong) {
+    return (int64_t) 0x7fffffffffffffffULL;
+  } else if (d <= kMinLong) {
+    return (int64_t) 0x8000000000000000ULL;
+  } else if (d != d)  { // NaN case
+    return 0;
+  } else {
+    return (int64_t) d;
+  }
+}
+
+int64_t F2L(float f) {
+  static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
+  static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
+  if (f >= kMaxLong) {
+    return (int64_t) 0x7fffffffffffffffULL;
+  } else if (f <= kMinLong) {
+    return (int64_t) 0x8000000000000000ULL;
+  } else if (f != f) { // NaN case
+    return 0;
+  } else {
+    return (int64_t) f;
+  }
+}
+
+int32_t D2I(double d) {
+  static const double kMaxInt = (double) (int32_t) 0x7fffffffUL;
+  static const double kMinInt = (double) (int32_t) 0x80000000UL;
+  if (d >= kMaxInt) {
+    return (int32_t) 0x7fffffffUL;
+  } else if (d <= kMinInt) {
+    return (int32_t) 0x80000000UL;
+  } else if (d != d)  { // NaN case
+    return 0;
+  } else {
+    return (int32_t) d;
+  }
+}
+
+int32_t F2I(float f) {
+  static const float kMaxInt = (float) (int32_t) 0x7fffffffUL;
+  static const float kMinInt = (float) (int32_t) 0x80000000UL;
+  if (f >= kMaxInt) {
+    return (int32_t) 0x7fffffffUL;
+  } else if (f <= kMinInt) {
+    return (int32_t) 0x80000000UL;
+  } else if (f != f) { // NaN case
+    return 0;
+  } else {
+    return (int32_t) f;
+  }
+}
+
 void ThrowNewIllegalAccessErrorClass(Thread* self,
                                      Class* referrer,
                                      Class* accessed) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 673a535..0fb1b2b 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -19,11 +19,11 @@
 
 #include "class_linker.h"
 #include "dex_file.h"
-#include "dex_verifier.h"
 #include "invoke_type.h"
 #include "object.h"
 #include "object_utils.h"
 #include "thread.h"
+#include "verifier/method_verifier.h"
 
 extern "C" void art_proxy_invoke_handler();
 extern "C" void art_work_around_app_jni_bugs();
@@ -36,6 +36,11 @@
 class Method;
 class Object;
 
+int64_t D2L(double d);
+int32_t D2I(double d);
+int64_t F2L(float f);
+int32_t F2I(float f);
+
 // Helpers to give consistent descriptive exception messages
 void ThrowNewIllegalAccessErrorClass(Thread* self, Class* referrer, Class* accessed);
 void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self, Class* referrer,
diff --git a/src/thread.cc b/src/thread.cc
index fbc718c..930e0df 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -31,11 +31,12 @@
 #include "debugger.h"
 #include "class_linker.h"
 #include "class_loader.h"
-#include "dex_verifier.h"
 #include "heap.h"
 #include "jni_internal.h"
 #include "monitor.h"
+#if !defined(ART_USE_LLVM_COMPILER)
 #include "oat/runtime/context.h"
+#endif
 #include "object.h"
 #include "object_utils.h"
 #include "reflection.h"
@@ -49,6 +50,7 @@
 #include "stack_indirect_reference_table.h"
 #include "thread_list.h"
 #include "utils.h"
+#include "verifier/gc_map.h"
 
 namespace art {
 
@@ -76,12 +78,20 @@
 }
 
 void Thread::InitFunctionPointers() {
+#if defined(ART_USE_LLVM_COMPILER)
+  memset(&entrypoints_, 0, sizeof(entrypoints_));
+#else
   InitEntryPoints(&entrypoints_);
+#endif
 }
 
 void Thread::SetDebuggerUpdatesEnabled(bool enabled) {
   LOG(INFO) << "Turning debugger updates " << (enabled ? "on" : "off") << " for " << *this;
+#if !defined(ART_USE_LLVM_COMPILER)
   ChangeDebuggerEntryPoint(&entrypoints_, enabled);
+#else
+  UNIMPLEMENTED(FATAL);
+#endif
 }
 
 void Thread::InitTid() {
@@ -852,7 +862,9 @@
   delete wait_cond_;
   delete wait_mutex_;
 
+#if !defined(ART_USE_LLVM_COMPILER)
   delete long_jump_context_;
+#endif
 
   delete debug_invoke_req_;
   delete trace_stack_;
@@ -1127,6 +1139,7 @@
   jobject local_ref_;
 };
 
+#if !defined(ART_USE_LLVM_COMPILER)
 // TODO: remove this.
 static uintptr_t ManglePc(uintptr_t pc) {
   // Move the PC back 2 bytes as a call will frequently terminate the
@@ -1136,6 +1149,7 @@
   if (pc > 0) { pc -= 2; }
   return pc;
 }
+#endif
 
 // TODO: remove this.
 static uintptr_t DemanglePc(uintptr_t pc) {
@@ -1590,9 +1604,13 @@
     } else {
       // Unwind stack when an exception occurs during method tracing
       if (UNLIKELY(method_tracing_active_)) {
+#if !defined(ART_USE_LLVM_COMPILER)
         if (IsTraceExitPc(DemanglePc(pc))) {
           pc = ManglePc(TraceMethodUnwindFromCode(Thread::Current()));
         }
+#else
+        UNIMPLEMENTED(FATAL);
+#endif
       }
       dex_pc = method->ToDexPC(pc);
     }
@@ -1604,8 +1622,10 @@
         return false;  // End stack walk.
       }
     }
+#if !defined(ART_USE_LLVM_COMPILER)
     // Caller may be handler, fill in callee saves in context
     long_jump_context_->FillCalleeSaves(fr);
+#endif
     return true;  // Continue stack walk.
   }
 
@@ -1624,6 +1644,7 @@
 };
 
 void Thread::DeliverException() {
+#if !defined(ART_USE_LLVM_COMPILER)
   const bool kDebugExceptionDelivery = false;
   Throwable* exception = GetException();  // Get exception from thread
   CHECK(exception != NULL);
@@ -1666,15 +1687,18 @@
   long_jump_context->SetPC(catch_native_pc);
   long_jump_context->SmashCallerSaves();
   long_jump_context->DoLongJump();
+#endif
   LOG(FATAL) << "UNREACHABLE";
 }
 
 Context* Thread::GetLongJumpContext() {
   Context* result = long_jump_context_;
+#if !defined(ART_USE_LLVM_COMPILER)
   if (result == NULL) {
     result = Context::Create();
     long_jump_context_ = result;
   }
+#endif
   return result;
 }
 
@@ -1722,6 +1746,7 @@
   return gThread_daemon->GetBoolean(peer_);
 }
 
+#if !defined(ART_USE_LLVM_COMPILER)
 class ReferenceMapVisitor : public Thread::StackVisitor {
  public:
   ReferenceMapVisitor(Context* context, Heap::RootVisitor* root_visitor, void* arg) :
@@ -1795,6 +1820,7 @@
   // Argument to call-back
   void* arg_;
 };
+#endif
 
 void Thread::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
   if (exception_ != NULL) {
diff --git a/src/trace.cc b/src/trace.cc
index 588979b..e84e7c3 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -21,7 +21,9 @@
 #include "class_linker.h"
 #include "debugger.h"
 #include "dex_cache.h"
+#if !defined(ART_USE_LLVM_COMPILER)
 #include "oat/runtime/oat_support_entrypoints.h"
+#endif
 #include "object_utils.h"
 #include "os.h"
 #include "scoped_thread_list_lock.h"
@@ -152,6 +154,9 @@
       if (t->IsTraceStackEmpty()) {
         break;
       }
+#if defined(ART_USE_LLVM_COMPILER)
+      UNIMPLEMENTED(FATAL);
+#else
       uintptr_t pc = frame.GetReturnPC();
       Method* method = frame.GetMethod();
       if (IsTraceExitPc(pc)) {
@@ -159,6 +164,7 @@
         frame.SetReturnPC(trace_frame.return_pc_);
         CHECK(method == trace_frame.method_);
       }
+#endif
     }
   }
 }
@@ -182,10 +188,14 @@
 }
 
 void Trace::SaveAndUpdateCode(Method* method) {
+#if defined(ART_USE_LLVM_COMPILER)
+  UNIMPLEMENTED(FATAL);
+#else
   void* trace_stub = GetLogTraceEntryPoint();
   CHECK(GetSavedCodeFromMap(method) == NULL);
   AddSavedCodeToMap(method, method->GetCode());
   method->SetCode(trace_stub);
+#endif
 }
 
 void Trace::ResetSavedCode(Method* method) {
diff --git a/src/verifier/gc_map.cc b/src/verifier/gc_map.cc
new file mode 100644
index 0000000..b9a3ef4
--- /dev/null
+++ b/src/verifier/gc_map.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gc_map.h"
+
+#include "logging.h"
+
+namespace art {
+namespace verifier {
+
+const uint8_t* PcToReferenceMap::FindBitMap(uint16_t dex_pc, bool error_if_not_present) const {
+  size_t num_entries = NumEntries();
+  // Do linear or binary search?
+  static const size_t kSearchThreshold = 8;
+  if (num_entries < kSearchThreshold) {
+    for (size_t i = 0; i < num_entries; i++)  {
+      if (GetPC(i) == dex_pc) {
+        return GetBitMap(i);
+      }
+    }
+  } else {
+    int lo = 0;
+    int hi = num_entries -1;
+    while (hi >= lo) {
+      int mid = (hi + lo) / 2;
+      int mid_pc = GetPC(mid);
+      if (dex_pc > mid_pc) {
+        lo = mid + 1;
+      } else if (dex_pc < mid_pc) {
+        hi = mid - 1;
+      } else {
+        return GetBitMap(mid);
+      }
+    }
+  }
+  if (error_if_not_present) {
+    LOG(ERROR) << "Didn't find reference bit map for dex_pc " << dex_pc;
+  }
+  return NULL;
+}
+
+}  // verifier
+}  // art
diff --git a/src/verifier/gc_map.h b/src/verifier/gc_map.h
new file mode 100644
index 0000000..07f6317
--- /dev/null
+++ b/src/verifier/gc_map.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_GC_MAP_H_
+#define ART_SRC_VERIFIER_GC_MAP_H_
+
+#include "logging.h"
+#include "macros.h"
+#include <stdint.h>
+
+namespace art {
+namespace verifier {
+
+/*
+ * Format enumeration for RegisterMap data area.
+ */
+enum RegisterMapFormat {
+  kRegMapFormatUnknown = 0,
+  kRegMapFormatNone = 1,      // Indicates no map data follows.
+  kRegMapFormatCompact8 = 2,  // Compact layout, 8-bit addresses.
+  kRegMapFormatCompact16 = 3, // Compact layout, 16-bit addresses.
+};
+
+// Lightweight wrapper for PC to reference bit maps.
+class PcToReferenceMap {
+ public:
+  PcToReferenceMap(const uint8_t* data, size_t data_length) {
+    data_ = data;
+    CHECK(data_ != NULL);
+    // Check the size of the table agrees with the number of entries
+    size_t data_size = data_length - 4;
+    DCHECK_EQ(EntryWidth() * NumEntries(), data_size);
+  }
+
+  // The number of entries in the table
+  size_t NumEntries() const {
+    return GetData()[2] | (GetData()[3] << 8);
+  }
+
+  // Get the PC at the given index
+  uint16_t GetPC(size_t index) const {
+    size_t entry_offset = index * EntryWidth();
+    if (PcWidth() == 1) {
+      return Table()[entry_offset];
+    } else {
+      return Table()[entry_offset] | (Table()[entry_offset + 1] << 8);
+    }
+  }
+
+  // Return address of bitmap encoding what are live references
+  const uint8_t* GetBitMap(size_t index) const {
+    size_t entry_offset = index * EntryWidth();
+    return &Table()[entry_offset + PcWidth()];
+  }
+
+  // Find the bitmap associated with the given dex pc
+  const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const;
+
+  // The number of bytes used to encode registers
+  size_t RegWidth() const {
+    return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift);
+  }
+
+ private:
+  // Table of num_entries * (dex pc, bitmap)
+  const uint8_t* Table() const {
+    return GetData() + 4;
+  }
+
+  // The format of the table of the PCs for the table
+  RegisterMapFormat Format() const {
+    return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask);
+  }
+
+  // Number of bytes used to encode a dex pc
+  size_t PcWidth() const {
+    RegisterMapFormat format = Format();
+    switch (format) {
+      case kRegMapFormatCompact8:
+        return 1;
+      case kRegMapFormatCompact16:
+        return 2;
+      default:
+        LOG(FATAL) << "Invalid format " << static_cast<int>(format);
+        return -1;
+    }
+  }
+
+  // The width of an entry in the table
+  size_t EntryWidth() const {
+    return PcWidth() + RegWidth();
+  }
+
+  const uint8_t* GetData() const {
+    return data_;
+  }
+
+  friend class MethodVerifier;
+
+  static const int kRegMapFormatShift = 5;
+  static const uint8_t kRegMapFormatMask = 0x7;
+
+  const uint8_t* data_;  // The header and table data
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_GC_MAP_H_
diff --git a/src/dex_verifier.cc b/src/verifier/method_verifier.cc
similarity index 77%
rename from src/dex_verifier.cc
rename to src/verifier/method_verifier.cc
index 4f523fa..1979940 100644
--- a/src/dex_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "dex_verifier.h"
+#include "method_verifier.h"
 
 #include <iostream>
 
@@ -24,7 +24,7 @@
 #include "dex_file.h"
 #include "dex_instruction.h"
 #include "dex_instruction_visitor.h"
-#include "dex_verifier.h"
+#include "gc_map.h"
 #include "intern_table.h"
 #include "leb128.h"
 #include "logging.h"
@@ -43,846 +43,106 @@
 
 static const bool gDebugVerify = false;
 
-static const char* type_strings[] = {
-    "Unknown",
-    "Conflict",
-    "Boolean",
-    "Byte",
-    "Short",
-    "Char",
-    "Integer",
-    "Float",
-    "Long (Low Half)",
-    "Long (High Half)",
-    "Double (Low Half)",
-    "Double (High Half)",
-    "64-bit Constant (Low Half)",
-    "64-bit Constant (High Half)",
-    "32-bit Constant",
-    "Unresolved Reference",
-    "Uninitialized Reference",
-    "Uninitialized This Reference",
-    "Unresolved And Uninitialized Reference",
-    "Reference",
+class InsnFlags {
+ public:
+  InsnFlags() : length_(0), flags_(0) {}
+
+  void SetLengthInCodeUnits(size_t length) {
+    CHECK_LT(length, 65536u);
+    length_ = length;
+  }
+  size_t GetLengthInCodeUnits() {
+    return length_;
+  }
+  bool IsOpcode() const {
+    return length_ != 0;
+  }
+
+  void SetInTry() {
+    flags_ |= 1 << kInTry;
+  }
+  void ClearInTry() {
+    flags_ &= ~(1 << kInTry);
+  }
+  bool IsInTry() const {
+    return (flags_ & (1 << kInTry)) != 0;
+  }
+
+  void SetBranchTarget() {
+    flags_ |= 1 << kBranchTarget;
+  }
+  void ClearBranchTarget() {
+    flags_ &= ~(1 << kBranchTarget);
+  }
+  bool IsBranchTarget() const {
+    return (flags_ & (1 << kBranchTarget)) != 0;
+  }
+
+  void SetGcPoint() {
+    flags_ |= 1 << kGcPoint;
+  }
+  void ClearGcPoint() {
+    flags_ &= ~(1 << kGcPoint);
+  }
+  bool IsGcPoint() const {
+    return (flags_ & (1 << kGcPoint)) != 0;
+  }
+
+  void SetVisited() {
+    flags_ |= 1 << kVisited;
+  }
+  void ClearVisited() {
+    flags_ &= ~(1 << kVisited);
+  }
+  bool IsVisited() const {
+    return (flags_ & (1 << kVisited)) != 0;
+  }
+
+  void SetChanged() {
+    flags_ |= 1 << kChanged;
+  }
+  void ClearChanged() {
+    flags_ &= ~(1 << kChanged);
+  }
+  bool IsChanged() const {
+    return (flags_ & (1 << kChanged)) != 0;
+  }
+
+  bool IsVisitedOrChanged() const {
+    return IsVisited() || IsChanged();
+  }
+
+  std::string Dump() {
+    char encoding[6];
+    if (!IsOpcode()) {
+      strncpy(encoding, "XXXXX", sizeof(encoding));
+    } else {
+      strncpy(encoding, "-----", sizeof(encoding));
+      if (IsInTry())        encoding[kInTry] = 'T';
+      if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
+      if (IsGcPoint())      encoding[kGcPoint] = 'G';
+      if (IsVisited())      encoding[kVisited] = 'V';
+      if (IsChanged())      encoding[kChanged] = 'C';
+    }
+    return std::string(encoding);
+  }
+ private:
+  enum {
+    kInTry,
+    kBranchTarget,
+    kGcPoint,
+    kVisited,
+    kChanged,
+  };
+
+  // Size of instruction in code units
+  uint16_t length_;
+  uint8_t flags_;
 };
 
-std::string RegType::Dump() const {
-  DCHECK(type_ >=  kRegTypeUnknown && type_ <= kRegTypeReference);
-  std::string result;
-  if (IsConstant()) {
-    uint32_t val = ConstantValue();
-    if (val == 0) {
-      result = "Zero";
-    } else {
-      if (IsConstantShort()) {
-        result = StringPrintf("32-bit Constant: %d", val);
-      } else {
-        result = StringPrintf("32-bit Constant: 0x%x", val);
-      }
-    }
-  } else {
-    result = type_strings[type_];
-    if (IsReferenceTypes()) {
-      result += ": ";
-      if (IsUnresolvedTypes()) {
-        result += PrettyDescriptor(GetDescriptor());
-      } else {
-        result += PrettyDescriptor(GetClass());
-      }
-    }
-  }
-  return result;
-}
-
-const RegType& RegType::HighHalf(RegTypeCache* cache) const {
-  CHECK(IsLowHalf());
-  if (type_ == kRegTypeLongLo) {
-    return cache->FromType(kRegTypeLongHi);
-  } else if (type_ == kRegTypeDoubleLo) {
-    return cache->FromType(kRegTypeDoubleHi);
-  } else {
-    return cache->FromType(kRegTypeConstHi);
-  }
-}
-
-/*
- * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
- * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
- * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
- * is the deepest (lowest upper bound) parent of S and T).
- *
- * This operation applies for regular classes and arrays, however, for interface types there needn't
- * be a partial ordering on the types. We could solve the problem of a lack of a partial order by
- * introducing sets of types, however, the only operation permissible on an interface is
- * invoke-interface. In the tradition of Java verifiers we defer the verification of interface
- * types until an invoke-interface call on the interface typed reference at runtime and allow
- * the perversion of any Object being assignable to an interface type (note, however, that we don't
- * allow assignment of Object or Interface to any concrete subclass of Object and are therefore type
- * safe; further the Join on a Object cannot result in a sub-class by definition).
- */
-Class* RegType::ClassJoin(Class* s, Class* t) {
-  DCHECK(!s->IsPrimitive()) << PrettyClass(s);
-  DCHECK(!t->IsPrimitive()) << PrettyClass(t);
-  if (s == t) {
-    return s;
-  } else if (s->IsAssignableFrom(t)) {
-    return s;
-  } else if (t->IsAssignableFrom(s)) {
-    return t;
-  } else if (s->IsArrayClass() && t->IsArrayClass()) {
-    Class* s_ct = s->GetComponentType();
-    Class* t_ct = t->GetComponentType();
-    if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
-      // Given the types aren't the same, if either array is of primitive types then the only
-      // common parent is java.lang.Object
-      Class* result = s->GetSuperClass();  // short-cut to java.lang.Object
-      DCHECK(result->IsObjectClass());
-      return result;
-    }
-    Class* common_elem = ClassJoin(s_ct, t_ct);
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    const ClassLoader* class_loader = s->GetClassLoader();
-    std::string descriptor("[");
-    descriptor += ClassHelper(common_elem).GetDescriptor();
-    Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
-    DCHECK(array_class != NULL);
-    return array_class;
-  } else {
-    size_t s_depth = s->Depth();
-    size_t t_depth = t->Depth();
-    // Get s and t to the same depth in the hierarchy
-    if (s_depth > t_depth) {
-      while (s_depth > t_depth) {
-        s = s->GetSuperClass();
-        s_depth--;
-      }
-    } else {
-      while (t_depth > s_depth) {
-        t = t->GetSuperClass();
-        t_depth--;
-      }
-    }
-    // Go up the hierarchy until we get to the common parent
-    while (s != t) {
-      s = s->GetSuperClass();
-      t = t->GetSuperClass();
-    }
-    return s;
-  }
-}
-
-bool RegType::IsAssignableFrom(const RegType& src) const {
-  if (Equals(src)) {
-    return true;
-  } else {
-    switch (GetType()) {
-      case RegType::kRegTypeBoolean:  return src.IsBooleanTypes();
-      case RegType::kRegTypeByte:     return src.IsByteTypes();
-      case RegType::kRegTypeShort:    return src.IsShortTypes();
-      case RegType::kRegTypeChar:     return src.IsCharTypes();
-      case RegType::kRegTypeInteger:  return src.IsIntegralTypes();
-      case RegType::kRegTypeFloat:    return src.IsFloatTypes();
-      case RegType::kRegTypeLongLo:   return src.IsLongTypes();
-      case RegType::kRegTypeDoubleLo: return src.IsDoubleTypes();
-      default:
-        if (!IsReferenceTypes()) {
-          LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" << src << "'";
-        }
-        if (src.IsZero()) {
-          return true;  // all reference types can be assigned null
-        } else if (!src.IsReferenceTypes()) {
-          return false;  // expect src to be a reference type
-        } else if (IsJavaLangObject()) {
-          return true;  // all reference types can be assigned to Object
-        } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
-          return true;  // We allow assignment to any interface, see comment in ClassJoin
-        } else if (IsJavaLangObjectArray()) {
-          return src.IsObjectArrayTypes();  // All reference arrays may be assigned to Object[]
-        } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
-                   GetClass()->IsAssignableFrom(src.GetClass())) {
-          // We're assignable from the Class point-of-view
-          return true;
-        } else {
-          return false;
-        }
-    }
-  }
-}
-
-static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
-  return a.IsConstant() ? b : a;
-}
-
-const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
-  DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
-  if (IsUnknown() && incoming_type.IsUnknown()) {
-    return *this;  // Unknown MERGE Unknown => Unknown
-  } else if (IsConflict()) {
-    return *this;  // Conflict MERGE * => Conflict
-  } else if (incoming_type.IsConflict()) {
-    return incoming_type;  // * MERGE Conflict => Conflict
-  } else if (IsUnknown() || incoming_type.IsUnknown()) {
-    return reg_types->Conflict();  // Unknown MERGE * => Conflict
-  } else if (IsConstant() && incoming_type.IsConstant()) {
-    int32_t val1 = ConstantValue();
-    int32_t val2 = incoming_type.ConstantValue();
-    if (val1 >= 0 && val2 >= 0) {
-      // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
-      if (val1 >= val2) {
-        return *this;
-      } else {
-        return incoming_type;
-      }
-    } else if (val1 < 0 && val2 < 0) {
-      // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
-      if (val1 <= val2) {
-        return *this;
-      } else {
-        return incoming_type;
-      }
-    } else {
-      // Values are +ve and -ve, choose smallest signed type in which they both fit
-      if (IsConstantByte()) {
-        if (incoming_type.IsConstantByte()) {
-          return reg_types->ByteConstant();
-        } else if (incoming_type.IsConstantShort()) {
-          return reg_types->ShortConstant();
-        } else {
-          return reg_types->IntConstant();
-        }
-      } else if (IsConstantShort()) {
-        if (incoming_type.IsConstantShort()) {
-          return reg_types->ShortConstant();
-        } else {
-          return reg_types->IntConstant();
-        }
-      } else {
-        return reg_types->IntConstant();
-      }
-    }
-  } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
-    if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
-      return reg_types->Boolean();  // boolean MERGE boolean => boolean
-    }
-    if (IsByteTypes() && incoming_type.IsByteTypes()) {
-      return reg_types->Byte();  // byte MERGE byte => byte
-    }
-    if (IsShortTypes() && incoming_type.IsShortTypes()) {
-      return reg_types->Short();  // short MERGE short => short
-    }
-    if (IsCharTypes() && incoming_type.IsCharTypes()) {
-      return reg_types->Char();  // char MERGE char => char
-    }
-    return reg_types->Integer();  // int MERGE * => int
-  } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
-             (IsLongTypes() && incoming_type.IsLongTypes()) ||
-             (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
-             (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
-             (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
-    // check constant case was handled prior to entry
-    DCHECK(!IsConstant() || !incoming_type.IsConstant());
-    // float/long/double MERGE float/long/double_constant => float/long/double
-    return SelectNonConstant(*this, incoming_type);
-  } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
-    if (IsZero() || incoming_type.IsZero()) {
-      return SelectNonConstant(*this, incoming_type);  // 0 MERGE ref => ref
-    } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
-      return reg_types->JavaLangObject();  // Object MERGE ref => Object
-    } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes() ||
-               IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
-      // Can only merge an unresolved or uninitialized type with itself, 0 or Object, we've already
-      // checked these so => Conflict
-      return reg_types->Conflict();
-    } else {  // Two reference types, compute Join
-      Class* c1 = GetClass();
-      Class* c2 = incoming_type.GetClass();
-      DCHECK(c1 != NULL && !c1->IsPrimitive());
-      DCHECK(c2 != NULL && !c2->IsPrimitive());
-      Class* join_class = ClassJoin(c1, c2);
-      if (c1 == join_class) {
-        return *this;
-      } else if (c2 == join_class) {
-        return incoming_type;
-      } else {
-        return reg_types->FromClass(join_class);
-      }
-    }
-  } else {
-    return reg_types->Conflict();  // Unexpected types => Conflict
-  }
-}
-
-static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
-  switch (prim_type) {
-    case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
-    case Primitive::kPrimByte:    return RegType::kRegTypeByte;
-    case Primitive::kPrimShort:   return RegType::kRegTypeShort;
-    case Primitive::kPrimChar:    return RegType::kRegTypeChar;
-    case Primitive::kPrimInt:     return RegType::kRegTypeInteger;
-    case Primitive::kPrimLong:    return RegType::kRegTypeLongLo;
-    case Primitive::kPrimFloat:   return RegType::kRegTypeFloat;
-    case Primitive::kPrimDouble:  return RegType::kRegTypeDoubleLo;
-    case Primitive::kPrimVoid:
-    default:                      return RegType::kRegTypeUnknown;
-  }
-}
-
-static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
-  if (descriptor.length() == 1) {
-    switch (descriptor[0]) {
-      case 'Z': return RegType::kRegTypeBoolean;
-      case 'B': return RegType::kRegTypeByte;
-      case 'S': return RegType::kRegTypeShort;
-      case 'C': return RegType::kRegTypeChar;
-      case 'I': return RegType::kRegTypeInteger;
-      case 'J': return RegType::kRegTypeLongLo;
-      case 'F': return RegType::kRegTypeFloat;
-      case 'D': return RegType::kRegTypeDoubleLo;
-      case 'V':
-      default:  return RegType::kRegTypeUnknown;
-    }
-  } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
-    return RegType::kRegTypeReference;
-  } else {
-    return RegType::kRegTypeUnknown;
-  }
-}
-
-std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
-  os << rhs.Dump();
-  return os;
-}
-
-const RegType& RegTypeCache::FromDescriptor(const ClassLoader* loader,
-                                            const char* descriptor) {
-  return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
-}
-
-const RegType& RegTypeCache::From(RegType::Type type, const ClassLoader* loader,
-                                  const char* descriptor) {
-  if (type <= RegType::kRegTypeLastFixedLocation) {
-    // entries should be sized greater than primitive types
-    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
-    RegType* entry = entries_[type];
-    if (entry == NULL) {
-      Class* klass = NULL;
-      if (strlen(descriptor) != 0) {
-        klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
-      }
-      entry = new RegType(type, klass, 0, type);
-      entries_[type] = entry;
-    }
-    return *entry;
-  } else {
-    DCHECK(type == RegType::kRegTypeReference);
-    ClassHelper kh;
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      // check resolved and unresolved references, ignore uninitialized references
-      if (cur_entry->IsReference()) {
-        kh.ChangeClass(cur_entry->GetClass());
-        if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
-          return *cur_entry;
-        }
-      } else if (cur_entry->IsUnresolvedReference() &&
-                 cur_entry->GetDescriptor()->Equals(descriptor)) {
-        return *cur_entry;
-      }
-    }
-    Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
-    if (klass != NULL) {
-      // Able to resolve so create resolved register type
-      RegType* entry = new RegType(type, klass, 0, entries_.size());
-      entries_.push_back(entry);
-      return *entry;
-    } else {
-      // TODO: we assume unresolved, but we may be able to do better by validating whether the
-      // descriptor string is valid
-      // Unable to resolve so create unresolved register type
-      DCHECK(Thread::Current()->IsExceptionPending());
-      Thread::Current()->ClearException();
-      if (IsValidDescriptor(descriptor)) {
-        String* string_descriptor =
-            Runtime::Current()->GetInternTable()->InternStrong(descriptor);
-        RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
-                                     entries_.size());
-        entries_.push_back(entry);
-        return *entry;
-      } else {
-        // The descriptor is broken return the unknown type as there's nothing sensible that
-        // could be done at runtime
-        return Unknown();
-      }
-    }
-  }
-}
-
-const RegType& RegTypeCache::FromClass(Class* klass) {
-  if (klass->IsPrimitive()) {
-    RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
-    // entries should be sized greater than primitive types
-    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
-    RegType* entry = entries_[type];
-    if (entry == NULL) {
-      entry = new RegType(type, klass, 0, type);
-      entries_[type] = entry;
-    }
-    return *entry;
-  } else {
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
-        return *cur_entry;
-      }
-    }
-    RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
-    entries_.push_back(entry);
-    return *entry;
-  }
-}
-
-const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
-  RegType* entry;
-  if (type.IsUnresolvedTypes()) {
-    String* descriptor = type.GetDescriptor();
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      if (cur_entry->IsUnresolvedAndUninitializedReference() &&
-          cur_entry->GetAllocationPc() == allocation_pc &&
-          cur_entry->GetDescriptor() == descriptor) {
-        return *cur_entry;
-      }
-    }
-    entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
-                        descriptor, allocation_pc, entries_.size());
-  } else {
-    Class* klass = type.GetClass();
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      if (cur_entry->IsUninitializedReference() &&
-          cur_entry->GetAllocationPc() == allocation_pc &&
-          cur_entry->GetClass() == klass) {
-        return *cur_entry;
-      }
-    }
-    entry = new RegType(RegType::kRegTypeUninitializedReference,
-                        klass, allocation_pc, entries_.size());
-  }
-  entries_.push_back(entry);
-  return *entry;
-}
-
-const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
-  RegType* entry;
-  if (uninit_type.IsUnresolvedTypes()) {
-    String* descriptor = uninit_type.GetDescriptor();
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
-        return *cur_entry;
-      }
-    }
-    entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
-  } else {
-    Class* klass = uninit_type.GetClass();
-    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-      RegType* cur_entry = entries_[i];
-      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
-        return *cur_entry;
-      }
-    }
-    entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
-  }
-  entries_.push_back(entry);
-  return *entry;
-}
-
-const RegType& RegTypeCache::UninitializedThisArgument(Class* klass) {
-  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-    RegType* cur_entry = entries_[i];
-    if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
-      return *cur_entry;
-    }
-  }
-  RegType* entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0,
-                               entries_.size());
-  entries_.push_back(entry);
-  return *entry;
-}
-
-const RegType& RegTypeCache::FromType(RegType::Type type) {
-  CHECK(type < RegType::kRegTypeReference);
-  switch (type) {
-    case RegType::kRegTypeBoolean:  return From(type, NULL, "Z");
-    case RegType::kRegTypeByte:     return From(type, NULL, "B");
-    case RegType::kRegTypeShort:    return From(type, NULL, "S");
-    case RegType::kRegTypeChar:     return From(type, NULL, "C");
-    case RegType::kRegTypeInteger:  return From(type, NULL, "I");
-    case RegType::kRegTypeFloat:    return From(type, NULL, "F");
-    case RegType::kRegTypeLongLo:
-    case RegType::kRegTypeLongHi:   return From(type, NULL, "J");
-    case RegType::kRegTypeDoubleLo:
-    case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
-    default:                        return From(type, NULL, "");
-  }
-}
-
-const RegType& RegTypeCache::FromCat1Const(int32_t value) {
-  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
-    RegType* cur_entry = entries_[i];
-    if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
-      return *cur_entry;
-    }
-  }
-  RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
-  entries_.push_back(entry);
-  return *entry;
-}
-
-const RegType& RegTypeCache::GetComponentType(const RegType& array, const ClassLoader* loader) {
-  CHECK(array.IsArrayTypes());
-  if (array.IsUnresolvedTypes()) {
-    std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
-    std::string component(descriptor.substr(1, descriptor.size() - 1));
-    return FromDescriptor(loader, component.c_str());
-  } else {
-    return FromClass(array.GetClass()->GetComponentType());
-  }
-}
-
-
-bool RegisterLine::CheckConstructorReturn() const {
-  for (size_t i = 0; i < num_regs_; i++) {
-    if (GetRegisterType(i).IsUninitializedThisReference()) {
-      verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
-          << "Constructor returning without calling superclass constructor";
-      return false;
-    }
-  }
-  return true;
-}
-
-bool RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) {
-  DCHECK(vdst < num_regs_);
-  if (new_type.IsLowHalf()) {
-    line_[vdst] = new_type.GetId();
-    line_[vdst + 1] = new_type.HighHalf(verifier_->GetRegTypeCache()).GetId();
-  } else if (new_type.IsHighHalf()) {
-    /* should never set these explicitly */
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Explicit set of high register type";
-    return false;
-  } else if (new_type.IsConflict()) {  // should only be set during a merge
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Set register to unknown type " << new_type;
-    return false;
-  } else {
-    line_[vdst] = new_type.GetId();
-  }
-  // Clear the monitor entry bits for this register.
-  ClearAllRegToLockDepths(vdst);
-  return true;
-}
-
-void RegisterLine::SetResultTypeToUnknown() {
-  uint16_t unknown_id = verifier_->GetRegTypeCache()->Unknown().GetId();
-  result_[0] = unknown_id;
-  result_[1] = unknown_id;
-}
-
-void RegisterLine::SetResultRegisterType(const RegType& new_type) {
-  result_[0] = new_type.GetId();
-  if (new_type.IsLowHalf()) {
-    DCHECK_EQ(new_type.HighHalf(verifier_->GetRegTypeCache()).GetId(), new_type.GetId() + 1);
-    result_[1] = new_type.GetId() + 1;
-  } else {
-    result_[1] = verifier_->GetRegTypeCache()->Unknown().GetId();
-  }
-}
-
-const RegType& RegisterLine::GetRegisterType(uint32_t vsrc) const {
-  // The register index was validated during the static pass, so we don't need to check it here.
-  DCHECK_LT(vsrc, num_regs_);
-  return verifier_->GetRegTypeCache()->GetFromId(line_[vsrc]);
-}
-
-const RegType& RegisterLine::GetInvocationThis(const DecodedInstruction& dec_insn) {
-  if (dec_insn.vA < 1) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke lacks 'this'";
-    return verifier_->GetRegTypeCache()->Unknown();
-  }
-  /* get the element type of the array held in vsrc */
-  const RegType& this_type = GetRegisterType(dec_insn.vC);
-  if (!this_type.IsReferenceTypes()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "tried to get class from non-reference register v"
-                                                 << dec_insn.vC << " (type=" << this_type << ")";
-    return verifier_->GetRegTypeCache()->Unknown();
-  }
-  return this_type;
-}
-
-bool RegisterLine::VerifyRegisterType(uint32_t vsrc, const RegType& check_type) {
-  // Verify the src register type against the check type refining the type of the register
-  const RegType& src_type = GetRegisterType(vsrc);
-  if (!check_type.IsAssignableFrom(src_type)) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "register v" << vsrc << " has type " << src_type
-                                                 << " but expected " << check_type;
-    return false;
-  }
-  if (check_type.IsLowHalf()) {
-    const RegType& src_type_h = GetRegisterType(vsrc + 1);
-    if (!src_type.CheckWidePair(src_type_h)) {
-      verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "wide register v" << vsrc << " has type "
-                                                   << src_type << "/" << src_type_h;
-      return false;
-    }
-  }
-  // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less
-  // precise than the subtype in vsrc so leave it for reference types. For primitive types
-  // if they are a defined type then they are as precise as we can get, however, for constant
-  // types we may wish to refine them. Unfortunately constant propagation has rendered this useless.
-  return true;
-}
-
-void RegisterLine::MarkRefsAsInitialized(const RegType& uninit_type) {
-  DCHECK(uninit_type.IsUninitializedTypes());
-  const RegType& init_type = verifier_->GetRegTypeCache()->FromUninitialized(uninit_type);
-  size_t changed = 0;
-  for (size_t i = 0; i < num_regs_; i++) {
-    if (GetRegisterType(i).Equals(uninit_type)) {
-      line_[i] = init_type.GetId();
-      changed++;
-    }
-  }
-  DCHECK_GT(changed, 0u);
-}
-
-void RegisterLine::MarkUninitRefsAsInvalid(const RegType& uninit_type) {
-  for (size_t i = 0; i < num_regs_; i++) {
-    if (GetRegisterType(i).Equals(uninit_type)) {
-      line_[i] = verifier_->GetRegTypeCache()->Conflict().GetId();
-      ClearAllRegToLockDepths(i);
-    }
-  }
-}
-
-void RegisterLine::CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat) {
-  DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
-  const RegType& type = GetRegisterType(vsrc);
-  if (!SetRegisterType(vdst, type)) {
-    return;
-  }
-  if ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
-      (cat == kTypeCategoryRef && !type.IsReferenceTypes())) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type
-                                                 << " cat=" << static_cast<int>(cat);
-  } else if (cat == kTypeCategoryRef) {
-    CopyRegToLockDepth(vdst, vsrc);
-  }
-}
-
-void RegisterLine::CopyRegister2(uint32_t vdst, uint32_t vsrc) {
-  const RegType& type_l = GetRegisterType(vsrc);
-  const RegType& type_h = GetRegisterType(vsrc + 1);
-
-  if (!type_l.CheckWidePair(type_h)) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy2 v" << vdst << "<-v" << vsrc
-                                                 << " type=" << type_l << "/" << type_h;
-  } else {
-    SetRegisterType(vdst, type_l);  // implicitly sets the second half
-  }
-}
-
-void RegisterLine::CopyResultRegister1(uint32_t vdst, bool is_reference) {
-  const RegType& type = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
-  if ((!is_reference && !type.IsCategory1Types()) ||
-      (is_reference && !type.IsReferenceTypes())) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
-        << "copyRes1 v" << vdst << "<- result0"  << " type=" << type;
-  } else {
-    DCHECK(verifier_->GetRegTypeCache()->GetFromId(result_[1]).IsUnknown());
-    SetRegisterType(vdst, type);
-    result_[0] = verifier_->GetRegTypeCache()->Unknown().GetId();
-  }
-}
-
-/*
- * Implement "move-result-wide". Copy the category-2 value from the result
- * register to another register, and reset the result register.
- */
-void RegisterLine::CopyResultRegister2(uint32_t vdst) {
-  const RegType& type_l = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
-  const RegType& type_h = verifier_->GetRegTypeCache()->GetFromId(result_[1]);
-  if (!type_l.IsCategory2Types()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
-        << "copyRes2 v" << vdst << "<- result0"  << " type=" << type_l;
-  } else {
-    DCHECK(type_l.CheckWidePair(type_h));  // Set should never allow this case
-    SetRegisterType(vdst, type_l);  // also sets the high
-    result_[0] = verifier_->GetRegTypeCache()->Unknown().GetId();
-    result_[1] = verifier_->GetRegTypeCache()->Unknown().GetId();
-  }
-}
-
-void RegisterLine::CheckUnaryOp(const DecodedInstruction& dec_insn,
-                                const RegType& dst_type, const RegType& src_type) {
-  if (VerifyRegisterType(dec_insn.vB, src_type)) {
-    SetRegisterType(dec_insn.vA, dst_type);
-  }
-}
-
-void RegisterLine::CheckBinaryOp(const DecodedInstruction& dec_insn,
-                                 const RegType& dst_type,
-                                 const RegType& src_type1, const RegType& src_type2,
-                                 bool check_boolean_op) {
-  if (VerifyRegisterType(dec_insn.vB, src_type1) &&
-      VerifyRegisterType(dec_insn.vC, src_type2)) {
-    if (check_boolean_op) {
-      DCHECK(dst_type.IsInteger());
-      if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
-          GetRegisterType(dec_insn.vC).IsBooleanTypes()) {
-        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
-        return;
-      }
-    }
-    SetRegisterType(dec_insn.vA, dst_type);
-  }
-}
-
-void RegisterLine::CheckBinaryOp2addr(const DecodedInstruction& dec_insn,
-                                      const RegType& dst_type, const RegType& src_type1,
-                                      const RegType& src_type2, bool check_boolean_op) {
-  if (VerifyRegisterType(dec_insn.vA, src_type1) &&
-      VerifyRegisterType(dec_insn.vB, src_type2)) {
-    if (check_boolean_op) {
-      DCHECK(dst_type.IsInteger());
-      if (GetRegisterType(dec_insn.vA).IsBooleanTypes() &&
-          GetRegisterType(dec_insn.vB).IsBooleanTypes()) {
-        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
-        return;
-      }
-    }
-    SetRegisterType(dec_insn.vA, dst_type);
-  }
-}
-
-void RegisterLine::CheckLiteralOp(const DecodedInstruction& dec_insn,
-                                  const RegType& dst_type, const RegType& src_type,
-                                  bool check_boolean_op) {
-  if (VerifyRegisterType(dec_insn.vB, src_type)) {
-    if (check_boolean_op) {
-      DCHECK(dst_type.IsInteger());
-      /* check vB with the call, then check the constant manually */
-      if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
-          (dec_insn.vC == 0 || dec_insn.vC == 1)) {
-        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
-        return;
-      }
-    }
-    SetRegisterType(dec_insn.vA, dst_type);
-  }
-}
-
-void RegisterLine::PushMonitor(uint32_t reg_idx, int32_t insn_idx) {
-  const RegType& reg_type = GetRegisterType(reg_idx);
-  if (!reg_type.IsReferenceTypes()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter on non-object (" << reg_type << ")";
-  } else if (monitors_.size() >= 32) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter stack overflow: " << monitors_.size();
-  } else {
-    SetRegToLockDepth(reg_idx, monitors_.size());
-    monitors_.push_back(insn_idx);
-  }
-}
-
-void RegisterLine::PopMonitor(uint32_t reg_idx) {
-  const RegType& reg_type = GetRegisterType(reg_idx);
-  if (!reg_type.IsReferenceTypes()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit on non-object (" << reg_type << ")";
-  } else if (monitors_.empty()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit stack underflow";
-  } else {
-    monitors_.pop_back();
-    if (!IsSetLockDepth(reg_idx, monitors_.size())) {
-      // Bug 3215458: Locks and unlocks are on objects, if that object is a literal then before
-      // format "036" the constant collector may create unlocks on the same object but referenced
-      // via different registers.
-      ((verifier_->DexFileVersion() >= 36) ? verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
-                                           : verifier_->LogVerifyInfo())
-            << "monitor-exit not unlocking the top of the monitor stack";
-    } else {
-      // Record the register was unlocked
-      ClearRegToLockDepth(reg_idx, monitors_.size());
-    }
-  }
-}
-
-bool RegisterLine::VerifyMonitorStackEmpty() {
-  if (MonitorStackDepth() != 0) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected empty monitor stack";
-    return false;
-  } else {
-    return true;
-  }
-}
-
-bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) {
-  bool changed = false;
-  for (size_t idx = 0; idx < num_regs_; idx++) {
-    if (line_[idx] != incoming_line->line_[idx]) {
-      const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx);
-      const RegType& cur_type = GetRegisterType(idx);
-      const RegType& new_type = cur_type.Merge(incoming_reg_type, verifier_->GetRegTypeCache());
-      changed = changed || !cur_type.Equals(new_type);
-      line_[idx] = new_type.GetId();
-    }
-  }
-  if (monitors_.size() != incoming_line->monitors_.size()) {
-    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths (depth="
-        << MonitorStackDepth() << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
-  } else if (reg_to_lock_depths_ != incoming_line->reg_to_lock_depths_) {
-    for (uint32_t idx = 0; idx < num_regs_; idx++) {
-      size_t depths = reg_to_lock_depths_.count(idx);
-      size_t incoming_depths = incoming_line->reg_to_lock_depths_.count(idx);
-      if (depths != incoming_depths) {
-        if (depths == 0 || incoming_depths == 0) {
-          reg_to_lock_depths_.erase(idx);
-        } else {
-          verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths for register v" << idx
-                                                       << ": " << depths  << " != " << incoming_depths;
-          break;
-        }
-      }
-    }
-  }
-  return changed;
-}
-
-void RegisterLine::WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes) {
-  for (size_t i = 0; i < num_regs_; i += 8) {
-    uint8_t val = 0;
-    for (size_t j = 0; j < 8 && (i + j) < num_regs_; j++) {
-      // Note: we write 1 for a Reference but not for Null
-      if (GetRegisterType(i + j).IsNonZeroReferenceTypes()) {
-        val |= 1 << j;
-      }
-    }
-    if ((i / 8) >= max_bytes) {
-      DCHECK_EQ(0, val);
-      continue;
-    }
-    DCHECK_LT(i / 8, max_bytes) << "val=" << static_cast<uint32_t>(val);
-    data.push_back(val);
-  }
-}
-
-std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs) {
-  os << rhs.Dump();
-  return os;
-}
-
-
 void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InsnFlags* flags,
                                  uint32_t insns_size, uint16_t registers_size,
-                                 DexVerifier* verifier) {
+                                 MethodVerifier* verifier) {
   DCHECK_GT(insns_size, 0U);
 
   for (uint32_t i = 0; i < insns_size; i++) {
@@ -906,7 +166,7 @@
   }
 }
 
-bool DexVerifier::VerifyClass(const Class* klass, std::string& error) {
+bool MethodVerifier::VerifyClass(const Class* klass, std::string& error) {
   if (klass->IsVerified()) {
     return true;
   }
@@ -947,8 +207,8 @@
   return true;
 }
 
-bool DexVerifier::VerifyMethod(Method* method) {
-  DexVerifier verifier(method);
+bool MethodVerifier::VerifyMethod(Method* method) {
+  MethodVerifier verifier(method);
   bool success = verifier.VerifyAll();
   CHECK_EQ(success, verifier.failure_ == VERIFY_ERROR_NONE);
 
@@ -972,16 +232,16 @@
   return success;
 }
 
-void DexVerifier::VerifyMethodAndDump(Method* method) {
-  DexVerifier verifier(method);
+void MethodVerifier::VerifyMethodAndDump(Method* method) {
+  MethodVerifier verifier(method);
   verifier.VerifyAll();
 
   LOG(INFO) << "Dump of method " << PrettyMethod(method) << " "
             << verifier.fail_messages_.str() << std::endl
-            << verifier.info_messages_.str() << Dumpable<DexVerifier>(verifier);
+            << verifier.info_messages_.str() << Dumpable<MethodVerifier>(verifier);
 }
 
-bool DexVerifier::VerifyClass(const DexFile* dex_file, DexCache* dex_cache,
+bool MethodVerifier::VerifyClass(const DexFile* dex_file, DexCache* dex_cache,
     const ClassLoader* class_loader, uint32_t class_def_idx, std::string& error) {
   const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
   const byte* class_data = dex_file->GetClassData(class_def);
@@ -1016,11 +276,11 @@
   return true;
 }
 
-bool DexVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
+bool MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
     const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item) {
-  DexVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item);
+  MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item);
 
-  // Without a method*, we can only verify the struture.
+  // Without a method*, we can only verify the structure.
   bool success = verifier.VerifyStructure();
   CHECK_EQ(success, verifier.failure_ == VERIFY_ERROR_NONE);
 
@@ -1044,7 +304,7 @@
   return success;
 }
 
-DexVerifier::DexVerifier(Method* method)
+MethodVerifier::MethodVerifier(Method* method)
     : work_insn_idx_(-1),
       method_(method),
       failure_(VERIFY_ERROR_NONE),
@@ -1060,7 +320,7 @@
   class_def_idx_ = dex_file_->GetIndexForClassDef(*class_def);
 }
 
-DexVerifier::DexVerifier(const DexFile* dex_file, DexCache* dex_cache,
+MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
     const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item)
     : work_insn_idx_(-1),
       method_(NULL),
@@ -1074,7 +334,7 @@
       monitor_enter_count_(0) {
 }
 
-bool DexVerifier::VerifyAll() {
+bool MethodVerifier::VerifyAll() {
   CHECK(method_ != NULL);
   // If there aren't any instructions, make sure that's expected, then exit successfully.
   if (code_item_ == NULL) {
@@ -1088,7 +348,7 @@
   return VerifyStructure() && VerifyCodeFlow();
 }
 
-bool DexVerifier::VerifyStructure() {
+bool MethodVerifier::VerifyStructure() {
   if (code_item_ == NULL) {
     return true;
   }
@@ -1109,7 +369,7 @@
   return result;
 }
 
-std::ostream& DexVerifier::Fail(VerifyError error) {
+std::ostream& MethodVerifier::Fail(VerifyError error) {
   CHECK_EQ(failure_, VERIFY_ERROR_NONE);
   if (Runtime::Current()->IsCompiler()) {
     switch (error) {
@@ -1141,7 +401,7 @@
                         << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : ";
 }
 
-bool DexVerifier::ComputeWidthsAndCountOps() {
+bool MethodVerifier::ComputeWidthsAndCountOps() {
   const uint16_t* insns = code_item_->insns_;
   size_t insns_size = code_item_->insns_size_in_code_units_;
   const Instruction* inst = Instruction::At(insns);
@@ -1173,7 +433,7 @@
   return true;
 }
 
-bool DexVerifier::ScanTryCatchBlocks() {
+bool MethodVerifier::ScanTryCatchBlocks() {
   uint32_t tries_size = code_item_->tries_size_;
   if (tries_size == 0) {
     return true;
@@ -1234,7 +494,7 @@
   return true;
 }
 
-bool DexVerifier::VerifyInstructions() {
+bool MethodVerifier::VerifyInstructions() {
   const Instruction* inst = Instruction::At(code_item_->insns_);
 
   /* Flag the start of the method as a branch target. */
@@ -1257,7 +517,7 @@
   return true;
 }
 
-bool DexVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_offset) {
+bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_offset) {
   DecodedInstruction dec_insn(inst);
   bool result = true;
   switch (inst->GetVerifyTypeArgumentA()) {
@@ -1332,7 +592,7 @@
   return result;
 }
 
-bool DexVerifier::CheckRegisterIndex(uint32_t idx) {
+bool MethodVerifier::CheckRegisterIndex(uint32_t idx) {
   if (idx >= code_item_->registers_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register index out of range (" << idx << " >= "
                                       << code_item_->registers_size_ << ")";
@@ -1341,7 +601,7 @@
   return true;
 }
 
-bool DexVerifier::CheckWideRegisterIndex(uint32_t idx) {
+bool MethodVerifier::CheckWideRegisterIndex(uint32_t idx) {
   if (idx + 1 >= code_item_->registers_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register index out of range (" << idx
                                       << "+1 >= " << code_item_->registers_size_ << ")";
@@ -1350,7 +610,7 @@
   return true;
 }
 
-bool DexVerifier::CheckFieldIndex(uint32_t idx) {
+bool MethodVerifier::CheckFieldIndex(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().field_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad field index " << idx << " (max "
                                       << dex_file_->GetHeader().field_ids_size_ << ")";
@@ -1359,7 +619,7 @@
   return true;
 }
 
-bool DexVerifier::CheckMethodIndex(uint32_t idx) {
+bool MethodVerifier::CheckMethodIndex(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().method_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad method index " << idx << " (max "
                                       << dex_file_->GetHeader().method_ids_size_ << ")";
@@ -1368,7 +628,7 @@
   return true;
 }
 
-bool DexVerifier::CheckNewInstance(uint32_t idx) {
+bool MethodVerifier::CheckNewInstance(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().type_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
                                       << dex_file_->GetHeader().type_ids_size_ << ")";
@@ -1383,7 +643,7 @@
   return true;
 }
 
-bool DexVerifier::CheckStringIndex(uint32_t idx) {
+bool MethodVerifier::CheckStringIndex(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().string_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad string index " << idx << " (max "
                                       << dex_file_->GetHeader().string_ids_size_ << ")";
@@ -1392,7 +652,7 @@
   return true;
 }
 
-bool DexVerifier::CheckTypeIndex(uint32_t idx) {
+bool MethodVerifier::CheckTypeIndex(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().type_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
                                       << dex_file_->GetHeader().type_ids_size_ << ")";
@@ -1401,7 +661,7 @@
   return true;
 }
 
-bool DexVerifier::CheckNewArray(uint32_t idx) {
+bool MethodVerifier::CheckNewArray(uint32_t idx) {
   if (idx >= dex_file_->GetHeader().type_ids_size_) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
                                       << dex_file_->GetHeader().type_ids_size_ << ")";
@@ -1425,7 +685,7 @@
   return true;
 }
 
-bool DexVerifier::CheckArrayData(uint32_t cur_offset) {
+bool MethodVerifier::CheckArrayData(uint32_t cur_offset) {
   const uint32_t insn_count = code_item_->insns_size_in_code_units_;
   const uint16_t* insns = code_item_->insns_ + cur_offset;
   const uint16_t* array_data;
@@ -1462,7 +722,7 @@
   return true;
 }
 
-bool DexVerifier::CheckBranchTarget(uint32_t cur_offset) {
+bool MethodVerifier::CheckBranchTarget(uint32_t cur_offset) {
   int32_t offset;
   bool isConditional, selfOkay;
   if (!GetBranchOffset(cur_offset, &offset, &isConditional, &selfOkay)) {
@@ -1490,7 +750,7 @@
   return true;
 }
 
-bool DexVerifier::GetBranchOffset(uint32_t cur_offset, int32_t* pOffset, bool* pConditional,
+bool MethodVerifier::GetBranchOffset(uint32_t cur_offset, int32_t* pOffset, bool* pConditional,
                                   bool* selfOkay) {
   const uint16_t* insns = code_item_->insns_ + cur_offset;
   *pConditional = false;
@@ -1528,7 +788,7 @@
   return true;
 }
 
-bool DexVerifier::CheckSwitchTargets(uint32_t cur_offset) {
+bool MethodVerifier::CheckSwitchTargets(uint32_t cur_offset) {
   const uint32_t insn_count = code_item_->insns_size_in_code_units_;
   DCHECK_LT(cur_offset, insn_count);
   const uint16_t* insns = code_item_->insns_ + cur_offset;
@@ -1605,7 +865,7 @@
   return true;
 }
 
-bool DexVerifier::CheckVarArgRegs(uint32_t vA, uint32_t arg[]) {
+bool MethodVerifier::CheckVarArgRegs(uint32_t vA, uint32_t arg[]) {
   if (vA > 5) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid arg count (" << vA << ") in non-range invoke)";
     return false;
@@ -1622,7 +882,7 @@
   return true;
 }
 
-bool DexVerifier::CheckVarArgRangeRegs(uint32_t vA, uint32_t vC) {
+bool MethodVerifier::CheckVarArgRangeRegs(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.
@@ -1652,7 +912,7 @@
   return length_prefixed_gc_map;
 }
 
-bool DexVerifier::VerifyCodeFlow() {
+bool MethodVerifier::VerifyCodeFlow() {
   uint16_t registers_size = code_item_->registers_size_;
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
 
@@ -1689,20 +949,20 @@
 #endif
   const std::vector<uint8_t>* gc_map = CreateLengthPrefixedGcMap(*(map.get()));
   Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
-  verifier::DexVerifier::SetGcMap(ref, *gc_map);
+  verifier::MethodVerifier::SetGcMap(ref, *gc_map);
 
   method_->SetGcMap(&gc_map->at(0));
 
 #if defined(ART_USE_LLVM_COMPILER)
   /* Generate Inferred Register Category for LLVM-based Code Generator */
   const InferredRegCategoryMap* table = GenerateInferredRegCategoryMap();
-  verifier::DexVerifier::SetInferredRegCategoryMap(ref, *table);
+  verifier::MethodVerifier::SetInferredRegCategoryMap(ref, *table);
 #endif
 
   return true;
 }
 
-void DexVerifier::Dump(std::ostream& os) {
+void MethodVerifier::Dump(std::ostream& os) {
   if (code_item_ == NULL) {
     os << "Native method" << std::endl;
     return;
@@ -1737,7 +997,7 @@
   }
 }
 
-bool DexVerifier::SetTypesFromSignature() {
+bool MethodVerifier::SetTypesFromSignature() {
   RegisterLine* reg_line = reg_table_.GetLine(0);
   int arg_start = code_item_->registers_size_ - code_item_->ins_size_;
   size_t expected_args = code_item_->ins_size_;   /* long/double count as two */
@@ -1857,7 +1117,7 @@
   return result;
 }
 
-bool DexVerifier::CodeFlowVerifyMethod() {
+bool MethodVerifier::CodeFlowVerifyMethod() {
   const uint16_t* insns = code_item_->insns_;
   const uint32_t insns_size = code_item_->insns_size_in_code_units_;
 
@@ -1961,7 +1221,7 @@
   return true;
 }
 
-bool DexVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
+bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
 #ifdef VERIFIER_STATS
   if (CurrentInsnFlags().IsVisited()) {
     gDvm.verifierStats.instrsReexamined++;
@@ -2008,7 +1268,7 @@
    * from the "successful" code path (e.g. a check-cast that "improves"
    * a type) to be visible to the exception handler.
    */
-  if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags().IsInTry()) {
+  if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags()->IsInTry()) {
     saved_line_->CopyFromLine(work_line_.get());
   } else {
 #ifndef NDEBUG
@@ -2979,7 +2239,7 @@
 
   /* Handle "continue". Tag the next consecutive instruction. */
   if ((opcode_flags & Instruction::kContinue) != 0) {
-    uint32_t next_insn_idx = work_insn_idx_ + CurrentInsnFlags().GetLengthInCodeUnits();
+    uint32_t next_insn_idx = work_insn_idx_ + CurrentInsnFlags()->GetLengthInCodeUnits();
     if (next_insn_idx >= code_item_->insns_size_in_code_units_) {
       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Execution can walk off end of code area";
       return false;
@@ -3139,7 +2399,7 @@
   return true;
 }
 
-const RegType& DexVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
+const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
   const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
   Class* referrer = method_->GetDeclaringClass();
   Class* klass = method_->GetDexCacheResolvedTypes()->Get(class_idx);
@@ -3165,7 +2425,7 @@
   }
 }
 
-const RegType& DexVerifier::GetCaughtExceptionType() {
+const RegType& MethodVerifier::GetCaughtExceptionType() {
   const RegType* common_super = NULL;
   if (code_item_->tries_size_ != 0) {
     const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
@@ -3207,7 +2467,7 @@
   return *common_super;
 }
 
-Method* DexVerifier::ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type) {
+Method* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type) {
   const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
   const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
   if (failure_ != VERIFY_ERROR_NONE) {
@@ -3297,7 +2557,7 @@
   return res_method;
 }
 
-Method* DexVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn,
+Method* MethodVerifier::VerifyInvocationArgs(const DecodedInstruction& dec_insn,
                                           MethodType method_type, bool is_range, bool is_super) {
   // Resolve the method. This could be an abstract or concrete method depending on what sort of call
   // we're making.
@@ -3401,12 +2661,12 @@
   }
 }
 
-const RegType& DexVerifier::GetMethodReturnType() {
+const RegType& MethodVerifier::GetMethodReturnType() {
   return reg_types_.FromDescriptor(method_->GetDeclaringClass()->GetClassLoader(),
                                    MethodHelper(method_).GetReturnTypeDescriptor());
 }
 
-void DexVerifier::VerifyNewArray(const DecodedInstruction& dec_insn, bool is_filled,
+void MethodVerifier::VerifyNewArray(const DecodedInstruction& dec_insn, bool is_filled,
                                  bool is_range) {
   const RegType& res_type = ResolveClassAndCheckAccess(is_filled ? dec_insn.vB : dec_insn.vC);
   if (res_type.IsUnknown()) {
@@ -3439,7 +2699,7 @@
   }
 }
 
-void DexVerifier::VerifyAGet(const DecodedInstruction& dec_insn,
+void MethodVerifier::VerifyAGet(const DecodedInstruction& dec_insn,
                              const RegType& insn_type, bool is_primitive) {
   const RegType& index_type = work_line_->GetRegisterType(dec_insn.vC);
   if (!index_type.IsArrayIndexTypes()) {
@@ -3483,7 +2743,7 @@
   }
 }
 
-void DexVerifier::VerifyAPut(const DecodedInstruction& dec_insn,
+void MethodVerifier::VerifyAPut(const DecodedInstruction& dec_insn,
                              const RegType& insn_type, bool is_primitive) {
   const RegType& index_type = work_line_->GetRegisterType(dec_insn.vC);
   if (!index_type.IsArrayIndexTypes()) {
@@ -3520,7 +2780,7 @@
   }
 }
 
-Field* DexVerifier::GetStaticField(int field_idx) {
+Field* MethodVerifier::GetStaticField(int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class
   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
@@ -3554,7 +2814,7 @@
   }
 }
 
-Field* DexVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
+Field* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class
   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
@@ -3608,7 +2868,7 @@
   }
 }
 
-void DexVerifier::VerifyISGet(const DecodedInstruction& dec_insn,
+void MethodVerifier::VerifyISGet(const DecodedInstruction& dec_insn,
                               const RegType& insn_type, bool is_primitive, bool is_static) {
   uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
   Field* field;
@@ -3660,7 +2920,7 @@
   }
 }
 
-void DexVerifier::VerifyISPut(const DecodedInstruction& dec_insn,
+void MethodVerifier::VerifyISPut(const DecodedInstruction& dec_insn,
                               const RegType& insn_type, bool is_primitive, bool is_static) {
   uint32_t field_idx = is_static ? dec_insn.vB : dec_insn.vC;
   Field* field;
@@ -3742,7 +3002,7 @@
   }
 }
 
-bool DexVerifier::CheckNotMoveException(const uint16_t* insns, int insn_idx) {
+bool MethodVerifier::CheckNotMoveException(const uint16_t* insns, int insn_idx) {
   if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid use of move-exception";
     return false;
@@ -3750,7 +3010,7 @@
   return true;
 }
 
-void DexVerifier::ReplaceFailingInstruction() {
+void MethodVerifier::ReplaceFailingInstruction() {
   if (Runtime::Current()->IsStarted()) {
     LOG(ERROR) << "Verification attempting to replace instructions in " << PrettyMethod(method_)
                << " " << fail_messages_.str();
@@ -3840,7 +3100,7 @@
   }
 }
 
-bool DexVerifier::UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line) {
+bool MethodVerifier::UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line) {
   bool changed = true;
   RegisterLine* target_line = reg_table_.GetLine(next_insn);
   if (!insn_flags_[next_insn].IsVisitedOrChanged()) {
@@ -3873,7 +3133,11 @@
   return true;
 }
 
-void DexVerifier::ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits,
+InsnFlags* MethodVerifier::CurrentInsnFlags() {
+  return &insn_flags_[work_insn_idx_];
+}
+
+void MethodVerifier::ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits,
                                     size_t* log2_max_gc_pc) {
   size_t local_gc_points = 0;
   size_t max_insn = 0;
@@ -3895,7 +3159,7 @@
   *log2_max_gc_pc = i;
 }
 
-const std::vector<uint8_t>* DexVerifier::GenerateGcMap() {
+const std::vector<uint8_t>* MethodVerifier::GenerateGcMap() {
   size_t num_entries, ref_bitmap_bits, pc_bits;
   ComputeGcMapSizes(&num_entries, &ref_bitmap_bits, &pc_bits);
   // There's a single byte to encode the size of each bitmap
@@ -3934,7 +3198,8 @@
     return NULL;
   }
   // Write table header
-  table->push_back(format | ((ref_bitmap_bytes >> kRegMapFormatShift) & ~kRegMapFormatMask));
+  table->push_back(format | ((ref_bitmap_bytes >> PcToReferenceMap::kRegMapFormatShift) &
+                             ~PcToReferenceMap::kRegMapFormatMask));
   table->push_back(ref_bitmap_bytes & 0xFF);
   table->push_back(num_entries & 0xFF);
   table->push_back((num_entries >> 8) & 0xFF);
@@ -3953,7 +3218,7 @@
   return table;
 }
 
-void DexVerifier::VerifyGcMap(const std::vector<uint8_t>& data) {
+void MethodVerifier::VerifyGcMap(const std::vector<uint8_t>& data) {
   // Check that for every GC point there is a map entry, there aren't entries for non-GC points,
   // that the table data is well formed and all references are marked (or not) in the bitmap
   PcToReferenceMap map(&data[0], data.size());
@@ -3982,47 +3247,16 @@
   }
 }
 
-const uint8_t* PcToReferenceMap::FindBitMap(uint16_t dex_pc, bool error_if_not_present) const {
-  size_t num_entries = NumEntries();
-  // Do linear or binary search?
-  static const size_t kSearchThreshold = 8;
-  if (num_entries < kSearchThreshold) {
-    for (size_t i = 0; i < num_entries; i++)  {
-      if (GetPC(i) == dex_pc) {
-        return GetBitMap(i);
-      }
-    }
-  } else {
-    int lo = 0;
-    int hi = num_entries -1;
-    while (hi >= lo) {
-      int mid = (hi + lo) / 2;
-      int mid_pc = GetPC(mid);
-      if (dex_pc > mid_pc) {
-        lo = mid + 1;
-      } else if (dex_pc < mid_pc) {
-        hi = mid - 1;
-      } else {
-        return GetBitMap(mid);
-      }
-    }
-  }
-  if (error_if_not_present) {
-    LOG(ERROR) << "Didn't find reference bit map for dex_pc " << dex_pc;
-  }
-  return NULL;
-}
+Mutex* MethodVerifier::gc_maps_lock_ = NULL;
+MethodVerifier::GcMapTable* MethodVerifier::gc_maps_ = NULL;
 
-Mutex* DexVerifier::gc_maps_lock_ = NULL;
-DexVerifier::GcMapTable* DexVerifier::gc_maps_ = NULL;
-
-void DexVerifier::InitGcMaps() {
+void MethodVerifier::InitGcMaps() {
   gc_maps_lock_ = new Mutex("verifier GC maps lock");
   MutexLock mu(*gc_maps_lock_);
-  gc_maps_ = new DexVerifier::GcMapTable;
+  gc_maps_ = new MethodVerifier::GcMapTable;
 }
 
-void DexVerifier::DeleteGcMaps() {
+void MethodVerifier::DeleteGcMaps() {
   {
     MutexLock mu(*gc_maps_lock_);
     STLDeleteValues(gc_maps_);
@@ -4033,7 +3267,7 @@
   gc_maps_lock_ = NULL;
 }
 
-void DexVerifier::SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) {
+void MethodVerifier::SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) {
   MutexLock mu(*gc_maps_lock_);
   GcMapTable::iterator it = gc_maps_->find(ref);
   if (it != gc_maps_->end()) {
@@ -4044,7 +3278,7 @@
   CHECK(GetGcMap(ref) != NULL);
 }
 
-const std::vector<uint8_t>* DexVerifier::GetGcMap(Compiler::MethodReference ref) {
+const std::vector<uint8_t>* MethodVerifier::GetGcMap(Compiler::MethodReference ref) {
   MutexLock mu(*gc_maps_lock_);
   GcMapTable::const_iterator it = gc_maps_->find(ref);
   if (it == gc_maps_->end()) {
@@ -4064,20 +3298,20 @@
   return rejected_classes;
 }
 
-void DexVerifier::AddRejectedClass(Compiler::ClassReference ref) {
+void MethodVerifier::AddRejectedClass(Compiler::ClassReference ref) {
   MutexLock mu(GetRejectedClassesLock());
   GetRejectedClasses().insert(ref);
   CHECK(IsClassRejected(ref));
 }
 
-bool DexVerifier::IsClassRejected(Compiler::ClassReference ref) {
+bool MethodVerifier::IsClassRejected(Compiler::ClassReference ref) {
   MutexLock mu(GetRejectedClassesLock());
   std::set<Compiler::ClassReference>& rejected_classes(GetRejectedClasses());
   return (rejected_classes.find(ref) != rejected_classes.end());
 }
 
 #if defined(ART_USE_LLVM_COMPILER)
-const InferredRegCategoryMap* DexVerifier::GenerateInferredRegCategoryMap() {
+const InferredRegCategoryMap* MethodVerifier::GenerateInferredRegCategoryMap() {
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
   uint16_t regs_size = code_item_->registers_size_;
 
@@ -4107,16 +3341,16 @@
   return table.release();
 }
 
-Mutex* DexVerifier::inferred_reg_category_maps_lock_ = NULL;
-DexVerifier::InferredRegCategoryMapTable* DexVerifier::inferred_reg_category_maps_ = NULL;
+Mutex* MethodVerifier::inferred_reg_category_maps_lock_ = NULL;
+MethodVerifier::InferredRegCategoryMapTable* MethodVerifier::inferred_reg_category_maps_ = NULL;
 
-void DexVerifier::InitInferredRegCategoryMaps() {
+void MethodVerifier::InitInferredRegCategoryMaps() {
   inferred_reg_category_maps_lock_ = new Mutex("verifier GC maps lock");
   MutexLock mu(*inferred_reg_category_maps_lock_);
-  inferred_reg_category_maps_ = new DexVerifier::InferredRegCategoryMapTable;
+  inferred_reg_category_maps_ = new MethodVerifier::InferredRegCategoryMapTable;
 }
 
-void DexVerifier::DeleteInferredRegCategoryMaps() {
+void MethodVerifier::DeleteInferredRegCategoryMaps() {
   {
     MutexLock mu(*inferred_reg_category_maps_lock_);
     STLDeleteValues(inferred_reg_category_maps_);
@@ -4128,23 +3362,22 @@
 }
 
 
-void DexVerifier::SetInferredRegCategoryMap(Compiler::MethodReference ref,
-                                            const InferredRegCategoryMap& inferred_reg_category_map) {
+void MethodVerifier::SetInferredRegCategoryMap(Compiler::MethodReference ref,
+                                          const InferredRegCategoryMap& inferred_reg_category_map) {
   MutexLock mu(*inferred_reg_category_maps_lock_);
-  const InferredRegCategoryMap* existing_inferred_reg_category_map =
-    GetInferredRegCategoryMap(ref);
+  const InferredRegCategoryMap* existing_inferred_reg_category_map = GetInferredRegCategoryMap(ref);
 
   if (existing_inferred_reg_category_map != NULL) {
     CHECK(*existing_inferred_reg_category_map == inferred_reg_category_map);
     delete existing_inferred_reg_category_map;
   }
 
-  (*inferred_reg_category_maps_)[ref] = &inferred_reg_category_map;
+  inferred_reg_category_maps_->Put(ref, &inferred_reg_category_map);
   CHECK(GetInferredRegCategoryMap(ref) != NULL);
 }
 
 const InferredRegCategoryMap*
-DexVerifier::GetInferredRegCategoryMap(Compiler::MethodReference ref) {
+MethodVerifier::GetInferredRegCategoryMap(Compiler::MethodReference ref) {
   MutexLock mu(*inferred_reg_category_maps_lock_);
 
   InferredRegCategoryMapTable::const_iterator it =
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
new file mode 100644
index 0000000..fc5b7ea
--- /dev/null
+++ b/src/verifier/method_verifier.h
@@ -0,0 +1,630 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_METHOD_VERIFIER_H_
+#define ART_SRC_VERIFIER_METHOD_VERIFIER_H_
+
+#include <deque>
+#include <limits>
+#include <set>
+#include <vector>
+
+#include "casts.h"
+#include "compiler.h"
+#include "dex_file.h"
+#include "dex_instruction.h"
+#include "macros.h"
+#include "object.h"
+#include "reg_type.h"
+#include "reg_type_cache.h"
+#include "register_line.h"
+#include "safe_map.h"
+#include "stl_util.h"
+#include "UniquePtr.h"
+
+namespace art {
+
+struct ReferenceMap2Visitor;
+
+#if defined(ART_USE_LLVM_COMPILER)
+namespace compiler_llvm {
+  class InferredRegCategoryMap;
+}  // namespace compiler_llvm
+#endif
+
+namespace verifier {
+
+class MethodVerifier;
+class InsnFlags;
+class PcToReferenceMap;
+
+/*
+ * Set this to enable dead code scanning. This is not required, but it's very useful when testing
+ * changes to the verifier (to make sure we're not skipping over stuff). The only reason not to do
+ * it is that it slightly increases the time required to perform verification.
+ */
+#define DEAD_CODE_SCAN kIsDebugBuild
+
+/*
+ * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
+ * method determines which list we search, and whether we travel up into superclasses.
+ *
+ * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
+ * All others are stored in the "virtual" list.)
+ */
+enum MethodType {
+  METHOD_UNKNOWN  = 0,
+  METHOD_DIRECT,      // <init>, private
+  METHOD_STATIC,      // static
+  METHOD_VIRTUAL,     // virtual, super
+  METHOD_INTERFACE    // interface
+};
+
+/*
+ * An enumeration of problems that can turn up during verification.
+ * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
+ * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
+ * that can potentially be corrected, and the verifier will try again at runtime.
+ * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
+ * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
+ * to be rewritten to fail at runtime.
+ */
+enum VerifyError {
+  VERIFY_ERROR_NONE = 0,       // No error; must be zero.
+  VERIFY_ERROR_BAD_CLASS_HARD, // VerifyError; hard error that skips compilation.
+  VERIFY_ERROR_BAD_CLASS_SOFT, // VerifyError; soft error that verifies again at runtime.
+
+  VERIFY_ERROR_NO_CLASS,       // NoClassDefFoundError.
+  VERIFY_ERROR_NO_FIELD,       // NoSuchFieldError.
+  VERIFY_ERROR_NO_METHOD,      // NoSuchMethodError.
+  VERIFY_ERROR_ACCESS_CLASS,   // IllegalAccessError.
+  VERIFY_ERROR_ACCESS_FIELD,   // IllegalAccessError.
+  VERIFY_ERROR_ACCESS_METHOD,  // IllegalAccessError.
+  VERIFY_ERROR_CLASS_CHANGE,   // IncompatibleClassChangeError.
+  VERIFY_ERROR_INSTANTIATION,  // InstantiationError.
+};
+std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
+
+/*
+ * Identifies the type of reference in the instruction that generated the verify error
+ * (e.g. VERIFY_ERROR_ACCESS_CLASS could come from a method, field, or class reference).
+ *
+ * This must fit in two bits.
+ */
+enum VerifyErrorRefType {
+  VERIFY_ERROR_REF_CLASS  = 0,
+  VERIFY_ERROR_REF_FIELD  = 1,
+  VERIFY_ERROR_REF_METHOD = 2,
+};
+const int kVerifyErrorRefTypeShift = 6;
+
+// We don't need to store the register data for many instructions, because we either only need
+// it at branch points (for verification) or GC points and branches (for verification +
+// type-precise register analysis).
+enum RegisterTrackingMode {
+  kTrackRegsBranches,
+  kTrackRegsGcPoints,
+  kTrackRegsAll,
+};
+
+class PcToRegisterLineTable {
+ public:
+  PcToRegisterLineTable() {}
+  ~PcToRegisterLineTable() {
+    STLDeleteValues(&pc_to_register_line_);
+  }
+
+  // Initialize the RegisterTable. Every instruction address can have a different set of information
+  // about what's in which register, but for verification purposes we only need to store it at
+  // branch target addresses (because we merge into that).
+  void Init(RegisterTrackingMode mode, InsnFlags* flags, uint32_t insns_size,
+            uint16_t registers_size, MethodVerifier* verifier);
+
+  RegisterLine* GetLine(size_t idx) {
+    Table::iterator result = pc_to_register_line_.find(idx);  // TODO: C++0x auto
+    if (result == pc_to_register_line_.end()) {
+      return NULL;
+    } else {
+      return result->second;
+    }
+  }
+
+ private:
+  typedef SafeMap<int32_t, RegisterLine*> Table;
+  // Map from a dex pc to the register status associated with it
+  Table pc_to_register_line_;
+};
+
+// The verifier
+class MethodVerifier {
+ public:
+  /* Verify a class. Returns "true" on success. */
+  static bool VerifyClass(const Class* klass, std::string& error);
+
+  /*
+   * Structurally verify a class. Returns "true" on success. Used at compile time
+   * when the pointer for the method or declaring class can't be resolved.
+   */
+  static bool VerifyClass(const DexFile* dex_file, DexCache* dex_cache,
+      const ClassLoader* class_loader, uint32_t class_def_idx, std::string& error);
+
+  uint8_t EncodePcToReferenceMapData() const;
+
+  uint32_t DexFileVersion() const {
+    return dex_file_->GetVersion();
+  }
+
+  RegTypeCache* GetRegTypeCache() {
+    return &reg_types_;
+  }
+
+  // Verification failed
+  std::ostream& Fail(VerifyError error);
+
+  // Log for verification information
+  std::ostream& LogVerifyInfo() {
+    return info_messages_ << "VFY: " << PrettyMethod(method_)
+                          << '[' << reinterpret_cast<void*>(work_insn_idx_) << "] : ";
+  }
+
+  // Dump the state of the verifier, namely each instruction, what flags are set on it, register
+  // information
+  void Dump(std::ostream& os);
+
+  static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref);
+  static void InitGcMaps();
+  static void DeleteGcMaps();
+
+#if defined(ART_USE_LLVM_COMPILER)
+  static const compiler_llvm::InferredRegCategoryMap* GetInferredRegCategoryMap(Compiler::MethodReference ref);
+  static void InitInferredRegCategoryMaps();
+  static void DeleteInferredRegCategoryMaps();
+#endif
+
+  static bool IsClassRejected(Compiler::ClassReference ref);
+
+ private:
+
+  explicit MethodVerifier(Method* method);
+  explicit MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
+      const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item);
+
+  /*
+   * Perform verification on a single method.
+   *
+   * We do this in three passes:
+   *  (1) Walk through all code units, determining instruction locations,
+   *      widths, and other characteristics.
+   *  (2) Walk through all code units, performing static checks on
+   *      operands.
+   *  (3) Iterate through the method, checking type safety and looking
+   *      for code flow problems.
+   *
+   * Some checks may be bypassed depending on the verification mode. We can't
+   * turn this stuff off completely if we want to do "exact" GC.
+   *
+   * Confirmed here:
+   * - code array must not be empty
+   * Confirmed by ComputeWidthsAndCountOps():
+   * - opcode of first instruction begins at index 0
+   * - only documented instructions may appear
+   * - each instruction follows the last
+   * - last byte of last instruction is at (code_length-1)
+   */
+  static bool VerifyMethod(Method* method);
+  static void VerifyMethodAndDump(Method* method);
+
+  /*
+   * Perform structural verification on a single method. Used at compile time
+   * when the pointer for the method or declaring class can't be resolved.
+   *
+   * We do this in two passes:
+   *  (1) Walk through all code units, determining instruction locations,
+   *      widths, and other characteristics.
+   *  (2) Walk through all code units, performing static checks on
+   *      operands.
+   *
+   * Code flow verification is skipped since a resolved method and class are
+   * necessary to perform all the checks.
+   */
+  static bool VerifyMethod(uint32_t method_idx, const DexFile* dex_file, DexCache* dex_cache,
+      const ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item);
+
+  /* Run both structural and code flow verification on the method. */
+  bool VerifyAll();
+
+  /* Perform structural verification on a single method. */
+  bool VerifyStructure();
+
+  /*
+   * Compute the width of the instruction at each address in the instruction stream, and store it in
+   * insn_flags_. Addresses that are in the middle of an instruction, or that are part of switch
+   * table data, are not touched (so the caller should probably initialize "insn_flags" to zero).
+   *
+   * The "new_instance_count_" and "monitor_enter_count_" fields in vdata are also set.
+   *
+   * Performs some static checks, notably:
+   * - opcode of first instruction begins at index 0
+   * - only documented instructions may appear
+   * - each instruction follows the last
+   * - last byte of last instruction is at (code_length-1)
+   *
+   * Logs an error and returns "false" on failure.
+   */
+  bool ComputeWidthsAndCountOps();
+
+  /*
+   * Set the "in try" flags for all instructions protected by "try" statements. Also sets the
+   * "branch target" flags for exception handlers.
+   *
+   * Call this after widths have been set in "insn_flags".
+   *
+   * Returns "false" if something in the exception table looks fishy, but we're expecting the
+   * exception table to be somewhat sane.
+   */
+  bool ScanTryCatchBlocks();
+
+  /*
+   * Perform static verification on all instructions in a method.
+   *
+   * Walks through instructions in a method calling VerifyInstruction on each.
+   */
+  bool VerifyInstructions();
+
+  /*
+   * Perform static verification on an instruction.
+   *
+   * As a side effect, this sets the "branch target" flags in InsnFlags.
+   *
+   * "(CF)" items are handled during code-flow analysis.
+   *
+   * v3 4.10.1
+   * - target of each jump and branch instruction must be valid
+   * - targets of switch statements must be valid
+   * - operands referencing constant pool entries must be valid
+   * - (CF) operands of getfield, putfield, getstatic, putstatic must be valid
+   * - (CF) operands of method invocation instructions must be valid
+   * - (CF) only invoke-direct can call a method starting with '<'
+   * - (CF) <clinit> must never be called explicitly
+   * - operands of instanceof, checkcast, new (and variants) must be valid
+   * - new-array[-type] limited to 255 dimensions
+   * - can't use "new" on an array class
+   * - (?) limit dimensions in multi-array creation
+   * - local variable load/store register values must be in valid range
+   *
+   * v3 4.11.1.2
+   * - branches must be within the bounds of the code array
+   * - targets of all control-flow instructions are the start of an instruction
+   * - register accesses fall within range of allocated registers
+   * - (N/A) access to constant pool must be of appropriate type
+   * - code does not end in the middle of an instruction
+   * - execution cannot fall off the end of the code
+   * - (earlier) for each exception handler, the "try" area must begin and
+   *   end at the start of an instruction (end can be at the end of the code)
+   * - (earlier) for each exception handler, the handler must start at a valid
+   *   instruction
+   */
+  bool VerifyInstruction(const Instruction* inst, uint32_t code_offset);
+
+  /* Ensure that the register index is valid for this code item. */
+  bool CheckRegisterIndex(uint32_t idx);
+
+  /* Ensure that the wide register index is valid for this code item. */
+  bool CheckWideRegisterIndex(uint32_t idx);
+
+  // Perform static checks on a field get or set instruction. All we do here is ensure that the
+  // field index is in the valid range.
+  bool CheckFieldIndex(uint32_t idx);
+
+  // Perform static checks on a method invocation instruction. All we do here is ensure that the
+  // method index is in the valid range.
+  bool CheckMethodIndex(uint32_t idx);
+
+  // Perform static checks on a "new-instance" instruction. Specifically, make sure the class
+  // reference isn't for an array class.
+  bool CheckNewInstance(uint32_t idx);
+
+  /* Ensure that the string index is in the valid range. */
+  bool CheckStringIndex(uint32_t idx);
+
+  // Perform static checks on an instruction that takes a class constant. Ensure that the class
+  // index is in the valid range.
+  bool CheckTypeIndex(uint32_t idx);
+
+  // Perform static checks on a "new-array" instruction. Specifically, make sure they aren't
+  // creating an array of arrays that causes the number of dimensions to exceed 255.
+  bool CheckNewArray(uint32_t idx);
+
+  // Verify an array data table. "cur_offset" is the offset of the fill-array-data instruction.
+  bool CheckArrayData(uint32_t cur_offset);
+
+  // Verify that the target of a branch instruction is valid. We don't expect code to jump directly
+  // into an exception handler, but it's valid to do so as long as the target isn't a
+  // "move-exception" instruction. We verify that in a later stage.
+  // The dex format forbids certain instructions from branching to themselves.
+  // Updates "insnFlags", setting the "branch target" flag.
+  bool CheckBranchTarget(uint32_t cur_offset);
+
+  // Verify a switch table. "cur_offset" is the offset of the switch instruction.
+  // Updates "insnFlags", setting the "branch target" flag.
+  bool CheckSwitchTargets(uint32_t cur_offset);
+
+  // Check the register indices used in a "vararg" instruction, such as invoke-virtual or
+  // filled-new-array.
+  // - vA holds word count (0-5), args[] have values.
+  // There are some tests we don't do here, e.g. we don't try to verify that invoking a method that
+  // takes a double is done with consecutive registers. This requires parsing the target method
+  // signature, which we will be doing later on during the code flow analysis.
+  bool CheckVarArgRegs(uint32_t vA, uint32_t arg[]);
+
+  // Check the register indices used in a "vararg/range" instruction, such as invoke-virtual/range
+  // or filled-new-array/range.
+  // - vA holds word count, vC holds index of first reg.
+  bool CheckVarArgRangeRegs(uint32_t vA, uint32_t vC);
+
+  // Extract the relative offset from a branch instruction.
+  // Returns "false" on failure (e.g. this isn't a branch instruction).
+  bool GetBranchOffset(uint32_t cur_offset, int32_t* pOffset, bool* pConditional,
+                       bool* selfOkay);
+
+  /* Perform detailed code-flow analysis on a single method. */
+  bool VerifyCodeFlow();
+
+  // Set the register types for the first instruction in the method based on the method signature.
+  // This has the side-effect of validating the signature.
+  bool SetTypesFromSignature();
+
+  /*
+   * Perform code flow on a method.
+   *
+   * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit on the first
+   * instruction, process it (setting additional "changed" bits), and repeat until there are no
+   * more.
+   *
+   * v3 4.11.1.1
+   * - (N/A) operand stack is always the same size
+   * - operand stack [registers] contain the correct types of values
+   * - local variables [registers] contain the correct types of values
+   * - methods are invoked with the appropriate arguments
+   * - fields are assigned using values of appropriate types
+   * - opcodes have the correct type values in operand registers
+   * - there is never an uninitialized class instance in a local variable in code protected by an
+   *   exception handler (operand stack is okay, because the operand stack is discarded when an
+   *   exception is thrown) [can't know what's a local var w/o the debug info -- should fall out of
+   *   register typing]
+   *
+   * v3 4.11.1.2
+   * - execution cannot fall off the end of the code
+   *
+   * (We also do many of the items described in the "static checks" sections, because it's easier to
+   * do them here.)
+   *
+   * We need an array of RegType values, one per register, for every instruction. If the method uses
+   * monitor-enter, we need extra data for every register, and a stack for every "interesting"
+   * instruction. In theory this could become quite large -- up to several megabytes for a monster
+   * function.
+   *
+   * NOTE:
+   * The spec forbids backward branches when there's an uninitialized reference in a register. The
+   * idea is to prevent something like this:
+   *   loop:
+   *     move r1, r0
+   *     new-instance r0, MyClass
+   *     ...
+   *     if-eq rN, loop  // once
+   *   initialize r0
+   *
+   * This leaves us with two different instances, both allocated by the same instruction, but only
+   * one is initialized. The scheme outlined in v3 4.11.1.4 wouldn't catch this, so they work around
+   * it by preventing backward branches. We achieve identical results without restricting code
+   * reordering by specifying that you can't execute the new-instance instruction if a register
+   * contains an uninitialized instance created by that same instruction.
+   */
+  bool CodeFlowVerifyMethod();
+
+  /*
+   * Perform verification for a single instruction.
+   *
+   * This requires fully decoding the instruction to determine the effect it has on registers.
+   *
+   * Finds zero or more following instructions and sets the "changed" flag if execution at that
+   * point needs to be (re-)evaluated. Register changes are merged into "reg_types_" at the target
+   * addresses. Does not set or clear any other flags in "insn_flags_".
+   */
+  bool CodeFlowVerifyInstruction(uint32_t* start_guess);
+
+  // Perform verification of a new array instruction
+  void VerifyNewArray(const DecodedInstruction& dec_insn, bool is_filled,
+                      bool is_range);
+
+  // Perform verification of an aget instruction. The destination register's type will be set to
+  // be that of component type of the array unless the array type is unknown, in which case a
+  // bottom type inferred from the type of instruction is used. is_primitive is false for an
+  // aget-object.
+  void VerifyAGet(const DecodedInstruction& insn, const RegType& insn_type,
+                  bool is_primitive);
+
+  // Perform verification of an aput instruction.
+  void VerifyAPut(const DecodedInstruction& insn, const RegType& insn_type,
+                  bool is_primitive);
+
+  // Lookup instance field and fail for resolution violations
+  Field* GetInstanceField(const RegType& obj_type, int field_idx);
+
+  // Lookup static field and fail for resolution violations
+  Field* GetStaticField(int field_idx);
+
+  // Perform verification of an iget or sget instruction.
+  void VerifyISGet(const DecodedInstruction& insn, const RegType& insn_type,
+                   bool is_primitive, bool is_static);
+
+  // Perform verification of an iput or sput instruction.
+  void VerifyISPut(const DecodedInstruction& insn, const RegType& insn_type,
+                   bool is_primitive, bool is_static);
+
+  // Resolves a class based on an index and performs access checks to ensure the referrer can
+  // access the resolved class.
+  const RegType& ResolveClassAndCheckAccess(uint32_t class_idx);
+
+  /*
+   * For the "move-exception" instruction at "work_insn_idx_", which must be at an exception handler
+   * address, determine the Join of all exceptions that can land here. Fails if no matching
+   * exception handler can be found or if the Join of exception types fails.
+   */
+  const RegType& GetCaughtExceptionType();
+
+  /*
+   * Resolves a method based on an index and performs access checks to ensure
+   * the referrer can access the resolved method.
+   * Does not throw exceptions.
+   */
+  Method* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type);
+
+  /*
+   * Verify the arguments to a method. We're executing in "method", making
+   * a call to the method reference in vB.
+   *
+   * If this is a "direct" invoke, we allow calls to <init>. For calls to
+   * <init>, the first argument may be an uninitialized reference. Otherwise,
+   * calls to anything starting with '<' will be rejected, as will any
+   * uninitialized reference arguments.
+   *
+   * For non-static method calls, this will verify that the method call is
+   * appropriate for the "this" argument.
+   *
+   * The method reference is in vBBBB. The "is_range" parameter determines
+   * whether we use 0-4 "args" values or a range of registers defined by
+   * vAA and vCCCC.
+   *
+   * Widening conversions on integers and references are allowed, but
+   * narrowing conversions are not.
+   *
+   * Returns the resolved method on success, NULL on failure (with *failure
+   * set appropriately).
+   */
+  Method* VerifyInvocationArgs(const DecodedInstruction& dec_insn,
+                               MethodType method_type, bool is_range, bool is_super);
+
+  /*
+   * Return the register type for the method. We can't just use the already-computed
+   * DalvikJniReturnType, because if it's a reference type we need to do the class lookup.
+   * Returned references are assumed to be initialized. Returns kRegTypeUnknown for "void".
+   */
+  const RegType& GetMethodReturnType();
+
+  /*
+   * Verify that the target instruction is not "move-exception". It's important that the only way
+   * to execute a move-exception is as the first instruction of an exception handler.
+   * Returns "true" if all is well, "false" if the target instruction is move-exception.
+   */
+  bool CheckNotMoveException(const uint16_t* insns, int insn_idx);
+
+  /*
+   * Replace an instruction with "throw-verification-error". This allows us to
+   * defer error reporting until the code path is first used.
+   */
+  void ReplaceFailingInstruction();
+
+  /*
+  * Control can transfer to "next_insn". Merge the registers from merge_line into the table at
+  * next_insn, and set the changed flag on the target address if any of the registers were changed.
+  * Returns "false" if an error is encountered.
+  */
+  bool UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line);
+
+#if defined(ART_USE_LLVM_COMPILER)
+  /*
+   * Generate the inferred register category for LLVM-based code generator.
+   * Returns a pointer to a two-dimension Class array, or NULL on failure.
+   */
+  const compiler_llvm::InferredRegCategoryMap* GenerateInferredRegCategoryMap();
+#endif
+
+  /*
+   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
+   * verification). For type-precise determination we have all the data we need, so we just need to
+   * encode it in some clever fashion.
+   * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
+   */
+  const std::vector<uint8_t>* GenerateGcMap();
+
+  // Verify that the GC map associated with method_ is well formed
+  void VerifyGcMap(const std::vector<uint8_t>& data);
+
+  // Compute sizes for GC map data
+  void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
+
+  InsnFlags* CurrentInsnFlags();
+
+  // All the GC maps that the verifier has created
+  typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable;
+  static Mutex* gc_maps_lock_;
+  static GcMapTable* gc_maps_;
+  static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map);
+
+#if defined(ART_USE_LLVM_COMPILER)
+  // All the inferred register category maps that the verifier has created
+  typedef SafeMap<const Compiler::MethodReference,
+                  const compiler_llvm::InferredRegCategoryMap*> InferredRegCategoryMapTable;
+  static Mutex* inferred_reg_category_maps_lock_;
+  static InferredRegCategoryMapTable* inferred_reg_category_maps_;
+  static void SetInferredRegCategoryMap(Compiler::MethodReference ref,
+                                        const compiler_llvm::InferredRegCategoryMap& m);
+#endif
+
+  static void AddRejectedClass(Compiler::ClassReference ref);
+
+  RegTypeCache reg_types_;
+
+  PcToRegisterLineTable reg_table_;
+
+  // Storage for the register status we're currently working on.
+  UniquePtr<RegisterLine> work_line_;
+
+  // The address of the instruction we're currently working on, note that this is in 2 byte
+  // quantities
+  uint32_t work_insn_idx_;
+
+  // Storage for the register status we're saving for later.
+  UniquePtr<RegisterLine> saved_line_;
+
+  Method* method_;  // The method we're working on.
+  const DexFile* dex_file_;  // The dex file containing the method.
+  DexCache* dex_cache_;  // The dex_cache for the declaring class of the method.
+  const ClassLoader* class_loader_;  // The class loader for the declaring class of the method.
+  uint32_t class_def_idx_;  // The class def index of the declaring class of the method.
+  const DexFile::CodeItem* code_item_;  // The code item containing the code for the method.
+  UniquePtr<InsnFlags[]> insn_flags_;  // Instruction widths and flags, one entry per code unit.
+
+  // The type of any error that occurs
+  VerifyError failure_;
+
+  // Failure message log
+  std::ostringstream fail_messages_;
+  // Info message log
+  std::ostringstream info_messages_;
+
+  // The number of occurrences of specific opcodes.
+  size_t new_instance_count_;
+  size_t monitor_enter_count_;
+
+  friend struct art::ReferenceMap2Visitor; // for VerifyMethodAndDump
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_METHOD_VERIFIER_H_
diff --git a/src/verifier/method_verifier_test.cc b/src/verifier/method_verifier_test.cc
new file mode 100644
index 0000000..f35d8a1
--- /dev/null
+++ b/src/verifier/method_verifier_test.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include "UniquePtr.h"
+#include "class_linker.h"
+#include "common_test.h"
+#include "dex_file.h"
+#include "method_verifier.h"
+
+namespace art {
+namespace verifier {
+
+class MethodVerifierTest : public CommonTest {
+ protected:
+  void VerifyClass(const std::string& descriptor) {
+    ASSERT_TRUE(descriptor != NULL);
+    Class* klass = class_linker_->FindSystemClass(descriptor.c_str());
+
+    // Verify the class
+    std::string error_msg;
+    ASSERT_TRUE(MethodVerifier::VerifyClass(klass, error_msg)) << error_msg;
+  }
+
+  void VerifyDexFile(const DexFile* dex) {
+    ASSERT_TRUE(dex != NULL);
+
+    // Verify all the classes defined in this file
+    for (size_t i = 0; i < dex->NumClassDefs(); i++) {
+      const DexFile::ClassDef& class_def = dex->GetClassDef(i);
+      const char* descriptor = dex->GetClassDescriptor(class_def);
+      VerifyClass(descriptor);
+    }
+  }
+};
+
+TEST_F(MethodVerifierTest, LibCore) {
+  VerifyDexFile(java_lang_dex_file_);
+}
+
+TEST_F(MethodVerifierTest, IntMath) {
+  SirtRef<ClassLoader> class_loader(LoadDex("IntMath"));
+  Class* klass = class_linker_->FindClass("LIntMath;", class_loader.get());
+  std::string error_msg;
+  ASSERT_TRUE(MethodVerifier::VerifyClass(klass, error_msg)) << error_msg;
+}
+
+}  // namespace verifier
+}  // namespace art
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
new file mode 100644
index 0000000..f72ad6a
--- /dev/null
+++ b/src/verifier/reg_type.cc
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "reg_type.h"
+
+#include "object_utils.h"
+#include "reg_type_cache.h"
+
+namespace art {
+namespace verifier {
+
+static const char* type_strings[] = {
+    "Unknown",
+    "Conflict",
+    "Boolean",
+    "Byte",
+    "Short",
+    "Char",
+    "Integer",
+    "Float",
+    "Long (Low Half)",
+    "Long (High Half)",
+    "Double (Low Half)",
+    "Double (High Half)",
+    "64-bit Constant (Low Half)",
+    "64-bit Constant (High Half)",
+    "32-bit Constant",
+    "Unresolved Reference",
+    "Uninitialized Reference",
+    "Uninitialized This Reference",
+    "Unresolved And Uninitialized Reference",
+    "Reference",
+};
+
+std::string RegType::Dump() const {
+  DCHECK(type_ >=  kRegTypeUnknown && type_ <= kRegTypeReference);
+  std::string result;
+  if (IsConstant()) {
+    uint32_t val = ConstantValue();
+    if (val == 0) {
+      result = "Zero";
+    } else {
+      if (IsConstantShort()) {
+        result = StringPrintf("32-bit Constant: %d", val);
+      } else {
+        result = StringPrintf("32-bit Constant: 0x%x", val);
+      }
+    }
+  } else {
+    result = type_strings[type_];
+    if (IsReferenceTypes()) {
+      result += ": ";
+      if (IsUnresolvedTypes()) {
+        result += PrettyDescriptor(GetDescriptor());
+      } else {
+        result += PrettyDescriptor(GetClass());
+      }
+    }
+  }
+  return result;
+}
+
+const RegType& RegType::HighHalf(RegTypeCache* cache) const {
+  CHECK(IsLowHalf());
+  if (type_ == kRegTypeLongLo) {
+    return cache->FromType(kRegTypeLongHi);
+  } else if (type_ == kRegTypeDoubleLo) {
+    return cache->FromType(kRegTypeDoubleHi);
+  } else {
+    return cache->FromType(kRegTypeConstHi);
+  }
+}
+
+/*
+ * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
+ * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
+ * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
+ * is the deepest (lowest upper bound) parent of S and T).
+ *
+ * This operation applies for regular classes and arrays, however, for interface types there needn't
+ * be a partial ordering on the types. We could solve the problem of a lack of a partial order by
+ * introducing sets of types, however, the only operation permissible on an interface is
+ * invoke-interface. In the tradition of Java verifiers we defer the verification of interface
+ * types until an invoke-interface call on the interface typed reference at runtime and allow
+ * the perversion of any Object being assignable to an interface type (note, however, that we don't
+ * allow assignment of Object or Interface to any concrete subclass of Object and are therefore type
+ * safe; further the Join on a Object cannot result in a sub-class by definition).
+ */
+Class* RegType::ClassJoin(Class* s, Class* t) {
+  DCHECK(!s->IsPrimitive()) << PrettyClass(s);
+  DCHECK(!t->IsPrimitive()) << PrettyClass(t);
+  if (s == t) {
+    return s;
+  } else if (s->IsAssignableFrom(t)) {
+    return s;
+  } else if (t->IsAssignableFrom(s)) {
+    return t;
+  } else if (s->IsArrayClass() && t->IsArrayClass()) {
+    Class* s_ct = s->GetComponentType();
+    Class* t_ct = t->GetComponentType();
+    if (s_ct->IsPrimitive() || t_ct->IsPrimitive()) {
+      // Given the types aren't the same, if either array is of primitive types then the only
+      // common parent is java.lang.Object
+      Class* result = s->GetSuperClass();  // short-cut to java.lang.Object
+      DCHECK(result->IsObjectClass());
+      return result;
+    }
+    Class* common_elem = ClassJoin(s_ct, t_ct);
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+    const ClassLoader* class_loader = s->GetClassLoader();
+    std::string descriptor("[");
+    descriptor += ClassHelper(common_elem).GetDescriptor();
+    Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
+    DCHECK(array_class != NULL);
+    return array_class;
+  } else {
+    size_t s_depth = s->Depth();
+    size_t t_depth = t->Depth();
+    // Get s and t to the same depth in the hierarchy
+    if (s_depth > t_depth) {
+      while (s_depth > t_depth) {
+        s = s->GetSuperClass();
+        s_depth--;
+      }
+    } else {
+      while (t_depth > s_depth) {
+        t = t->GetSuperClass();
+        t_depth--;
+      }
+    }
+    // Go up the hierarchy until we get to the common parent
+    while (s != t) {
+      s = s->GetSuperClass();
+      t = t->GetSuperClass();
+    }
+    return s;
+  }
+}
+
+bool RegType::IsAssignableFrom(const RegType& src) const {
+  if (Equals(src)) {
+    return true;
+  } else {
+    switch (GetType()) {
+      case RegType::kRegTypeBoolean:  return src.IsBooleanTypes();
+      case RegType::kRegTypeByte:     return src.IsByteTypes();
+      case RegType::kRegTypeShort:    return src.IsShortTypes();
+      case RegType::kRegTypeChar:     return src.IsCharTypes();
+      case RegType::kRegTypeInteger:  return src.IsIntegralTypes();
+      case RegType::kRegTypeFloat:    return src.IsFloatTypes();
+      case RegType::kRegTypeLongLo:   return src.IsLongTypes();
+      case RegType::kRegTypeDoubleLo: return src.IsDoubleTypes();
+      default:
+        if (!IsReferenceTypes()) {
+          LOG(FATAL) << "Unexpected register type in IsAssignableFrom: '" << src << "'";
+        }
+        if (src.IsZero()) {
+          return true;  // all reference types can be assigned null
+        } else if (!src.IsReferenceTypes()) {
+          return false;  // expect src to be a reference type
+        } else if (IsJavaLangObject()) {
+          return true;  // all reference types can be assigned to Object
+        } else if (!IsUnresolvedTypes() && GetClass()->IsInterface()) {
+          return true;  // We allow assignment to any interface, see comment in ClassJoin
+        } else if (IsJavaLangObjectArray()) {
+          return src.IsObjectArrayTypes();  // All reference arrays may be assigned to Object[]
+        } else if (!IsUnresolvedTypes() && !src.IsUnresolvedTypes() &&
+                   GetClass()->IsAssignableFrom(src.GetClass())) {
+          // We're assignable from the Class point-of-view
+          return true;
+        } else {
+          return false;
+        }
+    }
+  }
+}
+
+static const RegType& SelectNonConstant(const RegType& a, const RegType& b) {
+  return a.IsConstant() ? b : a;
+}
+
+const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_types) const {
+  DCHECK(!Equals(incoming_type));  // Trivial equality handled by caller
+  if (IsUnknown() && incoming_type.IsUnknown()) {
+    return *this;  // Unknown MERGE Unknown => Unknown
+  } else if (IsConflict()) {
+    return *this;  // Conflict MERGE * => Conflict
+  } else if (incoming_type.IsConflict()) {
+    return incoming_type;  // * MERGE Conflict => Conflict
+  } else if (IsUnknown() || incoming_type.IsUnknown()) {
+    return reg_types->Conflict();  // Unknown MERGE * => Conflict
+  } else if (IsConstant() && incoming_type.IsConstant()) {
+    int32_t val1 = ConstantValue();
+    int32_t val2 = incoming_type.ConstantValue();
+    if (val1 >= 0 && val2 >= 0) {
+      // +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
+      if (val1 >= val2) {
+        return *this;
+      } else {
+        return incoming_type;
+      }
+    } else if (val1 < 0 && val2 < 0) {
+      // -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
+      if (val1 <= val2) {
+        return *this;
+      } else {
+        return incoming_type;
+      }
+    } else {
+      // Values are +ve and -ve, choose smallest signed type in which they both fit
+      if (IsConstantByte()) {
+        if (incoming_type.IsConstantByte()) {
+          return reg_types->ByteConstant();
+        } else if (incoming_type.IsConstantShort()) {
+          return reg_types->ShortConstant();
+        } else {
+          return reg_types->IntConstant();
+        }
+      } else if (IsConstantShort()) {
+        if (incoming_type.IsConstantShort()) {
+          return reg_types->ShortConstant();
+        } else {
+          return reg_types->IntConstant();
+        }
+      } else {
+        return reg_types->IntConstant();
+      }
+    }
+  } else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
+    if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
+      return reg_types->Boolean();  // boolean MERGE boolean => boolean
+    }
+    if (IsByteTypes() && incoming_type.IsByteTypes()) {
+      return reg_types->Byte();  // byte MERGE byte => byte
+    }
+    if (IsShortTypes() && incoming_type.IsShortTypes()) {
+      return reg_types->Short();  // short MERGE short => short
+    }
+    if (IsCharTypes() && incoming_type.IsCharTypes()) {
+      return reg_types->Char();  // char MERGE char => char
+    }
+    return reg_types->Integer();  // int MERGE * => int
+  } else if ((IsFloatTypes() && incoming_type.IsFloatTypes()) ||
+             (IsLongTypes() && incoming_type.IsLongTypes()) ||
+             (IsLongHighTypes() && incoming_type.IsLongHighTypes()) ||
+             (IsDoubleTypes() && incoming_type.IsDoubleTypes()) ||
+             (IsDoubleHighTypes() && incoming_type.IsDoubleHighTypes())) {
+    // check constant case was handled prior to entry
+    DCHECK(!IsConstant() || !incoming_type.IsConstant());
+    // float/long/double MERGE float/long/double_constant => float/long/double
+    return SelectNonConstant(*this, incoming_type);
+  } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) {
+    if (IsZero() || incoming_type.IsZero()) {
+      return SelectNonConstant(*this, incoming_type);  // 0 MERGE ref => ref
+    } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
+      return reg_types->JavaLangObject();  // Object MERGE ref => Object
+    } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes() ||
+               IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
+      // Can only merge an unresolved or uninitialized type with itself, 0 or Object, we've already
+      // checked these so => Conflict
+      return reg_types->Conflict();
+    } else {  // Two reference types, compute Join
+      Class* c1 = GetClass();
+      Class* c2 = incoming_type.GetClass();
+      DCHECK(c1 != NULL && !c1->IsPrimitive());
+      DCHECK(c2 != NULL && !c2->IsPrimitive());
+      Class* join_class = ClassJoin(c1, c2);
+      if (c1 == join_class) {
+        return *this;
+      } else if (c2 == join_class) {
+        return incoming_type;
+      } else {
+        return reg_types->FromClass(join_class);
+      }
+    }
+  } else {
+    return reg_types->Conflict();  // Unexpected types => Conflict
+  }
+}
+
+std::ostream& operator<<(std::ostream& os, const RegType& rhs) {
+  os << rhs.Dump();
+  return os;
+}
+
+}  // verifier
+}  // art
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
new file mode 100644
index 0000000..3b4e10b
--- /dev/null
+++ b/src/verifier/reg_type.h
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_REG_TYPE_H_
+#define ART_SRC_VERIFIER_REG_TYPE_H_
+
+#include "macros.h"
+#include "object.h"
+
+#include <stdint.h>
+
+namespace art {
+namespace verifier {
+
+class RegTypeCache;
+
+/*
+ * RegType holds information about the "type" of data held in a register.
+ */
+class RegType {
+ public:
+  enum Type {
+    kRegTypeUnknown = 0,    // Initial state.
+    kRegTypeConflict,       // Merge clash makes this reg's type unknowable.
+    kRegTypeBoolean,        // Z.
+    kRegType1nrSTART = kRegTypeBoolean,
+    kRegTypeIntegralSTART = kRegTypeBoolean,
+    kRegTypeByte,           // B.
+    kRegTypeShort,          // S.
+    kRegTypeChar,           // C.
+    kRegTypeInteger,        // I.
+    kRegTypeIntegralEND = kRegTypeInteger,
+    kRegTypeFloat,          // F.
+    kRegType1nrEND = kRegTypeFloat,
+    kRegTypeLongLo,         // J - lower-numbered register; endian-independent.
+    kRegTypeLongHi,
+    kRegTypeDoubleLo,       // D.
+    kRegTypeDoubleHi,
+    kRegTypeConstLo,        // Const derived wide, lower half - could be long or double.
+    kRegTypeConstHi,        // Const derived wide, upper half - could be long or double.
+    kRegTypeLastFixedLocation = kRegTypeConstHi,
+    kRegTypeConst,          // 32-bit constant derived value - could be float or int.
+    kRegTypeUnresolvedReference,        // Reference type that couldn't be resolved.
+    kRegTypeUninitializedReference,     // Freshly allocated reference type.
+    kRegTypeUninitializedThisReference, // Freshly allocated reference passed as "this".
+    kRegTypeUnresolvedAndUninitializedReference, // Freshly allocated unresolved reference type.
+    kRegTypeReference,                  // Reference type.
+  };
+
+  Type GetType() const {
+    return type_;
+  }
+
+  bool IsUnknown() const { return type_ == kRegTypeUnknown; }
+  bool IsConflict() const { return type_ == kRegTypeConflict; }
+  bool IsBoolean() const { return type_ == kRegTypeBoolean; }
+  bool IsByte()    const { return type_ == kRegTypeByte; }
+  bool IsChar()    const { return type_ == kRegTypeChar; }
+  bool IsShort()   const { return type_ == kRegTypeShort; }
+  bool IsInteger() const { return type_ == kRegTypeInteger; }
+  bool IsLong()    const { return type_ == kRegTypeLongLo; }
+  bool IsFloat()   const { return type_ == kRegTypeFloat; }
+  bool IsDouble()  const { return type_ == kRegTypeDoubleLo; }
+  bool IsUnresolvedReference() const { return type_ == kRegTypeUnresolvedReference; }
+  bool IsUninitializedReference() const { return type_ == kRegTypeUninitializedReference; }
+  bool IsUninitializedThisReference() const { return type_ == kRegTypeUninitializedThisReference; }
+  bool IsUnresolvedAndUninitializedReference() const {
+    return type_ == kRegTypeUnresolvedAndUninitializedReference;
+  }
+  bool IsReference() const { return type_ == kRegTypeReference; }
+  bool IsUninitializedTypes() const {
+    return IsUninitializedReference() || IsUninitializedThisReference() ||
+        IsUnresolvedAndUninitializedReference();
+  }
+  bool IsUnresolvedTypes() const {
+    return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference();
+  }
+  bool IsLowHalf() const { return type_ == kRegTypeLongLo ||
+                                  type_ == kRegTypeDoubleLo ||
+                                  type_ == kRegTypeConstLo; }
+  bool IsHighHalf() const { return type_ == kRegTypeLongHi ||
+                                   type_ == kRegTypeDoubleHi ||
+                                   type_ == kRegTypeConstHi; }
+
+  bool IsLongOrDoubleTypes() const { return IsLowHalf(); }
+
+  // Check this is the low half, and that type_h is its matching high-half
+  bool CheckWidePair(const RegType& type_h) const {
+    return IsLowHalf() && (type_h.type_ == type_ + 1);
+  }
+
+  // The high half that corresponds to this low half
+  const RegType& HighHalf(RegTypeCache* cache) const;
+
+  bool IsConstant() const { return type_ == kRegTypeConst; }
+  bool IsLongConstant() const { return type_ == kRegTypeConstLo; }
+  bool IsLongConstantHigh() const { return type_ == kRegTypeConstHi; }
+
+  // If this is a 32-bit constant, what is the value? This value may just
+  // approximate to the actual constant value by virtue of merging.
+  int32_t ConstantValue() const {
+    DCHECK(IsConstant());
+    return allocation_pc_or_constant_;
+  }
+
+  bool IsZero()         const { return IsConstant() && ConstantValue() == 0; }
+  bool IsOne()          const { return IsConstant() && ConstantValue() == 1; }
+  bool IsConstantBoolean() const { return IsZero() || IsOne(); }
+  bool IsConstantByte() const {
+    return IsConstant() &&
+        ConstantValue() >= std::numeric_limits<jbyte>::min() &&
+        ConstantValue() <= std::numeric_limits<jbyte>::max();
+  }
+  bool IsConstantShort() const {
+    return IsConstant() &&
+        ConstantValue() >= std::numeric_limits<jshort>::min() &&
+        ConstantValue() <= std::numeric_limits<jshort>::max();
+  }
+  bool IsConstantChar() const {
+    return IsConstant() && ConstantValue() >= 0 &&
+        ConstantValue() <= std::numeric_limits<jchar>::max();
+  }
+
+  bool IsReferenceTypes() const {
+    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
+        IsUninitializedThisReference() || IsUnresolvedAndUninitializedReference() || IsZero();
+  }
+  bool IsNonZeroReferenceTypes() const {
+    return IsReference() || IsUnresolvedReference() || IsUninitializedReference() ||
+        IsUninitializedThisReference();
+  }
+  bool IsCategory1Types() const {
+    return (type_ >= kRegType1nrSTART && type_ <= kRegType1nrEND) || IsConstant();
+  }
+  bool IsCategory2Types() const {
+    return IsLowHalf();  // Don't expect explicit testing of high halves
+  }
+
+  bool IsBooleanTypes() const { return IsBoolean() || IsConstantBoolean(); }
+  bool IsByteTypes() const { return IsByte() || IsBoolean() || IsConstantByte(); }
+  bool IsShortTypes() const { return IsShort() || IsByte() || IsBoolean() || IsConstantShort(); }
+  bool IsCharTypes() const { return IsChar() || IsBooleanTypes() || IsConstantChar(); }
+  bool IsIntegralTypes() const {
+    return (type_ >= kRegTypeIntegralSTART && type_ <= kRegTypeIntegralEND) || IsConstant();
+  }
+  bool IsArrayIndexTypes() const { return IsIntegralTypes(); }
+
+  // Float type may be derived from any constant type
+  bool IsFloatTypes() const { return IsFloat() || IsConstant(); }
+
+  bool IsLongTypes() const {
+    return IsLong() || IsLongConstant();
+  }
+  bool IsLongHighTypes() const {
+    return type_ == kRegTypeLongHi || type_ == kRegTypeConstHi;
+  }
+  bool IsDoubleTypes() const {
+    return IsDouble() || IsLongConstant();
+  }
+  bool IsDoubleHighTypes() const {
+    return type_ == kRegTypeDoubleHi || type_ == kRegTypeConstHi;
+  }
+
+  uint32_t GetAllocationPc() const {
+    DCHECK(IsUninitializedTypes());
+    return allocation_pc_or_constant_;
+  }
+
+  Class* GetClass() const {
+    DCHECK(!IsUnresolvedReference());
+    DCHECK(klass_or_descriptor_ != NULL);
+    DCHECK(klass_or_descriptor_->IsClass());
+    return down_cast<Class*>(klass_or_descriptor_);
+  }
+
+  bool IsJavaLangObject() const {
+    return IsReference() && GetClass()->IsObjectClass();
+  }
+
+  bool IsArrayTypes() const {
+    if (IsUnresolvedTypes()) {
+      return GetDescriptor()->CharAt(0) == '[';
+    } else if (IsReference()) {
+      return GetClass()->IsArrayClass();
+    } else {
+      return false;
+    }
+  }
+
+  bool IsObjectArrayTypes() const {
+    if (IsUnresolvedTypes()) {
+      // Primitive arrays will always resolve
+      DCHECK(GetDescriptor()->CharAt(1) == 'L' || GetDescriptor()->CharAt(1) == '[');
+      return GetDescriptor()->CharAt(0) == '[';
+    } else if (IsReference()) {
+      Class* type = GetClass();
+      return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
+    } else {
+      return false;
+    }
+  }
+
+  Primitive::Type GetPrimitiveType() const {
+    if (IsNonZeroReferenceTypes()) {
+      return Primitive::kPrimNot;
+    } else if (IsBooleanTypes()) {
+      return Primitive::kPrimBoolean;
+    } else if (IsByteTypes()) {
+      return Primitive::kPrimByte;
+    } else if (IsShortTypes()) {
+      return Primitive::kPrimShort;
+    } else if (IsCharTypes()) {
+      return Primitive::kPrimChar;
+    } else if (IsFloat()) {
+      return Primitive::kPrimFloat;
+    } else if (IsIntegralTypes()) {
+      return Primitive::kPrimInt;
+    } else if (IsDouble()) {
+      return Primitive::kPrimDouble;
+    } else {
+      DCHECK(IsLongTypes());
+      return Primitive::kPrimLong;
+    }
+  }
+
+  bool IsJavaLangObjectArray() const {
+    if (IsReference()) {
+      Class* type = GetClass();
+      return type->IsArrayClass() && type->GetComponentType()->IsObjectClass();
+    }
+    return false;
+  }
+
+  bool IsInstantiableTypes() const {
+    return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
+  }
+
+  String* GetDescriptor() const {
+    DCHECK(IsUnresolvedTypes());
+    DCHECK(klass_or_descriptor_ != NULL);
+    DCHECK(klass_or_descriptor_->GetClass()->IsStringClass());
+    return down_cast<String*>(klass_or_descriptor_);
+  }
+
+  uint16_t GetId() const {
+    return cache_id_;
+  }
+
+  std::string Dump() const;
+
+  bool IsAssignableFrom(const RegType& src) const;
+
+  const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const;
+
+  bool Equals(const RegType& other) const { return GetId() == other.GetId(); }
+
+  /*
+   * A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
+   * S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
+   * S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
+   * is the deepest (lowest upper bound) parent of S and T).
+   *
+   * This operation applies for regular classes and arrays, however, for interface types there needn't
+   * be a partial ordering on the types. We could solve the problem of a lack of a partial order by
+   * introducing sets of types, however, the only operation permissible on an interface is
+   * invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
+   * types until an invoke-interface call on the interface typed reference at runtime and allow
+   * the perversion of Object being assignable to an interface type (note, however, that we don't
+   * allow assignment of Object or Interface to any concrete class and are therefore type safe).
+   *
+   * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
+   */
+  static Class* ClassJoin(Class* s, Class* t);
+
+ private:
+  friend class RegTypeCache;
+
+  RegType(Type type, Object* klass_or_descriptor, uint32_t allocation_pc_or_constant, uint16_t cache_id) :
+    type_(type), klass_or_descriptor_(klass_or_descriptor), allocation_pc_or_constant_(allocation_pc_or_constant),
+    cache_id_(cache_id) {
+    DCHECK(IsConstant() || IsUninitializedTypes() || allocation_pc_or_constant == 0);
+    if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUnknown() &&
+        !IsConflict()) {
+      DCHECK(klass_or_descriptor != NULL);
+      DCHECK(IsUnresolvedTypes() || klass_or_descriptor_->IsClass());
+      DCHECK(!IsUnresolvedTypes() || klass_or_descriptor_->GetClass()->IsStringClass());
+    }
+  }
+
+  const Type type_;  // The current type of the register
+
+  // If known the type of the register, else a String for the descriptor
+  Object* klass_or_descriptor_;
+
+  // Overloaded field that:
+  //   - if IsConstant() holds a 32bit constant value
+  //   - is IsReference() holds the allocation_pc or kInitArgAddr for an initialized reference or
+  //     kUninitThisArgAddr for an uninitialized this ptr
+  const uint32_t allocation_pc_or_constant_;
+
+  // A RegType cache densely encodes types, this is the location in the cache for this type
+  const uint16_t cache_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegType);
+};
+std::ostream& operator<<(std::ostream& os, const RegType& rhs);
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_REG_TYPE_H_
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
new file mode 100644
index 0000000..d06377a
--- /dev/null
+++ b/src/verifier/reg_type_cache.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "reg_type_cache.h"
+
+#include "object_utils.h"
+
+namespace art {
+namespace verifier {
+
+static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
+  switch (prim_type) {
+    case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
+    case Primitive::kPrimByte:    return RegType::kRegTypeByte;
+    case Primitive::kPrimShort:   return RegType::kRegTypeShort;
+    case Primitive::kPrimChar:    return RegType::kRegTypeChar;
+    case Primitive::kPrimInt:     return RegType::kRegTypeInteger;
+    case Primitive::kPrimLong:    return RegType::kRegTypeLongLo;
+    case Primitive::kPrimFloat:   return RegType::kRegTypeFloat;
+    case Primitive::kPrimDouble:  return RegType::kRegTypeDoubleLo;
+    case Primitive::kPrimVoid:
+    default:                      return RegType::kRegTypeUnknown;
+  }
+}
+
+static RegType::Type RegTypeFromDescriptor(const std::string& descriptor) {
+  if (descriptor.length() == 1) {
+    switch (descriptor[0]) {
+      case 'Z': return RegType::kRegTypeBoolean;
+      case 'B': return RegType::kRegTypeByte;
+      case 'S': return RegType::kRegTypeShort;
+      case 'C': return RegType::kRegTypeChar;
+      case 'I': return RegType::kRegTypeInteger;
+      case 'J': return RegType::kRegTypeLongLo;
+      case 'F': return RegType::kRegTypeFloat;
+      case 'D': return RegType::kRegTypeDoubleLo;
+      case 'V':
+      default:  return RegType::kRegTypeUnknown;
+    }
+  } else if (descriptor[0] == 'L' || descriptor[0] == '[') {
+    return RegType::kRegTypeReference;
+  } else {
+    return RegType::kRegTypeUnknown;
+  }
+}
+
+const RegType& RegTypeCache::FromDescriptor(const ClassLoader* loader,
+                                            const char* descriptor) {
+  return From(RegTypeFromDescriptor(descriptor), loader, descriptor);
+}
+
+const RegType& RegTypeCache::From(RegType::Type type, const ClassLoader* loader,
+                                  const char* descriptor) {
+  if (type <= RegType::kRegTypeLastFixedLocation) {
+    // entries should be sized greater than primitive types
+    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
+    RegType* entry = entries_[type];
+    if (entry == NULL) {
+      Class* klass = NULL;
+      if (strlen(descriptor) != 0) {
+        klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
+      }
+      entry = new RegType(type, klass, 0, type);
+      entries_[type] = entry;
+    }
+    return *entry;
+  } else {
+    DCHECK(type == RegType::kRegTypeReference);
+    ClassHelper kh;
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      // check resolved and unresolved references, ignore uninitialized references
+      if (cur_entry->IsReference()) {
+        kh.ChangeClass(cur_entry->GetClass());
+        if (strcmp(descriptor, kh.GetDescriptor()) == 0) {
+          return *cur_entry;
+        }
+      } else if (cur_entry->IsUnresolvedReference() &&
+                 cur_entry->GetDescriptor()->Equals(descriptor)) {
+        return *cur_entry;
+      }
+    }
+    Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
+    if (klass != NULL) {
+      // Able to resolve so create resolved register type
+      RegType* entry = new RegType(type, klass, 0, entries_.size());
+      entries_.push_back(entry);
+      return *entry;
+    } else {
+      // TODO: we assume unresolved, but we may be able to do better by validating whether the
+      // descriptor string is valid
+      // Unable to resolve so create unresolved register type
+      DCHECK(Thread::Current()->IsExceptionPending());
+      Thread::Current()->ClearException();
+      if (IsValidDescriptor(descriptor)) {
+        String* string_descriptor =
+            Runtime::Current()->GetInternTable()->InternStrong(descriptor);
+        RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
+                                     entries_.size());
+        entries_.push_back(entry);
+        return *entry;
+      } else {
+        // The descriptor is broken return the unknown type as there's nothing sensible that
+        // could be done at runtime
+        return Unknown();
+      }
+    }
+  }
+}
+
+const RegType& RegTypeCache::FromClass(Class* klass) {
+  if (klass->IsPrimitive()) {
+    RegType::Type type = RegTypeFromPrimitiveType(klass->GetPrimitiveType());
+    // entries should be sized greater than primitive types
+    DCHECK_GT(entries_.size(), static_cast<size_t>(type));
+    RegType* entry = entries_[type];
+    if (entry == NULL) {
+      entry = new RegType(type, klass, 0, type);
+      entries_[type] = entry;
+    }
+    return *entry;
+  } else {
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    RegType* entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+    entries_.push_back(entry);
+    return *entry;
+  }
+}
+
+const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
+  RegType* entry;
+  if (type.IsUnresolvedTypes()) {
+    String* descriptor = type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedAndUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUnresolvedAndUninitializedReference,
+                        descriptor, allocation_pc, entries_.size());
+  } else {
+    Class* klass = type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUninitializedReference() &&
+          cur_entry->GetAllocationPc() == allocation_pc &&
+          cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUninitializedReference,
+                        klass, allocation_pc, entries_.size());
+  }
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
+  RegType* entry;
+  if (uninit_type.IsUnresolvedTypes()) {
+    String* descriptor = uninit_type.GetDescriptor();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
+  } else {
+    Class* klass = uninit_type.GetClass();
+    for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+      RegType* cur_entry = entries_[i];
+      if (cur_entry->IsReference() && cur_entry->GetClass() == klass) {
+        return *cur_entry;
+      }
+    }
+    entry = new RegType(RegType::kRegTypeReference, klass, 0, entries_.size());
+  }
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::UninitializedThisArgument(Class* klass) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+    RegType* cur_entry = entries_[i];
+    if (cur_entry->IsUninitializedThisReference() && cur_entry->GetClass() == klass) {
+      return *cur_entry;
+    }
+  }
+  RegType* entry = new RegType(RegType::kRegTypeUninitializedThisReference, klass, 0,
+                               entries_.size());
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::FromType(RegType::Type type) {
+  CHECK(type < RegType::kRegTypeReference);
+  switch (type) {
+    case RegType::kRegTypeBoolean:  return From(type, NULL, "Z");
+    case RegType::kRegTypeByte:     return From(type, NULL, "B");
+    case RegType::kRegTypeShort:    return From(type, NULL, "S");
+    case RegType::kRegTypeChar:     return From(type, NULL, "C");
+    case RegType::kRegTypeInteger:  return From(type, NULL, "I");
+    case RegType::kRegTypeFloat:    return From(type, NULL, "F");
+    case RegType::kRegTypeLongLo:
+    case RegType::kRegTypeLongHi:   return From(type, NULL, "J");
+    case RegType::kRegTypeDoubleLo:
+    case RegType::kRegTypeDoubleHi: return From(type, NULL, "D");
+    default:                        return From(type, NULL, "");
+  }
+}
+
+const RegType& RegTypeCache::FromCat1Const(int32_t value) {
+  for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
+    RegType* cur_entry = entries_[i];
+    if (cur_entry->IsConstant() && cur_entry->ConstantValue() == value) {
+      return *cur_entry;
+    }
+  }
+  RegType* entry = new RegType(RegType::kRegTypeConst, NULL, value, entries_.size());
+  entries_.push_back(entry);
+  return *entry;
+}
+
+const RegType& RegTypeCache::GetComponentType(const RegType& array, const ClassLoader* loader) {
+  CHECK(array.IsArrayTypes());
+  if (array.IsUnresolvedTypes()) {
+    std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
+    std::string component(descriptor.substr(1, descriptor.size() - 1));
+    return FromDescriptor(loader, component.c_str());
+  } else {
+    return FromClass(array.GetClass()->GetComponentType());
+  }
+}
+
+}  // verifier
+}  // art
diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h
new file mode 100644
index 0000000..9c5e227
--- /dev/null
+++ b/src/verifier/reg_type_cache.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_REG_TYPE_CACHE_H_
+#define ART_SRC_VERIFIER_REG_TYPE_CACHE_H_
+
+#include "macros.h"
+#include "reg_type.h"
+#include "stl_util.h"
+
+namespace art {
+namespace verifier {
+
+class RegTypeCache {
+ public:
+  explicit RegTypeCache() : entries_(RegType::kRegTypeLastFixedLocation + 1) {
+    Unknown();  // ensure Unknown is initialized
+  }
+  ~RegTypeCache() {
+    STLDeleteElements(&entries_);
+  }
+
+  const RegType& GetFromId(uint16_t id) {
+    DCHECK_LT(id, entries_.size());
+    RegType* result = entries_[id];
+    DCHECK(result != NULL);
+    return *result;
+  }
+
+  const RegType& From(RegType::Type type, const ClassLoader* loader, const char* descriptor);
+  const RegType& FromClass(Class* klass);
+  const RegType& FromCat1Const(int32_t value);
+  const RegType& FromDescriptor(const ClassLoader* loader, const char* descriptor);
+  const RegType& FromType(RegType::Type);
+
+  const RegType& Boolean() { return FromType(RegType::kRegTypeBoolean); }
+  const RegType& Byte()    { return FromType(RegType::kRegTypeByte); }
+  const RegType& Char()    { return FromType(RegType::kRegTypeChar); }
+  const RegType& Short()   { return FromType(RegType::kRegTypeShort); }
+  const RegType& Integer() { return FromType(RegType::kRegTypeInteger); }
+  const RegType& Float()   { return FromType(RegType::kRegTypeFloat); }
+  const RegType& Long()    { return FromType(RegType::kRegTypeLongLo); }
+  const RegType& Double()  { return FromType(RegType::kRegTypeDoubleLo); }
+
+  const RegType& JavaLangClass()  { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Class;"); }
+  const RegType& JavaLangObject() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Object;"); }
+  const RegType& JavaLangString() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/String;"); }
+  const RegType& JavaLangThrowable() { return From(RegType::kRegTypeReference, NULL, "Ljava/lang/Throwable;"); }
+
+  const RegType& Unknown()  { return FromType(RegType::kRegTypeUnknown); }
+  const RegType& Conflict() { return FromType(RegType::kRegTypeConflict); }
+  const RegType& ConstLo()  { return FromType(RegType::kRegTypeConstLo); }
+  const RegType& Zero()     { return FromCat1Const(0); }
+
+  const RegType& Uninitialized(const RegType& type, uint32_t allocation_pc);
+  const RegType& UninitializedThisArgument(Class* klass);
+  const RegType& FromUninitialized(const RegType& uninit_type);
+
+  // Representatives of various constant types. When merging constants we can't infer a type,
+  // (an int may later be used as a float) so we select these representative values meaning future
+  // merges won't know the exact constant value but have some notion of its size.
+  const RegType& ByteConstant() { return FromCat1Const(std::numeric_limits<jbyte>::min()); }
+  const RegType& ShortConstant() { return FromCat1Const(std::numeric_limits<jshort>::min()); }
+  const RegType& IntConstant() { return FromCat1Const(std::numeric_limits<jint>::max()); }
+
+  const RegType& GetComponentType(const RegType& array, const ClassLoader* loader);
+ private:
+  // The allocated entries
+  std::vector<RegType*> entries_;
+
+  DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_REG_TYPE_CACHE_H_
diff --git a/src/dex_verifier_test.cc b/src/verifier/reg_type_test.cc
similarity index 89%
rename from src/dex_verifier_test.cc
rename to src/verifier/reg_type_test.cc
index fba1d34..52e4228 100644
--- a/src/dex_verifier_test.cc
+++ b/src/verifier/reg_type_test.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,53 +14,18 @@
  * limitations under the License.
  */
 
-#include "dex_verifier.h"
+#include "reg_type.h"
 
-#include <stdio.h>
+#include "reg_type_cache.h"
 
-#include "UniquePtr.h"
-#include "class_linker.h"
 #include "common_test.h"
-#include "dex_file.h"
 
 namespace art {
 namespace verifier {
 
-class DexVerifierTest : public CommonTest {
- protected:
-  void VerifyClass(const std::string& descriptor) {
-    ASSERT_TRUE(descriptor != NULL);
-    Class* klass = class_linker_->FindSystemClass(descriptor.c_str());
+class RegTypeTest : public CommonTest {};
 
-    // Verify the class
-    std::string error_msg;
-    ASSERT_TRUE(DexVerifier::VerifyClass(klass, error_msg)) << error_msg;
-  }
-
-  void VerifyDexFile(const DexFile* dex) {
-    ASSERT_TRUE(dex != NULL);
-
-    // Verify all the classes defined in this file
-    for (size_t i = 0; i < dex->NumClassDefs(); i++) {
-      const DexFile::ClassDef& class_def = dex->GetClassDef(i);
-      const char* descriptor = dex->GetClassDescriptor(class_def);
-      VerifyClass(descriptor);
-    }
-  }
-};
-
-TEST_F(DexVerifierTest, LibCore) {
-  VerifyDexFile(java_lang_dex_file_);
-}
-
-TEST_F(DexVerifierTest, IntMath) {
-  SirtRef<ClassLoader> class_loader(LoadDex("IntMath"));
-  Class* klass = class_linker_->FindClass("LIntMath;", class_loader.get());
-  std::string error_msg;
-  ASSERT_TRUE(DexVerifier::VerifyClass(klass, error_msg)) << error_msg;
-}
-
-TEST_F(DexVerifierTest, RegTypes_Primitives) {
+TEST_F(RegTypeTest, Primitives) {
   RegTypeCache cache;
 
   const RegType& bool_reg_type = cache.Boolean();
diff --git a/src/verifier/register_line.cc b/src/verifier/register_line.cc
new file mode 100644
index 0000000..6a86411
--- /dev/null
+++ b/src/verifier/register_line.cc
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "register_line.h"
+
+#include "method_verifier.h"
+
+namespace art {
+namespace verifier {
+
+bool RegisterLine::CheckConstructorReturn() const {
+  for (size_t i = 0; i < num_regs_; i++) {
+    if (GetRegisterType(i).IsUninitializedThisReference()) {
+      verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
+          << "Constructor returning without calling superclass constructor";
+      return false;
+    }
+  }
+  return true;
+}
+
+bool RegisterLine::SetRegisterType(uint32_t vdst, const RegType& new_type) {
+  DCHECK(vdst < num_regs_);
+  if (new_type.IsLowHalf()) {
+    line_[vdst] = new_type.GetId();
+    line_[vdst + 1] = new_type.HighHalf(verifier_->GetRegTypeCache()).GetId();
+  } else if (new_type.IsHighHalf()) {
+    /* should never set these explicitly */
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Explicit set of high register type";
+    return false;
+  } else if (new_type.IsConflict()) {  // should only be set during a merge
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Set register to unknown type " << new_type;
+    return false;
+  } else {
+    line_[vdst] = new_type.GetId();
+  }
+  // Clear the monitor entry bits for this register.
+  ClearAllRegToLockDepths(vdst);
+  return true;
+}
+
+void RegisterLine::SetResultTypeToUnknown() {
+  uint16_t unknown_id = verifier_->GetRegTypeCache()->Unknown().GetId();
+  result_[0] = unknown_id;
+  result_[1] = unknown_id;
+}
+
+void RegisterLine::SetResultRegisterType(const RegType& new_type) {
+  result_[0] = new_type.GetId();
+  if (new_type.IsLowHalf()) {
+    DCHECK_EQ(new_type.HighHalf(verifier_->GetRegTypeCache()).GetId(), new_type.GetId() + 1);
+    result_[1] = new_type.GetId() + 1;
+  } else {
+    result_[1] = verifier_->GetRegTypeCache()->Unknown().GetId();
+  }
+}
+
+const RegType& RegisterLine::GetRegisterType(uint32_t vsrc) const {
+  // The register index was validated during the static pass, so we don't need to check it here.
+  DCHECK_LT(vsrc, num_regs_);
+  return verifier_->GetRegTypeCache()->GetFromId(line_[vsrc]);
+}
+
+const RegType& RegisterLine::GetInvocationThis(const DecodedInstruction& dec_insn) {
+  if (dec_insn.vA < 1) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke lacks 'this'";
+    return verifier_->GetRegTypeCache()->Unknown();
+  }
+  /* get the element type of the array held in vsrc */
+  const RegType& this_type = GetRegisterType(dec_insn.vC);
+  if (!this_type.IsReferenceTypes()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "tried to get class from non-reference register v"
+                                                 << dec_insn.vC << " (type=" << this_type << ")";
+    return verifier_->GetRegTypeCache()->Unknown();
+  }
+  return this_type;
+}
+
+bool RegisterLine::VerifyRegisterType(uint32_t vsrc, const RegType& check_type) {
+  // Verify the src register type against the check type refining the type of the register
+  const RegType& src_type = GetRegisterType(vsrc);
+  if (!check_type.IsAssignableFrom(src_type)) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "register v" << vsrc << " has type " << src_type
+                                                 << " but expected " << check_type;
+    return false;
+  }
+  if (check_type.IsLowHalf()) {
+    const RegType& src_type_h = GetRegisterType(vsrc + 1);
+    if (!src_type.CheckWidePair(src_type_h)) {
+      verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "wide register v" << vsrc << " has type "
+                                                   << src_type << "/" << src_type_h;
+      return false;
+    }
+  }
+  // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less
+  // precise than the subtype in vsrc so leave it for reference types. For primitive types
+  // if they are a defined type then they are as precise as we can get, however, for constant
+  // types we may wish to refine them. Unfortunately constant propagation has rendered this useless.
+  return true;
+}
+
+void RegisterLine::MarkRefsAsInitialized(const RegType& uninit_type) {
+  DCHECK(uninit_type.IsUninitializedTypes());
+  const RegType& init_type = verifier_->GetRegTypeCache()->FromUninitialized(uninit_type);
+  size_t changed = 0;
+  for (size_t i = 0; i < num_regs_; i++) {
+    if (GetRegisterType(i).Equals(uninit_type)) {
+      line_[i] = init_type.GetId();
+      changed++;
+    }
+  }
+  DCHECK_GT(changed, 0u);
+}
+
+void RegisterLine::MarkUninitRefsAsInvalid(const RegType& uninit_type) {
+  for (size_t i = 0; i < num_regs_; i++) {
+    if (GetRegisterType(i).Equals(uninit_type)) {
+      line_[i] = verifier_->GetRegTypeCache()->Conflict().GetId();
+      ClearAllRegToLockDepths(i);
+    }
+  }
+}
+
+void RegisterLine::CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat) {
+  DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
+  const RegType& type = GetRegisterType(vsrc);
+  if (!SetRegisterType(vdst, type)) {
+    return;
+  }
+  if ((cat == kTypeCategory1nr && !type.IsCategory1Types()) ||
+      (cat == kTypeCategoryRef && !type.IsReferenceTypes())) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type
+                                                 << " cat=" << static_cast<int>(cat);
+  } else if (cat == kTypeCategoryRef) {
+    CopyRegToLockDepth(vdst, vsrc);
+  }
+}
+
+void RegisterLine::CopyRegister2(uint32_t vdst, uint32_t vsrc) {
+  const RegType& type_l = GetRegisterType(vsrc);
+  const RegType& type_h = GetRegisterType(vsrc + 1);
+
+  if (!type_l.CheckWidePair(type_h)) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy2 v" << vdst << "<-v" << vsrc
+                                                 << " type=" << type_l << "/" << type_h;
+  } else {
+    SetRegisterType(vdst, type_l);  // implicitly sets the second half
+  }
+}
+
+void RegisterLine::CopyResultRegister1(uint32_t vdst, bool is_reference) {
+  const RegType& type = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
+  if ((!is_reference && !type.IsCategory1Types()) ||
+      (is_reference && !type.IsReferenceTypes())) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
+        << "copyRes1 v" << vdst << "<- result0"  << " type=" << type;
+  } else {
+    DCHECK(verifier_->GetRegTypeCache()->GetFromId(result_[1]).IsUnknown());
+    SetRegisterType(vdst, type);
+    result_[0] = verifier_->GetRegTypeCache()->Unknown().GetId();
+  }
+}
+
+/*
+ * Implement "move-result-wide". Copy the category-2 value from the result
+ * register to another register, and reset the result register.
+ */
+void RegisterLine::CopyResultRegister2(uint32_t vdst) {
+  const RegType& type_l = verifier_->GetRegTypeCache()->GetFromId(result_[0]);
+  const RegType& type_h = verifier_->GetRegTypeCache()->GetFromId(result_[1]);
+  if (!type_l.IsCategory2Types()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD)
+        << "copyRes2 v" << vdst << "<- result0"  << " type=" << type_l;
+  } else {
+    DCHECK(type_l.CheckWidePair(type_h));  // Set should never allow this case
+    SetRegisterType(vdst, type_l);  // also sets the high
+    result_[0] = verifier_->GetRegTypeCache()->Unknown().GetId();
+    result_[1] = verifier_->GetRegTypeCache()->Unknown().GetId();
+  }
+}
+
+void RegisterLine::CheckUnaryOp(const DecodedInstruction& dec_insn,
+                                const RegType& dst_type, const RegType& src_type) {
+  if (VerifyRegisterType(dec_insn.vB, src_type)) {
+    SetRegisterType(dec_insn.vA, dst_type);
+  }
+}
+
+void RegisterLine::CheckBinaryOp(const DecodedInstruction& dec_insn,
+                                 const RegType& dst_type,
+                                 const RegType& src_type1, const RegType& src_type2,
+                                 bool check_boolean_op) {
+  if (VerifyRegisterType(dec_insn.vB, src_type1) &&
+      VerifyRegisterType(dec_insn.vC, src_type2)) {
+    if (check_boolean_op) {
+      DCHECK(dst_type.IsInteger());
+      if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
+          GetRegisterType(dec_insn.vC).IsBooleanTypes()) {
+        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
+        return;
+      }
+    }
+    SetRegisterType(dec_insn.vA, dst_type);
+  }
+}
+
+void RegisterLine::CheckBinaryOp2addr(const DecodedInstruction& dec_insn,
+                                      const RegType& dst_type, const RegType& src_type1,
+                                      const RegType& src_type2, bool check_boolean_op) {
+  if (VerifyRegisterType(dec_insn.vA, src_type1) &&
+      VerifyRegisterType(dec_insn.vB, src_type2)) {
+    if (check_boolean_op) {
+      DCHECK(dst_type.IsInteger());
+      if (GetRegisterType(dec_insn.vA).IsBooleanTypes() &&
+          GetRegisterType(dec_insn.vB).IsBooleanTypes()) {
+        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
+        return;
+      }
+    }
+    SetRegisterType(dec_insn.vA, dst_type);
+  }
+}
+
+void RegisterLine::CheckLiteralOp(const DecodedInstruction& dec_insn,
+                                  const RegType& dst_type, const RegType& src_type,
+                                  bool check_boolean_op) {
+  if (VerifyRegisterType(dec_insn.vB, src_type)) {
+    if (check_boolean_op) {
+      DCHECK(dst_type.IsInteger());
+      /* check vB with the call, then check the constant manually */
+      if (GetRegisterType(dec_insn.vB).IsBooleanTypes() &&
+          (dec_insn.vC == 0 || dec_insn.vC == 1)) {
+        SetRegisterType(dec_insn.vA, verifier_->GetRegTypeCache()->Boolean());
+        return;
+      }
+    }
+    SetRegisterType(dec_insn.vA, dst_type);
+  }
+}
+
+void RegisterLine::PushMonitor(uint32_t reg_idx, int32_t insn_idx) {
+  const RegType& reg_type = GetRegisterType(reg_idx);
+  if (!reg_type.IsReferenceTypes()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter on non-object (" << reg_type << ")";
+  } else if (monitors_.size() >= 32) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-enter stack overflow: " << monitors_.size();
+  } else {
+    SetRegToLockDepth(reg_idx, monitors_.size());
+    monitors_.push_back(insn_idx);
+  }
+}
+
+void RegisterLine::PopMonitor(uint32_t reg_idx) {
+  const RegType& reg_type = GetRegisterType(reg_idx);
+  if (!reg_type.IsReferenceTypes()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit on non-object (" << reg_type << ")";
+  } else if (monitors_.empty()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "monitor-exit stack underflow";
+  } else {
+    monitors_.pop_back();
+    if (!IsSetLockDepth(reg_idx, monitors_.size())) {
+      // Bug 3215458: Locks and unlocks are on objects, if that object is a literal then before
+      // format "036" the constant collector may create unlocks on the same object but referenced
+      // via different registers.
+      ((verifier_->DexFileVersion() >= 36) ? verifier_->Fail(VERIFY_ERROR_BAD_CLASS_SOFT)
+                                           : verifier_->LogVerifyInfo())
+            << "monitor-exit not unlocking the top of the monitor stack";
+    } else {
+      // Record the register was unlocked
+      ClearRegToLockDepth(reg_idx, monitors_.size());
+    }
+  }
+}
+
+bool RegisterLine::VerifyMonitorStackEmpty() {
+  if (MonitorStackDepth() != 0) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected empty monitor stack";
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) {
+  bool changed = false;
+  for (size_t idx = 0; idx < num_regs_; idx++) {
+    if (line_[idx] != incoming_line->line_[idx]) {
+      const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx);
+      const RegType& cur_type = GetRegisterType(idx);
+      const RegType& new_type = cur_type.Merge(incoming_reg_type, verifier_->GetRegTypeCache());
+      changed = changed || !cur_type.Equals(new_type);
+      line_[idx] = new_type.GetId();
+    }
+  }
+  if (monitors_.size() != incoming_line->monitors_.size()) {
+    verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths (depth="
+        << MonitorStackDepth() << ", incoming depth=" << incoming_line->MonitorStackDepth() << ")";
+  } else if (reg_to_lock_depths_ != incoming_line->reg_to_lock_depths_) {
+    for (uint32_t idx = 0; idx < num_regs_; idx++) {
+      size_t depths = reg_to_lock_depths_.count(idx);
+      size_t incoming_depths = incoming_line->reg_to_lock_depths_.count(idx);
+      if (depths != incoming_depths) {
+        if (depths == 0 || incoming_depths == 0) {
+          reg_to_lock_depths_.erase(idx);
+        } else {
+          verifier_->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "mismatched stack depths for register v" << idx
+                                                       << ": " << depths  << " != " << incoming_depths;
+          break;
+        }
+      }
+    }
+  }
+  return changed;
+}
+
+void RegisterLine::WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes) {
+  for (size_t i = 0; i < num_regs_; i += 8) {
+    uint8_t val = 0;
+    for (size_t j = 0; j < 8 && (i + j) < num_regs_; j++) {
+      // Note: we write 1 for a Reference but not for Null
+      if (GetRegisterType(i + j).IsNonZeroReferenceTypes()) {
+        val |= 1 << j;
+      }
+    }
+    if ((i / 8) >= max_bytes) {
+      DCHECK_EQ(0, val);
+      continue;
+    }
+    DCHECK_LT(i / 8, max_bytes) << "val=" << static_cast<uint32_t>(val);
+    data.push_back(val);
+  }
+}
+
+std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs) {
+  os << rhs.Dump();
+  return os;
+}
+
+}  // namespace verifier
+}  // namespace art
diff --git a/src/verifier/register_line.h b/src/verifier/register_line.h
new file mode 100644
index 0000000..6b921cc
--- /dev/null
+++ b/src/verifier/register_line.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_REGISTER_LINE_H_
+#define ART_SRC_VERIFIER_REGISTER_LINE_H_
+
+#include <deque>
+#include <vector>
+
+#include "dex_instruction.h"
+#include "reg_type.h"
+#include "safe_map.h"
+
+namespace art {
+namespace verifier {
+
+class MethodVerifier;
+
+/*
+ * Register type categories, for type checking.
+ *
+ * The spec says category 1 includes boolean, byte, char, short, int, float, reference, and
+ * returnAddress. Category 2 includes long and double.
+ *
+ * We treat object references separately, so we have "category1nr". We don't support jsr/ret, so
+ * there is no "returnAddress" type.
+ */
+enum TypeCategory {
+  kTypeCategoryUnknown = 0,
+  kTypeCategory1nr = 1,         // boolean, byte, char, short, int, float
+  kTypeCategory2 = 2,           // long, double
+  kTypeCategoryRef = 3,         // object reference
+};
+
+// During verification, we associate one of these with every "interesting" instruction. We track
+// the status of all registers, and (if the method has any monitor-enter instructions) maintain a
+// stack of entered monitors (identified by code unit offset).
+// If live-precise register maps are enabled, the "liveRegs" vector will be populated. Unlike the
+// other lists of registers here, we do not track the liveness of the method result register
+// (which is not visible to the GC).
+class RegisterLine {
+ public:
+  RegisterLine(size_t num_regs, MethodVerifier* verifier) :
+    line_(new uint16_t[num_regs]), verifier_(verifier), num_regs_(num_regs) {
+    memset(line_.get(), 0, num_regs_ * sizeof(uint16_t));
+    result_[0] = RegType::kRegTypeUnknown;
+    result_[1] = RegType::kRegTypeUnknown;
+  }
+
+  // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
+  void CopyRegister1(uint32_t vdst, uint32_t vsrc, TypeCategory cat);
+
+  // Implement category-2 "move" instructions. Copy a 64-bit value from "vsrc" to "vdst". This
+  // copies both halves of the register.
+  void CopyRegister2(uint32_t vdst, uint32_t vsrc);
+
+  // Implement "move-result". Copy the category-1 value from the result register to another
+  // register, and reset the result register.
+  void CopyResultRegister1(uint32_t vdst, bool is_reference);
+
+  // Implement "move-result-wide". Copy the category-2 value from the result register to another
+  // register, and reset the result register.
+  void CopyResultRegister2(uint32_t vdst);
+
+  // Set the invisible result register to unknown
+  void SetResultTypeToUnknown();
+
+  // Set the type of register N, verifying that the register is valid.  If "newType" is the "Lo"
+  // part of a 64-bit value, register N+1 will be set to "newType+1".
+  // The register index was validated during the static pass, so we don't need to check it here.
+  bool SetRegisterType(uint32_t vdst, const RegType& new_type);
+
+  /* Set the type of the "result" register. */
+  void SetResultRegisterType(const RegType& new_type);
+
+  // Get the type of register vsrc.
+  const RegType& GetRegisterType(uint32_t vsrc) const;
+
+  bool VerifyRegisterType(uint32_t vsrc, const RegType& check_type);
+
+  void CopyFromLine(const RegisterLine* src) {
+    DCHECK_EQ(num_regs_, src->num_regs_);
+    memcpy(line_.get(), src->line_.get(), num_regs_ * sizeof(uint16_t));
+    monitors_ = src->monitors_;
+    reg_to_lock_depths_ = src->reg_to_lock_depths_;
+  }
+
+  std::string Dump() const {
+    std::string result;
+    for (size_t i = 0; i < num_regs_; i++) {
+      result += StringPrintf("%zd:[", i);
+      result += GetRegisterType(i).Dump();
+      result += "],";
+    }
+    typedef std::deque<uint32_t>::const_iterator It; // TODO: C++0x auto
+    for (It it = monitors_.begin(), end = monitors_.end(); it != end ; ++it) {
+      result += StringPrintf("{%d},", *it);
+    }
+    return result;
+  }
+
+  void FillWithGarbage() {
+    memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t));
+    while (!monitors_.empty()) {
+      monitors_.pop_back();
+    }
+    reg_to_lock_depths_.clear();
+  }
+
+  /*
+   * We're creating a new instance of class C at address A. Any registers holding instances
+   * previously created at address A must be initialized by now. If not, we mark them as "conflict"
+   * to prevent them from being used (otherwise, MarkRefsAsInitialized would mark the old ones and
+   * the new ones at the same time).
+   */
+  void MarkUninitRefsAsInvalid(const RegType& uninit_type);
+
+  /*
+   * Update all registers holding "uninit_type" to instead hold the corresponding initialized
+   * reference type. This is called when an appropriate constructor is invoked -- all copies of
+   * the reference must be marked as initialized.
+   */
+  void MarkRefsAsInitialized(const RegType& uninit_type);
+
+  /*
+   * Check constraints on constructor return. Specifically, make sure that the "this" argument got
+   * initialized.
+   * The "this" argument to <init> uses code offset kUninitThisArgAddr, which puts it at the start
+   * of the list in slot 0. If we see a register with an uninitialized slot 0 reference, we know it
+   * somehow didn't get initialized.
+   */
+  bool CheckConstructorReturn() const;
+
+  // Compare two register lines. Returns 0 if they match.
+  // Using this for a sort is unwise, since the value can change based on machine endianness.
+  int CompareLine(const RegisterLine* line2) const {
+    DCHECK(monitors_ == line2->monitors_);
+    // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_);
+    return memcmp(line_.get(), line2->line_.get(), num_regs_ * sizeof(uint16_t));
+  }
+
+  size_t NumRegs() const {
+    return num_regs_;
+  }
+
+  /*
+   * Get the "this" pointer from a non-static method invocation. This returns the RegType so the
+   * caller can decide whether it needs the reference to be initialized or not. (Can also return
+   * kRegTypeZero if the reference can only be zero at this point.)
+   *
+   * The argument count is in vA, and the first argument is in vC, for both "simple" and "range"
+   * versions. We just need to make sure vA is >= 1 and then return vC.
+   */
+  const RegType& GetInvocationThis(const DecodedInstruction& dec_insn);
+
+  /*
+   * Verify types for a simple two-register instruction (e.g. "neg-int").
+   * "dst_type" is stored into vA, and "src_type" is verified against vB.
+   */
+  void CheckUnaryOp(const DecodedInstruction& dec_insn,
+                    const RegType& dst_type, const RegType& src_type);
+
+  /*
+   * Verify types for a simple three-register instruction (e.g. "add-int").
+   * "dst_type" is stored into vA, and "src_type1"/"src_type2" are verified
+   * against vB/vC.
+   */
+  void CheckBinaryOp(const DecodedInstruction& dec_insn,
+                     const RegType& dst_type, const RegType& src_type1, const RegType& src_type2,
+                     bool check_boolean_op);
+
+  /*
+   * Verify types for a binary "2addr" operation. "src_type1"/"src_type2"
+   * are verified against vA/vB, then "dst_type" is stored into vA.
+   */
+  void CheckBinaryOp2addr(const DecodedInstruction& dec_insn,
+                          const RegType& dst_type,
+                          const RegType& src_type1, const RegType& src_type2,
+                          bool check_boolean_op);
+
+  /*
+   * Verify types for A two-register instruction with a literal constant (e.g. "add-int/lit8").
+   * "dst_type" is stored into vA, and "src_type" is verified against vB.
+   *
+   * If "check_boolean_op" is set, we use the constant value in vC.
+   */
+  void CheckLiteralOp(const DecodedInstruction& dec_insn,
+                      const RegType& dst_type, const RegType& src_type, bool check_boolean_op);
+
+  // Verify/push monitor onto the monitor stack, locking the value in reg_idx at location insn_idx.
+  void PushMonitor(uint32_t reg_idx, int32_t insn_idx);
+
+  // Verify/pop monitor from monitor stack ensuring that we believe the monitor is locked
+  void PopMonitor(uint32_t reg_idx);
+
+  // Stack of currently held monitors and where they were locked
+  size_t MonitorStackDepth() const {
+    return monitors_.size();
+  }
+
+  // We expect no monitors to be held at certain points, such a method returns. Verify the stack
+  // is empty, failing and returning false if not.
+  bool VerifyMonitorStackEmpty();
+
+  bool MergeRegisters(const RegisterLine* incoming_line);
+
+  size_t GetMaxNonZeroReferenceReg(size_t max_ref_reg) {
+    size_t i = static_cast<int>(max_ref_reg) < 0 ? 0 : max_ref_reg;
+    for (; i < num_regs_; i++) {
+      if (GetRegisterType(i).IsNonZeroReferenceTypes()) {
+        max_ref_reg = i;
+      }
+    }
+    return max_ref_reg;
+  }
+
+  // Write a bit at each register location that holds a reference
+  void WriteReferenceBitMap(std::vector<uint8_t>& data, size_t max_bytes);
+ private:
+
+  void CopyRegToLockDepth(size_t dst, size_t src) {
+    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(src);
+    if (it != reg_to_lock_depths_.end()) {
+      reg_to_lock_depths_.Put(dst, it->second);
+    }
+  }
+
+  bool IsSetLockDepth(size_t reg, size_t depth) {
+    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
+    if (it != reg_to_lock_depths_.end()) {
+      return (it->second & (1 << depth)) != 0;
+    } else {
+      return false;
+    }
+  }
+
+  void SetRegToLockDepth(size_t reg, size_t depth) {
+    CHECK_LT(depth, 32u);
+    DCHECK(!IsSetLockDepth(reg, depth));
+    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
+    if (it == reg_to_lock_depths_.end()) {
+      reg_to_lock_depths_.Put(reg, 1 << depth);
+    } else {
+      it->second |= (1 << depth);
+    }
+  }
+
+  void ClearRegToLockDepth(size_t reg, size_t depth) {
+    CHECK_LT(depth, 32u);
+    DCHECK(IsSetLockDepth(reg, depth));
+    SafeMap<uint32_t, uint32_t>::iterator it = reg_to_lock_depths_.find(reg);
+    DCHECK(it != reg_to_lock_depths_.end());
+    uint32_t depths = it->second ^ (1 << depth);
+    if (depths != 0) {
+      it->second = depths;
+    } else {
+      reg_to_lock_depths_.erase(it);
+    }
+  }
+
+  void ClearAllRegToLockDepths(size_t reg) {
+    reg_to_lock_depths_.erase(reg);
+  }
+
+  // Storage for the result register's type, valid after an invocation
+  uint16_t result_[2];
+
+  // An array of RegType Ids associated with each dex register
+  UniquePtr<uint16_t[]> line_;
+
+  // Back link to the verifier
+  MethodVerifier* verifier_;
+
+  // Length of reg_types_
+  const size_t num_regs_;
+  // A stack of monitor enter locations
+  std::deque<uint32_t> monitors_;
+  // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
+  // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
+  // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5
+  SafeMap<uint32_t, uint32_t> reg_to_lock_depths_;
+};
+std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs);
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_REGISTER_LINE_H_