Clean up ArraySlice<>.

Remove constructors that take ranges (one of them created
ambiguity with the constructor taking just the length) and
add SubArray() to serve as a replacement API.

Remove the AsRange() function as the translation to the
IterationRange<> seems totally unnecessary, we can simply
return ArraySlice<> from the functions that used it.

Remove the At() function as the comparison with the
std::vector<>::at() is confusing given that we do not
use C++ exceptions.

Add some standard container API, i.e. nested types and
more functions.

Test: m test-art-host-gtest
Test: testrunner.py --host
Change-Id: Ifcd39222cf8f36b7ebf8029398ed7fc67aafcaf0
diff --git a/runtime/base/array_slice.h b/runtime/base/array_slice.h
index 32283d0..0da977d 100644
--- a/runtime/base/array_slice.h
+++ b/runtime/base/array_slice.h
@@ -17,7 +17,6 @@
 #ifndef ART_RUNTIME_BASE_ARRAY_SLICE_H_
 #define ART_RUNTIME_BASE_ARRAY_SLICE_H_
 
-#include "length_prefixed_array.h"
 #include "stride_iterator.h"
 #include "base/bit_utils.h"
 #include "base/casts.h"
@@ -27,9 +26,21 @@
 
 // An ArraySlice is an abstraction over an array or a part of an array of a particular type. It does
 // bounds checking and can be made from several common array-like structures in Art.
-template<typename T>
+template <typename T>
 class ArraySlice {
  public:
+  using value_type = T;
+  using reference = T&;
+  using const_reference = const T&;
+  using pointer = T*;
+  using const_pointer = const T*;
+  using iterator = StrideIterator<T>;
+  using const_iterator = StrideIterator<const T>;
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using difference_type = ptrdiff_t;
+  using size_type = size_t;
+
   // Create an empty array slice.
   ArraySlice() : array_(nullptr), size_(0), element_size_(0) {}
 
@@ -44,85 +55,74 @@
     DCHECK(array_ != nullptr || length == 0);
   }
 
-  // Create an array slice of the elements between start_offset and end_offset of the array with
-  // each element being element_size bytes long. Both start_offset and end_offset are in
-  // element_size units.
-  ArraySlice(T* array,
-             uint32_t start_offset,
-             uint32_t end_offset,
-             size_t element_size = sizeof(T))
-      : array_(nullptr),
-        size_(end_offset - start_offset),
-        element_size_(element_size) {
-    DCHECK(array_ != nullptr || size_ == 0);
-    DCHECK_LE(start_offset, end_offset);
-    if (size_ != 0) {
-      uintptr_t offset = start_offset * element_size_;
-      array_ = *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array) + offset);
-    }
-  }
+  // Iterators.
+  iterator begin() { return iterator(&AtUnchecked(0), element_size_); }
+  const_iterator begin() const { return const_iterator(&AtUnchecked(0), element_size_); }
+  const_iterator cbegin() const { return const_iterator(&AtUnchecked(0), element_size_); }
+  StrideIterator<T> end() { return StrideIterator<T>(&AtUnchecked(size_), element_size_); }
+  const_iterator end() const { return const_iterator(&AtUnchecked(size_), element_size_); }
+  const_iterator cend() const { return const_iterator(&AtUnchecked(size_), element_size_); }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+  const_reverse_iterator crbegin() const { return const_reverse_iterator(cend()); }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+  const_reverse_iterator crend() const { return const_reverse_iterator(cbegin()); }
 
