Code cleanup in preparation for x64 backend.

- Use InvokeDexCallingConventionVisitor for setting
  up HParameterValues
- Use kVregSize instead of kX86WordSize when dealing with
  virtual registers.

Change-Id: Ia520223010194c70a3ff0ed659077f55cec4e7d8
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index d459dd5..5c7cac1 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -26,6 +26,8 @@
 
 namespace art {
 
+static size_t constexpr kVRegSize = 4;
+
 class DexCompilationUnit;
 
 class CodeAllocator {
@@ -323,10 +325,10 @@
     return registers_[index];
   }
 
-  uint8_t GetStackOffsetOf(size_t index) const {
+  uint8_t GetStackOffsetOf(size_t index, size_t word_size) const {
     // We still reserve the space for parameters passed by registers.
-    // Add kWordSize for the method pointer.
-    return index * kWordSize + kWordSize;
+    // Add word_size for the method pointer.
+    return index * kVRegSize + word_size;
   }
 
  private:
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index cdd9696..27691ac 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -48,9 +48,11 @@
   core_spill_mask_ |= (1 << LR);
   __ PushList((1 << LR));
 
-  // Add the current ART method to the frame size, the return PC, and the filler.
-  SetFrameSize(RoundUp((
-      GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kArmWordSize,
+  SetFrameSize(RoundUp(
+      (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
+      + kVRegSize  // filler
+      + kArmWordSize  // Art method
+      + kNumberOfPushedRegistersAtEntry * kArmWordSize,
       kStackAlignment));
   // The return PC has already been pushed on the stack.
   __ AddConstant(SP, -(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kArmWordSize));
@@ -73,85 +75,56 @@
   if (reg_number >= number_of_vregs - number_of_in_vregs) {
     // Local is a parameter of the method. It is stored in the caller's frame.
     return GetFrameSize() + kArmWordSize  // ART method
-                          + (reg_number - number_of_vregs + number_of_in_vregs) * kArmWordSize;
+                          + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
   } else {
     // Local is a temporary in this method. It is stored in this method's frame.
     return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
-                          - kArmWordSize  // filler.
-                          - (number_of_vregs * kArmWordSize)
-                          + (reg_number * kArmWordSize);
+                          - kVRegSize  // filler.
+                          - (number_of_vregs * kVRegSize)
+                          + (reg_number * kVRegSize);
   }
 }
 
-static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
-static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 };
-static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
-
-class InvokeDexCallingConvention : public CallingConvention<Register> {
- public:
-  InvokeDexCallingConvention()
-      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
-
-  RegisterPair GetRegisterPairAt(size_t argument_index) {
-    DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
-    return kParameterCorePairRegisters[argument_index];
-  }
-
- private:
-  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));
-        }
+Location InvokeDexCallingConventionVisitor::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, kArmWordSize));
       }
-
-      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();
+
+    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, kArmWordSize));
+      }
+    }
+
+    case Primitive::kPrimDouble:
+    case Primitive::kPrimFloat:
+      LOG(FATAL) << "Unimplemented parameter type " << type;
+      break;
+
+    case Primitive::kPrimVoid:
+      LOG(FATAL) << "Unexpected parameter type " << type;
+      break;
   }
-
- private:
-  InvokeDexCallingConvention calling_convention;
-  uint32_t gp_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
-};
+  return Location();
+}
 
 void CodeGeneratorARM::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
