Refactor verification results.

Rename VerificationMethodsData to VerificationResults.
Create new class VerifiedMethod to hold all the data for
a given method.

Change-Id: Ife1ac67cede20f3a2f9c7f5345f08a851cf1ed20
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 25dfb0a..c6662c2 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -59,7 +59,8 @@
 	dex/frontend.cc \
 	dex/mir_graph.cc \
 	dex/mir_analysis.cc \
-	dex/verified_methods_data.cc \
+	dex/verified_method.cc \
+	dex/verification_results.cc \
 	dex/vreg_analysis.cc \
 	dex/ssa_transformation.cc \
 	driver/compiler_driver.cc \
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 1eb79c9..cb36813 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -21,7 +21,7 @@
 #include "mir_to_lir-inl.h"
 #include "dex/quick/dex_file_method_inliner.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
-#include "dex/verified_methods_data.h"
+#include "dex/verification_results.h"
 #include "verifier/dex_gc_map.h"
 #include "verifier/method_verifier.h"
 
@@ -764,7 +764,7 @@
   }
   MethodReference method_ref(cu_->dex_file, cu_->method_idx);
   const std::vector<uint8_t>* gc_map_raw =
-      cu_->compiler_driver->GetVerifiedMethodsData()->GetDexGcMap(method_ref);
+      cu_->compiler_driver->GetVerificationResults()->GetDexGcMap(method_ref);
   verifier::DexPcToReferenceMap dex_gc_map(&(*gc_map_raw)[0]);
   DCHECK_EQ(gc_map_raw->size(), dex_gc_map.RawSize());
   // Compute native offset to references size.
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
new file mode 100644
index 0000000..8b4fa1a
--- /dev/null
+++ b/compiler/dex/verification_results.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2013 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 "verification_results.h"
+
+#include "base/stl_util.h"
+#include "base/mutex.h"
+#include "base/mutex-inl.h"
+#include "thread.h"
+#include "thread-inl.h"
+#include "verified_method.h"
+#include "verifier/method_verifier.h"
+#include "verifier/method_verifier-inl.h"
+
+namespace art {
+
+VerificationResults::VerificationResults()
+    : verified_methods_lock_("compiler verified methods lock"),
+      verified_methods_(),
+      rejected_classes_lock_("compiler rejected classes lock"),
+      rejected_classes_() {
+}
+
+VerificationResults::~VerificationResults() {
+  Thread* self = Thread::Current();
+  {
+    WriterMutexLock mu(self, verified_methods_lock_);
+    STLDeleteValues(&verified_methods_);
+  }
+}
+
+bool VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) {
+  MethodReference ref = method_verifier->GetMethodReference();
+  bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags());
+  // TODO: Check also for virtual/interface invokes when DEX-to-DEX supports devirtualization.
+  if (!compile && !method_verifier->HasCheckCasts()) {
+    return true;
+  }
+
+  const VerifiedMethod* verified_method = VerifiedMethod::Create(method_verifier, compile);
+  if (verified_method == nullptr) {
+    DCHECK(method_verifier->HasFailures());
+    return false;
+  }
+
+  WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
+  auto it = verified_methods_.find(ref);
+  if (it != verified_methods_.end()) {
+    // TODO: Investigate why are we doing the work again for this method and try to avoid it.
+    LOG(WARNING) << "Method processed more than once: "
+        << PrettyMethod(ref.dex_method_index, *ref.dex_file);
+    DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size());
+    DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size());
+    DCHECK_EQ(it->second->GetDexGcMap().size(), verified_method->GetDexGcMap().size());
+    delete it->second;
+    verified_methods_.erase(it);
+  }
+  verified_methods_.Put(ref, verified_method);
+  DCHECK(verified_methods_.find(ref) != verified_methods_.end());
+  return true;
+}
+
+const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) {
+  ReaderMutexLock mu(Thread::Current(), verified_methods_lock_);
+  auto it = verified_methods_.find(ref);
+  return (it != verified_methods_.end()) ? it->second : nullptr;
+}
+
+const std::vector<uint8_t>* VerificationResults::GetDexGcMap(MethodReference ref) {
+  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
+  CHECK(verified_method != nullptr)
+    << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
+  return &verified_method->GetDexGcMap();
+}
+
+const MethodReference* VerificationResults::GetDevirtMap(const MethodReference& ref,
+                                                                    uint32_t dex_pc) {
+  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
+  return (verified_method != nullptr) ? verified_method->GetDevirtTarget(dex_pc) : nullptr;
+}
+
+bool VerificationResults::IsSafeCast(MethodReference ref, uint32_t pc) {
+  const VerifiedMethod* verified_method = GetVerifiedMethod(ref);
+  return (verified_method != nullptr) && (verified_method->IsSafeCast(pc));
+}
+
+void VerificationResults::AddRejectedClass(ClassReference ref) {
+  {
+    WriterMutexLock mu(Thread::Current(), rejected_classes_lock_);
+    rejected_classes_.insert(ref);
+  }
+  DCHECK(IsClassRejected(ref));
+}
+
+bool VerificationResults::IsClassRejected(ClassReference ref) {
+  ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_);
+  return (rejected_classes_.find(ref) != rejected_classes_.end());
+}
+
+bool VerificationResults::IsCandidateForCompilation(MethodReference& method_ref,
+                                                    const uint32_t access_flags) {
+#ifdef ART_SEA_IR_MODE
+    bool use_sea = Runtime::Current()->IsSeaIRMode();
+    use_sea = use_sea && (std::string::npos != PrettyMethod(
+                          method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
+    if (use_sea) return true;
+#endif
+  // Don't compile class initializers, ever.
+  if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
+    return false;
+  }
+  return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly);
+}
+
+}  // namespace art
diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h
new file mode 100644
index 0000000..e9cdb53
--- /dev/null
+++ b/compiler/dex/verification_results.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 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_COMPILER_DEX_VERIFICATION_RESULTS_H_
+#define ART_COMPILER_DEX_VERIFICATION_RESULTS_H_
+
+#include <stdint.h>
+#include <set>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/mutex.h"
+#include "class_reference.h"
+#include "method_reference.h"
+#include "safe_map.h"
+
+namespace art {
+
+namespace verifier {
+class MethodVerifier;
+}  // namespace verifier
+
+class VerifiedMethod;
+
+class VerificationResults {
+  public:
+    VerificationResults();
+    ~VerificationResults();
+
+    bool ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier)
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+        LOCKS_EXCLUDED(verified_methods_lock_);
+
+    const VerifiedMethod* GetVerifiedMethod(MethodReference ref)
+        LOCKS_EXCLUDED(verified_methods_lock_);
+
+    const std::vector<uint8_t>* GetDexGcMap(MethodReference ref)
+        LOCKS_EXCLUDED(verified_methods_lock_);
+
+    const MethodReference* GetDevirtMap(const MethodReference& ref, uint32_t dex_pc)
+        LOCKS_EXCLUDED(verified_methods_lock_);
+
+    // Returns true if the cast can statically be verified to be redundant
+    // by using the check-cast elision peephole optimization in the verifier.
+    bool IsSafeCast(MethodReference ref, uint32_t pc) LOCKS_EXCLUDED(safecast_map_lock_);
+
+    void AddRejectedClass(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
+    bool IsClassRejected(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
+
+    static bool IsCandidateForCompilation(MethodReference& method_ref,
+                                          const uint32_t access_flags);
+
+  private:
+    // Verified methods.
+    typedef SafeMap<MethodReference, const VerifiedMethod*,
+        MethodReferenceComparator> VerifiedMethodMap;
+    ReaderWriterMutex verified_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+    VerifiedMethodMap verified_methods_;
+
+    // Rejected classes.
+    ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+    std::set<ClassReference> rejected_classes_ GUARDED_BY(rejected_classes_lock_);
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_VERIFICATION_RESULTS_H_
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
new file mode 100644
index 0000000..0f812a4
--- /dev/null
+++ b/compiler/dex/verified_method.cc
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2014 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 "verified_method.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "dex_file.h"
+#include "dex_instruction.h"
+#include "dex_instruction-inl.h"
+#include "base/mutex.h"
+#include "base/mutex-inl.h"
+#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
+#include "mirror/class.h"
+#include "mirror/class-inl.h"
+#include "mirror/dex_cache.h"
+#include "mirror/dex_cache-inl.h"
+#include "mirror/object.h"
+#include "mirror/object-inl.h"
+#include "UniquePtr.h"
+#include "verifier/dex_gc_map.h"
+#include "verifier/method_verifier.h"
+#include "verifier/method_verifier-inl.h"
+#include "verifier/register_line.h"
+#include "verifier/register_line-inl.h"
+
+namespace art {
+
+const VerifiedMethod* VerifiedMethod::Create(verifier::MethodVerifier* method_verifier,
+                                             bool compile) {
+  UniquePtr<VerifiedMethod> verified_method(new VerifiedMethod);
+  if (compile) {
+    /* Generate a register map. */
+    if (!verified_method->GenerateGcMap(method_verifier)) {
+      CHECK(method_verifier->HasFailures());
+      return nullptr;  // Not a real failure, but a failure to encode.
+    }
+    if (kIsDebugBuild) {
+      VerifyGcMap(method_verifier, verified_method->dex_gc_map_);
+    }
+
+    // TODO: move this out when DEX-to-DEX supports devirtualization.
+    if (method_verifier->HasVirtualOrInterfaceInvokes()) {
+      verified_method->GenerateDevirtMap(method_verifier);
+    }
+  }
+
+  if (method_verifier->HasCheckCasts()) {
+    verified_method->GenerateSafeCastSet(method_verifier);
+  }
+  return verified_method.release();
+}
+
+const MethodReference* VerifiedMethod::GetDevirtTarget(uint32_t dex_pc) const {
+  auto it = devirt_map_.find(dex_pc);
+  return (it != devirt_map_.end()) ? &it->second : nullptr;
+}
+
+bool VerifiedMethod::IsSafeCast(uint32_t pc) const {
+  return std::binary_search(safe_cast_set_.begin(), safe_cast_set_.end(), pc);
+}
+
+bool VerifiedMethod::GenerateGcMap(verifier::MethodVerifier* method_verifier) {
+  DCHECK(dex_gc_map_.empty());
+  size_t num_entries, ref_bitmap_bits, pc_bits;
+  ComputeGcMapSizes(method_verifier, &num_entries, &ref_bitmap_bits, &pc_bits);
+  // There's a single byte to encode the size of each bitmap.
+  if (ref_bitmap_bits >= (8 /* bits per byte */ * 8192 /* 13-bit size */ )) {
+    // TODO: either a better GC map format or per method failures
+    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
+        << "Cannot encode GC map for method with " << ref_bitmap_bits << " registers";
+    return false;
+  }
+  size_t ref_bitmap_bytes = (ref_bitmap_bits + 7) / 8;
+  // There are 2 bytes to encode the number of entries.
+  if (num_entries >= 65536) {
+    // TODO: Either a better GC map format or per method failures.
+    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
+        << "Cannot encode GC map for method with " << num_entries << " entries";
+    return false;
+  }
+  size_t pc_bytes;
+  verifier::RegisterMapFormat format;
+  if (pc_bits <= 8) {
+    format = verifier::kRegMapFormatCompact8;
+    pc_bytes = 1;
+  } else if (pc_bits <= 16) {
+    format = verifier::kRegMapFormatCompact16;
+    pc_bytes = 2;
+  } else {
+    // TODO: Either a better GC map format or per method failures.
+    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
+        << "Cannot encode GC map for method with "
+        << (1 << pc_bits) << " instructions (number is rounded up to nearest power of 2)";
+    return false;
+  }
+  size_t table_size = ((pc_bytes + ref_bitmap_bytes) * num_entries) + 4;
+  dex_gc_map_.reserve(table_size);
+  // Write table header.
+  dex_gc_map_.push_back(format | ((ref_bitmap_bytes & ~0xFF) >> 5));
+  dex_gc_map_.push_back(ref_bitmap_bytes & 0xFF);
+  dex_gc_map_.push_back(num_entries & 0xFF);
+  dex_gc_map_.push_back((num_entries >> 8) & 0xFF);
+  // Write table data.
+  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
+  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
+    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
+      dex_gc_map_.push_back(i & 0xFF);
+      if (pc_bytes == 2) {
+        dex_gc_map_.push_back((i >> 8) & 0xFF);
+      }
+      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
+      line->WriteReferenceBitMap(dex_gc_map_, ref_bitmap_bytes);
+    }
+  }
+  DCHECK_EQ(dex_gc_map_.size(), table_size);
+  return true;
+}
+
+void VerifiedMethod::VerifyGcMap(verifier::MethodVerifier* method_verifier,
+                                 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.
+  verifier::DexPcToReferenceMap map(&data[0]);
+  DCHECK_EQ(data.size(), map.RawSize());
+  size_t map_index = 0;
+  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
+  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
+    const uint8_t* reg_bitmap = map.FindBitMap(i, false);
+    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
+      DCHECK_LT(map_index, map.NumEntries());
+      DCHECK_EQ(map.GetDexPc(map_index), i);
+      DCHECK_EQ(map.GetBitMap(map_index), reg_bitmap);
+      map_index++;
+      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
+      for (size_t j = 0; j < code_item->registers_size_; j++) {
+        if (line->GetRegisterType(j).IsNonZeroReferenceTypes()) {
+          DCHECK_LT(j / 8, map.RegWidth());
+          DCHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1);
+        } else if ((j / 8) < map.RegWidth()) {
+          DCHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 0);
+        } else {
+          // If a register doesn't contain a reference then the bitmap may be shorter than the line.
+        }
+      }
+    } else {
+      DCHECK(reg_bitmap == NULL);
+    }
+  }
+}
+
+void VerifiedMethod::ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
+                                       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;
+  size_t max_ref_reg = -1;
+  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
+  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
+    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
+      local_gc_points++;
+      max_insn = i;
+      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
+      max_ref_reg = line->GetMaxNonZeroReferenceReg(max_ref_reg);
+    }
+  }
+  *gc_points = local_gc_points;
+  *ref_bitmap_bits = max_ref_reg + 1;  // If max register is 0 we need 1 bit to encode (ie +1).
+  size_t i = 0;
+  while ((1U << i) <= max_insn) {
+    i++;
+  }
+  *log2_max_gc_pc = i;
+}
+
+void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier) {
+  // It is risky to rely on reg_types for sharpening in cases of soft
+  // verification, we might end up sharpening to a wrong implementation. Just abort.
+  if (method_verifier->HasFailures()) {
+    return;
+  }
+
+  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
+  const uint16_t* insns = code_item->insns_;
+  const Instruction* inst = Instruction::At(insns);
+  const Instruction* end = Instruction::At(insns + code_item->insns_size_in_code_units_);
+
+  for (; inst < end; inst = inst->Next()) {
+    bool is_virtual   = (inst->Opcode() == Instruction::INVOKE_VIRTUAL) ||
+        (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE);
+    bool is_interface = (inst->Opcode() == Instruction::INVOKE_INTERFACE) ||
+        (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
+
+    if (!is_interface && !is_virtual) {
+      continue;
+    }
+    // Get reg type for register holding the reference to the object that will be dispatched upon.
+    uint32_t dex_pc = inst->GetDexPc(insns);
+    verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
+    bool is_range = (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE) ||
+        (inst->Opcode() ==  Instruction::INVOKE_INTERFACE_RANGE);
+    const verifier::RegType&
+        reg_type(line->GetRegisterType(is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
+
+    if (!reg_type.HasClass()) {
+      // We will compute devirtualization information only when we know the Class of the reg type.
+      continue;
+    }
+    mirror::Class* reg_class = reg_type.GetClass();
+    if (reg_class->IsInterface()) {
+      // We can't devirtualize when the known type of the register is an interface.
+      continue;
+    }
+    if (reg_class->IsAbstract() && !reg_class->IsArrayClass()) {
+      // We can't devirtualize abstract classes except on arrays of abstract classes.
+      continue;
+    }
+    mirror::ArtMethod* abstract_method = method_verifier->GetDexCache()->GetResolvedMethod(
+        is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
+    if (abstract_method == NULL) {
+      // If the method is not found in the cache this means that it was never found
+      // by ResolveMethodAndCheckAccess() called when verifying invoke_*.
+      continue;
+    }
+    // Find the concrete method.
+    mirror::ArtMethod* concrete_method = NULL;
+    if (is_interface) {
+      concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(abstract_method);
+    }
+    if (is_virtual) {
+      concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(abstract_method);
+    }
+    if (concrete_method == NULL || concrete_method->IsAbstract()) {
+      // In cases where concrete_method is not found, or is abstract, continue to the next invoke.
+      continue;
+    }
+    if (reg_type.IsPreciseReference() || concrete_method->IsFinal() ||
+        concrete_method->GetDeclaringClass()->IsFinal()) {
+      // If we knew exactly the class being dispatched upon, or if the target method cannot be
+      // overridden record the target to be used in the compiler driver.
+      MethodReference concrete_ref(
+          concrete_method->GetDeclaringClass()->GetDexCache()->GetDexFile(),
+          concrete_method->GetDexMethodIndex());
+      devirt_map_.Put(dex_pc, concrete_ref);
+    }
+  }
+}
+
+void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifier) {
+  /*
+   * Walks over the method code and adds any cast instructions in which
+   * the type cast is implicit to a set, which is used in the code generation
+   * to elide these casts.
+   */
+  if (method_verifier->HasFailures()) {
+    return;
+  }
+  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
+  const Instruction* inst = Instruction::At(code_item->insns_);
+  const Instruction* end = Instruction::At(code_item->insns_ +
+                                           code_item->insns_size_in_code_units_);
+
+  for (; inst < end; inst = inst->Next()) {
+    Instruction::Code code = inst->Opcode();
+    if ((code == Instruction::CHECK_CAST) || (code == Instruction::APUT_OBJECT)) {
+      uint32_t dex_pc = inst->GetDexPc(code_item->insns_);
+      const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
+      bool is_safe_cast = false;
+      if (code == Instruction::CHECK_CAST) {
+        const verifier::RegType& reg_type(line->GetRegisterType(inst->VRegA_21c()));
+        const verifier::RegType& cast_type =
+            method_verifier->ResolveCheckedClass(inst->VRegB_21c());
+        is_safe_cast = cast_type.IsStrictlyAssignableFrom(reg_type);
+      } else {
+        const verifier::RegType& array_type(line->GetRegisterType(inst->VRegB_23x()));
+        // We only know its safe to assign to an array if the array type is precise. For example,
+        // an Object[] can have any type of object stored in it, but it may also be assigned a
+        // String[] in which case the stores need to be of Strings.
+        if (array_type.IsPreciseReference()) {
+          const verifier::RegType& value_type(line->GetRegisterType(inst->VRegA_23x()));
+          const verifier::RegType& component_type = method_verifier->GetRegTypeCache()
+              ->GetComponentType(array_type, method_verifier->GetClassLoader());
+          is_safe_cast = component_type.IsStrictlyAssignableFrom(value_type);
+        }
+      }
+      if (is_safe_cast) {
+        // Verify ordering for push_back() to the sorted vector.
+        DCHECK(safe_cast_set_.empty() || safe_cast_set_.back() < dex_pc);
+        safe_cast_set_.push_back(dex_pc);
+      }
+    }
+  }
+}
+
+}  // namespace art
diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h
new file mode 100644
index 0000000..aa0e72a
--- /dev/null
+++ b/compiler/dex/verified_method.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 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_COMPILER_DEX_VERIFIED_METHOD_H_
+#define ART_COMPILER_DEX_VERIFIED_METHOD_H_
+
+#include <vector>
+
+#include "method_reference.h"
+#include "safe_map.h"
+
+namespace art {
+
+namespace verifier {
+class MethodVerifier;
+}  // namespace verifier
+
+class VerifiedMethod {
+ public:
+  // Cast elision set type.
+  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
+  // is better for performance (not just memory usage), especially for large sets.
+  typedef std::vector<uint32_t> SafeCastSet;
+
+  // Devirtualization map type maps dex offset to concrete method reference.
+  typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;
+
+  static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ~VerifiedMethod() = default;
+
+  const std::vector<uint8_t>& GetDexGcMap() const {
+    return dex_gc_map_;
+  }
+
+  const DevirtualizationMap& GetDevirtMap() const {
+    return devirt_map_;
+  }
+
+  const SafeCastSet& GetSafeCastSet() const {
+    return safe_cast_set_;
+  }
+
+  // Returns the devirtualization target method, or nullptr if none.
+  const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;
+
+  // Returns true if the cast can statically be verified to be redundant
+  // by using the check-cast elision peephole optimization in the verifier.
+  bool IsSafeCast(uint32_t pc) const;
+
+ private:
+  VerifiedMethod() = default;
+
+  /*
+   * 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.
+   * Stores the data in dex_gc_map_, returns true on success and false on failure.
+   */
+  bool GenerateGcMap(verifier::MethodVerifier* method_verifier);
+
+  // Verify that the GC map associated with method_ is well formed.
+  static void VerifyGcMap(verifier::MethodVerifier* method_verifier,
+                          const std::vector<uint8_t>& data);
+
+  // Compute sizes for GC map data.
+  static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
+                                size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
+
+  // Generate devirtualizaion map into devirt_map_.
+  void GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Generate safe case set into safe_cast_set_.
+  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  std::vector<uint8_t> dex_gc_map_;
+  DevirtualizationMap devirt_map_;
+  SafeCastSet safe_cast_set_;
+};
+
+}  // namespace art
+
+#endif  // ART_COMPILER_DEX_VERIFIED_METHOD_H_
diff --git a/compiler/dex/verified_methods_data.cc b/compiler/dex/verified_methods_data.cc
deleted file mode 100644
index e6c4dda..0000000
--- a/compiler/dex/verified_methods_data.cc
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2013 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 "base/stl_util.h"
-#include "dex_file.h"
-#include "dex_instruction.h"
-#include "dex_instruction-inl.h"
-#include "base/mutex.h"
-#include "base/mutex-inl.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
-#include "mirror/class.h"
-#include "mirror/class-inl.h"
-#include "mirror/dex_cache.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/object.h"
-#include "mirror/object-inl.h"
-#include "verified_methods_data.h"
-#include "verifier/dex_gc_map.h"
-#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
-#include "verifier/register_line.h"
-#include "verifier/register_line-inl.h"
-
-namespace art {
-
-VerifiedMethodsData::VerifiedMethodsData()
-    : dex_gc_maps_lock_("compiler GC maps lock"),
-      dex_gc_maps_(),
-      safecast_map_lock_("compiler Cast Elision lock"),
-      safecast_map_(),
-      devirt_maps_lock_("compiler Devirtualization lock"),
-      devirt_maps_(),
-      rejected_classes_lock_("compiler rejected classes lock"),
-      rejected_classes_() {
-}
-
-VerifiedMethodsData::~VerifiedMethodsData() {
-  Thread* self = Thread::Current();
-  {
-    WriterMutexLock mu(self, dex_gc_maps_lock_);
-    STLDeleteValues(&dex_gc_maps_);
-  }
-  {
-    WriterMutexLock mu(self, safecast_map_lock_);
-    STLDeleteValues(&safecast_map_);
-  }
-  {
-    WriterMutexLock mu(self, devirt_maps_lock_);
-    STLDeleteValues(&devirt_maps_);
-  }
-}
-
-bool VerifiedMethodsData::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) {
-  MethodReference ref = method_verifier->GetMethodReference();
-  bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags());
-  if (compile) {
-    /* Generate a register map and add it to the method. */
-    const std::vector<uint8_t>* dex_gc_map = GenerateGcMap(method_verifier);
-    if (dex_gc_map == NULL) {
-      DCHECK(method_verifier->HasFailures());
-      return false;  // Not a real failure, but a failure to encode
-    }
-    if (kIsDebugBuild) {
-      VerifyGcMap(method_verifier, *dex_gc_map);
-    }
-    SetDexGcMap(ref, dex_gc_map);
-
-    // TODO: move this out when DEX-to-DEX supports devirtualization.
-    if (method_verifier->HasVirtualOrInterfaceInvokes()) {
-      PcToConcreteMethodMap* pc_to_concrete_method = GenerateDevirtMap(method_verifier);
-      if (pc_to_concrete_method != NULL) {
-        SetDevirtMap(ref, pc_to_concrete_method);
-      }
-    }
-  }
-
-  if (method_verifier->HasCheckCasts()) {
-    MethodSafeCastSet* method_to_safe_casts = GenerateSafeCastSet(method_verifier);
-    if (method_to_safe_casts != NULL) {
-      SetSafeCastMap(ref, method_to_safe_casts);
-    }
-  }
-  return true;
-}
-
-const std::vector<uint8_t>* VerifiedMethodsData::GetDexGcMap(MethodReference ref) {
-  ReaderMutexLock mu(Thread::Current(), dex_gc_maps_lock_);
-  DexGcMapTable::const_iterator it = dex_gc_maps_.find(ref);
-  CHECK(it != dex_gc_maps_.end())
-    << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
-  CHECK(it->second != NULL);
-  return it->second;
-}
-
-const MethodReference* VerifiedMethodsData::GetDevirtMap(const MethodReference& ref,
-                                                                    uint32_t dex_pc) {
-  ReaderMutexLock mu(Thread::Current(), devirt_maps_lock_);
-  DevirtualizationMapTable::const_iterator it = devirt_maps_.find(ref);
-  if (it == devirt_maps_.end()) {
-    return NULL;
-  }
-
-  // Look up the PC in the map, get the concrete method to execute and return its reference.
-  PcToConcreteMethodMap::const_iterator pc_to_concrete_method = it->second->find(dex_pc);
-  if (pc_to_concrete_method != it->second->end()) {
-    return &(pc_to_concrete_method->second);
-  } else {
-    return NULL;
-  }
-}
-
-bool VerifiedMethodsData::IsSafeCast(MethodReference ref, uint32_t pc) {
-  ReaderMutexLock mu(Thread::Current(), safecast_map_lock_);
-  SafeCastMap::const_iterator it = safecast_map_.find(ref);
-  if (it == safecast_map_.end()) {
-    return false;
-  }
-
-  // Look up the cast address in the set of safe casts
-  // Use binary_search for lookup in the sorted vector.
-  return std::binary_search(it->second->begin(), it->second->end(), pc);
-}
-
-void VerifiedMethodsData::AddRejectedClass(ClassReference ref) {
-  {
-    WriterMutexLock mu(Thread::Current(), rejected_classes_lock_);
-    rejected_classes_.insert(ref);
-  }
-  DCHECK(IsClassRejected(ref));
-}
-
-bool VerifiedMethodsData::IsClassRejected(ClassReference ref) {
-  ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_);
-  return (rejected_classes_.find(ref) != rejected_classes_.end());
-}
-
-bool VerifiedMethodsData::IsCandidateForCompilation(MethodReference& method_ref,
-                                                    const uint32_t access_flags) {
-#ifdef ART_SEA_IR_MODE
-    bool use_sea = Runtime::Current()->IsSeaIRMode();
-    use_sea = use_sea && (std::string::npos != PrettyMethod(
-                          method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
-    if (use_sea) return true;
-#endif
-  // Don't compile class initializers, ever.
-  if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
-    return false;
-  }
-  return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly);
-}
-
-const std::vector<uint8_t>* VerifiedMethodsData::GenerateGcMap(
-    verifier::MethodVerifier* method_verifier) {
-  size_t num_entries, ref_bitmap_bits, pc_bits;
-  ComputeGcMapSizes(method_verifier, &num_entries, &ref_bitmap_bits, &pc_bits);
-  // There's a single byte to encode the size of each bitmap
-  if (ref_bitmap_bits >= (8 /* bits per byte */ * 8192 /* 13-bit size */ )) {
-    // TODO: either a better GC map format or per method failures
-    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
-        << "Cannot encode GC map for method with " << ref_bitmap_bits << " registers";
-    return NULL;
-  }
-  size_t ref_bitmap_bytes = (ref_bitmap_bits + 7) / 8;
-  // There are 2 bytes to encode the number of entries
-  if (num_entries >= 65536) {
-    // TODO: either a better GC map format or per method failures
-    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
-        << "Cannot encode GC map for method with " << num_entries << " entries";
-    return NULL;
-  }
-  size_t pc_bytes;
-  verifier::RegisterMapFormat format;
-  if (pc_bits <= 8) {
-    format = verifier::kRegMapFormatCompact8;
-    pc_bytes = 1;
-  } else if (pc_bits <= 16) {
-    format = verifier::kRegMapFormatCompact16;
-    pc_bytes = 2;
-  } else {
-    // TODO: either a better GC map format or per method failures
-    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
-        << "Cannot encode GC map for method with "
-        << (1 << pc_bits) << " instructions (number is rounded up to nearest power of 2)";
-    return NULL;
-  }
-  size_t table_size = ((pc_bytes + ref_bitmap_bytes) * num_entries) + 4;
-  std::vector<uint8_t>* table = new std::vector<uint8_t>;
-  if (table == NULL) {
-    method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD)
-        << "Failed to encode GC map (size=" << table_size << ")";
-    return NULL;
-  }
-  table->reserve(table_size);
-  // Write table header
-  table->push_back(format | ((ref_bitmap_bytes & ~0xFF) >> 5));
-  table->push_back(ref_bitmap_bytes & 0xFF);
-  table->push_back(num_entries & 0xFF);
-  table->push_back((num_entries >> 8) & 0xFF);
-  // Write table data
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
-    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
-      table->push_back(i & 0xFF);
-      if (pc_bytes == 2) {
-        table->push_back((i >> 8) & 0xFF);
-      }
-      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
-      line->WriteReferenceBitMap(*table, ref_bitmap_bytes);
-    }
-  }
-  DCHECK_EQ(table->size(), table_size);
-  return table;
-}
-
-void VerifiedMethodsData::VerifyGcMap(verifier::MethodVerifier* method_verifier,
-                                      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
-  verifier::DexPcToReferenceMap map(&data[0]);
-  DCHECK_EQ(data.size(), map.RawSize());
-  size_t map_index = 0;
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
-    const uint8_t* reg_bitmap = map.FindBitMap(i, false);
-    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
-      CHECK_LT(map_index, map.NumEntries());
-      CHECK_EQ(map.GetDexPc(map_index), i);
-      CHECK_EQ(map.GetBitMap(map_index), reg_bitmap);
-      map_index++;
-      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
-      for (size_t j = 0; j < code_item->registers_size_; j++) {
-        if (line->GetRegisterType(j).IsNonZeroReferenceTypes()) {
-          CHECK_LT(j / 8, map.RegWidth());
-          CHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1);
-        } else if ((j / 8) < map.RegWidth()) {
-          CHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 0);
-        } else {
-          // If a register doesn't contain a reference then the bitmap may be shorter than the line
-        }
-      }
-    } else {
-      CHECK(reg_bitmap == NULL);
-    }
-  }
-}
-
-void VerifiedMethodsData::ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
-                                            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;
-  size_t max_ref_reg = -1;
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  for (size_t i = 0; i < code_item->insns_size_in_code_units_; i++) {
-    if (method_verifier->GetInstructionFlags(i).IsCompileTimeInfoPoint()) {
-      local_gc_points++;
-      max_insn = i;
-      verifier::RegisterLine* line = method_verifier->GetRegLine(i);
-      max_ref_reg = line->GetMaxNonZeroReferenceReg(max_ref_reg);
-    }
-  }
-  *gc_points = local_gc_points;
-  *ref_bitmap_bits = max_ref_reg + 1;  // if max register is 0 we need 1 bit to encode (ie +1)
-  size_t i = 0;
-  while ((1U << i) <= max_insn) {
-    i++;
-  }
-  *log2_max_gc_pc = i;
-}
-
-void VerifiedMethodsData::SetDexGcMap(MethodReference ref, const std::vector<uint8_t>* gc_map) {
-  DCHECK(Runtime::Current()->IsCompiler());
-  {
-    WriterMutexLock mu(Thread::Current(), dex_gc_maps_lock_);
-    DexGcMapTable::iterator it = dex_gc_maps_.find(ref);
-    if (it != dex_gc_maps_.end()) {
-      delete it->second;
-      dex_gc_maps_.erase(it);
-    }
-    dex_gc_maps_.Put(ref, gc_map);
-  }
-  DCHECK(GetDexGcMap(ref) != NULL);
-}
-
-VerifiedMethodsData::MethodSafeCastSet* VerifiedMethodsData::GenerateSafeCastSet(
-    verifier::MethodVerifier* method_verifier) {
-  /*
-   * Walks over the method code and adds any cast instructions in which
-   * the type cast is implicit to a set, which is used in the code generation
-   * to elide these casts.
-   */
-  if (method_verifier->HasFailures()) {
-    return NULL;
-  }
-  UniquePtr<MethodSafeCastSet> mscs;
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  const Instruction* inst = Instruction::At(code_item->insns_);
-  const Instruction* end = Instruction::At(code_item->insns_ +
-                                           code_item->insns_size_in_code_units_);
-
-  for (; inst < end; inst = inst->Next()) {
-    Instruction::Code code = inst->Opcode();
-    if ((code == Instruction::CHECK_CAST) || (code == Instruction::APUT_OBJECT)) {
-      uint32_t dex_pc = inst->GetDexPc(code_item->insns_);
-      const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
-      bool is_safe_cast = false;
-      if (code == Instruction::CHECK_CAST) {
-        const verifier::RegType& reg_type(line->GetRegisterType(inst->VRegA_21c()));
-        const verifier::RegType& cast_type =
-            method_verifier->ResolveCheckedClass(inst->VRegB_21c());
-        is_safe_cast = cast_type.IsStrictlyAssignableFrom(reg_type);
-      } else {
-        const verifier::RegType& array_type(line->GetRegisterType(inst->VRegB_23x()));
-        // We only know its safe to assign to an array if the array type is precise. For example,
-        // an Object[] can have any type of object stored in it, but it may also be assigned a
-        // String[] in which case the stores need to be of Strings.
-        if (array_type.IsPreciseReference()) {
-          const verifier::RegType& value_type(line->GetRegisterType(inst->VRegA_23x()));
-          const verifier::RegType& component_type = method_verifier->GetRegTypeCache()
-              ->GetComponentType(array_type, method_verifier->GetClassLoader());
-          is_safe_cast = component_type.IsStrictlyAssignableFrom(value_type);
-        }
-      }
-      if (is_safe_cast) {
-        if (mscs.get() == nullptr) {
-          mscs.reset(new MethodSafeCastSet());
-        } else {
-          DCHECK_LT(mscs->back(), dex_pc);  // Verify ordering for push_back() to the sorted vector.
-        }
-        mscs->push_back(dex_pc);
-      }
-    }
-  }
-  return mscs.release();
-}
-
-void  VerifiedMethodsData::SetSafeCastMap(MethodReference ref, const MethodSafeCastSet* cast_set) {
-  WriterMutexLock mu(Thread::Current(), safecast_map_lock_);
-  SafeCastMap::iterator it = safecast_map_.find(ref);
-  if (it != safecast_map_.end()) {
-    delete it->second;
-    safecast_map_.erase(it);
-  }
-  safecast_map_.Put(ref, cast_set);
-  DCHECK(safecast_map_.find(ref) != safecast_map_.end());
-}
-
-VerifiedMethodsData::PcToConcreteMethodMap* VerifiedMethodsData::GenerateDevirtMap(
-    verifier::MethodVerifier* method_verifier) {
-  // It is risky to rely on reg_types for sharpening in cases of soft
-  // verification, we might end up sharpening to a wrong implementation. Just abort.
-  if (method_verifier->HasFailures()) {
-    return NULL;
-  }
-
-  UniquePtr<PcToConcreteMethodMap> pc_to_concrete_method_map;
-  const DexFile::CodeItem* code_item = method_verifier->CodeItem();
-  const uint16_t* insns = code_item->insns_;
-  const Instruction* inst = Instruction::At(insns);
-  const Instruction* end = Instruction::At(insns + code_item->insns_size_in_code_units_);
-
-  for (; inst < end; inst = inst->Next()) {
-    bool is_virtual   = (inst->Opcode() == Instruction::INVOKE_VIRTUAL) ||
-        (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE);
-    bool is_interface = (inst->Opcode() == Instruction::INVOKE_INTERFACE) ||
-        (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
-
-    if (!is_interface && !is_virtual) {
-      continue;
-    }
-    // Get reg type for register holding the reference to the object that will be dispatched upon.
-    uint32_t dex_pc = inst->GetDexPc(insns);
-    verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
-    bool is_range = (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE) ||
-        (inst->Opcode() ==  Instruction::INVOKE_INTERFACE_RANGE);
-    const verifier::RegType&
-        reg_type(line->GetRegisterType(is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
-
-    if (!reg_type.HasClass()) {
-      // We will compute devirtualization information only when we know the Class of the reg type.
-      continue;
-    }
-    mirror::Class* reg_class = reg_type.GetClass();
-    if (reg_class->IsInterface()) {
-      // We can't devirtualize when the known type of the register is an interface.
-      continue;
-    }
-    if (reg_class->IsAbstract() && !reg_class->IsArrayClass()) {
-      // We can't devirtualize abstract classes except on arrays of abstract classes.
-      continue;
-    }
-    mirror::ArtMethod* abstract_method = method_verifier->GetDexCache()->GetResolvedMethod(
-        is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
-    if (abstract_method == NULL) {
-      // If the method is not found in the cache this means that it was never found
-      // by ResolveMethodAndCheckAccess() called when verifying invoke_*.
-      continue;
-    }
-    // Find the concrete method.
-    mirror::ArtMethod* concrete_method = NULL;
-    if (is_interface) {
-      concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(abstract_method);
-    }
-    if (is_virtual) {
-      concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(abstract_method);
-    }
-    if (concrete_method == NULL || concrete_method->IsAbstract()) {
-      // In cases where concrete_method is not found, or is abstract, continue to the next invoke.
-      continue;
-    }
-    if (reg_type.IsPreciseReference() || concrete_method->IsFinal() ||
-        concrete_method->GetDeclaringClass()->IsFinal()) {
-      // If we knew exactly the class being dispatched upon, or if the target method cannot be
-      // overridden record the target to be used in the compiler driver.
-      if (pc_to_concrete_method_map.get() == NULL) {
-        pc_to_concrete_method_map.reset(new PcToConcreteMethodMap());
-      }
-      MethodReference concrete_ref(
-          concrete_method->GetDeclaringClass()->GetDexCache()->GetDexFile(),
-          concrete_method->GetDexMethodIndex());
-      pc_to_concrete_method_map->Put(dex_pc, concrete_ref);
-    }
-  }
-  return pc_to_concrete_method_map.release();
-}
-
-void  VerifiedMethodsData::SetDevirtMap(MethodReference ref,
-                                   const PcToConcreteMethodMap* devirt_map) {
-  WriterMutexLock mu(Thread::Current(), devirt_maps_lock_);
-  DevirtualizationMapTable::iterator it = devirt_maps_.find(ref);
-  if (it != devirt_maps_.end()) {
-    delete it->second;
-    devirt_maps_.erase(it);
-  }
-
-  devirt_maps_.Put(ref, devirt_map);
-  DCHECK(devirt_maps_.find(ref) != devirt_maps_.end());
-}
-
-}  // namespace art
diff --git a/compiler/dex/verified_methods_data.h b/compiler/dex/verified_methods_data.h
deleted file mode 100644
index d495dff..0000000
--- a/compiler/dex/verified_methods_data.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2013 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_COMPILER_DEX_VERIFIED_METHODS_DATA_H_
-#define ART_COMPILER_DEX_VERIFIED_METHODS_DATA_H_
-
-#include <stdint.h>
-#include <set>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "class_reference.h"
-#include "method_reference.h"
-#include "safe_map.h"
-
-namespace art {
-
-namespace verifier {
-class MethodVerifier;
-}  // namespace verifier
-
-class VerifiedMethodsData {
-  public:
-    VerifiedMethodsData();
-    ~VerifiedMethodsData();
-
-    bool ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        LOCKS_EXCLUDED(dex_gc_maps_lock_, devirt_maps_lock_, safecast_map_lock_);
-
-    const std::vector<uint8_t>* GetDexGcMap(MethodReference ref)
-        LOCKS_EXCLUDED(dex_gc_maps_lock_);
-
-    const MethodReference* GetDevirtMap(const MethodReference& ref, uint32_t dex_pc)
-        LOCKS_EXCLUDED(devirt_maps_lock_);
-
-    // Returns true if the cast can statically be verified to be redundant
-    // by using the check-cast elision peephole optimization in the verifier
-    bool IsSafeCast(MethodReference ref, uint32_t pc) LOCKS_EXCLUDED(safecast_map_lock_);
-
-    void AddRejectedClass(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
-    bool IsClassRejected(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_);
-
-    static bool IsCandidateForCompilation(MethodReference& method_ref,
-                                          const uint32_t access_flags);
-
-  private:
-    /*
-     * 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(verifier::MethodVerifier* method_verifier);
-
-    // Verify that the GC map associated with method_ is well formed
-    void VerifyGcMap(verifier::MethodVerifier* method_verifier, const std::vector<uint8_t>& data);
-
-    // Compute sizes for GC map data
-    void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
-                           size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
-
-    // All the GC maps that the verifier has created
-    typedef SafeMap<const MethodReference, const std::vector<uint8_t>*,
-        MethodReferenceComparator> DexGcMapTable;
-    ReaderWriterMutex dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-    DexGcMapTable dex_gc_maps_ GUARDED_BY(dex_gc_maps_lock_);
-    void SetDexGcMap(MethodReference ref, const std::vector<uint8_t>* dex_gc_map)
-        LOCKS_EXCLUDED(dex_gc_maps_lock_);
-
-    // Cast elision types.
-    // Since we're adding the dex PCs to the set in increasing order, a sorted vector
-    // is better for performance (not just memory usage), especially for large sets.
-    typedef std::vector<uint32_t> MethodSafeCastSet;
-    typedef SafeMap<MethodReference, const MethodSafeCastSet*,
-        MethodReferenceComparator> SafeCastMap;
-    MethodSafeCastSet* GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-    void SetSafeCastMap(MethodReference ref, const MethodSafeCastSet* mscs)
-        LOCKS_EXCLUDED(safecast_map_lock_);
-    ReaderWriterMutex safecast_map_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-    SafeCastMap safecast_map_ GUARDED_BY(safecast_map_lock_);
-
-    // Devirtualization map.
-    typedef SafeMap<uint32_t, MethodReference> PcToConcreteMethodMap;
-    typedef SafeMap<MethodReference, const PcToConcreteMethodMap*,
-        MethodReferenceComparator> DevirtualizationMapTable;
-    PcToConcreteMethodMap* GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-    ReaderWriterMutex devirt_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-    DevirtualizationMapTable devirt_maps_ GUARDED_BY(devirt_maps_lock_);
-    void SetDevirtMap(MethodReference ref, const PcToConcreteMethodMap* pc_method_map)
-          LOCKS_EXCLUDED(devirt_maps_lock_);
-
-    // Rejected classes
-    typedef std::set<ClassReference> RejectedClassesTable;
-    ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-    RejectedClassesTable rejected_classes_ GUARDED_BY(rejected_classes_lock_);
-};
-
-}  // namespace art
-
-#endif  // ART_COMPILER_DEX_VERIFIED_METHODS_DATA_H_
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index f390b41..f84e01f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -27,7 +27,7 @@
 #include "class_linker.h"
 #include "dex_compilation_unit.h"
 #include "dex_file-inl.h"
-#include "dex/verified_methods_data.h"
+#include "dex/verification_results.h"
 #include "jni_internal.h"
 #include "object_utils.h"
 #include "runtime.h"
@@ -336,13 +336,13 @@
 extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
                                                std::string const& filename);
 
-CompilerDriver::CompilerDriver(VerifiedMethodsData* verified_methods_data,
+CompilerDriver::CompilerDriver(VerificationResults* verification_results,
                                DexFileToMethodInlinerMap* method_inliner_map,
                                CompilerBackend compiler_backend, InstructionSet instruction_set,
                                InstructionSetFeatures instruction_set_features,
                                bool image, DescriptorSet* image_classes, size_t thread_count,
                                bool dump_stats)
-    : verified_methods_data_(verified_methods_data),
+    : verification_results_(verification_results),
       method_inliner_map_(method_inliner_map),
       compiler_backend_(compiler_backend),
       instruction_set_(instruction_set),
@@ -1274,7 +1274,7 @@
           // Did the verifier record a more precise invoke target based on its type information?
           const MethodReference caller_method(mUnit->GetDexFile(), mUnit->GetDexMethodIndex());
           const MethodReference* devirt_map_target =
-              verified_methods_data_->GetDevirtMap(caller_method, dex_pc);
+              verification_results_->GetDevirtMap(caller_method, dex_pc);
           if (devirt_map_target != NULL) {
             SirtRef<mirror::DexCache> target_dex_cache(soa.Self(), mUnit->GetClassLinker()->FindDexCache(*devirt_map_target->dex_file));
             SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
@@ -1322,7 +1322,7 @@
 }
 
 bool CompilerDriver::IsSafeCast(const MethodReference& mr, uint32_t dex_pc) {
-  bool result = verified_methods_data_->IsSafeCast(mr, dex_pc);
+  bool result = verification_results_->IsSafeCast(mr, dex_pc);
   if (result) {
     stats_->SafeCast();
   } else {
@@ -2268,7 +2268,7 @@
   }
   ClassReference ref(&dex_file, class_def_index);
   // Skip compiling classes with generic verifier failures since they will still fail at runtime
-  if (manager->GetCompiler()->verified_methods_data_->IsClassRejected(ref)) {
+  if (manager->GetCompiler()->verification_results_->IsClassRejected(ref)) {
     return;
   }
   const byte* class_data = dex_file.GetClassData(class_def);
@@ -2351,7 +2351,7 @@
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
     MethodReference method_ref(&dex_file, method_idx);
-    bool compile = VerifiedMethodsData::IsCandidateForCompilation(method_ref, access_flags);
+    bool compile = VerificationResults::IsCandidateForCompilation(method_ref, access_flags);
 
     if (compile) {
       CompilerFn compiler = compiler_;
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index eef94a1..f8aa868 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -44,7 +44,7 @@
 class DexFileToMethodInlinerMap;
 class OatWriter;
 class TimingLogger;
-class VerifiedMethodsData;
+class VerificationResults;
 
 enum CompilerBackend {
   kQuick,
@@ -92,7 +92,7 @@
   // enabled.  "image_classes" lets the compiler know what classes it
   // can assume will be in the image, with NULL implying all available
   // classes.
-  explicit CompilerDriver(VerifiedMethodsData* verified_methods_data,
+  explicit CompilerDriver(VerificationResults* verification_results,
                           DexFileToMethodInlinerMap* method_inliner_map,
                           CompilerBackend compiler_backend, InstructionSet instruction_set,
                           InstructionSetFeatures instruction_set_features,
@@ -109,8 +109,8 @@
   void CompileOne(const mirror::ArtMethod* method, TimingLogger& timings)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  VerifiedMethodsData* GetVerifiedMethodsData() const {
-    return verified_methods_data_;
+  VerificationResults* GetVerificationResults() const {
+    return verification_results_;
   }
 
   DexFileToMethodInlinerMap* GetMethodInlinerMap() const {
@@ -486,7 +486,7 @@
   std::vector<const CallPatchInformation*> methods_to_patch_;
   std::vector<const TypePatchInformation*> classes_to_patch_;
 
-  VerifiedMethodsData* verified_methods_data_;
+  VerificationResults* verification_results_;
   DexFileToMethodInlinerMap* method_inliner_map_;
 
   CompilerBackend compiler_backend_;
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
index 35d1ecd..8f996fa 100644
--- a/compiler/llvm/compiler_llvm.cc
+++ b/compiler/llvm/compiler_llvm.cc
@@ -20,7 +20,7 @@
 #include "base/stl_util.h"
 #include "class_linker.h"
 #include "compiled_method.h"
-#include "dex/verified_methods_data.h"
+#include "dex/verification_results.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
 #include "globals.h"
@@ -157,7 +157,7 @@
                        dex_compilation_unit->GetDexMethodIndex());
   return new CompiledMethod(*compiler_driver_, compiler_driver_->GetInstructionSet(),
                             cunit->GetElfObject(),
-                            *compiler_driver_->GetVerifiedMethodsData()->GetDexGcMap(mref),
+                            *compiler_driver_->GetVerificationResults()->GetDexGcMap(mref),
                             cunit->GetDexCompilationUnit()->GetSymbol());
 }
 
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 2434262..fc45412 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -79,10 +79,10 @@
   InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86;
 
   InstructionSetFeatures insn_features;
-  verified_methods_data_.reset(new VerifiedMethodsData);
+  verification_results_.reset(new VerificationResults);
   method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr);
-  callbacks_.Reset(verified_methods_data_.get(), method_inliner_map_.get());
-  compiler_driver_.reset(new CompilerDriver(verified_methods_data_.get(),
+  callbacks_.Reset(verification_results_.get(), method_inliner_map_.get());
+  compiler_driver_.reset(new CompilerDriver(verification_results_.get(),
                                             method_inliner_map_.get(),
                                             compiler_backend, insn_set,
                                             insn_features, false, NULL, 2, true));
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 199a2b8..7a902d8 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -23,7 +23,7 @@
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "dex_file-inl.h"
-#include "dex/verified_methods_data.h"
+#include "dex/verification_results.h"
 #include "gc/space/space.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/array.h"
@@ -218,7 +218,7 @@
       mirror::Class::Status status;
       if (compiled_class != NULL) {
         status = compiled_class->GetStatus();
-      } else if (compiler_driver_->GetVerifiedMethodsData()->IsClassRejected(class_ref)) {
+      } else if (compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) {
         status = mirror::Class::kStatusError;
       } else {
         status = mirror::Class::kStatusNotReady;
@@ -433,7 +433,7 @@
       mirror::Class::Status status;
       if (compiled_class != NULL) {
         status = compiled_class->GetStatus();
-      } else if (compiler_driver_->GetVerifiedMethodsData()->IsClassRejected(class_ref)) {
+      } else if (compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) {
         status = mirror::Class::kStatusError;
       } else {
         status = mirror::Class::kStatusNotReady;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 26fac23..97df199 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -32,7 +32,7 @@
 #include "class_linker.h"
 #include "compiler_callbacks.h"
 #include "dex_file-inl.h"
-#include "dex/verified_methods_data.h"
+#include "dex/verification_results.h"
 #include "driver/compiler_driver.h"
 #include "elf_fixup.h"
 #include "elf_stripper.h"
@@ -268,7 +268,7 @@
       Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path_files);
     }
 
-    UniquePtr<CompilerDriver> driver(new CompilerDriver(verified_methods_data_.get(),
+    UniquePtr<CompilerDriver> driver(new CompilerDriver(verification_results_.get(),
                                                         method_inliner_map_.get(),
                                                         compiler_backend_,
                                                         instruction_set_,
@@ -348,15 +348,15 @@
  private:
   class Dex2OatCompilerCallbacks : public CompilerCallbacks {
     public:
-      Dex2OatCompilerCallbacks(VerifiedMethodsData* verified_methods_data,
+      Dex2OatCompilerCallbacks(VerificationResults* verification_results,
                                DexFileToMethodInlinerMap* method_inliner_map)
-          : verified_methods_data_(verified_methods_data),
+          : verification_results_(verification_results),
             method_inliner_map_(method_inliner_map) { }
       virtual ~Dex2OatCompilerCallbacks() { }
 
       virtual bool MethodVerified(verifier::MethodVerifier* verifier)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-        bool result = verified_methods_data_->ProcessVerifiedMethod(verifier);
+        bool result = verification_results_->ProcessVerifiedMethod(verifier);
         if (result && method_inliner_map_ != nullptr) {
           MethodReference ref = verifier->GetMethodReference();
           method_inliner_map_->GetMethodInliner(ref.dex_file)
@@ -365,11 +365,11 @@
         return result;
       }
       virtual void ClassRejected(ClassReference ref) {
-        verified_methods_data_->AddRejectedClass(ref);
+        verification_results_->AddRejectedClass(ref);
       }
 
     private:
-      VerifiedMethodsData* verified_methods_data_;
+      VerificationResults* verification_results_;
       DexFileToMethodInlinerMap* method_inliner_map_;
   };
 
@@ -380,9 +380,9 @@
       : compiler_backend_(compiler_backend),
         instruction_set_(instruction_set),
         instruction_set_features_(instruction_set_features),
-        verified_methods_data_(new VerifiedMethodsData),
+        verification_results_(new VerificationResults),
         method_inliner_map_(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr),
-        callbacks_(verified_methods_data_.get(), method_inliner_map_.get()),
+        callbacks_(verification_results_.get(), method_inliner_map_.get()),
         runtime_(nullptr),
         thread_count_(thread_count),
         start_ns_(NanoTime()) {
@@ -446,7 +446,7 @@
   const InstructionSet instruction_set_;
   const InstructionSetFeatures instruction_set_features_;
 
-  UniquePtr<VerifiedMethodsData> verified_methods_data_;
+  UniquePtr<VerificationResults> verification_results_;
   UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_;
   Dex2OatCompilerCallbacks callbacks_;
   Runtime* runtime_;
diff --git a/runtime/common_test.h b/runtime/common_test.h
index ee95d5b..5e6354e 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -26,7 +26,7 @@
 
 #include "../../external/icu4c/common/unicode/uvernum.h"
 #include "../compiler/dex/quick/dex_file_to_method_inliner_map.h"
-#include "../compiler/dex/verified_methods_data.h"
+#include "../compiler/dex/verification_results.h"
 #include "../compiler/driver/compiler_driver.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
@@ -425,9 +425,9 @@
     CompilerBackend compiler_backend = kQuick;
 #endif
 
-    verified_methods_data_.reset(new VerifiedMethodsData);
+    verification_results_.reset(new VerificationResults);
     method_inliner_map_.reset(compiler_backend == kQuick ? new DexFileToMethodInlinerMap : nullptr);
-    callbacks_.Reset(verified_methods_data_.get(), method_inliner_map_.get());
+    callbacks_.Reset(verification_results_.get(), method_inliner_map_.get());
     Runtime::Options options;
     options.push_back(std::make_pair("compilercallbacks", static_cast<CompilerCallbacks*>(&callbacks_)));
     options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
@@ -474,7 +474,7 @@
         }
       }
       class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
-      compiler_driver_.reset(new CompilerDriver(verified_methods_data_.get(),
+      compiler_driver_.reset(new CompilerDriver(verification_results_.get(),
                                                 method_inliner_map_.get(),
                                                 compiler_backend, instruction_set,
                                                 instruction_set_features,
@@ -526,7 +526,7 @@
     compiler_driver_.reset();
     callbacks_.Reset(nullptr, nullptr);
     method_inliner_map_.reset();
-    verified_methods_data_.reset();
+    verification_results_.reset();
     STLDeleteElements(&opened_dex_files_);
 
     Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
@@ -654,18 +654,18 @@
 
   class TestCompilerCallbacks : public CompilerCallbacks {
    public:
-    TestCompilerCallbacks() : verified_methods_data_(nullptr), method_inliner_map_(nullptr) { }
+    TestCompilerCallbacks() : verification_results_(nullptr), method_inliner_map_(nullptr) { }
 
-    void Reset(VerifiedMethodsData* verified_methods_data,
+    void Reset(VerificationResults* verification_results,
                DexFileToMethodInlinerMap* method_inliner_map) {
-        verified_methods_data_ = verified_methods_data;
+        verification_results_ = verification_results;
         method_inliner_map_ = method_inliner_map;
     }
 
     virtual bool MethodVerified(verifier::MethodVerifier* verifier)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-      CHECK(verified_methods_data_);
-      bool result = verified_methods_data_->ProcessVerifiedMethod(verifier);
+      CHECK(verification_results_);
+      bool result = verification_results_->ProcessVerifiedMethod(verifier);
       if (result && method_inliner_map_ != nullptr) {
         MethodReference ref = verifier->GetMethodReference();
         method_inliner_map_->GetMethodInliner(ref.dex_file)
@@ -674,11 +674,11 @@
       return result;
     }
     virtual void ClassRejected(ClassReference ref) {
-      verified_methods_data_->AddRejectedClass(ref);
+      verification_results_->AddRejectedClass(ref);
     }
 
    private:
-    VerifiedMethodsData* verified_methods_data_;
+    VerificationResults* verification_results_;
     DexFileToMethodInlinerMap* method_inliner_map_;
   };
 
@@ -689,7 +689,7 @@
   UniquePtr<Runtime> runtime_;
   // Owned by the runtime
   ClassLinker* class_linker_;
-  UniquePtr<VerifiedMethodsData> verified_methods_data_;
+  UniquePtr<VerificationResults> verification_results_;
   UniquePtr<DexFileToMethodInlinerMap> method_inliner_map_;
   TestCompilerCallbacks callbacks_;
   UniquePtr<CompilerDriver> compiler_driver_;
diff --git a/runtime/method_reference.h b/runtime/method_reference.h
index 1ff4ea0..8e46d7e 100644
--- a/runtime/method_reference.h
+++ b/runtime/method_reference.h
@@ -17,6 +17,8 @@
 #ifndef ART_RUNTIME_METHOD_REFERENCE_H_
 #define ART_RUNTIME_METHOD_REFERENCE_H_
 
+#include <stdint.h>
+
 namespace art {
 
 class DexFile;