diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-11-26 11:21:15 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-11-26 16:06:35 -0800 |
commit | 91c2f0cde2a009bd52aa1c3d1dee705cc02c932f (patch) | |
tree | 55c02c51308df051c76d89a09627ad16d8f45f72 /runtime | |
parent | bd6bb37c377e78aeafb4faf9acd70efbcbc62d30 (diff) | |
download | android_art-91c2f0cde2a009bd52aa1c3d1dee705cc02c932f.tar.gz android_art-91c2f0cde2a009bd52aa1c3d1dee705cc02c932f.tar.bz2 android_art-91c2f0cde2a009bd52aa1c3d1dee705cc02c932f.zip |
Trim reference tables when we trim the heap
Before:
System server:
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
2200 300 229 0 80 0 220 77 /dev/ashmem/dalvik-indirect ref table (deleted)
Location:
1896 128 102 0 28 0 100 39 /dev/ashmem/dalvik-indirect ref table (deleted)
After:
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
System server:
2216 64 64 0 0 0 64 79 /dev/ashmem/dalvik-indirect ref table (deleted)
Location:
2120 48 48 0 0 0 48 67 /dev/ashmem/dalvik-indirect ref table (deleted)
No pause time regression measured in memalloc test.
(cherry picked from commit 84dc99d2fa67e5dff018685661cb2bff62132989)
Change-Id: I80d9bd3b98e888fa8f77d03df69f8479ed209986
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/gc/heap.cc | 29 | ||||
-rw-r--r-- | runtime/indirect_reference_table.cc | 10 | ||||
-rw-r--r-- | runtime/indirect_reference_table.h | 3 | ||||
-rw-r--r-- | runtime/java_vm_ext.cc | 5 | ||||
-rw-r--r-- | runtime/java_vm_ext.h | 3 |
5 files changed, 48 insertions, 2 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 0cceaa4467..7b679ea988 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -977,6 +977,22 @@ void Heap::DoPendingTransitionOrTrim() { Trim(); } +class TrimIndirectReferenceTableClosure : public Closure { + public: + explicit TrimIndirectReferenceTableClosure(Barrier* barrier) : barrier_(barrier) { + } + virtual void Run(Thread* thread) OVERRIDE NO_THREAD_SAFETY_ANALYSIS { + ATRACE_BEGIN("Trimming reference table"); + thread->GetJniEnv()->locals.Trim(); + ATRACE_END(); + barrier_->Pass(Thread::Current()); + } + + private: + Barrier* const barrier_; +}; + + void Heap::Trim() { Thread* self = Thread::Current(); { @@ -998,6 +1014,19 @@ void Heap::Trim() { WaitForGcToCompleteLocked(kGcCauseTrim, self); collector_type_running_ = kCollectorTypeHeapTrim; } + // Trim reference tables. + { + ScopedObjectAccess soa(self); + JavaVMExt* vm = soa.Vm(); + // Trim globals indirect reference table. + vm->TrimGlobals(); + // Trim locals indirect reference tables. + Barrier barrier(0); + TrimIndirectReferenceTableClosure closure(&barrier); + ScopedThreadStateChange tsc(self, kWaitingForCheckPointsToRun); + size_t barrier_count = Runtime::Current()->GetThreadList()->RunCheckpoint(&closure); + barrier.Increment(self, barrier_count); + } uint64_t start_ns = NanoTime(); // Trim the managed spaces. uint64_t total_alloc_space_allocated = 0; diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index 4d177a32d8..0d84a1ef98 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -162,13 +162,12 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { DCHECK(table_ != NULL); DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); - int idx = ExtractIndex(iref); - if (GetIndirectRefKind(iref) == kHandleScopeOrInvalid && Thread::Current()->HandleScopeContains(reinterpret_cast<jobject>(iref))) { LOG(WARNING) << "Attempt to remove local handle scope entry from IRT, ignoring"; return true; } + const int idx = ExtractIndex(iref); if (idx < bottomIndex) { // Wrong segment. LOG(WARNING) << "Attempt to remove index outside index area (" << idx @@ -236,6 +235,13 @@ bool IndirectReferenceTable::Remove(uint32_t cookie, IndirectRef iref) { return true; } +void IndirectReferenceTable::Trim() { + const size_t top_index = Capacity(); + auto* release_start = AlignUp(reinterpret_cast<uint8_t*>(&table_[top_index]), kPageSize); + uint8_t* release_end = table_mem_map_->End(); + madvise(release_start, release_end - release_start, MADV_DONTNEED); +} + void IndirectReferenceTable::VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) { for (auto ref : *this) { diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index 168f9f2764..fbd5714688 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -331,6 +331,9 @@ class IndirectReferenceTable { return Offset(OFFSETOF_MEMBER(IndirectReferenceTable, segment_state_)); } + // Release pages past the end of the table that may have previously held references. + void Trim() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + private: // Extract the table index from an indirect reference. static uint32_t ExtractIndex(IndirectRef iref) { diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index a5abce6ab1..5d04faccb5 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -756,6 +756,11 @@ void JavaVMExt::SweepJniWeakGlobals(IsMarkedCallback* callback, void* arg) { } } +void JavaVMExt::TrimGlobals() { + WriterMutexLock mu(Thread::Current(), globals_lock_); + globals_.Trim(); +} + void JavaVMExt::VisitRoots(RootCallback* callback, void* arg) { Thread* self = Thread::Current(); { diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h index 2957ba3fae..749b9fb6c0 100644 --- a/runtime/java_vm_ext.h +++ b/runtime/java_vm_ext.h @@ -131,6 +131,9 @@ class JavaVMExt : public JavaVM { return unchecked_functions_; } + void TrimGlobals() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) + LOCKS_EXCLUDED(globals_lock_); + private: Runtime* const runtime_; |