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,