Add support for new-instance and invoke-direct.

Change-Id: I2daed646904f7711972a7da15d88be7573426932
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 0554876..d90405a 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -193,7 +193,8 @@
       break;
     }
 
-    case Instruction::INVOKE_STATIC: {
+    case Instruction::INVOKE_STATIC:
+    case Instruction::INVOKE_DIRECT: {
       uint32_t method_idx = instruction.VRegB_35c();
       const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
       uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
@@ -204,6 +205,7 @@
         return false;
       }
 
+      // Treat invoke-direct like static calls for now.
       HInvokeStatic* invoke = new (arena_) HInvokeStatic(
           arena_, number_of_arguments, dex_offset, method_idx);
 
@@ -221,7 +223,8 @@
       break;
     }
 
-    case Instruction::INVOKE_STATIC_RANGE: {
+    case Instruction::INVOKE_STATIC_RANGE:
+    case Instruction::INVOKE_DIRECT_RANGE: {
       uint32_t method_idx = instruction.VRegB_3rc();
       const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
       uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
@@ -232,6 +235,7 @@
         return false;
       }
 
+      // Treat invoke-direct like static calls for now.
       HInvokeStatic* invoke = new (arena_) HInvokeStatic(
           arena_, number_of_arguments, dex_offset, method_idx);
       int32_t register_index = instruction.VRegC();
@@ -277,6 +281,13 @@
       break;
     }
 
+    case Instruction::NEW_INSTANCE: {
+      current_block_->AddInstruction(
+          new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c()));
+      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+      break;
+    }
+
     case Instruction::NOP:
       break;
 
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 09d6f7b..0aeeef7 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -185,7 +185,7 @@
 }
 
 static constexpr Register kParameterCoreRegisters[] = { R1, R2, R3 };
-static constexpr int kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
+static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
 
 class InvokeStaticCallingConvention : public CallingConvention<Register> {
  public:
@@ -287,5 +287,37 @@
   }
 }
 
+static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1 };
+static constexpr size_t kRuntimeParameterCoreRegistersLength =
+    arraysize(kRuntimeParameterCoreRegisters);
+
+class InvokeRuntimeCallingConvention : public CallingConvention<Register> {
+ public:
+  InvokeRuntimeCallingConvention()
+      : CallingConvention(kRuntimeParameterCoreRegisters,
+                          kRuntimeParameterCoreRegistersLength) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
+};
+
+void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+  locations->SetOut(Location(R0));
+  instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) {
+  InvokeRuntimeCallingConvention calling_convention;
+  LoadCurrentMethod(calling_convention.GetRegisterAt(1));
+  __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex());
+
+  int32_t offset = QUICK_ENTRYPOINT_OFFSET(kWordSize, pAllocObjectWithAccessCheck).Int32Value();
+  __ ldr(LR, Address(TR, offset));
+  __ blx(LR);
+
+  codegen_->RecordPcInfo(instruction->GetDexPc());
+}
+
 }  // namespace arm
 }  // namespace art
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 7b0a087..882541b 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -188,7 +188,7 @@
 }
 
 static constexpr Register kParameterCoreRegisters[] = { ECX, EDX, EBX };
-static constexpr int kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
+static constexpr size_t kParameterCoreRegistersLength = arraysize(kParameterCoreRegisters);
 
 class InvokeStaticCallingConvention : public CallingConvention<Register> {
  public:
@@ -199,6 +199,20 @@
   DISALLOW_COPY_AND_ASSIGN(InvokeStaticCallingConvention);
 };
 
+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);
   InvokeStaticCallingConvention calling_convention;
@@ -284,5 +298,22 @@
   }
 }
 
