Merge "Simplify HInvokeStatic code generation."
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 637cf17..1efdd38 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -282,9 +282,7 @@
   size_t start_index = 0;
   if (is_instance_call) {
     HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
-    HInstruction* push = new (arena_) HPushArgument(arg, 0);
-    current_block_->AddInstruction(push);
-    invoke->SetArgumentAt(0, push);
+    invoke->SetArgumentAt(0, arg);
     start_index = 1;
   }
 
@@ -305,9 +303,7 @@
           return false;
         }
         HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
-        HInstruction* push = new (arena_) HPushArgument(arg, i);
-        current_block_->AddInstruction(push);
-        invoke->SetArgumentAt(argument_index, push);
+        invoke->SetArgumentAt(argument_index, arg);
         if (type == Primitive::kPrimLong) {
           i++;
         }
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index fe61333..cdd9696 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -101,6 +101,58 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
 };
 
+class InvokeDexCallingConventionVisitor {
+ public:
+  InvokeDexCallingConventionVisitor() : gp_index_(0) {}
+
+  Location GetNextLocation(Primitive::Type type) {
+    switch (type) {
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+      case Primitive::kPrimInt:
+      case Primitive::kPrimNot: {
+        uint32_t index = gp_index_++;
+        if (index < calling_convention.GetNumberOfRegisters()) {
+          return ArmCoreLocation(calling_convention.GetRegisterAt(index));
+        } else {
+          return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
+        }
+      }
+
+      case Primitive::kPrimLong: {
+        uint32_t index = gp_index_;
+        gp_index_ += 2;
+        if (index + 1 < calling_convention.GetNumberOfRegisters()) {
+          return Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
+              calling_convention.GetRegisterPairAt(index)));
+        } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
+          return Location::QuickParameter(index);
+        } else {
+          return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
+        }
+      }
+
+      case Primitive::kPrimDouble:
+      case Primitive::kPrimFloat:
+        LOG(FATAL) << "Unimplemented parameter type " << type;
+        break;
+
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "Unexpected parameter type " << type;
+        break;
+    }
+    return Location();
+  }
+
+ private:
+  InvokeDexCallingConvention calling_convention;
+  uint32_t gp_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
+};
+
 void CodeGeneratorARM::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
     return;
@@ -417,52 +469,17 @@
   codegen_->GenerateFrameExit();
 }
 
-void LocationsBuilderARM::VisitPushArgument(HPushArgument* argument) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
-  InvokeDexCallingConvention calling_convention;
-  uint32_t argument_index = argument->GetArgumentIndex();
-  switch (argument->InputAt(0)->GetType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimNot: {
-      if (argument_index < calling_convention.GetNumberOfRegisters()) {
-        locations->SetInAt(0, ArmCoreLocation(calling_convention.GetRegisterAt(argument_index)));
-      } else {
-        locations->SetInAt(
-            0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index)));
-      }
-      break;
-    }
-    case Primitive::kPrimLong: {
-      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
-        Location location = Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
-            calling_convention.GetRegisterPairAt(argument_index)));
-        locations->SetInAt(0, location);
-      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
-        locations->SetInAt(0, Location::QuickParameter(argument_index));
-      } else {
-        locations->SetInAt(
-            0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index)));
-      }
-      break;
-    }
-    default:
-      LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType();
-  }
-  argument->SetLocations(locations);
-}
-
-void InstructionCodeGeneratorARM::VisitPushArgument(HPushArgument* argument) {
-  // Nothing to do.
-}
-
 void LocationsBuilderARM::VisitInvokeStatic(HInvokeStatic* invoke) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
   locations->AddTemp(ArmCoreLocation(R0));
