summaryrefslogtreecommitdiffstats
path: root/runtime/mirror
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2013-09-12 21:33:12 -0700
committerHiroshi Yamauchi <yamauchi@google.com>2013-09-25 20:28:49 -0700
commit3b4c18933c24b8a33f38573c2ebcdb9aa16efeb5 (patch)
tree5298ccd9c1f1f6b329c0cb6cefac6a8df43dd633 /runtime/mirror
parentf7e090ebcded6d6693894c018d89c4add79253ff (diff)
downloadart-3b4c18933c24b8a33f38573c2ebcdb9aa16efeb5.tar.gz
art-3b4c18933c24b8a33f38573c2ebcdb9aa16efeb5.tar.bz2
art-3b4c18933c24b8a33f38573c2ebcdb9aa16efeb5.zip
Split the allocation path into 'instrumented' and 'uninstrumented'
ones. The instrumented path is equivalent to the existing allocation path that checks for three instrumentation mechanisms (the debugger allocation tracking, the runtime allocation stats collection, and valgrind) for every allocation. The uinstrumented path does not perform these checks. We use the uninstrumented path by default and enable the instrumented path only when any of the three mechanisms is enabled. The uninstrumented version of Heap::AllocObject() is inlined. This change improves the Ritz MemAllocTest by ~4% on Nexus 4 and ~3% on Host/x86. Bug: 9986565 Change-Id: I3e68dfff6789d77bbdcea98457b694e1b5fcef5f
Diffstat (limited to 'runtime/mirror')
-rw-r--r--runtime/mirror/array-inl.h46
-rw-r--r--runtime/mirror/array.h14
-rw-r--r--runtime/mirror/class-inl.h14
-rw-r--r--runtime/mirror/class.h9
4 files changed, 72 insertions, 11 deletions
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index c7b370f877..c60e714d44 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -20,6 +20,7 @@
#include "array.h"
#include "class.h"
+#include "gc/heap-inl.h"
#include "thread.h"
#include "utils.h"
@@ -35,8 +36,9 @@ inline size_t Array::SizeOf() const {
return header_size + data_size;
}
-inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count,
- size_t component_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());
@@ -51,21 +53,49 @@ inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_c
self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
PrettyDescriptor(array_class).c_str(),
component_count).c_str());
- return NULL;
+ return 0; // failure
}
+ return size;
+}
- gc::Heap* heap = Runtime::Current()->GetHeap();
- Array* array = down_cast<Array*>(heap->AllocObject(self, array_class, size));
+static inline Array* SetArrayLength(Array* array, size_t length) {
if (LIKELY(array != NULL)) {
DCHECK(array->IsArrayInstance());
- array->SetLength(component_count);
+ array->SetLength(length);
}
return array;
}
-inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) {
+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 Alloc(self, array_class, component_count, array_class->GetComponentSize());
+ return AllocUninstrumented(self, array_class, component_count, array_class->GetComponentSize());
}
} // namespace mirror
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index db6132df59..570dcaa292 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -27,10 +27,24 @@ class MANAGED Array : public Object {
// A convenience for code that doesn't know the component size,
// and doesn't want to have to work it out itself.
static Array* Alloc(Thread* self, Class* array_class, int32_t component_count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return AllocInstrumented(self, array_class, component_count);
+ }
+ static Array* AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static Array* AllocInstrumented(Thread* self, Class* array_class, int32_t component_count)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Array* Alloc(Thread* self, Class* array_class, int32_t component_count,
size_t component_size)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return AllocInstrumented(self, array_class, component_count, component_size);
+ }
+ static Array* AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count,
+ size_t component_size)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static Array* AllocInstrumented(Thread* self, Class* array_class, int32_t component_count,
+ size_t component_size)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions)
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 438ce81db2..88cffb77fc 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -23,6 +23,7 @@
#include "art_method.h"
#include "class_loader.h"
#include "dex_cache.h"
+#include "gc/heap-inl.h"
#include "iftable.h"
#include "object_array-inl.h"
#include "runtime.h"
@@ -342,13 +343,22 @@ inline void Class::SetName(String* name) {
SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
}
-inline Object* Class::AllocObject(Thread* self) {
+inline void Class::CheckObjectAlloc() {
DCHECK(!IsArrayClass()) << PrettyClass(this);
DCHECK(IsInstantiable()) << PrettyClass(this);
// TODO: decide whether we want this check. It currently fails during bootstrap.
// DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this);
DCHECK_GE(this->object_size_, sizeof(Object));
- return Runtime::Current()->GetHeap()->AllocObject(self, this, this->object_size_);
+}
+
+inline Object* Class::AllocObjectInstrumented(Thread* self) {
+ CheckObjectAlloc();
+ return Runtime::Current()->GetHeap()->AllocObjectInstrumented(self, this, this->object_size_);
+}
+
+inline Object* Class::AllocObjectUninstrumented(Thread* self) {
+ CheckObjectAlloc();
+ return Runtime::Current()->GetHeap()->AllocObjectUninstrumented(self, this, this->object_size_);
}
} // namespace mirror
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index d97b603ad8..4f8ab7d90a 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -371,7 +371,12 @@ 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_);
+ Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return AllocObjectInstrumented(self);
+ }
+
+ Object* AllocObjectUninstrumented(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ Object* AllocObjectInstrumented(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsVariableSize() const {
// Classes and arrays vary in size, and so the object_size_ field cannot
@@ -764,6 +769,8 @@ class MANAGED Class : public StaticStorageBase {
bool IsAssignableFromArray(const Class* klass) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void CheckObjectAlloc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// defining class loader, or NULL for the "bootstrap" system loader
ClassLoader* class_loader_;