@@ -188,7 +161,7 @@
       __ Mov(destination.AsArm().AsRegisterPairLow(),
              calling_convention.GetRegisterAt(argument_index));
       __ ldr(destination.AsArm().AsRegisterPairHigh(),
-             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize()));
     } else {
       DCHECK(source.IsDoubleStackSlot());
       if (destination.AsArm().AsRegisterPair() == R1_R2) {
@@ -205,12 +178,12 @@
     if (source.IsRegister()) {
       __ Mov(calling_convention.GetRegisterAt(argument_index), source.AsArm().AsRegisterPairLow());
       __ str(source.AsArm().AsRegisterPairHigh(),
-             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize)));
     } else {
       DCHECK(source.IsDoubleStackSlot());
       __ ldr(calling_convention.GetRegisterAt(argument_index), Address(SP, source.GetStackIndex()));
       __ ldr(R0, Address(SP, source.GetHighStackIndex(kArmWordSize)));
-      __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1)));
+      __ str(R0, Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize)));
     }
   } else {
     DCHECK(destination.IsDoubleStackSlot());
@@ -228,7 +201,7 @@
       __ str(calling_convention.GetRegisterAt(argument_index),
              Address(SP, destination.GetStackIndex()));
       __ ldr(R0,
-             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+             Address(SP, calling_convention.GetStackOffsetOf(argument_index + 1, kArmWordSize) + GetFrameSize()));
       __ str(R0, Address(SP, destination.GetHighStackIndex(kArmWordSize)));
     } else {
       DCHECK(source.IsDoubleStackSlot());
@@ -694,39 +667,13 @@
 
 void LocationsBuilderARM::VisitParameterValue(HParameterValue* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  InvokeDexCallingConvention calling_convention;
-  uint32_t argument_index = instruction->GetIndex();
-  switch (instruction->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->SetOut(ArmCoreLocation(calling_convention.GetRegisterAt(argument_index)));
-      } else {
-        locations->SetOut(Location::StackSlot(
-            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
-      }
-      break;
-
-    case Primitive::kPrimLong:
-      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
-        locations->SetOut(Location::RegisterLocation(ArmManagedRegister::FromRegisterPair(
-            (calling_convention.GetRegisterPairAt(argument_index)))));
-      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
-        // Spanning a register and a stack slot. Use the quick parameter kind.
-        locations->SetOut(Location::QuickParameter(argument_index));
-      } else {
-        locations->SetOut(Location::DoubleStackSlot(
-            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
-      }
-      break;
-
-    default:
-      LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType();
+  Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
+  if (location.IsStackSlot()) {
+    location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
+  } else if (location.IsDoubleStackSlot()) {
+    location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
   }
+  locations->SetOut(location);
   instruction->SetLocations(locations);
 }
 
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 3fbe631..ed35f94 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -28,6 +28,37 @@
 
 static constexpr size_t kArmWordSize = 4;
 
+static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
+static constexpr RegisterPair kParameterCorePairRegisters[] = { R1_R2, R2_R3 };
+static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
+
+class InvokeDexCallingConvention : public CallingConvention<Register> {
+ public:
+  InvokeDexCallingConvention()
+      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
+
+  RegisterPair GetRegisterPairAt(size_t argument_index) {
+    DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
+    return kParameterCorePairRegisters[argument_index];
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
+};
+
+class InvokeDexCallingConventionVisitor {
+ public:
+  InvokeDexCallingConventionVisitor() : gp_index_(0) {}
+
+  Location GetNextLocation(Primitive::Type type);
+
+ private:
+  InvokeDexCallingConvention calling_convention;
+  uint32_t gp_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
+};
+
 class LocationsBuilderARM : public HGraphVisitor {
  public:
   explicit LocationsBuilderARM(HGraph* graph, CodeGeneratorARM* codegen)
@@ -42,6 +73,7 @@
 
  private:
   CodeGeneratorARM* const codegen_;
+  InvokeDexCallingConventionVisitor parameter_visitor_;
 
   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderARM);
 };
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 7b3d31d..1142631 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -49,10 +49,13 @@
   static const int kFakeReturnRegister = 8;
   core_spill_mask_ |= (1 << kFakeReturnRegister);
 
-  // Add the current ART method to the frame size, the return PC, and the filler.
-  SetFrameSize(RoundUp((
-      GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs() + 3) * kX86WordSize,
+  SetFrameSize(RoundUp(
+      (GetGraph()->GetMaximumNumberOfOutVRegs() + GetGraph()->GetNumberOfVRegs()) * kVRegSize
+      + kVRegSize  // filler
+      + kX86WordSize  // Art method
+      + kNumberOfPushedRegistersAtEntry * kX86WordSize,
       kStackAlignment));
+
   // The return PC has already been pushed on the stack.
   __ subl(ESP, Immediate(GetFrameSize() - kNumberOfPushedRegistersAtEntry * kX86WordSize));
   __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
@@ -77,34 +80,16 @@
   if (reg_number >= number_of_vregs - number_of_in_vregs) {
     // Local is a parameter of the method. It is stored in the caller's frame.
     return GetFrameSize() + kX86WordSize  // ART method
-                          + (reg_number - number_of_vregs + number_of_in_vregs) * kX86WordSize;
+                          + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
   } else {
     // Local is a temporary in this method. It is stored in this method's frame.
     return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
-                          - kX86WordSize  // filler.
-                          - (number_of_vregs * kX86WordSize)
-                          + (reg_number * kX86WordSize);
+                          - kVRegSize  // filler.
+                          - (number_of_vregs * kVRegSize)
+                          + (reg_number * kVRegSize);
   }
 }
 
-static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX };
-static constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX };
-static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
-
-class InvokeDexCallingConvention : public CallingConvention<Register> {
- public:
-  InvokeDexCallingConvention()
-      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
-
-  RegisterPair GetRegisterPairAt(size_t argument_index) {
-    DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
-    return kParameterCorePairRegisters[argument_index];
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
-};
-
 static constexpr Register kRuntimeParameterCoreRegisters[] = { EAX, ECX, EDX };
 static constexpr size_t kRuntimeParameterCoreRegistersLength =
     arraysize(kRuntimeParameterCoreRegisters);
@@ -119,57 +104,46 @@
   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));
-        }
+Location InvokeDexCallingConventionVisitor::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, kX86WordSize));
       }
-
-      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();
+
+    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, kX86WordSize));
+      }
+    }
+
+    case Primitive::kPrimDouble:
+    case Primitive::kPrimFloat:
+      LOG(FATAL) << "Unimplemented parameter type " << type;
+      break;
+
+    case Primitive::kPrimVoid:
+      LOG(FATAL) << "Unexpected parameter type " << type;
+      break;
   }
