154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier/* 254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * Copyright (C) 2015 The Android Open Source Project 354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * 454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * you may not use this file except in compliance with the License. 654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * You may obtain a copy of the License at 754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * 854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * 1054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * Unless required by applicable law or agreed to in writing, software 1154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 1254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * See the License for the specific language governing permissions and 1454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier * limitations under the License. 1554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier */ 1654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 17e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light#ifndef ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_ 18e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_ 1954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 2054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier#include <stddef.h> // for offsetof() 21d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko#include <string.h> // for memset() 2254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 2354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier#include "stride_iterator.h" 24cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko#include "base/bit_utils.h" 25cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko#include "base/casts.h" 2654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier#include "base/iteration_range.h" 2754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 2854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartiernamespace art { 2954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 3054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartiertemplate<typename T> 3154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartierclass LengthPrefixedArray { 3254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier public: 33cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko explicit LengthPrefixedArray(size_t length) 3435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko : size_(dchecked_integral_cast<uint32_t>(length)) {} 3554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 36cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 3735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko DCHECK_LT(index, size_); 38cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko return AtUnchecked(index, element_size, alignment); 3954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 4054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 4135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const { 4235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko DCHECK_LT(index, size_); 4335831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return AtUnchecked(index, element_size, alignment); 4435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko } 4535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko 4635831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 47cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size); 4854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 4954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 5035831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko StrideIterator<const T> begin(size_t element_size = sizeof(T), 5135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko size_t alignment = alignof(T)) const { 5235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size); 5335831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko } 5435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko 5535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 5635831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size); 5735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko } 5835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko 5935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko StrideIterator<const T> end(size_t element_size = sizeof(T), 6035831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko size_t alignment = alignof(T)) const { 6135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size); 6254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 6354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 64cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko static size_t OffsetOfElement(size_t index, 65cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko size_t element_size = sizeof(T), 66cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko size_t alignment = alignof(T)) { 67cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko DCHECK_ALIGNED_PARAM(element_size, alignment); 68cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko return RoundUp(offsetof(LengthPrefixedArray<T>, data), alignment) + index * element_size; 6954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 7054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 71cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko static size_t ComputeSize(size_t num_elements, 72cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko size_t element_size = sizeof(T), 73cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko size_t alignment = alignof(T)) { 74cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko size_t result = OffsetOfElement(num_elements, element_size, alignment); 75cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko DCHECK_ALIGNED_PARAM(result, alignment); 76cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko return result; 7754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 7854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 7935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko size_t size() const { 8035831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return size_; 8154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier } 8254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 83c0fe56a4ee672bb346b124438941e753887e7416Mathieu Chartier // Update the length but does not reallocate storage. 8435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko void SetSize(size_t length) { 8535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko size_ = dchecked_integral_cast<uint32_t>(length); 86c0fe56a4ee672bb346b124438941e753887e7416Mathieu Chartier } 87c0fe56a4ee672bb346b124438941e753887e7416Mathieu Chartier 88d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko // Clear the potentially uninitialized padding between the size_ and actual data. 89d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 90d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko size_t gap_offset = offsetof(LengthPrefixedArray<T>, data); 91d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset; 92d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size); 93d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko } 94d9813cb37254a72b08424359c7ef80f6a2136a74Vladimir Marko 9554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier private: 96cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko T& AtUnchecked(size_t index, size_t element_size, size_t alignment) { 97cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko return *reinterpret_cast<T*>( 98cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment)); 99cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko } 100cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko 10135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const { 10235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko return *reinterpret_cast<T*>( 10335831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment)); 10435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko } 10535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko 10635831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko uint32_t size_; 107cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko uint8_t data[0]; 10854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier}; 10954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 11054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier// Returns empty iteration range if the array is null. 11154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartiertemplate<typename T> 11254d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu ChartierIterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray( 113cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) { 11454d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier return arr != nullptr ? 11535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) : 11654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0)); 11754d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier} 11854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 11954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier} // namespace art 12054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier 121e64300b8488716056775ecbfa2915dd1b4ce7e08Alex Light#endif // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_ 122