-  // Create an array slice of the elements between start_offset and end_offset of the array with
-  // each element being element_size bytes long and having the given alignment. Both start_offset
-  // and end_offset are in element_size units.
-  ArraySlice(LengthPrefixedArray<T>* array,
-             uint32_t start_offset,
-             uint32_t end_offset,
-             size_t element_size = sizeof(T),
-             size_t alignment = alignof(T))
-      : array_(nullptr),
-        size_(end_offset - start_offset),
-        element_size_(element_size) {
-    DCHECK(array != nullptr || size_ == 0);
-    if (size_ != 0) {
-      DCHECK_LE(start_offset, end_offset);
-      DCHECK_LE(start_offset, array->size());
-      DCHECK_LE(end_offset, array->size());
-      array_ = &array->At(start_offset, element_size_, alignment);
-    }
-  }
+  // Size.
+  size_type size() const { return size_; }
+  bool empty() const { return size() == 0u; }
 
-  T& At(size_t index) {
+  // Element access. NOTE: Not providing at() and data().
+
+  reference operator[](size_t index) {
     DCHECK_LT(index, size_);
     return AtUnchecked(index);
   }
 
-  const T& At(size_t index) const {
+  const_reference operator[](size_t index) const {
     DCHECK_LT(index, size_);
     return AtUnchecked(index);
   }
 
-  T& operator[](size_t index) {
-    return At(index);
+  reference front() {
+    DCHECK(!empty());
+    return (*this)[0];
   }
 
-  const T& operator[](size_t index) const {
-    return At(index);
+  const_reference front() const {
+    DCHECK(!empty());
+    return (*this)[0];
   }
 
-  StrideIterator<T> begin() {
-    return StrideIterator<T>(&AtUnchecked(0), element_size_);
+  reference back() {
+    DCHECK(!empty());
+    return (*this)[size_ - 1u];
   }
 
-  StrideIterator<const T> begin() const {
-    return StrideIterator<const T>(&AtUnchecked(0), element_size_);
+  const_reference back() const {
+    DCHECK(!empty());
+    return (*this)[size_ - 1u];
   }
 
-  StrideIterator<T> end() {
-    return StrideIterator<T>(&AtUnchecked(size_), element_size_);
+  ArraySlice<T> SubArray(size_type pos) {
+    return SubArray(pos, size() - pos);
   }
 
-  StrideIterator<const T> end() const {
-    return StrideIterator<const T>(&AtUnchecked(size_), element_size_);
+  ArraySlice<const T> SubArray(size_type pos) const {
+    return SubArray(pos, size() - pos);
   }
 
-  IterationRange<StrideIterator<T>> AsRange() {
-    return size() != 0 ? MakeIterationRange(begin(), end())
-                       : MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
+  ArraySlice<T> SubArray(size_type pos, size_type length) {
+    DCHECK_LE(pos, size());
+    DCHECK_LE(length, size() - pos);
+    return ArraySlice<T>(&AtUnchecked(pos), length, element_size_);
   }
 
-  size_t size() const {
-    return size_;
+  ArraySlice<const T> SubArray(size_type pos, size_type length) const {
+    DCHECK_LE(pos, size());
+    DCHECK_LE(length, size() - pos);
+    return ArraySlice<const T>(&AtUnchecked(pos), length, element_size_);
   }
 
   size_t ElementSize() const {
diff --git a/runtime/base/length_prefixed_array.h b/runtime/base/length_prefixed_array.h
index 8060263..a570b81 100644
--- a/runtime/base/length_prefixed_array.h
+++ b/runtime/base/length_prefixed_array.h
@@ -65,7 +65,7 @@
                                 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;
+    return RoundUp(offsetof(LengthPrefixedArray<T>, data_), alignment) + index * element_size;
   }
 
   static size_t ComputeSize(size_t num_elements,
@@ -87,7 +87,7 @@
 
   // Clear the potentially uninitialized padding between the size_ and actual data.
   void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
-    size_t gap_offset = offsetof(LengthPrefixedArray<T>, data);
+    size_t gap_offset = offsetof(LengthPrefixedArray<T>, data_);
     size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset;
     memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size);
   }
@@ -104,7 +104,7 @@
   }
 
   uint32_t size_;
-  uint8_t data[0];
+  uint8_t data_[0];
 };
 
 // Returns empty iteration range if the array is null.
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 88a5a13..01fc9ce 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -136,7 +136,7 @@
         // Rely on the fact that the methods are contiguous to determine the index of the method in
         // the slice.
         int throws_index = (reinterpret_cast<uintptr_t>(proxy_method) -
-            reinterpret_cast<uintptr_t>(&virtual_methods.At(0))) / method_size;
+            reinterpret_cast<uintptr_t>(&virtual_methods[0])) / method_size;
         CHECK_LT(throws_index, static_cast<int>(num_virtuals));
         mirror::ObjectArray<mirror::Class>* declared_exceptions =
             proxy_class->GetProxyThrows()->Get(throws_index);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index c8d4557..12baf38 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -127,11 +127,9 @@
 }
 
 inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(PointerSize pointer_size) {
-  return ArraySlice<ArtMethod>(GetMethodsPtr(),
-                               GetDirectMethodsStartOffset(),
-                               GetVirtualMethodsStartOffset(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size,
+                                       GetDirectMethodsStartOffset(),
+                                       GetVirtualMethodsStartOffset());
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -141,11 +139,9 @@
 }
 
 inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size) {
-  return ArraySlice<ArtMethod>(GetMethodsPtr(),
-                               GetDirectMethodsStartOffset(),
-                               GetCopiedMethodsStartOffset(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size,
+                                       GetDirectMethodsStartOffset(),
+                                       GetCopiedMethodsStartOffset());
 }
 template<VerifyObjectFlags kVerifyFlags>
 inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(PointerSize pointer_size) {
@@ -155,11 +151,9 @@
 
 inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked(
     PointerSize pointer_size) {
-  return ArraySlice<ArtMethod>(GetMethodsPtr(),
-                               GetVirtualMethodsStartOffset(),
-                               GetCopiedMethodsStartOffset(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size,
+                                       GetVirtualMethodsStartOffset(),
+                                       GetCopiedMethodsStartOffset());
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -169,12 +163,9 @@
 }
 
 inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(PointerSize pointer_size) {
-  LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
-  return ArraySlice<ArtMethod>(methods,
-                               GetVirtualMethodsStartOffset(),
-                               NumMethods(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size,
+                                       GetVirtualMethodsStartOffset(),
+                                       NumMethods());
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -184,12 +175,7 @@
 }
 
 inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(PointerSize pointer_size) {
-  LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
-  return ArraySlice<ArtMethod>(methods,
-                               GetCopiedMethodsStartOffset(),
-                               NumMethods(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size, GetCopiedMethodsStartOffset(), NumMethods());
 }
 
 inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() {
@@ -200,14 +186,28 @@
 template<VerifyObjectFlags kVerifyFlags>
 inline ArraySlice<ArtMethod> Class::GetMethodsSlice(PointerSize pointer_size) {
   DCHECK(IsLoaded() || IsErroneous());
-  LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
-  return ArraySlice<ArtMethod>(methods,
-                               0,
-                               NumMethods(),
-                               ArtMethod::Size(pointer_size),
-                               ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size, 0, NumMethods());
 }
 
+inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(PointerSize pointer_size,
+                                                                  uint32_t start_offset,
+                                                                  uint32_t end_offset) {
+  DCHECK_LE(start_offset, end_offset);
+  DCHECK_LE(end_offset, NumMethods());
+  uint32_t size = end_offset - start_offset;
+  if (size == 0u) {
+    return ArraySlice<ArtMethod>();
+  }
+  LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
+  DCHECK(methods != nullptr);
+  DCHECK_LE(end_offset, methods->size());
+  size_t method_size = ArtMethod::Size(pointer_size);
+  size_t method_alignment = ArtMethod::Alignment(pointer_size);
+  ArraySlice<ArtMethod> slice(&methods->At(0u, method_size, method_alignment),
+                              methods->size(),
+                              method_size);
+  return slice.SubArray(start_offset, size);
+}
 
 inline uint32_t Class::NumMethods() {
   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
@@ -216,12 +216,12 @@
 
 inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return &GetDirectMethodsSliceUnchecked(pointer_size).At(i);
+  return &GetDirectMethodsSliceUnchecked(pointer_size)[i];
 }
 
 inline ArtMethod* Class::GetDirectMethod(size_t i, PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return &GetDirectMethodsSlice(pointer_size).At(i);
+  return &GetDirectMethodsSlice(pointer_size)[i];
 }
 
 inline void Class::SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods,
@@ -264,7 +264,7 @@
 
 inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return &GetVirtualMethodsSliceUnchecked(pointer_size).At(i);
+  return &GetVirtualMethodsSliceUnchecked(pointer_size)[i];
 }
 
 template<VerifyObjectFlags kVerifyFlags,
@@ -944,38 +944,36 @@
   }
 }
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetDirectMethods(PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return GetDirectMethodsSliceUnchecked(pointer_size).AsRange();
+  return GetDirectMethodsSliceUnchecked(pointer_size);
 }
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredMethods(
+inline ArraySlice<ArtMethod> Class::GetDeclaredMethods(
       PointerSize pointer_size) {
-  return GetDeclaredMethodsSliceUnchecked(pointer_size).AsRange();
+  return GetDeclaredMethodsSliceUnchecked(pointer_size);
 }
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredVirtualMethods(
+inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethods(
       PointerSize pointer_size) {
-  return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size).AsRange();
+  return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size);
 }
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(
+inline ArraySlice<ArtMethod> Class::GetVirtualMethods(
     PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return GetVirtualMethodsSliceUnchecked(pointer_size).AsRange();
+  return GetVirtualMethodsSliceUnchecked(pointer_size);
 }
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetCopiedMethods(PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetCopiedMethods(PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return GetCopiedMethodsSliceUnchecked(pointer_size).AsRange();
+  return GetCopiedMethodsSliceUnchecked(pointer_size);
 }
 
 
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetMethods(PointerSize pointer_size) {
+inline ArraySlice<ArtMethod> Class::GetMethods(PointerSize pointer_size) {
   CheckPointerSize(pointer_size);
-  return MakeIterationRangeFromLengthPrefixedArray(GetMethodsPtr(),
-                                                   ArtMethod::Size(pointer_size),
-                                                   ArtMethod::Alignment(pointer_size));
+  return GetMethodsSliceRangeUnchecked(pointer_size, 0u, NumMethods());
 }
 
 inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 913ab79..61d6e05 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -716,7 +716,7 @@
   // Also updates the dex_cache_strings_ variable from new_dex_cache.
   void SetDexCache(ObjPtr<DexCache> new_dex_cache) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDirectMethods(PointerSize pointer_size)
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetDirectMethods(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetMethodsPtr()
@@ -726,7 +726,7 @@
     return MemberOffset(OFFSETOF_MEMBER(Class, methods_));
   }
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetMethods(PointerSize pointer_size)
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetMethods(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods,
@@ -763,7 +763,7 @@
   ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredMethodsSlice(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDeclaredMethods(
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredMethods(
         PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -784,7 +784,7 @@
   ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethodsSlice(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDeclaredVirtualMethods(
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethods(
         PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -792,14 +792,14 @@
   ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethodsSlice(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetCopiedMethods(PointerSize pointer_size)
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethods(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE ArraySlice<ArtMethod> GetVirtualMethodsSlice(PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetVirtualMethods(
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetVirtualMethods(
       PointerSize pointer_size)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -1347,6 +1347,11 @@
   ALWAYS_INLINE void SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  ALWAYS_INLINE ArraySlice<ArtMethod> GetMethodsSliceRangeUnchecked(PointerSize pointer_size,
+                                                                    uint32_t start_offset,
+                                                                    uint32_t end_offset)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   template <bool throw_on_failure, bool use_referrers_cache>
   bool ResolvedFieldAccessTest(ObjPtr<Class> access_to,
                                ArtField* field,