ART: Add generic system-weak holder infrastructure

Add an "interface" for a generic system-weak holder that is
integrated with the well-known instances in Runtime. Add a
simple implementation handling synchronization.

Add a test.

Bug: 31385027
Test: m test-art-host-gtest-system_weak_test
Test: m ART_USE_READ_BARRIER=true test-art-host-gtest-system_weak_test
Test: m ART_DEFAULT_GC_TYPE=SS test-art-host-gtest-system_weak_test
Test: m ART_DEFAULT_GC_TYPE=GSS test-art-host-gtest-system_weak_test
Change-Id: I1100e2cbd9ee57860993d0039de73d197681c542
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a365a73..71fc3ba 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -71,8 +71,10 @@
 #include "fault_handler.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
+#include "gc/scoped_gc_critical_section.h"
 #include "gc/space/image_space.h"
 #include "gc/space/space-inl.h"
+#include "gc/system_weak.h"
 #include "handle_scope-inl.h"
 #include "image-inl.h"
 #include "instrumentation.h"
@@ -473,6 +475,11 @@
   GetMonitorList()->SweepMonitorList(visitor);
   GetJavaVM()->SweepJniWeakGlobals(visitor);
   GetHeap()->SweepAllocationRecords(visitor);
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Sweep(visitor);
+  }
 }
 
 bool Runtime::ParseOptions(const RuntimeOptions& raw_options,
@@ -1708,6 +1715,11 @@
   intern_table_->ChangeWeakRootState(gc::kWeakRootStateNoReadsOrWrites);
   java_vm_->DisallowNewWeakGlobals();
   heap_->DisallowNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Disallow();
+  }
 }
 
 void Runtime::AllowNewSystemWeaks() {
@@ -1716,6 +1728,11 @@
   intern_table_->ChangeWeakRootState(gc::kWeakRootStateNormal);  // TODO: Do this in the sweeping.
   java_vm_->AllowNewWeakGlobals();
   heap_->AllowNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Allow();
+  }
 }
 
 void Runtime::BroadcastForNewSystemWeaks() {
@@ -1726,6 +1743,11 @@
   intern_table_->BroadcastForNewInterns();
   java_vm_->BroadcastForNewWeakGlobals();
   heap_->BroadcastForNewAllocationRecords();
+
+  // All other generic system-weak holders.
+  for (gc::AbstractSystemWeakHolder* holder : system_weak_holders_) {
+    holder->Broadcast();
+  }
 }
 
 void Runtime::SetInstructionSet(InstructionSet instruction_set) {
@@ -2064,4 +2086,21 @@
   return c_env_vector_.get();
 }
 
+void Runtime::AddSystemWeakHolder(gc::AbstractSystemWeakHolder* holder) {
+  gc::ScopedGCCriticalSection gcs(Thread::Current(),
+                                  gc::kGcCauseAddRemoveSystemWeakHolder,
+                                  gc::kCollectorTypeAddRemoveSystemWeakHolder);
+  system_weak_holders_.push_back(holder);
+}
+
+void Runtime::RemoveSystemWeakHolder(gc::AbstractSystemWeakHolder* holder) {
+  gc::ScopedGCCriticalSection gcs(Thread::Current(),
+                                  gc::kGcCauseAddRemoveSystemWeakHolder,
+                                  gc::kCollectorTypeAddRemoveSystemWeakHolder);
+  auto it = std::find(system_weak_holders_.begin(), system_weak_holders_.end(), holder);
+  if (it != system_weak_holders_.end()) {
+    system_weak_holders_.erase(it);
+  }
+}
+
 }  // namespace art