ART: Compress LengthPrefixedArray on 32-bit targets.

Previously, the LengthPrefixedArray<ArtMethod> on 32-bit
targets contained a 64-bit length field followed by the
ArtMethod elements with size only a multiple of 4, not 8.
Consequently, an odd-length array broke the alignment for
the following array which would have the 64-bit length
placed at an unaligned address.

To fix that, we make the length field 32-bit and explicitly
pass the alignment information to the LengthPrefixedArray.
This also makes the 32-bit boot image a bit smaller.
On Nexus 5, AOSP, ToT, the field section is 11528B smaller
and the method section is 21036B smaller. 64-bit targets
should see the same savings for the field section but no
difference for the methods section.

Change-Id: I3e03e7b94129025c8a1c117c27645a34dec516d2
diff --git a/runtime/length_prefixed_array.h b/runtime/length_prefixed_array.h
index 2b2e8d3..d9bc656 100644
--- a/runtime/length_prefixed_array.h
+++ b/runtime/length_prefixed_array.h
@@ -21,6 +21,8 @@
 
 #include "linear_alloc.h"
 #include "stride_iterator.h"
+#include "base/bit_utils.h"
+#include "base/casts.h"
 #include "base/iteration_range.h"
 
 namespace art {
@@ -28,29 +30,35 @@
 template<typename T>
 class LengthPrefixedArray {
  public:
-  explicit LengthPrefixedArray(uint64_t length) : length_(length) {}
+  explicit LengthPrefixedArray(size_t length)
+      : length_(dchecked_integral_cast<uint32_t>(length)) {}
 
-  T& At(size_t index, size_t element_size = sizeof(T)) {
+  T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
     DCHECK_LT(index, length_);
-    return *reinterpret_cast<T*>(&data_[0] + index * element_size);
+    return AtUnchecked(index, element_size, alignment);
   }
 
-  StrideIterator<T> Begin(size_t element_size = sizeof(T)) {
-    return StrideIterator<T>(reinterpret_cast<T*>(&data_[0]), element_size);
+  StrideIterator<T> Begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
+    return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
   }
 
-  StrideIterator<T> End(size_t element_size = sizeof(T)) {
-    return StrideIterator<T>(reinterpret_cast<T*>(&data_[0] + element_size * length_),
-                             element_size);
+  StrideIterator<T> End(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
+    return StrideIterator<T>(&AtUnchecked(length_, element_size, alignment), element_size);
   }
 
-  static size_t OffsetOfElement(size_t index, size_t element_size = sizeof(T)) {
-    return offsetof(LengthPrefixedArray<T>, data_) + index * element_size;
+  static size_t OffsetOfElement(size_t index,
+                                size_t element_size = sizeof(T),
+                                size_t alignment = alignof(T)) {
+    DCHECK_ALIGNED_PARAM(element_size, alignment);
+    return RoundUp(offsetof(LengthPrefixedArray<T>, data), alignment) + index * element_size;
   }
 
-  // Alignment is the caller's responsibility.
-  static size_t ComputeSize(size_t num_elements, size_t element_size = sizeof(T)) {
-    return OffsetOfElement(num_elements, element_size);
+  static size_t ComputeSize(size_t num_elements,
+                            size_t element_size = sizeof(T),
+                            size_t alignment = alignof(T)) {
+    size_t result = OffsetOfElement(num_elements, element_size, alignment);
+    DCHECK_ALIGNED_PARAM(result, alignment);
+    return result;
   }
 
   uint64_t Length() const {
@@ -58,21 +66,26 @@
   }
 
   // Update the length but does not reallocate storage.
-  void SetLength(uint64_t length) {
-    length_ = length;
+  void SetLength(size_t length) {
+    length_ = dchecked_integral_cast<uint32_t>(length);
   }
 
  private:
-  uint64_t length_;  // 64 bits for 8 byte alignment of data_.
-  uint8_t data_[0];
+  T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
+    return *reinterpret_cast<T*>(
+        reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
+  }
+
+  uint32_t length_;
+  uint8_t data[0];
 };
 
 // Returns empty iteration range if the array is null.
 template<typename T>
 IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
-    LengthPrefixedArray<T>* arr, size_t element_size) {
+    LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
   return arr != nullptr ?
-      MakeIterationRange(arr->Begin(element_size), arr->End(element_size)) :
+      MakeIterationRange(arr->Begin(element_size, alignment), arr->End(element_size, alignment)) :
       MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
 }