From 893263b7d5bc2ca43a91ecb8071867f5134fc60a Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Tue, 4 Mar 2014 11:07:42 -0800 Subject: Avoid marking old class linker and intern table roots during pause. The new root visiting logic has a concept of a root log which holds new roots which were added since the start of the GC. This is an optimization since it lets us only mark these newly added roots during the pause (or pre-cleaning) since the other roots intern table and class linker roots were marked concurrently at the start of the GC. Before (EvaluateAndApplyChanges): MarkConcurrentRoots: Sum: 605.193ms After: MarkConcurrentRoots: Sum: 271.858ms This should also reduce pathological GC pauses which used to be able to happen when the intern table or class linker became "dirty" during the concurrent GC. Change-Id: I433fab021f2c339d50c35aaae7161a50a0901dec --- runtime/runtime.cc | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'runtime/runtime.cc') diff --git a/runtime/runtime.cc b/runtime/runtime.cc index e80a473..7546729 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -797,18 +797,9 @@ void Runtime::DetachCurrentThread() { return pre_allocated_OutOfMemoryError_; } -void Runtime::VisitConcurrentRoots(RootCallback* callback, void* arg, bool only_dirty, - bool clean_dirty) { - intern_table_->VisitRoots(callback, arg, only_dirty, clean_dirty); - class_linker_->VisitRoots(callback, arg, only_dirty, clean_dirty); - // TODO: is it the right place ? - if (preinitialization_transaction != nullptr) { - preinitialization_transaction->VisitRoots(callback, arg); - } -} - -void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { - // Visit the classes held as static in mirror classes. +void Runtime::VisitConstantRoots(RootCallback* callback, void* arg) { + // Visit the classes held as static in mirror classes, these can be visited concurrently and only + // need to be visited once since they never change. mirror::ArtField::VisitRoots(callback, arg); mirror::ArtMethod::VisitRoots(callback, arg); mirror::Class::VisitRoots(callback, arg); @@ -824,6 +815,18 @@ void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { mirror::PrimitiveArray::VisitRoots(callback, arg); // IntArray mirror::PrimitiveArray::VisitRoots(callback, arg); // LongArray mirror::PrimitiveArray::VisitRoots(callback, arg); // ShortArray +} + +void Runtime::VisitConcurrentRoots(RootCallback* callback, void* arg, VisitRootFlags flags) { + intern_table_->VisitRoots(callback, arg, flags); + class_linker_->VisitRoots(callback, arg, flags); + if ((flags & kVisitRootFlagNewRoots) == 0) { + // Guaranteed to have no new roots in the constant roots. + VisitConstantRoots(callback, arg); + } +} + +void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { java_vm_->VisitRoots(callback, arg); if (pre_allocated_OutOfMemoryError_ != nullptr) { callback(reinterpret_cast(&pre_allocated_OutOfMemoryError_), arg, 0, @@ -838,7 +841,6 @@ void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { if (HasDefaultImt()) { callback(reinterpret_cast(&default_imt_), arg, 0, kRootVMInternal); } - for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { if (callee_save_methods_[i] != nullptr) { callback(reinterpret_cast(&callee_save_methods_[i]), arg, 0, @@ -851,6 +853,9 @@ void Runtime::VisitNonThreadRoots(RootCallback* callback, void* arg) { verifier->VisitRoots(callback, arg); } } + if (preinitialization_transaction != nullptr) { + preinitialization_transaction->VisitRoots(callback, arg); + } } void Runtime::VisitNonConcurrentRoots(RootCallback* callback, void* arg) { @@ -858,8 +863,8 @@ void Runtime::VisitNonConcurrentRoots(RootCallback* callback, void* arg) { VisitNonThreadRoots(callback, arg); } -void Runtime::VisitRoots(RootCallback* callback, void* arg, bool only_dirty, bool clean_dirty) { - VisitConcurrentRoots(callback, arg, only_dirty, clean_dirty); +void Runtime::VisitRoots(RootCallback* callback, void* arg, VisitRootFlags flags) { + VisitConcurrentRoots(callback, arg, flags); VisitNonConcurrentRoots(callback, arg); } -- cgit v1.1