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