Revert "Revert "ART: Compiler support for invoke-polymorphic.""

This reverts commit 0fb5af1c8287b1ec85c55c306a1c43820c38a337.

This takes us back to the original change and attempts to fix the
issues encountered:

- Adds transition record push/pop around artInvokePolymorphic.
- Changes X86/X64 relocations for MacSDK.
- Implements MIPS entrypoint for art_quick_invoke_polymorphic.
- Corrects size of returned reference in art_quick_invoke_polymorphic
  on ARM.

Bug: 30550796,33191393
Test: art/test/run-test 953
Test: m test-art-run-test

Change-Id: Ib6b93e00b37b9d4ab743a3470ab3d77fe857cda8
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 009d549..3cfabdd 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (C) 2016 The Android Open Source Project
  *
@@ -906,6 +907,33 @@
                       false /* is_unresolved */);
 }
 
+bool HInstructionBuilder::BuildInvokePolymorphic(const Instruction& instruction ATTRIBUTE_UNUSED,
+                                                 uint32_t dex_pc,
+                                                 uint32_t method_idx,
+                                                 uint32_t proto_idx,
+                                                 uint32_t number_of_vreg_arguments,
+                                                 bool is_range,
+                                                 uint32_t* args,
+                                                 uint32_t register_index) {
+  const char* descriptor = dex_file_->GetShorty(proto_idx);
+  DCHECK_EQ(1 + ArtMethod::NumArgRegisters(descriptor), number_of_vreg_arguments);
+  Primitive::Type return_type = Primitive::GetType(descriptor[0]);
+  size_t number_of_arguments = strlen(descriptor);
+  HInvoke* invoke = new (arena_) HInvokePolymorphic(arena_,
+                                                    number_of_arguments,
+                                                    return_type,
+                                                    dex_pc,
+                                                    method_idx);
+  return HandleInvoke(invoke,
+                      number_of_vreg_arguments,
+                      args,
+                      register_index,
+                      is_range,
+                      descriptor,
+                      nullptr /* clinit_check */,
+                      false /* is_unresolved */);
+}
+
 bool HInstructionBuilder::BuildNewInstance(dex::TypeIndex type_index, uint32_t dex_pc) {
   ScopedObjectAccess soa(Thread::Current());
   StackHandleScope<1> hs(soa.Self());
@@ -1915,6 +1943,37 @@
       break;
     }
 
+    case Instruction::INVOKE_POLYMORPHIC: {
+      uint16_t method_idx = instruction.VRegB_45cc();
+      uint16_t proto_idx = instruction.VRegH_45cc();
+      uint32_t number_of_vreg_arguments = instruction.VRegA_45cc();
+      uint32_t args[5];
+      instruction.GetVarArgs(args);
+      return BuildInvokePolymorphic(instruction,
+                                    dex_pc,
+                                    method_idx,
+                                    proto_idx,
+                                    number_of_vreg_arguments,
+                                    false,
+                                    args,
+                                    -1);
+    }
+
+    case Instruction::INVOKE_POLYMORPHIC_RANGE: {
+      uint16_t method_idx = instruction.VRegB_4rcc();
+      uint16_t proto_idx = instruction.VRegH_4rcc();
+      uint32_t number_of_vreg_arguments = instruction.VRegA_4rcc();
+      uint32_t register_index = instruction.VRegC_4rcc();
+      return BuildInvokePolymorphic(instruction,
+                                    dex_pc,
+                                    method_idx,
+                                    proto_idx,
+                                    number_of_vreg_arguments,
+                                    true,
+                                    nullptr,
+                                    register_index);
+    }
+
     case Instruction::NEG_INT: {
       Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc);
       break;