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/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_