summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/Android.mk1
-rw-r--r--runtime/gc/accounting/gc_allocator.cc33
-rw-r--r--runtime/gc/accounting/gc_allocator.h87
-rw-r--r--runtime/gc/accounting/heap_bitmap-inl.h4
-rw-r--r--runtime/gc/accounting/heap_bitmap.cc10
-rw-r--r--runtime/gc/accounting/heap_bitmap.h12
-rw-r--r--runtime/gc/accounting/mod_union_table.cc4
-rw-r--r--runtime/gc/accounting/mod_union_table.h10
-rw-r--r--runtime/gc/accounting/space_bitmap.h5
-rw-r--r--runtime/gc/heap.cc17
-rw-r--r--runtime/gc/heap.h8
-rw-r--r--runtime/gc/space/large_object_space.h8
-rw-r--r--runtime/safe_map.h8
-rw-r--r--runtime/utils.h12
14 files changed, 195 insertions, 24 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk
index ae62d36..4638e78 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -47,6 +47,7 @@ LIBART_COMMON_SRC_FILES := \
file_output_stream.cc \
gc/allocator/dlmalloc.cc \
gc/accounting/card_table.cc \
+ gc/accounting/gc_allocator.cc \
gc/accounting/heap_bitmap.cc \
gc/accounting/mod_union_table.cc \
gc/accounting/space_bitmap.cc \
diff --git a/runtime/gc/accounting/gc_allocator.cc b/runtime/gc/accounting/gc_allocator.cc
new file mode 100644
index 0000000..aff50df
--- /dev/null
+++ b/runtime/gc/accounting/gc_allocator.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gc_allocator.h"
+#include "gc/heap.h"
+#include "runtime.h"
+
+namespace art {
+namespace gc {
+namespace accounting {
+ void RegisterGCAllocation(size_t bytes) {
+ Runtime::Current()->GetHeap()->RegisterGCAllocation(bytes);
+ }
+
+ void RegisterGCDeAllocation(size_t bytes) {
+ Runtime::Current()->GetHeap()->RegisterGCDeAllocation(bytes);
+ }
+}
+}
+}
diff --git a/runtime/gc/accounting/gc_allocator.h b/runtime/gc/accounting/gc_allocator.h
new file mode 100644
index 0000000..12e16b5
--- /dev/null
+++ b/runtime/gc/accounting/gc_allocator.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_GC_ACCOUNTING_GC_ALLOCATOR_H_
+#define ART_RUNTIME_GC_ACCOUNTING_GC_ALLOCATOR_H_
+
+#include "gc/allocator/dlmalloc.h"
+#include "utils.h"
+
+#include <cstdlib>
+#include <limits>
+#include <memory>
+
+namespace art {
+namespace gc {
+namespace accounting {
+ void RegisterGCAllocation(size_t bytes);
+ void RegisterGCDeAllocation(size_t bytes);
+
+ static const bool kMeasureGCMemoryOverhead = false;
+
+ template <typename T>
+ class GCAllocatorImpl : public std::allocator<T> {
+ public:
+ typedef typename std::allocator<T>::value_type value_type;
+ typedef typename std::allocator<T>::size_type size_type;
+ typedef typename std::allocator<T>::difference_type difference_type;
+ typedef typename std::allocator<T>::pointer pointer;
+ typedef typename std::allocator<T>::const_pointer const_pointer;
+ typedef typename std::allocator<T>::reference reference;
+ typedef typename std::allocator<T>::const_reference const_reference;
+
+ // Used internally by STL data structures.
+ template <class U>
+ GCAllocatorImpl(const GCAllocatorImpl<U>& alloc) throw() {
+
+ }
+
+ // Used internally by STL data structures.
+ GCAllocatorImpl() throw() {
+
+ }
+
+ // Enables an allocator for objects of one type to allocate storage for objects of another type.
+ // Used internally by STL data structures.
+ template <class U>
+ struct rebind {
+ typedef GCAllocatorImpl<U> other;
+ };
+
+ pointer allocate(size_type n, const_pointer hint = 0) {
+ RegisterGCAllocation(n * sizeof(T));
+ return reinterpret_cast<pointer>(malloc(n * sizeof(T)));
+ }
+
+ template <typename PT>
+ void deallocate(PT p, size_type n) {
+ RegisterGCDeAllocation(n * sizeof(T));
+ free(p);
+ }
+ };
+
+ // C++ doesn't allow template typedefs. This is a workaround template typedef which is
+ // GCAllocatorImpl<T> if kMeasureGCMemoryOverhead is true, std::allocator<T> otherwise.
+ template <typename T>
+ class GCAllocator : public TypeStaticIf<kMeasureGCMemoryOverhead,
+ GCAllocatorImpl<T>,
+ std::allocator<T> >::value {
+ };
+}
+}
+}
+
+#endif // ART_RUNTIME_GC_ACCOUNTING_GC_ALLOCATOR_H_
diff --git a/runtime/gc/accounting/heap_bitmap-inl.h b/runtime/gc/accounting/heap_bitmap-inl.h
index 5edea95..f6cf2b5 100644
--- a/runtime/gc/accounting/heap_bitmap-inl.h
+++ b/runtime/gc/accounting/heap_bitmap-inl.h
@@ -26,14 +26,14 @@ namespace accounting {
template <typename Visitor>
inline void HeapBitmap::Visit(const Visitor& visitor) {
// TODO: C++0x auto
- typedef std::vector<SpaceBitmap*>::iterator It;
+ typedef SpaceBitmapVector::iterator It;
for (It it = continuous_space_bitmaps_.begin(), end = continuous_space_bitmaps_.end();
it != end; ++it) {
SpaceBitmap* bitmap = *it;
bitmap->VisitMarkedRange(bitmap->HeapBegin(), bitmap->HeapLimit(), visitor, VoidFunctor());
}
// TODO: C++0x auto
- typedef std::vector<SpaceSetMap*>::iterator It2;
+ typedef SpaceSetMapVector::iterator It2;
DCHECK(discontinuous_space_sets_.begin() != discontinuous_space_sets_.end());
for (It2 it = discontinuous_space_sets_.begin(), end = discontinuous_space_sets_.end();
it != end; ++it) {
diff --git a/runtime/gc/accounting/heap_bitmap.cc b/runtime/gc/accounting/heap_bitmap.cc
index 1bdc978..0462905 100644
--- a/runtime/gc/accounting/heap_bitmap.cc
+++ b/runtime/gc/accounting/heap_bitmap.cc
@@ -24,7 +24,7 @@ namespace accounting {
void HeapBitmap::ReplaceBitmap(SpaceBitmap* old_bitmap, SpaceBitmap* new_bitmap) {
// TODO: C++0x auto
- typedef std::vector<SpaceBitmap*>::iterator It;
+ typedef SpaceBitmapVector::iterator It;
for (It it = continuous_space_bitmaps_.begin(), end = continuous_space_bitmaps_.end();
it != end; ++it) {
if (*it == old_bitmap) {
@@ -37,7 +37,7 @@ void HeapBitmap::ReplaceBitmap(SpaceBitmap* old_bitmap, SpaceBitmap* new_bitmap)
void HeapBitmap::ReplaceObjectSet(SpaceSetMap* old_set, SpaceSetMap* new_set) {
// TODO: C++0x auto
- typedef std::vector<SpaceSetMap*>::iterator It;
+ typedef SpaceSetMapVector::iterator It;
for (It it = discontinuous_space_sets_.begin(), end = discontinuous_space_sets_.end();
it != end; ++it) {
if (*it == old_set) {
@@ -52,7 +52,7 @@ void HeapBitmap::AddContinuousSpaceBitmap(accounting::SpaceBitmap* bitmap) {
DCHECK(bitmap != NULL);
// Check for interval overlap.
- typedef std::vector<SpaceBitmap*>::iterator It;
+ typedef SpaceBitmapVector::iterator It;
for (It it = continuous_space_bitmaps_.begin(), end = continuous_space_bitmaps_.end();
it != end; ++it) {
SpaceBitmap* bitmap = *it;
@@ -71,14 +71,14 @@ void HeapBitmap::AddDiscontinuousObjectSet(SpaceSetMap* set) {
void HeapBitmap::Walk(SpaceBitmap::Callback* callback, void* arg) {
// TODO: C++0x auto
- typedef std::vector<SpaceBitmap*>::iterator It;
+ typedef SpaceBitmapVector::iterator It;
for (It it = continuous_space_bitmaps_.begin(), end = continuous_space_bitmaps_.end();
it != end; ++it) {
SpaceBitmap* bitmap = *it;
bitmap->Walk(callback, arg);
}
// TODO: C++0x auto
- typedef std::vector<SpaceSetMap*>::iterator It2;
+ typedef SpaceSetMapVector::iterator It2;
DCHECK(discontinuous_space_sets_.begin() != discontinuous_space_sets_.end());
for (It2 it = discontinuous_space_sets_.begin(), end = discontinuous_space_sets_.end();
it != end; ++it) {
diff --git a/runtime/gc/accounting/heap_bitmap.h b/runtime/gc/accounting/heap_bitmap.h
index 1710579..ada976f 100644
--- a/runtime/gc/accounting/heap_bitmap.h
+++ b/runtime/gc/accounting/heap_bitmap.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_GC_ACCOUNTING_HEAP_BITMAP_H_
#include "base/logging.h"
+#include "gc_allocator.h"
#include "locks.h"
#include "space_bitmap.h"
@@ -30,6 +31,9 @@ namespace accounting {
class HeapBitmap {
public:
+ typedef std::vector<SpaceBitmap*, GCAllocator<SpaceBitmap*> > SpaceBitmapVector;
+ typedef std::vector<SpaceSetMap*, GCAllocator<SpaceSetMap*> > SpaceSetMapVector;
+
bool Test(const mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
SpaceBitmap* bitmap = GetContinuousSpaceBitmap(obj);
if (LIKELY(bitmap != NULL)) {
@@ -63,7 +67,7 @@ class HeapBitmap {
SpaceBitmap* GetContinuousSpaceBitmap(const mirror::Object* obj) {
// TODO: C++0x auto
- typedef std::vector<SpaceBitmap*>::iterator It;
+ typedef SpaceBitmapVector::iterator It;
for (It it = continuous_space_bitmaps_.begin(), end = continuous_space_bitmaps_.end();
it != end; ++it) {
SpaceBitmap* bitmap = *it;
@@ -76,7 +80,7 @@ class HeapBitmap {
SpaceSetMap* GetDiscontinuousSpaceObjectSet(const mirror::Object* obj) {
// TODO: C++0x auto
- typedef std::vector<SpaceSetMap*>::iterator It;
+ typedef SpaceSetMapVector::iterator It;
for (It it = discontinuous_space_sets_.begin(), end = discontinuous_space_sets_.end();
it != end; ++it) {
SpaceSetMap* set = *it;
@@ -112,10 +116,10 @@ class HeapBitmap {
void AddDiscontinuousObjectSet(SpaceSetMap* set);
// Bitmaps covering continuous spaces.
- std::vector<SpaceBitmap*> continuous_space_bitmaps_;
+ SpaceBitmapVector continuous_space_bitmaps_;
// Sets covering discontinuous spaces.
- std::vector<SpaceSetMap*> discontinuous_space_sets_;
+ SpaceSetMapVector discontinuous_space_sets_;
friend class art::gc::Heap;
};
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index b33cbce..718dcf0 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -86,7 +86,7 @@ class ModUnionVisitor {
class ModUnionClearCardSetVisitor {
public:
- explicit ModUnionClearCardSetVisitor(std::set<byte*>* const cleared_cards)
+ explicit ModUnionClearCardSetVisitor(ModUnionTable::CardSet* const cleared_cards)
: cleared_cards_(cleared_cards) {
}
@@ -97,7 +97,7 @@ class ModUnionClearCardSetVisitor {
}
private:
- std::set<byte*>* const cleared_cards_;
+ ModUnionTable::CardSet* const cleared_cards_;
};
class ModUnionClearCardVisitor {
diff --git a/runtime/gc/accounting/mod_union_table.h b/runtime/gc/accounting/mod_union_table.h
index d46281c..eb7a754 100644
--- a/runtime/gc/accounting/mod_union_table.h
+++ b/runtime/gc/accounting/mod_union_table.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_GC_ACCOUNTING_MOD_UNION_TABLE_H_
#define ART_RUNTIME_GC_ACCOUNTING_MOD_UNION_TABLE_H_
+#include "gc_allocator.h"
#include "globals.h"
#include "safe_map.h"
@@ -49,6 +50,8 @@ class HeapBitmap;
// cleared between GC phases, reducing the number of dirty cards that need to be scanned.
class ModUnionTable {
public:
+ typedef std::set<byte*, std::less<byte*>, GCAllocator<byte*> > CardSet;
+
explicit ModUnionTable(Heap* heap) : heap_(heap) {}
virtual ~ModUnionTable() {}
@@ -111,10 +114,11 @@ class ModUnionTableReferenceCache : public ModUnionTable {
protected:
// Cleared card array, used to update the mod-union table.
- std::set<byte*> cleared_cards_;
+ ModUnionTable::CardSet cleared_cards_;
// Maps from dirty cards to their corresponding alloc space references.
- SafeMap<const byte*, std::vector<const mirror::Object*> > references_;
+ SafeMap<const byte*, std::vector<const mirror::Object*>, std::less<const byte*>,
+ GCAllocator<std::pair<const byte*, std::vector<const mirror::Object*> > > > references_;
};
// Card caching implementation. Keeps track of which cards we cleared and only this information.
@@ -141,7 +145,7 @@ class ModUnionTableCardCache : public ModUnionTable {
protected:
// Cleared card array, used to update the mod-union table.
- std::set<byte*> cleared_cards_;
+ CardSet cleared_cards_;
};
} // namespace accounting
diff --git a/runtime/gc/accounting/space_bitmap.h b/runtime/gc/accounting/space_bitmap.h
index 77f93a2..674c262 100644
--- a/runtime/gc/accounting/space_bitmap.h
+++ b/runtime/gc/accounting/space_bitmap.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_GC_ACCOUNTING_SPACE_BITMAP_H_
#include "locks.h"
+#include "gc_allocator.h"
#include "globals.h"
#include "mem_map.h"
#include "UniquePtr.h"
@@ -205,7 +206,9 @@ class SpaceBitmap {
// Like a bitmap except it keeps track of objects using sets.
class SpaceSetMap {
public:
- typedef std::set<const mirror::Object*> Objects;
+ typedef std::set<
+ const mirror::Object*, std::less<const mirror::Object*>,
+ GCAllocator<const mirror::Object*> > Objects;
bool IsEmpty() const {
return contained_.empty();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index b6cef58..edc5529 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -90,6 +90,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
num_bytes_allocated_(0),
native_bytes_allocated_(0),
process_state_(PROCESS_STATE_TOP),
+ gc_memory_overhead_(0),
verify_missing_card_marks_(false),
verify_system_weaks_(false),
verify_pre_gc_heap_(false),
@@ -177,7 +178,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
card_table_.reset(accounting::CardTable::Create(heap_begin, heap_capacity));
CHECK(card_table_.get() != NULL) << "Failed to create card table";
- image_mod_union_table_.reset(new accounting::ModUnionTableToZygoteAllocspace(this));
+ image_mod_union_table_.reset(new accounting::ModUnionTableCardCache(this));
CHECK(image_mod_union_table_.get() != NULL) << "Failed to create image mod-union table";
zygote_mod_union_table_.reset(new accounting::ModUnionTableCardCache(this));
@@ -273,6 +274,18 @@ void Heap::AddContinuousSpace(space::ContinuousSpace* space) {
}
}
+void Heap::RegisterGCAllocation(size_t bytes) {
+ if (this != NULL) {
+ gc_memory_overhead_.fetch_add(bytes);
+ }
+}
+
+void Heap::RegisterGCDeAllocation(size_t bytes) {
+ if (this != NULL) {
+ gc_memory_overhead_.fetch_sub(bytes);
+ }
+}
+
void Heap::AddDiscontinuousSpace(space::DiscontinuousSpace* space) {
WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
DCHECK(space != NULL);
@@ -333,6 +346,7 @@ void Heap::DumpGcPerformanceInfo(std::ostream& os) {
}
os << "Total mutator paused time: " << PrettyDuration(total_paused_time) << "\n";
os << "Total time waiting for GC to complete: " << PrettyDuration(total_wait_time_) << "\n";
+ os << "Approximate GC data structures memory overhead: " << gc_memory_overhead_;
}
Heap::~Heap() {
@@ -1128,6 +1142,7 @@ collector::GcType Heap::CollectGarbageInternal(collector::GcType gc_type, GcCaus
// Wake anyone who may have been waiting for the GC to complete.
gc_complete_cond_->Broadcast(self);
}
+
// Inform DDMS that a GC completed.
ATRACE_END();
Dbg::GcDidFinish();
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 4a043a7..853db93 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -24,6 +24,7 @@
#include "atomic_integer.h"
#include "base/timing_logger.h"
#include "gc/accounting/atomic_stack.h"
+#include "gc/accounting/gc_allocator.h"
#include "gc/accounting/card_table.h"
#include "gc/collector/gc_type.h"
#include "globals.h"
@@ -207,6 +208,10 @@ class Heap {
return target_utilization_;
}
+ // Data structure memory usage tracking.
+ void RegisterGCAllocation(size_t bytes);
+ void RegisterGCDeAllocation(size_t bytes);
+
// Set target ideal heap utilization ratio, implements
// dalvik.system.VMRuntime.setTargetHeapUtilization.
void SetTargetHeapUtilization(float target);
@@ -556,6 +561,9 @@ class Heap {
// Current process state, updated by activity manager.
ProcessState process_state_;
+ // Data structure GC overhead.
+ AtomicInteger gc_memory_overhead_;
+
// Heap verification flags.
const bool verify_missing_card_marks_;
const bool verify_system_weaks_;
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index 09c55ec..8cd5088 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -17,7 +17,7 @@
#ifndef ART_RUNTIME_GC_SPACE_LARGE_OBJECT_SPACE_H_
#define ART_RUNTIME_GC_SPACE_LARGE_OBJECT_SPACE_H_
-
+#include "gc/accounting/gc_allocator.h"
#include "dlmalloc_space.h"
#include "safe_map.h"
#include "space.h"
@@ -95,8 +95,10 @@ class LargeObjectMapSpace : public LargeObjectSpace {
// Used to ensure mutual exclusion when the allocation spaces data structures are being modified.
mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- std::vector<mirror::Object*> large_objects_ GUARDED_BY(lock_);
- typedef SafeMap<mirror::Object*, MemMap*> MemMaps;
+ std::vector<mirror::Object*,
+ accounting::GCAllocator<mirror::Object*> > large_objects_ GUARDED_BY(lock_);
+ typedef SafeMap<mirror::Object*, MemMap*, std::less<mirror::Object*>,
+ accounting::GCAllocator<std::pair<const mirror::Object*, MemMap*> > > MemMaps;
MemMaps mem_maps_ GUARDED_BY(lock_);
};
diff --git a/runtime/safe_map.h b/runtime/safe_map.h
index dcc172d..4b5202a 100644
--- a/runtime/safe_map.h
+++ b/runtime/safe_map.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_SAFE_MAP_H_
#include <map>
+#include <memory>
#include "base/logging.h"
@@ -25,10 +26,11 @@ namespace art {
// Equivalent to std::map, but without operator[] and its bug-prone semantics (in particular,
// the implicit insertion of a default-constructed value on failed lookups).
-template <typename K, typename V, typename Comparator = std::less<K> >
+template <typename K, typename V, typename Comparator = std::less<K>,
+ typename Allocator = std::allocator<std::pair<const K, V> > >
class SafeMap {
private:
- typedef SafeMap<K, V, Comparator> Self;
+ typedef SafeMap<K, V, Comparator, Allocator> Self;
public:
typedef typename ::std::map<K, V, Comparator>::iterator iterator;
@@ -87,7 +89,7 @@ class SafeMap {
}
private:
- ::std::map<K, V, Comparator> map_;
+ ::std::map<K, V, Comparator, Allocator> map_;
};
template <typename K, typename V, typename Comparator>
diff --git a/runtime/utils.h b/runtime/utils.h
index 72597f5..1c45048 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -107,6 +107,18 @@ static inline uint32_t High32Bits(uint64_t value) {
return static_cast<uint32_t>(value >> 32);
}
+// A static if which determines whether to return type A or B based on the condition boolean.
+template <const bool condition, typename A, typename B>
+struct TypeStaticIf {
+ typedef A value;
+};
+
+// Specialization to handle the false case.
+template <typename A, typename B>
+struct TypeStaticIf<false, A, B> {
+ typedef B value;
+};
+
template<typename T>
static inline T RoundDown(T x, int n) {
CHECK(IsPowerOfTwo(n));