• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2011 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #ifndef ART_RUNTIME_MIRROR_ARRAY_ALLOC_INL_H_
18  #define ART_RUNTIME_MIRROR_ARRAY_ALLOC_INL_H_
19  
20  #include "array-inl.h"
21  
22  #include <android-base/logging.h>
23  #include <android-base/stringprintf.h>
24  
25  #include "base/bit_utils.h"
26  #include "base/casts.h"
27  #include "class.h"
28  #include "gc/allocator_type.h"
29  #include "gc/heap-inl.h"
30  #include "obj_ptr-inl.h"
31  #include "runtime.h"
32  
33  namespace art {
34  namespace mirror {
35  
ComputeArraySize(int32_t component_count,size_t component_size_shift)36  static inline size_t ComputeArraySize(int32_t component_count, size_t component_size_shift) {
37    DCHECK_GE(component_count, 0);
38  
39    size_t component_size = 1U << component_size_shift;
40    size_t header_size = Array::DataOffset(component_size).SizeValue();
41    size_t data_size = static_cast<size_t>(component_count) << component_size_shift;
42    size_t size = header_size + data_size;
43  
44    // Check for size_t overflow if this was an unreasonable request
45    // but let the caller throw OutOfMemoryError.
46  #ifdef __LP64__
47    // 64-bit. No overflow as component_count is 32-bit and the maximum
48    // component size is 8.
49    DCHECK_LE((1U << component_size_shift), 8U);
50  #else
51    // 32-bit.
52    DCHECK_NE(header_size, 0U);
53    DCHECK_EQ(RoundUp(header_size, component_size), header_size);
54    // The array length limit (exclusive).
55    const size_t length_limit = (0U - header_size) >> component_size_shift;
56    if (UNLIKELY(length_limit <= static_cast<size_t>(component_count))) {
57      return 0;  // failure
58    }
59  #endif
60    return size;
61  }
62  
63  // Used for setting the array length in the allocation code path to ensure it is guarded by a
64  // StoreStore fence.
65  class SetLengthVisitor {
66   public:
SetLengthVisitor(int32_t length)67    explicit SetLengthVisitor(int32_t length) : length_(length) {
68    }
69  
operator()70    void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const
71        REQUIRES_SHARED(Locks::mutator_lock_) {
72      // Avoid AsArray as object is not yet in live bitmap or allocation stack.
73      ObjPtr<Array> array = ObjPtr<Array>::DownCast(obj);
74      // DCHECK(array->IsArrayInstance());
75      array->SetLength(length_);
76    }
77  
78   private:
79    const int32_t length_;
80  
81    DISALLOW_COPY_AND_ASSIGN(SetLengthVisitor);
82  };
83  
84  // Similar to SetLengthVisitor, used for setting the array length to fill the usable size of an
85  // array.
86  class SetLengthToUsableSizeVisitor {
87   public:
SetLengthToUsableSizeVisitor(int32_t min_length,size_t header_size,size_t component_size_shift)88    SetLengthToUsableSizeVisitor(int32_t min_length, size_t header_size,
89                                 size_t component_size_shift) :
90        minimum_length_(min_length), header_size_(header_size),
91        component_size_shift_(component_size_shift) {
92    }
93  
operator()94    void operator()(ObjPtr<Object> obj, size_t usable_size) const
95        REQUIRES_SHARED(Locks::mutator_lock_) {
96      // Avoid AsArray as object is not yet in live bitmap or allocation stack.
97      ObjPtr<Array> array = ObjPtr<Array>::DownCast(obj);
98      // DCHECK(array->IsArrayInstance());
99      int32_t length = (usable_size - header_size_) >> component_size_shift_;
100      DCHECK_GE(length, minimum_length_);
101      uint8_t* old_end = reinterpret_cast<uint8_t*>(array->GetRawData(1U << component_size_shift_,
102                                                                      minimum_length_));
103      uint8_t* new_end = reinterpret_cast<uint8_t*>(array->GetRawData(1U << component_size_shift_,
104                                                                      length));
105      // Ensure space beyond original allocation is zeroed.
106      memset(old_end, 0, new_end - old_end);
107      array->SetLength(length);
108    }
109  
110   private:
111    const int32_t minimum_length_;
112    const size_t header_size_;
113    const size_t component_size_shift_;
114  
115    DISALLOW_COPY_AND_ASSIGN(SetLengthToUsableSizeVisitor);
116  };
117  
118  template <bool kIsInstrumented, bool kFillUsable>
Alloc(Thread * self,ObjPtr<Class> array_class,int32_t component_count,size_t component_size_shift,gc::AllocatorType allocator_type)119  inline ObjPtr<Array> Array::Alloc(Thread* self,
120                                    ObjPtr<Class> array_class,
121                                    int32_t component_count,
122                                    size_t component_size_shift,
123                                    gc::AllocatorType allocator_type) {
124    DCHECK(allocator_type != gc::kAllocatorTypeLOS);
125    DCHECK(array_class != nullptr);
126    DCHECK(array_class->IsArrayClass());
127    DCHECK_EQ(array_class->GetComponentSizeShift(), component_size_shift);
128    DCHECK_EQ(array_class->GetComponentSize(), (1U << component_size_shift));
129    size_t size = ComputeArraySize(component_count, component_size_shift);
130  #ifdef __LP64__
131    // 64-bit. No size_t overflow.
132    DCHECK_NE(size, 0U);
133  #else
134    // 32-bit.
135    if (UNLIKELY(size == 0)) {
136      self->ThrowOutOfMemoryError(android::base::StringPrintf("%s of length %d would overflow",
137                                                              array_class->PrettyDescriptor().c_str(),
138                                                              component_count).c_str());
139      return nullptr;
140    }
141  #endif
142    gc::Heap* heap = Runtime::Current()->GetHeap();
143    ObjPtr<Array> result;
144    if (!kFillUsable) {
145      SetLengthVisitor visitor(component_count);
146      result = ObjPtr<Array>::DownCast(
147          heap->AllocObjectWithAllocator<kIsInstrumented>(
148              self, array_class, size, allocator_type, visitor));
149    } else {
150      SetLengthToUsableSizeVisitor visitor(component_count,
151                                           DataOffset(1U << component_size_shift).SizeValue(),
152                                           component_size_shift);
153      result = ObjPtr<Array>::DownCast(
154          heap->AllocObjectWithAllocator<kIsInstrumented>(
155              self, array_class, size, allocator_type, visitor));
156    }
157    if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
158      array_class = result->GetClass();  // In case the array class moved.
159      CHECK_EQ(array_class->GetComponentSize(), 1U << component_size_shift);
160      if (!kFillUsable) {
161        CHECK_EQ(result->SizeOf(), size);
162      } else {
163        CHECK_GE(result->SizeOf(), size);
164      }
165    }
166    return result;
167  }
168  
169  template<typename T>
AllocateAndFill(Thread * self,const T * data,size_t length)170  inline ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::AllocateAndFill(Thread* self,
171                                                                     const T* data,
172                                                                     size_t length) {
173    StackHandleScope<1> hs(self);
174    Handle<PrimitiveArray<T>> arr(hs.NewHandle(PrimitiveArray<T>::Alloc(self, length)));
175    if (!arr.IsNull()) {
176      // Copy it in. Just skip if it's null
177      memcpy(arr->GetData(), data, sizeof(T) * length);
178    }
179    return arr.Get();
180  }
181  
182  }  // namespace mirror
183  }  // namespace art
184  
185  #endif  // ART_RUNTIME_MIRROR_ARRAY_ALLOC_INL_H_
186