+void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+  locations->SetOut(Location(EAX));
+  instruction->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorX86::VisitNewInstance(HNewInstance* instruction) {
+  InvokeRuntimeCallingConvention calling_convention;
+  LoadCurrentMethod(calling_convention.GetRegisterAt(1));
+  __ movl(calling_convention.GetRegisterAt(0),
+          Immediate(instruction->GetTypeIndex()));
+
+  __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kWordSize, pAllocObjectWithAccessCheck)));
+
+  codegen_->RecordPcInfo(instruction->GetDexPc());
+}
+
 }  // namespace x86
 }  // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 2b21905..830d0c7 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -201,6 +201,7 @@
   M(InvokeStatic)                                          \
   M(LoadLocal)                                             \
   M(Local)                                                 \
+  M(NewInstance)                                           \
   M(PushArgument)                                          \
   M(Return)                                                \
   M(ReturnVoid)                                            \
@@ -593,7 +594,7 @@
 
 class HInvoke : public HInstruction {
  public:
-  HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, int32_t dex_pc)
+  HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, uint32_t dex_pc)
     : inputs_(arena, number_of_arguments),
       dex_pc_(dex_pc) {
     inputs_.SetSize(number_of_arguments);
@@ -606,11 +607,11 @@
     inputs_.Put(index, argument);
   }
 
-  int32_t GetDexPc() const { return dex_pc_; }
+  uint32_t GetDexPc() const { return dex_pc_; }
 
  protected:
   GrowableArray<HInstruction*> inputs_;
-  const int32_t dex_pc_;
+  const uint32_t dex_pc_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(HInvoke);
@@ -620,8 +621,8 @@
  public:
   HInvokeStatic(ArenaAllocator* arena,
                 uint32_t number_of_arguments,
-                int32_t dex_pc,
-                int32_t index_in_dex_cache)
+                uint32_t dex_pc,
+                uint32_t index_in_dex_cache)
       : HInvoke(arena, number_of_arguments, dex_pc), index_in_dex_cache_(index_in_dex_cache) {}
 
   uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
@@ -634,6 +635,22 @@
   DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
 };
 
+class HNewInstance : public HTemplateInstruction<0> {
+ public:
+  HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
+
+  uint32_t GetDexPc() const { return dex_pc_; }
+  uint16_t GetTypeIndex() const { return type_index_; }
+
+  DECLARE_INSTRUCTION(NewInstance)
+
+ private:
+  const uint32_t dex_pc_;
+  const uint16_t type_index_;
+
+  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> {
diff --git a/test/401-optimizing-compiler/expected.txt b/test/401-optimizing-compiler/expected.txt
index 268da55..a65e544 100644
--- a/test/401-optimizing-compiler/expected.txt
+++ b/test/401-optimizing-compiler/expected.txt
@@ -4,3 +4,6 @@
 In static method with 7 args 1 2 3 4 5 6 7
 Forced GC
 java.lang.Error: Error
+Forced GC
+In static method with object arg class java.lang.Object
+Forced GC
diff --git a/test/401-optimizing-compiler/src/Main.java b/test/401-optimizing-compiler/src/Main.java
index 4031ff1..aa08137 100644
--- a/test/401-optimizing-compiler/src/Main.java
+++ b/test/401-optimizing-compiler/src/Main.java
@@ -26,6 +26,8 @@
       error = e;
     }
     System.out.println(error);
+
+    $opt$TestInvokeNew();
   }
 
   public static void $opt$TestInvokeStatic() {
@@ -37,6 +39,13 @@
     throwStaticMethod();
   }
 
+  public static void $opt$TestInvokeNew() {
+    Object o = new Object();
+    forceGCStaticMethod();
+    printStaticMethodWithObjectArg(o);
+    forceGCStaticMethod();
+  }
+
   public static void printStaticMethod() {
     System.out.println("In static method");
   }
@@ -55,6 +64,10 @@
         + a + " " + b + " " + c + " " + d + " " + e + " " + f + " " + g);
   }
 
+  public static void printStaticMethodWithObjectArg(Object a) {
+    System.out.println("In static method with object arg " + a.getClass());
+  }
+
   public static void forceGCStaticMethod() {
     Runtime.getRuntime().gc();
     Runtime.getRuntime().gc();