Detect special methods at the end of verification.

This moves special method handling to method inliner
and prepares for eventual inlining of these methods.

Change-Id: I51c51b940fb7bc714e33135cd61be69467861352
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 23ea407..8226b24 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -18,6 +18,7 @@
 
 #include "arm_lir.h"
 #include "codegen_arm.h"
+#include "dex/quick/dex_file_method_inliner.h"
 #include "dex/quick/mir_to_lir-inl.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 
@@ -217,58 +218,43 @@
  * Special-case code genration for simple non-throwing leaf methods.
  */
 void ArmMir2Lir::GenSpecialCase(BasicBlock* bb, MIR* mir,
-                                SpecialCaseHandler special_case) {
+                                const InlineMethod& special) {
+  // TODO: Generate the method using only the data in special. (Requires FastInstance() field
+  // validation in DexFileMethodInliner::AnalyseIGetMethod()/AnalyseIPutMethod().)
+  DCHECK(special.flags & kInlineSpecial);
   current_dalvik_offset_ = mir->offset;
   MIR* next_mir = NULL;
-  switch (special_case) {
-    case kNullMethod:
+  switch (special.opcode) {
+    case kInlineOpNop:
       DCHECK(mir->dalvikInsn.opcode == Instruction::RETURN_VOID);
       next_mir = mir;
       break;
-    case kConstFunction:
+    case kInlineOpConst:
       ArmMir2Lir::GenPrintLabel(mir);
-      LoadConstant(rARM_RET0, mir->dalvikInsn.vB);
+      LoadConstant(rARM_RET0, special.data);
       next_mir = GetNextMir(&bb, mir);
       break;
-    case kIGet:
-      next_mir = SpecialIGet(&bb, mir, kWord, false, false);
+    case kInlineOpIGet: {
+      InlineIGetIPutData data;
+      data.data = special.data;
+      OpSize op_size = static_cast<OpSize>(data.d.op_size);
+      DCHECK_NE(data.d.op_size, kDouble);  // The inliner doesn't distinguish kDouble, uses kLong.
+      bool long_or_double = (data.d.op_size == kLong);
+      bool is_object = data.d.is_object;
+      next_mir = SpecialIGet(&bb, mir, op_size, long_or_double, is_object);
       break;
-    case kIGetBoolean:
-    case kIGetByte:
-      next_mir = SpecialIGet(&bb, mir, kUnsignedByte, false, false);
+    }
+    case kInlineOpIPut: {
+      InlineIGetIPutData data;
+      data.data = special.data;
+      OpSize op_size = static_cast<OpSize>(data.d.op_size);
+      DCHECK_NE(data.d.op_size, kDouble);  // The inliner doesn't distinguish kDouble, uses kLong.
+      bool long_or_double = (data.d.op_size == kLong);
+      bool is_object = data.d.is_object;
+      next_mir = SpecialIPut(&bb, mir, op_size, long_or_double, is_object);
       break;
-    case kIGetObject:
-      next_mir = SpecialIGet(&bb, mir, kWord, false, true);
-      break;
-    case kIGetChar:
-      next_mir = SpecialIGet(&bb, mir, kUnsignedHalf, false, false);
-      break;
-    case kIGetShort:
-      next_mir = SpecialIGet(&bb, mir, kSignedHalf, false, false);
-      break;
-    case kIGetWide:
-      next_mir = SpecialIGet(&bb, mir, kLong, true, false);
-      break;
-    case kIPut:
-      next_mir = SpecialIPut(&bb, mir, kWord, false, false);
-      break;
-    case kIPutBoolean:
-    case kIPutByte:
-      next_mir = SpecialIPut(&bb, mir, kUnsignedByte, false, false);
-      break;
-    case kIPutObject:
-      next_mir = SpecialIPut(&bb, mir, kWord, false, true);
-      break;
-    case kIPutChar:
-      next_mir = SpecialIPut(&bb, mir, kUnsignedHalf, false, false);
-      break;
-    case kIPutShort:
-      next_mir = SpecialIPut(&bb, mir, kSignedHalf, false, false);
-      break;
-    case kIPutWide:
-      next_mir = SpecialIPut(&bb, mir, kLong, true, false);
-      break;
-    case kIdentity:
+    }
+    case kInlineOpReturnArg:
       next_mir = SpecialIdentity(mir);
       break;
     default:
@@ -276,7 +262,7 @@
   }
   if (next_mir != NULL) {
     current_dalvik_offset_ = next_mir->offset;
-    if (special_case != kIdentity) {
+    if (special.opcode != kInlineOpReturnArg) {
       ArmMir2Lir::GenPrintLabel(next_mir);
     }
     NewLIR1(kThumbBx, rARM_LR);