diff options
| author | Mathieu Chartier <mathieuc@google.com> | 2013-11-14 17:45:16 -0800 |
|---|---|---|
| committer | Mathieu Chartier <mathieuc@google.com> | 2013-11-20 11:14:11 -0800 |
| commit | cbb2d20bea2861f244da2e2318d8c088300a3710 (patch) | |
| tree | 9735d496716cf165ea0ee2d7e2f62d723ffc7734 /runtime/mirror | |
| parent | d31fb9718a6180304cd951619dc36be8e090a641 (diff) | |
| download | art-cbb2d20bea2861f244da2e2318d8c088300a3710.tar.gz art-cbb2d20bea2861f244da2e2318d8c088300a3710.tar.bz2 art-cbb2d20bea2861f244da2e2318d8c088300a3710.zip | |
Refactor allocation entrypoints.
Adds support for switching entrypoints during runtime. Enables
addition of new allocators with out requiring significant copy
paste. Slight speedup on ritzperf probably due to more inlining.
TODO: Ensuring that the entire allocation path is inlined so
that the switch statement in the allocation code is optimized
out.
Rosalloc measurements:
4583
4453
4439
4434
4751
After change:
4184
4287
4131
4335
4097
Change-Id: I1352a3cbcdf6dae93921582726324d91312df5c9
Diffstat (limited to 'runtime/mirror')
| -rw-r--r-- | runtime/mirror/array-inl.h | 45 | ||||
| -rw-r--r-- | runtime/mirror/array.cc | 5 | ||||
| -rw-r--r-- | runtime/mirror/array.h | 18 | ||||
| -rw-r--r-- | runtime/mirror/class-inl.h | 27 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 14 | ||||
| -rw-r--r-- | runtime/mirror/object.cc | 4 | ||||
| -rw-r--r-- | runtime/mirror/object_array-inl.h | 22 | ||||
| -rw-r--r-- | runtime/mirror/object_array.h | 5 | ||||
| -rw-r--r-- | runtime/mirror/object_test.cc | 9 |
9 files changed, 89 insertions, 60 deletions
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h index ef73e4df47..2955faa3c8 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -59,43 +59,44 @@ static inline size_t ComputeArraySize(Thread* self, Class* array_class, int32_t } static inline Array* SetArrayLength(Array* array, size_t length) { - if (LIKELY(array != NULL)) { + if (LIKELY(array != nullptr)) { DCHECK(array->IsArrayInstance()); array->SetLength(length); } return array; } -template <bool kIsMovable, bool kIsInstrumented> +template <bool kIsInstrumented> inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, - size_t component_size) { + size_t component_size, gc::AllocatorType allocator_type) { size_t size = ComputeArraySize(self, array_class, component_count, component_size); if (UNLIKELY(size == 0)) { - return NULL; + return nullptr; } gc::Heap* heap = Runtime::Current()->GetHeap(); - Array* array = nullptr; - if (kIsMovable) { - if (kIsInstrumented) { - array = down_cast<Array*>(heap->AllocMovableObjectInstrumented(self, array_class, size)); - } else { - array = down_cast<Array*>(heap->AllocMovableObjectUninstrumented(self, array_class, size)); - } - } else { - if (kIsInstrumented) { - array = down_cast<Array*>(heap->AllocNonMovableObjectInstrumented(self, array_class, size)); - } else { - array = down_cast<Array*>(heap->AllocNonMovableObjectUninstrumented(self, array_class, size)); - } - } + Array* array = down_cast<Array*>( + heap->AllocObjectWithAllocator<kIsInstrumented>(self, array_class, size, allocator_type)); return SetArrayLength(array, component_count); } -template <bool kIsMovable, bool kIsInstrumented> -inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) { +template <bool kIsInstrumented> +inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, + gc::AllocatorType allocator_type) { DCHECK(array_class->IsArrayClass()); - return Alloc<kIsMovable, kIsInstrumented>(self, array_class, component_count, - array_class->GetComponentSize()); + return Alloc<kIsInstrumented>(self, array_class, component_count, array_class->GetComponentSize(), + allocator_type); +} +template <bool kIsInstrumented> +inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) { + return Alloc<kIsInstrumented>(self, array_class, component_count, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); +} + +template <bool kIsInstrumented> +inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) { + return Alloc<kIsInstrumented>(self, array_class, component_count, component_size, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); } } // namespace mirror diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc index f8a283224c..00b88db299 100644 --- a/runtime/mirror/array.cc +++ b/runtime/mirror/array.cc @@ -44,8 +44,7 @@ static Array* RecursiveCreateMultiArray(Thread* self, Class* array_class, int cu SirtRef<mirror::IntArray>& dimensions) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { int32_t array_length = dimensions->Get(current_dimension); - SirtRef<Array> new_array(self, Array::Alloc<kMovingCollector, true>(self, array_class, - array_length)); + SirtRef<Array> new_array(self, Array::Alloc<true>(self, array_class, array_length)); if (UNLIKELY(new_array.get() == NULL)) { CHECK(self->IsExceptionPending()); return NULL; @@ -115,7 +114,7 @@ void Array::ThrowArrayStoreException(Object* object) const { template<typename T> PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { DCHECK(array_class_ != NULL); - Array* raw_array = Array::Alloc<kMovingCollector, true>(self, array_class_, length, sizeof(T)); + Array* raw_array = Array::Alloc<true>(self, array_class_, length, sizeof(T)); return down_cast<PrimitiveArray<T>*>(raw_array); } diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h index 584a4c095b..a332f97c02 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_MIRROR_ARRAY_H_ #include "object.h" +#include "gc/heap.h" namespace art { namespace mirror { @@ -26,13 +27,24 @@ class MANAGED Array : public Object { public: // A convenience for code that doesn't know the component size, and doesn't want to have to work // it out itself. - template <bool kIsMovable, bool kIsInstrumented> + template <bool kIsInstrumented> + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, + gc::AllocatorType allocator_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + template <bool kIsInstrumented> + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size, gc::AllocatorType allocator_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + template <bool kIsInstrumented> static Array* Alloc(Thread* self, Class* array_class, int32_t component_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - template <bool kIsMovable, bool kIsInstrumented> + template <bool kIsInstrumented> static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, - size_t component_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + size_t component_size) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 406ab1bbb3..4dcce1e8a1 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -357,23 +357,20 @@ inline void Class::CheckObjectAlloc() { DCHECK_GE(this->object_size_, sizeof(Object)); } -template <bool kIsMovable, bool kIsInstrumented> -inline Object* Class::Alloc(Thread* self) { +template <bool kIsInstrumented> +inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { CheckObjectAlloc(); gc::Heap* heap = Runtime::Current()->GetHeap(); - if (kIsMovable) { - if (kIsInstrumented) { - return heap->AllocMovableObjectInstrumented(self, this, this->object_size_); - } else { - return heap->AllocMovableObjectUninstrumented(self, this, this->object_size_); - } - } else { - if (kIsInstrumented) { - return heap->AllocNonMovableObjectInstrumented(self, this, this->object_size_); - } else { - return heap->AllocNonMovableObjectUninstrumented(self, this, this->object_size_); - } - } + return heap->AllocObjectWithAllocator<kIsInstrumented>(self, this, this->object_size_, + allocator_type); +} + +inline Object* Class::AllocObject(Thread* self) { + return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); +} + +inline Object* Class::AllocNonMovableObject(Thread* self) { + return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator()); } } // namespace mirror diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 82077dc52a..5f64bb4f8b 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -17,6 +17,7 @@ #ifndef ART_RUNTIME_MIRROR_CLASS_H_ #define ART_RUNTIME_MIRROR_CLASS_H_ +#include "gc/heap.h" #include "modifiers.h" #include "object.h" #include "primitive.h" @@ -377,13 +378,14 @@ class MANAGED Class : public StaticStorageBase { } // Creates a raw object instance but does not invoke the default constructor. - Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return Alloc<kMovingCollector, true>(self); - } + template <bool kIsInstrumented> + ALWAYS_INLINE Object* Alloc(Thread* self, gc::AllocatorType allocator_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Creates a raw object instance but does not invoke the default constructor. - template <bool kIsMovable, bool kIsInstrumented> - Object* Alloc(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* AllocObject(Thread* self) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* AllocNonMovableObject(Thread* self) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsVariableSize() const { // Classes and arrays vary in size, and so the object_size_ field cannot diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 385ef5ff89..008a17356f 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -75,9 +75,9 @@ Object* Object::Clone(Thread* self) { SirtRef<Object> this_object(self, this); Object* copy; if (heap->IsMovableObject(this)) { - copy = heap->AllocObject(self, GetClass(), num_bytes); + copy = heap->AllocObject<true>(self, GetClass(), num_bytes); } else { - copy = heap->AllocNonMovableObject(self, GetClass(), num_bytes); + copy = heap->AllocNonMovableObject<true>(self, GetClass(), num_bytes); } if (LIKELY(copy != nullptr)) { return CopyObject(self, copy, this_object.get(), num_bytes); diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h index 478f4ec210..be49b42f0d 100644 --- a/runtime/mirror/object_array-inl.h +++ b/runtime/mirror/object_array-inl.h @@ -30,16 +30,25 @@ namespace art { namespace mirror { template<class T> -inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) { - Array* array = Array::Alloc<kMovingCollector, true>(self, object_array_class, length, sizeof(Object*)); - if (UNLIKELY(array == NULL)) { - return NULL; +inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, + int32_t length, gc::AllocatorType allocator_type) { + Array* array = Array::Alloc<true>(self, object_array_class, length, sizeof(Object*), + allocator_type); + if (UNLIKELY(array == nullptr)) { + return nullptr; } else { return array->AsObjectArray<T>(); } } template<class T> +inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, + int32_t length) { + return Alloc(self, object_array_class, length, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); +} + +template<class T> inline T* ObjectArray<T>::Get(int32_t i) const { if (UNLIKELY(!IsValidIndex(i))) { return NULL; @@ -137,7 +146,10 @@ template<class T> inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) { // We may get copied by a compacting GC. SirtRef<ObjectArray<T> > sirt_this(self, this); - ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length); + gc::Heap* heap = Runtime::Current()->GetHeap(); + gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() : + heap->GetCurrentNonMovingAllocator(); + ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type); if (LIKELY(new_array != nullptr)) { Copy(sirt_this.get(), 0, new_array, 0, std::min(sirt_this->GetLength(), new_length)); } diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h index 09ff5193ae..5da8845196 100644 --- a/runtime/mirror/object_array.h +++ b/runtime/mirror/object_array.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_H_ #include "array.h" +#include "gc/heap.h" namespace art { namespace mirror { @@ -25,6 +26,10 @@ namespace mirror { template<class T> class MANAGED ObjectArray : public Array { public: + static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length, + gc::AllocatorType allocator_type) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc index 853031701a..8272ff8b1f 100644 --- a/runtime/mirror/object_test.cc +++ b/runtime/mirror/object_test.cc @@ -144,15 +144,15 @@ TEST_F(ObjectTest, AllocObjectArray) { TEST_F(ObjectTest, AllocArray) { ScopedObjectAccess soa(Thread::Current()); Class* c = class_linker_->FindSystemClass("[I"); - SirtRef<Array> a(soa.Self(), Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1)); + SirtRef<Array> a(soa.Self(), Array::Alloc<true>(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); c = class_linker_->FindSystemClass("[Ljava/lang/Object;"); - a.reset(Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1)); + a.reset(Array::Alloc<true>(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); c = class_linker_->FindSystemClass("[[Ljava/lang/Object;"); - a.reset(Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1)); + a.reset(Array::Alloc<true>(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); } @@ -221,7 +221,8 @@ TEST_F(ObjectTest, CheckAndAllocArrayFromCode) { java_lang_dex_file_->GetIndexForStringId(*string_id)); ASSERT_TRUE(type_id != NULL); uint32_t type_idx = java_lang_dex_file_->GetIndexForTypeId(*type_id); - Object* array = CheckAndAllocArrayFromCode(type_idx, sort, 3, Thread::Current(), false); + Object* array = CheckAndAllocArrayFromCode(type_idx, sort, 3, Thread::Current(), false, + Runtime::Current()->GetHeap()->GetCurrentAllocator()); EXPECT_TRUE(array->IsArrayInstance()); EXPECT_EQ(3, array->AsArray()->GetLength()); EXPECT_TRUE(array->GetClass()->IsArrayClass()); |
