diff options
Diffstat (limited to 'runtime/mirror/array-inl.h')
-rw-r--r-- | runtime/mirror/array-inl.h | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h index eb73c7dd38..c60e714d44 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -20,6 +20,9 @@ #include "array.h" #include "class.h" +#include "gc/heap-inl.h" +#include "thread.h" +#include "utils.h" namespace art { namespace mirror { @@ -33,6 +36,68 @@ inline size_t Array::SizeOf() const { return header_size + data_size; } +static inline size_t ComputeArraySize(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(array_class != NULL); + DCHECK_GE(component_count, 0); + DCHECK(array_class->IsArrayClass()); + + size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); + size_t data_size = component_count * component_size; + size_t size = header_size + data_size; + + // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. + size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size); + if (UNLIKELY(data_size >> component_shift != size_t(component_count) || size < data_size)) { + self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow", + PrettyDescriptor(array_class).c_str(), + component_count).c_str()); + return 0; // failure + } + return size; +} + +static inline Array* SetArrayLength(Array* array, size_t length) { + if (LIKELY(array != NULL)) { + DCHECK(array->IsArrayInstance()); + array->SetLength(length); + } + return array; +} + +inline Array* Array::AllocInstrumented(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) { + size_t size = ComputeArraySize(self, array_class, component_count, component_size); + if (UNLIKELY(size == 0)) { + return NULL; + } + gc::Heap* heap = Runtime::Current()->GetHeap(); + Array* array = down_cast<Array*>(heap->AllocObjectInstrumented(self, array_class, size)); + return SetArrayLength(array, component_count); +} + +inline Array* Array::AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) { + size_t size = ComputeArraySize(self, array_class, component_count, component_size); + if (UNLIKELY(size == 0)) { + return NULL; + } + gc::Heap* heap = Runtime::Current()->GetHeap(); + Array* array = down_cast<Array*>(heap->AllocObjectUninstrumented(self, array_class, size)); + return SetArrayLength(array, component_count); +} + +inline Array* Array::AllocInstrumented(Thread* self, Class* array_class, int32_t component_count) { + DCHECK(array_class->IsArrayClass()); + return AllocInstrumented(self, array_class, component_count, array_class->GetComponentSize()); +} + +inline Array* Array::AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count) { + DCHECK(array_class->IsArrayClass()); + return AllocUninstrumented(self, array_class, component_count, array_class->GetComponentSize()); +} + } // namespace mirror } // namespace art |