Merge "Add soft reference pre processing."
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index fe5a75f..8372734 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -145,6 +145,12 @@
&MarkObjectCallback, &ProcessMarkStackPausedCallback, this);
}
+void MarkSweep::PreProcessReferences(Thread* self) {
+ timings_.NewSplit("PreProcessReferences");
+ GetHeap()->ProcessSoftReferences(timings_, clear_soft_references_, &IsMarkedCallback,
+ &MarkObjectCallback, &ProcessMarkStackPausedCallback, this);
+}
+
bool MarkSweep::HandleDirtyObjectsPhase() {
TimingLogger::ScopedSplit split("(Paused)HandleDirtyObjectsPhase", &timings_);
Thread* self = Thread::Current();
@@ -255,6 +261,11 @@
MarkReachableObjects();
// Pre-clean dirtied cards to reduce pauses.
PreCleanCards();
+ if (IsConcurrent()) {
+ // No reason to do this for non-concurrent GC since pre processing soft references only helps
+ // pauses.
+ PreProcessReferences(self);
+ }
}
void MarkSweep::UpdateAndMarkModUnion() {
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index df19f88..b117b20 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -126,6 +126,10 @@
void ProcessReferences(Thread* self)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void PreProcessReferences(Thread* self)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Update and mark references from immune spaces. Virtual as overridden by StickyMarkSweep.
virtual void UpdateAndMarkModUnion()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index e8ee62f..a763e37 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -751,22 +751,31 @@
return args->mark_callback_(obj, args->arg_);
}
+void Heap::ProcessSoftReferences(TimingLogger& timings, bool clear_soft,
+ IsMarkedCallback* is_marked_callback,
+ MarkObjectCallback* mark_object_callback,
+ ProcessMarkStackCallback* process_mark_stack_callback, void* arg) {
+ // Unless required to clear soft references with white references, preserve some white referents.
+ if (!clear_soft) {
+ // Don't clear for sticky GC.
+ SoftReferenceArgs soft_reference_args;
+ soft_reference_args.is_marked_callback_ = is_marked_callback;
+ soft_reference_args.mark_callback_ = mark_object_callback;
+ soft_reference_args.arg_ = arg;
+ // References with a marked referent are removed from the list.
+ soft_reference_queue_.PreserveSomeSoftReferences(&PreserveSoftReferenceCallback,
+ &soft_reference_args);
+ process_mark_stack_callback(arg);
+ }
+}
+
// Process reference class instances and schedule finalizations.
void Heap::ProcessReferences(TimingLogger& timings, bool clear_soft,
IsMarkedCallback* is_marked_callback,
MarkObjectCallback* mark_object_callback,
ProcessMarkStackCallback* process_mark_stack_callback, void* arg) {
- // Unless we are in the zygote or required to clear soft references with white references,
- // preserve some white referents.
- if (!clear_soft && !Runtime::Current()->IsZygote()) {
- SoftReferenceArgs soft_reference_args;
- soft_reference_args.is_marked_callback_ = is_marked_callback;
- soft_reference_args.mark_callback_ = mark_object_callback;
- soft_reference_args.arg_ = arg;
- soft_reference_queue_.PreserveSomeSoftReferences(&PreserveSoftReferenceCallback,
- &soft_reference_args);
- process_mark_stack_callback(arg);
- }
+ ProcessSoftReferences(timings, clear_soft, is_marked_callback, mark_object_callback,
+ process_mark_stack_callback, arg);
timings.StartSplit("(Paused)ProcessReferences");
// Clear all remaining soft and weak references with white referents.
soft_reference_queue_.ClearWhiteReferences(cleared_references_, is_marked_callback, arg);
@@ -1813,7 +1822,10 @@
<< "Could not find garbage collector with concurrent=" << concurrent_gc_
<< " and type=" << gc_type;
ATRACE_BEGIN(StringPrintf("%s %s GC", PrettyCause(gc_cause), collector->GetName()).c_str());
- collector->Run(gc_cause, clear_soft_references);
+ if (!clear_soft_references) {
+ clear_soft_references = gc_type != collector::kGcTypeSticky; // TODO: GSS?
+ }
+ collector->Run(gc_cause, clear_soft_references || Runtime::Current()->IsZygote());
total_objects_freed_ever_ += collector->GetFreedObjects();
total_bytes_freed_ever_ += collector->GetFreedBytes();
RequestHeapTrim();
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index de20a4e..eb53ba9 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -314,6 +314,12 @@
}
static mirror::Object* PreserveSoftReferenceCallback(mirror::Object* obj, void* arg);
+ void ProcessSoftReferences(TimingLogger& timings, bool clear_soft,
+ IsMarkedCallback* is_marked_callback,
+ MarkObjectCallback* mark_object_callback,
+ ProcessMarkStackCallback* process_mark_stack_callback, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
void ProcessReferences(TimingLogger& timings, bool clear_soft,
IsMarkedCallback* is_marked_callback,
MarkObjectCallback* mark_object_callback,