diff options
| author | 2014-05-06 10:57:27 -0700 | |
|---|---|---|
| committer | 2014-05-07 15:28:35 -0700 | |
| commit | 78f7b4c04ab6e8b5581921bc95b67a9beee1c246 (patch) | |
| tree | 78b93c72007478b5bfc3b88ab413fa3d772da723 /runtime/gc/reference_processor.h | |
| parent | 052a647973b590c9d5007a2e16f313f4e32a70bd (diff) | |
Add concurrent reference processing.
Concurrent reference processing currently works by going into native
code from java.lang.ref.Reference.get(). From there, we have a fast
path if the references aren't being processed which returns the
referent without needing to access any locks. In the slow path we
block until reference processing is complete. It may be possible to
improve the slow path if the referent is blackened.
TODO: Investigate doing the fast path in java code by using racy reads
of a static volatile boolean. This will work as long as there are no
suspend points inbetween the boolean read and referent read.
Bug: 14381653
Change-Id: I1546b55be4691fe4ff4aa6d857b234cce7187d87
Diffstat (limited to 'runtime/gc/reference_processor.h')
| -rw-r--r-- | runtime/gc/reference_processor.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h new file mode 100644 index 0000000000..f082a9ec66 --- /dev/null +++ b/runtime/gc/reference_processor.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014 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_REFERENCE_PROCESSOR_H_ +#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_ + +#include "base/mutex.h" +#include "globals.h" +#include "jni.h" +#include "object_callbacks.h" +#include "reference_queue.h" + +namespace art { + +class TimingLogger; + +namespace mirror { +class Object; +class Reference; +} // namespace mirror + +namespace gc { + +class Heap; + +// Used to process java.lang.References concurrently or paused. +class ReferenceProcessor { + public: + explicit ReferenceProcessor(); + static mirror::Object* PreserveSoftReferenceCallback(mirror::Object* obj, void* arg); + void ProcessReferences(bool concurrent, TimingLogger* timings, bool clear_soft_references, + 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_) + LOCKS_EXCLUDED(lock_); + // Only allow setting this with mutators suspended so that we can avoid using a lock in the + // GetReferent fast path as an optimization. + void EnableSlowPath() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); + // Decode the referent, may block if references are being processed. + mirror::Object* GetReferent(Thread* self, mirror::Reference* reference) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_); + void EnqueueClearedReferences() LOCKS_EXCLUDED(Locks::mutator_lock_); + void DelayReferenceReferent(mirror::Class* klass, mirror::Reference* ref, + IsMarkedCallback is_marked_callback, void* arg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + private: + class ProcessReferencesArgs { + public: + ProcessReferencesArgs(IsMarkedCallback* is_marked_callback, + MarkObjectCallback* mark_callback, void* arg) + : is_marked_callback_(is_marked_callback), mark_callback_(mark_callback), arg_(arg) { + } + + // The is marked callback is null when the args aren't set up. + IsMarkedCallback* is_marked_callback_; + MarkObjectCallback* mark_callback_; + void* arg_; + }; + // Called by ProcessReferences. + void DisableSlowPath(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(lock_); + // If we are preserving references it means that some dead objects may become live, we use start + // and stop preserving to block mutators using GetReferrent from getting access to these + // referents. + void StartPreservingReferences(Thread* self) LOCKS_EXCLUDED(lock_); + void StopPreservingReferences(Thread* self) LOCKS_EXCLUDED(lock_); + // Process args, used by the GetReferent to return referents which are already marked. + ProcessReferencesArgs process_references_args_ GUARDED_BY(lock_); + // Boolean for whether or not we need to go slow path in GetReferent. + volatile bool slow_path_enabled_; + // Boolean for whether or not we are preserving references (either soft references or finalizers). + // If this is true, then we cannot return a referent (see comment in GetReferent). + bool preserving_references_ GUARDED_BY(lock_); + // Lock that guards the reference processing. + Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; + // Condition that people wait on if they attempt to get the referent of a reference while + // processing is in progress. + ConditionVariable condition_ GUARDED_BY(lock_); + // Reference queues used by the GC. + ReferenceQueue soft_reference_queue_; + ReferenceQueue weak_reference_queue_; + ReferenceQueue finalizer_reference_queue_; + ReferenceQueue phantom_reference_queue_; + ReferenceQueue cleared_references_; +}; + +} // namespace gc +} // namespace art + +#endif // ART_RUNTIME_GC_REFERENCE_PROCESSOR_H_ |