-    switch (invoke->GetType()) {
+
+  InvokeDexCallingConventionVisitor calling_convention_visitor;
+  for (int i = 0; i < invoke->InputCount(); i++) {
+    HInstruction* input = invoke->InputAt(i);
+    locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
+  }
+
+  switch (invoke->GetType()) {
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
     case Primitive::kPrimChar:
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 7507ee7..7b3d31d 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -105,6 +105,72 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
 };
 
+static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
+static constexpr size_t kRuntimeParameterCoreRegistersLength =
+    arraysize(kRuntimeParameterCoreRegisters);
+
+class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
+ public:
+  InvokeRuntimeCallingConvention()
+      : CallingConvention(kRuntimeParameterCoreRegisters,
+                          kRuntimeParameterCoreRegistersLength) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
+};
+
+class InvokeDexCallingConventionVisitor {
+ public:
+  InvokeDexCallingConventionVisitor() : gp_index_(0) {}
+
+  Location GetNextLocation(Primitive::Type type) {
+    switch (type) {
+      case Primitive::kPrimBoolean:
+      case Primitive::kPrimByte:
+      case Primitive::kPrimChar:
+      case Primitive::kPrimShort:
+      case Primitive::kPrimInt:
+      case Primitive::kPrimNot: {
+        uint32_t index = gp_index_++;
+        if (index < calling_convention.GetNumberOfRegisters()) {
+          return X86CpuLocation(calling_convention.GetRegisterAt(index));
+        } else {
+          return Location::StackSlot(calling_convention.GetStackOffsetOf(index));
+        }
+      }
+
+      case Primitive::kPrimLong: {
+        uint32_t index = gp_index_;
+        gp_index_ += 2;
+        if (index + 1 < calling_convention.GetNumberOfRegisters()) {
+          return Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
+              calling_convention.GetRegisterPairAt(index)));
+        } else if (index + 1 == calling_convention.GetNumberOfRegisters()) {
+          return Location::QuickParameter(index);
+        } else {
+          return Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(index));
+        }
+      }
+
+      case Primitive::kPrimDouble:
+      case Primitive::kPrimFloat:
+        LOG(FATAL) << "Unimplemented parameter type " << type;
+        break;
+
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "Unexpected parameter type " << type;
+        break;
+    }
+    return Location();
+  }
+
+ private:
+  InvokeDexCallingConvention calling_convention;
+  uint32_t gp_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
+};
+
 void CodeGeneratorX86::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
     return;
@@ -413,67 +479,16 @@
   __ ret();
 }
 
-static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
-static constexpr size_t kRuntimeParameterCoreRegistersLength =
-    arraysize(kRuntimeParameterCoreRegisters);
-
-class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
- public:
-  InvokeRuntimeCallingConvention()
-      : CallingConvention(kRuntimeParameterCoreRegisters,
-                          kRuntimeParameterCoreRegistersLength) {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
-};
-
-void LocationsBuilderX86::VisitPushArgument(HPushArgument* argument) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(argument);
-  InvokeDexCallingConvention calling_convention;
-  uint32_t argument_index = argument->GetArgumentIndex();
-  switch (argument->InputAt(0)->GetType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimNot: {
-      if (argument_index < calling_convention.GetNumberOfRegisters()) {
-        locations->SetInAt(
-            0, X86CpuLocation(calling_convention.GetRegisterAt(argument->GetArgumentIndex())));
-      } else {
-        locations->SetInAt(
-            0, Location::StackSlot(calling_convention.GetStackOffsetOf(argument_index)));
-      }
-      break;
-    }
-    case Primitive::kPrimLong: {
-      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
-        Location location = Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
-            calling_convention.GetRegisterPairAt(argument_index)));
-        locations->SetInAt(0, location);
-      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
-        locations->SetInAt(0, Location::QuickParameter(argument_index));
-      } else {
-        locations->SetInAt(
-            0, Location::DoubleStackSlot(calling_convention.GetStackOffsetOf(argument_index)));
-      }
-      break;
-    }
-    default:
-      LOG(FATAL) << "Unimplemented argument type " << argument->InputAt(0)->GetType();
-  }
-
-  argument->SetLocations(locations);
-}
-
-void InstructionCodeGeneratorX86::VisitPushArgument(HPushArgument* argument) {
-  // Nothing to do.
-}
-
 void LocationsBuilderX86::VisitInvokeStatic(HInvokeStatic* invoke) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(invoke);
   locations->AddTemp(X86CpuLocation(EAX));
+
+  InvokeDexCallingConventionVisitor calling_convention_visitor;
+  for (int i = 0; i < invoke->InputCount(); i++) {
+    HInstruction* input = invoke->InputAt(i);
+    locations->SetInAt(i, calling_convention_visitor.GetNextLocation(input->GetType()));
+  }
+
   switch (invoke->GetType()) {
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d7e74f8..3da9ed9 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -230,7 +230,6 @@
   M(NewInstance)                                           \
   M(Not)                                                   \
   M(ParameterValue)                                        \
-  M(PushArgument)                                          \
   M(Return)                                                \
   M(ReturnVoid)                                            \
   M(StoreLocal)                                            \
@@ -717,24 +716,6 @@
   DISALLOW_COPY_AND_ASSIGN(HNewInstance);
 };
 
-// HPushArgument nodes are inserted after the evaluation of an argument
-// of a call. Their mere purpose is to ease the code generator's work.
-class HPushArgument : public HTemplateInstruction<1> {
- public:
-  HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) {
-    SetRawInputAt(0, argument);
-  }
-
-  uint8_t GetArgumentIndex() const { return argument_index_; }
-
-  DECLARE_INSTRUCTION(PushArgument)
-
- private:
-  const uint8_t argument_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(HPushArgument);
-};
-
 class HAdd : public HBinaryOperation {
  public:
   HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)