summaryrefslogtreecommitdiff
path: root/runtime/gc/reference_processor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/gc/reference_processor.cc')
-rw-r--r--runtime/gc/reference_processor.cc43
1 files changed, 36 insertions, 7 deletions
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 99bd63fa8a..01e8795669 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -23,11 +23,14 @@
#include "reflection.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
+#include "task_processor.h"
#include "well_known_classes.h"
namespace art {
namespace gc {
+static constexpr bool kAsyncReferenceQueueAdd = false;
+
ReferenceProcessor::ReferenceProcessor()
: process_references_args_(nullptr, nullptr, nullptr),
preserving_references_(false),
@@ -213,17 +216,43 @@ void ReferenceProcessor::UpdateRoots(IsMarkedCallback* callback, void* arg) {
cleared_references_.UpdateRoots(callback, arg);
}
+class ClearedReferenceTask : public HeapTask {
+ public:
+ explicit ClearedReferenceTask(jobject cleared_references)
+ : HeapTask(NanoTime()), cleared_references_(cleared_references) {
+ }
+ virtual void Run(Thread* thread) {
+ ScopedObjectAccess soa(thread);
+ jvalue args[1];
+ args[0].l = cleared_references_;
+ InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args);
+ soa.Env()->DeleteGlobalRef(cleared_references_);
+ }
+
+ private:
+ const jobject cleared_references_;
+};
+
void ReferenceProcessor::EnqueueClearedReferences(Thread* self) {
Locks::mutator_lock_->AssertNotHeld(self);
+ // When a runtime isn't started there are no reference queues to care about so ignore.
if (!cleared_references_.IsEmpty()) {
- // When a runtime isn't started there are no reference queues to care about so ignore.
if (LIKELY(Runtime::Current()->IsStarted())) {
- ScopedObjectAccess soa(self);
- ScopedLocalRef<jobject> arg(self->GetJniEnv(),
- soa.AddLocalReference<jobject>(cleared_references_.GetList()));
- jvalue args[1];
- args[0].l = arg.get();
- InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args);
+ jobject cleared_references;
+ {
+ ReaderMutexLock mu(self, *Locks::mutator_lock_);
+ cleared_references = self->GetJniEnv()->vm->AddGlobalRef(
+ self, cleared_references_.GetList());
+ }
+ if (kAsyncReferenceQueueAdd) {
+ // TODO: This can cause RunFinalization to terminate before newly freed objects are
+ // finalized since they may not be enqueued by the time RunFinalization starts.
+ Runtime::Current()->GetHeap()->GetTaskProcessor()->AddTask(
+ self, new ClearedReferenceTask(cleared_references));
+ } else {
+ ClearedReferenceTask task(cleared_references);
+ task.Run(self);
+ }
}
cleared_references_.Clear();
}