Add verifier support for dequickening

Also some cleanup.

Bug: 17950037

Change-Id: I1f50fe07f1558e9c4f78953b7afa639d7f310b3c
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 17328c4..d684bc9 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -82,13 +82,13 @@
   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 */ )) {
+  if (ref_bitmap_bits >= kBitsPerByte * 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;
+  size_t ref_bitmap_bytes = RoundUp(ref_bitmap_bits, kBitsPerByte) / kBitsPerByte;
   // 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.
@@ -98,10 +98,10 @@
   }
   size_t pc_bytes;
   verifier::RegisterMapFormat format;
-  if (pc_bits <= 8) {
+  if (pc_bits <= kBitsPerByte) {
     format = verifier::kRegMapFormatCompact8;
     pc_bytes = 1;
-  } else if (pc_bits <= 16) {
+  } else if (pc_bits <= kBitsPerByte * 2) {
     format = verifier::kRegMapFormatCompact16;
     pc_bytes = 2;
   } else {
@@ -152,10 +152,10 @@
       verifier::RegisterLine* line = method_verifier->GetRegLine(i);
       for (size_t j = 0; j < code_item->registers_size_; j++) {
         if (line->GetRegisterType(method_verifier, 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);
+          DCHECK_LT(j / kBitsPerByte, map.RegWidth());
+          DCHECK_EQ((reg_bitmap[j / kBitsPerByte] >> (j % kBitsPerByte)) & 1, 1);
+        } else if ((j / kBitsPerByte) < map.RegWidth()) {
+          DCHECK_EQ((reg_bitmap[j / kBitsPerByte] >> (j % kBitsPerByte)) & 1, 0);
         } else {
           // If a register doesn't contain a reference then the bitmap may be shorter than the line.
         }
@@ -190,6 +190,31 @@
   *log2_max_gc_pc = i;
 }
 
+void VerifiedMethod::GenerateDeQuickenMap(verifier::MethodVerifier* method_verifier) {
+  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()) {
+    const bool is_virtual_quick = inst->Opcode() == Instruction::INVOKE_VIRTUAL_QUICK;
+    const bool is_range_quick = inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK;
+    if (is_virtual_quick || is_range_quick) {
+      uint32_t dex_pc = inst->GetDexPc(insns);
+      verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
+      mirror::ArtMethod* method = method_verifier->GetQuickInvokedMethod(inst, line,
+                                                                         is_range_quick);
+      CHECK(method != nullptr);
+      // The verifier must know what the type of the object was or else we would have gotten a
+      // failure. Put the dex method index in the dequicken map since we need this to get number of
+      // arguments in the compiler.
+      dequicken_map_.Put(dex_pc, method->ToMethodReference());
+    }
+  }
+}
+
 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.
@@ -203,10 +228,10 @@
   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);
+    const bool is_virtual = inst->Opcode() == Instruction::INVOKE_VIRTUAL ||
+        inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE;
+    const bool is_interface = inst->Opcode() == Instruction::INVOKE_INTERFACE ||
+        inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE;
 
     if (!is_interface && !is_virtual) {
       continue;
@@ -214,8 +239,8 @@
     // 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 bool is_range = inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
+        inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE;
     const verifier::RegType&
         reg_type(line->GetRegisterType(method_verifier,
                                        is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
@@ -241,14 +266,14 @@
       continue;
     }
     // Find the concrete method.
-    mirror::ArtMethod* concrete_method = NULL;
+    mirror::ArtMethod* concrete_method = nullptr;
     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()) {
+    if (concrete_method == nullptr || concrete_method->IsAbstract()) {
       // In cases where concrete_method is not found, or is abstract, continue to the next invoke.
       continue;
     }
@@ -256,10 +281,7 @@
         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);
+      devirt_map_.Put(dex_pc, concrete_method->ToMethodReference());
     }
   }
 }