Don't copy fill array data to quick literal pool.

Currently quick copies the fill array data from the dex file to the literal
pool. It then has to go through hoops to pass this PC relative address down
to out-of-line code. Instead, pass the offset of the table to the out-of-line
code and use the CodeItem data associated with the ArtMethod. This reduces
the size of oat code while greatly simplifying it.
Unify the FillArrayData implementation in quick, portable and the interpreters.

Change-Id: I9c6971cf46285fbf197856627368c0185fdc98ca
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 835d6e2..7b90339 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -344,4 +344,28 @@
     return zero;
   }
 }
+
+bool FillArrayData(mirror::Object* obj, const Instruction::ArrayDataPayload* payload) {
+  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
+  if (UNLIKELY(obj == nullptr)) {
+    ThrowNullPointerException(nullptr, "null array in FILL_ARRAY_DATA");
+    return false;
+  }
+  mirror::Array* array = obj->AsArray();
+  DCHECK(!array->IsObjectArray());
+  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
+    Thread* self = Thread::Current();
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    self->ThrowNewExceptionF(throw_location,
+                             "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                             array->GetLength(), payload->element_count);
+    return false;
+  }
+  // Copy data from dex file to memory assuming both are little endian.
+  uint32_t size_in_bytes = payload->element_count * payload->element_width;
+  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
+  return true;
+}
+
 }  // namespace art
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 08edecf..ce34993 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -22,6 +22,7 @@
 
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "dex_instruction.h"
 #include "gc/allocator_type.h"
 #include "invoke_type.h"
 #include "jvalue.h"
@@ -179,6 +180,9 @@
                                     std::vector<jvalue>& args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+bool FillArrayData(mirror::Object* obj, const Instruction::ArrayDataPayload* payload)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 // Entry point for deoptimization.
 extern "C" void art_quick_deoptimize();
 static inline uintptr_t GetQuickDeoptimizationEntryPoint() {
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
index 686954b..f0ad6de 100644
--- a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
@@ -15,9 +15,8 @@
  */
 
 #include "dex_instruction.h"
-#include "entrypoints/entrypoint_utils-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/art_method-inl.h"
-#include "mirror/object-inl.h"
 
 namespace art {
 
@@ -29,22 +28,7 @@
   const DexFile::CodeItem* code_item = method->GetCodeItem();
   const Instruction::ArrayDataPayload* payload =
       reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset);
-  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
-  if (UNLIKELY(array == NULL)) {
-    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-    return;  // Error
-  }
-  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-    Thread* self = Thread::Current();
-    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count - 1);
-    return;  // Error
-  }
-  uint32_t size_in_bytes = payload->element_count * payload->element_width;
-  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
+  FillArrayData(array, payload);
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index 4ec2879..06bbabc 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -15,49 +15,25 @@
  */
 
 #include "callee_save_frame.h"
-#include "common_throws.h"
-#include "dex_instruction.h"
 #include "mirror/array.h"
-#include "mirror/object-inl.h"
+#include "mirror/art_method-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 
 namespace art {
 
 /*
- * Fill the array with predefined constant values, throwing exceptions if the array is null or
- * not of sufficient length.
- *
- * NOTE: When dealing with a raw dex file, the data to be copied uses
- * little-endian ordering.  Require that oat2dex do any required swapping
- * so this routine can get by with a memcpy().
- *
- * Format of the data:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
+ * Handle fill array data by copying appropriate part of dex file into array.
  */
-extern "C" int artHandleFillArrayDataFromCode(mirror::Array* array,
-                                              const Instruction::ArrayDataPayload* payload,
-                                              Thread* self, StackReference<mirror::ArtMethod>* sp)
+extern "C" int artHandleFillArrayDataFromCode(uint32_t payload_offset, mirror::Array* array,
+                                              mirror::ArtMethod* method, Thread* self,
+                                              StackReference<mirror::ArtMethod>* sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
-  if (UNLIKELY(array == NULL)) {
-    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
-    return -1;  // Error
-  }
-  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
-    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
-                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count - 1);
-    return -1;  // Error
-  }
-  uint32_t size_in_bytes = payload->element_count * payload->element_width;
-  memcpy(array->GetRawData(payload->element_width, 0), payload->data, size_in_bytes);
-  return 0;  // Success
+  const uint16_t* const insns = method->GetCodeItem()->insns_;
+  const Instruction::ArrayDataPayload* payload =
+      reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + payload_offset);
+  bool success = FillArrayData(array, payload);
+  return success ? 0 : -1;
 }
 
 }  // namespace art