Merge "Change to implement fill-array-data with runtime function." into ics-mr1-plus-art
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 6d4b56b..a2da2b6 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -144,6 +144,10 @@
                                                    %JavaObject*)
 
 
+declare void @art_fill_array_data_from_code(%JavaObject*, i32,
+                                            %JavaObject*, i32)
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Type Checking, in the nature of casting
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 1237ec0..b3963ef 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -1,4 +1,4 @@
-// Generated with tools/gen_art_module_cc.sh
+// Generated with ../tools/gen_art_module_cc.sh
 
 
 #pragma GCC diagnostic ignored "-Wframe-larger-than="
@@ -278,52 +278,62 @@
 
 std::vector<Type*>FuncTy_29_args;
 FuncTy_29_args.push_back(PointerTy_1);
+FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32));
 FuncTy_29_args.push_back(PointerTy_1);
+FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32));
 FunctionType* FuncTy_29 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/Type::getVoidTy(mod->getContext()),
  /*Params=*/FuncTy_29_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_30_args;
-FuncTy_30_args.push_back(Type::getDoubleTy(mod->getContext()));
+FuncTy_30_args.push_back(PointerTy_1);
+FuncTy_30_args.push_back(PointerTy_1);
 FunctionType* FuncTy_30 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_30_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_31_args;
 FuncTy_31_args.push_back(Type::getDoubleTy(mod->getContext()));
 FunctionType* FuncTy_31 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_31_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_32_args;