-
- private:
-  InvokeDexCallingConvention calling_convention;
-  uint32_t gp_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
-};
+  return Location();
+}
 
 void CodeGeneratorX86::Move32(Location destination, Location source) {
   if (source.Equals(destination)) {
@@ -206,9 +180,8 @@
       InvokeDexCallingConvention calling_convention;
       __ movl(destination.AsX86().AsRegisterPairLow(),
               calling_convention.GetRegisterAt(argument_index));
-      __ movl(destination.AsX86().AsRegisterPairHigh(),
-              Address(ESP,
-                      calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+      __ movl(destination.AsX86().AsRegisterPairHigh(), Address(ESP,
+          calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
     } else {
       DCHECK(source.IsDoubleStackSlot());
       __ movl(destination.AsX86().AsRegisterPairLow(), Address(ESP, source.GetStackIndex()));
@@ -220,14 +193,14 @@
     uint32_t argument_index = destination.GetQuickParameterIndex();
     if (source.IsRegister()) {
       __ movl(calling_convention.GetRegisterAt(argument_index), source.AsX86().AsRegisterPairLow());
-      __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)),
+      __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)),
               source.AsX86().AsRegisterPairHigh());
     } else {
       DCHECK(source.IsDoubleStackSlot());
       __ movl(calling_convention.GetRegisterAt(argument_index),
               Address(ESP, source.GetStackIndex()));
       __ movl(EAX, Address(ESP, source.GetHighStackIndex(kX86WordSize)));
-      __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1)), EAX);
+      __ movl(Address(ESP, calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize)), EAX);
     }
   } else {
     if (source.IsRegister()) {
@@ -239,9 +212,8 @@
       uint32_t argument_index = source.GetQuickParameterIndex();
       __ movl(Address(ESP, destination.GetStackIndex()),
               calling_convention.GetRegisterAt(argument_index));
-      __ movl(EAX,
-              Address(ESP,
-                      calling_convention.GetStackOffsetOf(argument_index + 1) + GetFrameSize()));
+      __ movl(EAX, Address(ESP,
+          calling_convention.GetStackOffsetOf(argument_index + 1, kX86WordSize) + GetFrameSize()));
       __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), EAX);
     } else {
       DCHECK(source.IsDoubleStackSlot());
@@ -688,38 +660,13 @@
 
 void LocationsBuilderX86::VisitParameterValue(HParameterValue* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  InvokeDexCallingConvention calling_convention;
-  uint32_t argument_index = instruction->GetIndex();
-  switch (instruction->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->SetOut(X86CpuLocation(calling_convention.GetRegisterAt(argument_index)));
-      } else {
-        locations->SetOut(Location::StackSlot(
-            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
-      }
-      break;
-
-    case Primitive::kPrimLong:
-      if (argument_index + 1 < calling_convention.GetNumberOfRegisters()) {
-        locations->SetOut(Location::RegisterLocation(X86ManagedRegister::FromRegisterPair(
-            (calling_convention.GetRegisterPairAt(argument_index)))));
-      } else if (argument_index + 1 == calling_convention.GetNumberOfRegisters()) {
-        locations->SetOut(Location::QuickParameter(argument_index));
-      } else {
-        locations->SetOut(Location::DoubleStackSlot(
-            calling_convention.GetStackOffsetOf(argument_index) + codegen_->GetFrameSize()));
-      }
-      break;
-
-    default:
-      LOG(FATAL) << "Unimplemented parameter type " << instruction->GetType();
+  Location location = parameter_visitor_.GetNextLocation(instruction->GetType());
+  if (location.IsStackSlot()) {
+    location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
+  } else if (location.IsDoubleStackSlot()) {
+    location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
   }
+  locations->SetOut(location);
   instruction->SetLocations(locations);
 }
 
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 9108f80..f22890e 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -28,6 +28,37 @@
 
 class CodeGeneratorX86;
 
+static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX };
+static constexpr RegisterPair kParameterCorePairRegisters[] = { ECX_EDX, EDX_EBX };
+static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
+
+class InvokeDexCallingConvention : public CallingConvention<Register> {
+ public:
+  InvokeDexCallingConvention()
+      : CallingConvention(kParameterCoreRegisters, kParameterCoreRegistersLength) {}
+
+  RegisterPair GetRegisterPairAt(size_t argument_index) {
+    DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
+    return kParameterCorePairRegisters[argument_index];
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
+};
+
+class InvokeDexCallingConventionVisitor {
+ public:
+  InvokeDexCallingConventionVisitor() : gp_index_(0) {}
+
+  Location GetNextLocation(Primitive::Type type);
+
+ private:
+  InvokeDexCallingConvention calling_convention;
+  uint32_t gp_index_;
+
+  DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor);
+};
+
 class LocationsBuilderX86 : public HGraphVisitor {
  public:
   LocationsBuilderX86(HGraph* graph, CodeGeneratorX86* codegen)
@@ -42,6 +73,7 @@
 
  private:
   CodeGeneratorX86* const codegen_;
+  InvokeDexCallingConventionVisitor parameter_visitor_;
 
   DISALLOW_COPY_AND_ASSIGN(LocationsBuilderX86);
 };