-FuncTy_32_args.push_back(Type::getFloatTy(mod->getContext()));
+FuncTy_32_args.push_back(Type::getDoubleTy(mod->getContext()));
 FunctionType* FuncTy_32 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_32_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_33_args;
 FuncTy_33_args.push_back(Type::getFloatTy(mod->getContext()));
 FunctionType* FuncTy_33 = FunctionType::get(
- /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
  /*Params=*/FuncTy_33_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_34_args;
-FuncTy_34_args.push_back(PointerTy_1);
+FuncTy_34_args.push_back(Type::getFloatTy(mod->getContext()));
 FunctionType* FuncTy_34 = FunctionType::get(
- /*Result=*/PointerTy_1,
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
  /*Params=*/FuncTy_34_args,
  /*isVarArg=*/false);
 
 std::vector<Type*>FuncTy_35_args;
 FuncTy_35_args.push_back(PointerTy_1);
 FunctionType* FuncTy_35 = FunctionType::get(
- /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Result=*/PointerTy_1,
  /*Params=*/FuncTy_35_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_36_args;
+FuncTy_36_args.push_back(PointerTy_1);
+FunctionType* FuncTy_36 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_36_args,
  /*isVarArg=*/true);
 
 
@@ -857,10 +867,21 @@
 AttrListPtr func_art_decode_jobject_in_thread_PAL;
 func_art_decode_jobject_in_thread->setAttributes(func_art_decode_jobject_in_thread_PAL);
 
+Function* func_art_fill_array_data_from_code = mod->getFunction("art_fill_array_data_from_code");
+if (!func_art_fill_array_data_from_code) {
+func_art_fill_array_data_from_code = Function::Create(
+ /*Type=*/FuncTy_29,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_fill_array_data_from_code", mod); // (external, no body)
+func_art_fill_array_data_from_code->setCallingConv(CallingConv::C);
+}
+AttrListPtr func_art_fill_array_data_from_code_PAL;
+func_art_fill_array_data_from_code->setAttributes(func_art_fill_array_data_from_code_PAL);
+
 Function* func_art_is_assignable_from_code = mod->getFunction("art_is_assignable_from_code");
 if (!func_art_is_assignable_from_code) {
 func_art_is_assignable_from_code = Function::Create(
- /*Type=*/FuncTy_29,
+ /*Type=*/FuncTy_30,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_is_assignable_from_code", mod); // (external, no body)
 func_art_is_assignable_from_code->setCallingConv(CallingConv::C);
@@ -893,7 +914,7 @@
 Function* func_D2L = mod->getFunction("D2L");
 if (!func_D2L) {
 func_D2L = Function::Create(
- /*Type=*/FuncTy_30,
+ /*Type=*/FuncTy_31,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"D2L", mod); // (external, no body)
 func_D2L->setCallingConv(CallingConv::C);
@@ -904,7 +925,7 @@
 Function* func_D2I = mod->getFunction("D2I");
 if (!func_D2I) {
 func_D2I = Function::Create(
- /*Type=*/FuncTy_31,
+ /*Type=*/FuncTy_32,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"D2I", mod); // (external, no body)
 func_D2I->setCallingConv(CallingConv::C);
@@ -915,7 +936,7 @@
 Function* func_F2L = mod->getFunction("F2L");
 if (!func_F2L) {
 func_F2L = Function::Create(
- /*Type=*/FuncTy_32,
+ /*Type=*/FuncTy_33,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"F2L", mod); // (external, no body)
 func_F2L->setCallingConv(CallingConv::C);
@@ -926,7 +947,7 @@
 Function* func_F2I = mod->getFunction("F2I");
 if (!func_F2I) {
 func_F2I = Function::Create(
- /*Type=*/FuncTy_33,
+ /*Type=*/FuncTy_34,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"F2I", mod); // (external, no body)
 func_F2I->setCallingConv(CallingConv::C);
@@ -948,7 +969,7 @@
 Function* func_art_fix_stub_from_code = mod->getFunction("art_fix_stub_from_code");
 if (!func_art_fix_stub_from_code) {
 func_art_fix_stub_from_code = Function::Create(
- /*Type=*/FuncTy_34,
+ /*Type=*/FuncTy_35,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_fix_stub_from_code", mod); // (external, no body)
 func_art_fix_stub_from_code->setCallingConv(CallingConv::C);
@@ -959,7 +980,7 @@
 Function* func_art_proxy_invoke_handler_from_code = mod->getFunction("art_proxy_invoke_handler_from_code");
 if (!func_art_proxy_invoke_handler_from_code) {
 func_art_proxy_invoke_handler_from_code = Function::Create(
- /*Type=*/FuncTy_35,
+ /*Type=*/FuncTy_36,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_proxy_invoke_handler_from_code", mod); // (external, no body)
 func_art_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C);
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 2c0fef1..e444811 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -1893,65 +1893,31 @@
     reinterpret_cast<const Instruction::ArrayDataPayload*>(
         code_item_->insns_ + payload_offset);
 
-  uint32_t size_in_bytes = payload->element_width * payload->element_count;
-
-  // Load and check the array
+  // Load array object
   llvm::Value* array_addr = EmitLoadDalvikReg(dec_insn.vA, kObject, kAccurate);
 
-  EmitGuard_NullPointerException(dex_pc, array_addr);
+  if (payload->element_count == 0) {
+    // When the number of the elements in the payload is zero, we don't have
+    // to copy any numbers.  However, we should check whether the array object
+    // address is equal to null or not.
+    EmitGuard_NullPointerException(dex_pc, array_addr);
+  } else {
+    // To save the code size, we are going to call the runtime function to
+    // copy the content from DexFile.
 
-  if (payload->element_count > 0) {
-    // Test: Is array length big enough?
-    llvm::Constant* last_index = irb_.getJInt(payload->element_count - 1);
+    // NOTE: We will check for the NullPointerException in the runtime.
 
-    EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, last_index);
+    llvm::Function* runtime_func = irb_.GetRuntime(FillArrayData);
 
-    // Get array data field
-    llvm::Value* data_field_offset_value =
-      irb_.getPtrEquivInt(Array::DataOffset(payload->element_width).Int32Value());
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
 
-    llvm::Value* data_field_addr =
-      irb_.CreatePtrDisp(array_addr, data_field_offset_value,
-                         irb_.getInt8Ty()->getPointerTo());
+    EmitUpdateDexPC(dex_pc);
 
-    // Emit payload to bitcode constant pool
-    std::vector<llvm::Constant*> const_pool_data;
-    for (uint32_t i = 0; i < size_in_bytes; ++i) {
-      const_pool_data.push_back(irb_.getInt8(payload->data[i]));
-    }
+    irb_.CreateCall4(runtime_func,
+                     method_object_addr, irb_.getInt32(dex_pc),
+                     array_addr, irb_.getInt32(payload_offset));
 
-    llvm::Constant* const_pool_data_array_value = llvm::ConstantArray::get(
-      llvm::ArrayType::get(irb_.getInt8Ty(), size_in_bytes), const_pool_data);
-
-    llvm::Value* const_pool_data_array_addr =
-      new llvm::GlobalVariable(*module_,
-                               const_pool_data_array_value->getType(),
-                               false, llvm::GlobalVariable::InternalLinkage,
-                               const_pool_data_array_value,
-                               "array_data_payload");
-
-    // Find the memcpy intrinsic
-    llvm::Type* memcpy_arg_types[] = {
-      llvm::Type::getInt8Ty(*context_)->getPointerTo(),
-      llvm::Type::getInt8Ty(*context_)->getPointerTo(),
-      llvm::Type::getInt32Ty(*context_)
-    };
-
-    llvm::Function* memcpy_intrinsic =
-      llvm::Intrinsic::getDeclaration(module_,
-                                      llvm::Intrinsic::memcpy,
-                                      memcpy_arg_types);
-
-    // Copy now!
-    llvm::Value *args[] = {
-      data_field_addr,
-      irb_.CreateConstGEP2_32(const_pool_data_array_addr, 0, 0),
-      irb_.getInt32(size_in_bytes),
-      irb_.getInt32(0), // alignment: no guarantee
-      irb_.getFalse() // is_volatile: false
-    };
-
-    irb_.CreateCall(memcpy_intrinsic, args);
+    EmitGuard_ExceptionLandingPad(dex_pc);
   }
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
diff --git a/src/compiler_llvm/runtime_support_func_list.h b/src/compiler_llvm/runtime_support_func_list.h
index 7a51b90..5cf2374 100644
--- a/src/compiler_llvm/runtime_support_func_list.h
+++ b/src/compiler_llvm/runtime_support_func_list.h
@@ -59,6 +59,7 @@
   V(Get64Instance, art_get64_instance_from_code) \
   V(GetObjectInstance, art_get_obj_instance_from_code) \
   V(InitializeStaticStorage, art_initialize_static_storage_from_code) \
+  V(FillArrayData, art_fill_array_data_from_code) \
   V(IsExceptionPending, art_is_exception_pending_from_code) \
   V(FindCatchBlock, art_find_catch_block_from_code) \
   V(MarkGCCard, art_mark_gc_card_from_code) \
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index bdfd222..d0f6e8c 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -15,6 +15,8 @@
  */
 
 #include "class_linker.h"
+#include "dex_file.h"
+#include "dex_instruction.h"
 #include "nth_caller_visitor.h"
 #include "object.h"
 #include "object_utils.h"
@@ -496,6 +498,42 @@
   return thread->DecodeJObject(obj);
 }
 
+void art_fill_array_data_from_code(Method* method, uint32_t dex_pc,
+                                   Array* array, uint32_t payload_offset) {
+  // Test: Is array equal to null? (Guard NullPointerException)
+  if (UNLIKELY(array == NULL)) {
+    art_throw_null_pointer_exception_from_code(dex_pc);
+    return;
+  }
+
+  // Find the payload from the CodeItem
+  MethodHelper mh(method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+
+  DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
+
+  const Instruction::ArrayDataPayload* payload =
+    reinterpret_cast<const Instruction::ArrayDataPayload*>(
+        code_item->insns_ + payload_offset);
+
+  DCHECK_EQ(payload->ident,
+            static_cast<uint16_t>(Instruction::kArrayDataSignature));
+
+  // Test: Is array big enough?
+  uint32_t array_len = static_cast<uint32_t>(array->GetLength());
+  if (UNLIKELY(array_len < payload->element_count)) {
+    int32_t last_index = payload->element_count - 1;
+    art_throw_array_bounds_from_code(array_len, last_index);
+    return;
+  }
+
+  // Copy the data
+  size_t size = payload->element_width * payload->element_count;
+  memcpy(array->GetRawData(payload->element_width), payload->data, size);
+}
+
+
+
 //----------------------------------------------------------------------------
 // Type checking, in the nature of casting
 //----------------------------------------------------------------------------