1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "system_weak.h" 18 19 #include <stdint.h> 20 #include <stdio.h> 21 #include <memory> 22 23 #include "base/mutex.h" 24 #include "collector_type.h" 25 #include "common_runtime_test.h" 26 #include "gc_root-inl.h" 27 #include "handle_scope-inl.h" 28 #include "heap.h" 29 #include "mirror/object-inl.h" 30 #include "mirror/string.h" 31 #include "scoped_thread_state_change-inl.h" 32 #include "thread_list.h" 33 34 namespace art HIDDEN { 35 namespace gc { 36 37 class SystemWeakTest : public CommonRuntimeTest { 38 protected: SystemWeakTest()39 SystemWeakTest() { 40 use_boot_image_ = true; // Make the Runtime creation cheaper. 41 } 42 }; 43 44 struct CountingSystemWeakHolder : public SystemWeakHolder { CountingSystemWeakHolderart::gc::CountingSystemWeakHolder45 CountingSystemWeakHolder() 46 : SystemWeakHolder(kAllocTrackerLock), 47 allow_count_(0), 48 disallow_count_(0), 49 sweep_count_(0) {} 50 Allowart::gc::CountingSystemWeakHolder51 void Allow() override 52 REQUIRES_SHARED(Locks::mutator_lock_) 53 REQUIRES(!allow_disallow_lock_) { 54 SystemWeakHolder::Allow(); 55 56 allow_count_++; 57 } 58 Disallowart::gc::CountingSystemWeakHolder59 void Disallow() override 60 REQUIRES_SHARED(Locks::mutator_lock_) 61 REQUIRES(!allow_disallow_lock_) { 62 SystemWeakHolder::Disallow(); 63 64 disallow_count_++; 65 } 66 Broadcastart::gc::CountingSystemWeakHolder67 void Broadcast(bool broadcast_for_checkpoint) override 68 REQUIRES(!allow_disallow_lock_) { 69 SystemWeakHolder::Broadcast(broadcast_for_checkpoint); 70 71 if (!broadcast_for_checkpoint) { 72 // Don't count the broadcasts for running checkpoints. 73 allow_count_++; 74 } 75 } 76 Sweepart::gc::CountingSystemWeakHolder77 void Sweep(IsMarkedVisitor* visitor) override 78 REQUIRES_SHARED(Locks::mutator_lock_) 79 REQUIRES(!allow_disallow_lock_) { 80 MutexLock mu(Thread::Current(), allow_disallow_lock_); 81 mirror::Object* old_object = weak_.Read<kWithoutReadBarrier>(); 82 mirror::Object* new_object = old_object == nullptr ? nullptr : visitor->IsMarked(old_object); 83 weak_ = GcRoot<mirror::Object>(new_object); 84 85 sweep_count_++; 86 } 87 Getart::gc::CountingSystemWeakHolder88 GcRoot<mirror::Object> Get() 89 REQUIRES_SHARED(Locks::mutator_lock_) 90 REQUIRES(!allow_disallow_lock_) { 91 Thread* self = Thread::Current(); 92 MutexLock mu(self, allow_disallow_lock_); 93 Wait(self); 94 95 return weak_; 96 } 97 Setart::gc::CountingSystemWeakHolder98 void Set(GcRoot<mirror::Object> obj) 99 REQUIRES_SHARED(Locks::mutator_lock_) 100 REQUIRES(!allow_disallow_lock_) { 101 Thread* self = Thread::Current(); 102 MutexLock mu(self, allow_disallow_lock_); 103 Wait(self); 104 105 weak_ = obj; 106 } 107 108 size_t allow_count_; 109 size_t disallow_count_; 110 size_t sweep_count_; 111 GcRoot<mirror::Object> weak_ GUARDED_BY(allow_disallow_lock_); 112 }; 113 CollectorDoesAllowOrBroadcast()114 static bool CollectorDoesAllowOrBroadcast() { 115 CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType(); 116 switch (type) { 117 case CollectorType::kCollectorTypeCMS: 118 case CollectorType::kCollectorTypeCMC: 119 case CollectorType::kCollectorTypeCC: 120 case CollectorType::kCollectorTypeSS: 121 return true; 122 123 default: 124 return false; 125 } 126 } 127 CollectorDoesDisallow()128 static bool CollectorDoesDisallow() { 129 CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType(); 130 switch (type) { 131 case CollectorType::kCollectorTypeCMS: 132 case CollectorType::kCollectorTypeCMC: 133 return true; 134 135 default: 136 return false; 137 } 138 } 139 TEST_F(SystemWeakTest,Keep)140 TEST_F(SystemWeakTest, Keep) { 141 CountingSystemWeakHolder cswh; 142 Runtime::Current()->AddSystemWeakHolder(&cswh); 143 144 ScopedObjectAccess soa(Thread::Current()); 145 146 StackHandleScope<1> hs(soa.Self()); 147 148 // We use Strings because they are very easy to allocate. 149 Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); 150 cswh.Set(GcRoot<mirror::Object>(s.Get())); 151 152 // Trigger a GC. 153 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false); 154 155 // Expect the holder to have been called. 156 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_); 157 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_); 158 // Userfaultfd GC uses SweepSystemWeaks also for concurrent updation. 159 // TODO: Explore this can be reverted back to unconditionally compare with 1 160 // once concurrent updation of native roots is full implemented in userfaultfd 161 // GC. 162 size_t expected_sweep_count = gUseUserfaultfd ? 2U : 1U; 163 EXPECT_EQ(expected_sweep_count, cswh.sweep_count_); 164 165 // Expect the weak to not be cleared. 166 EXPECT_FALSE(cswh.Get().IsNull()); 167 EXPECT_EQ(cswh.Get().Read(), s.Get()); 168 } 169 TEST_F(SystemWeakTest,Discard)170 TEST_F(SystemWeakTest, Discard) { 171 CountingSystemWeakHolder cswh; 172 Runtime::Current()->AddSystemWeakHolder(&cswh); 173 174 ScopedObjectAccess soa(Thread::Current()); 175 176 cswh.Set(GcRoot<mirror::Object>(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); 177 178 // Trigger a GC. 179 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false); 180 181 // Expect the holder to have been called. 182 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_); 183 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_); 184 // Userfaultfd GC uses SweepSystemWeaks also for concurrent updation. 185 // TODO: Explore this can be reverted back to unconditionally compare with 1 186 // once concurrent updation of native roots is full implemented in userfaultfd 187 // GC. 188 size_t expected_sweep_count = gUseUserfaultfd ? 2U : 1U; 189 EXPECT_EQ(expected_sweep_count, cswh.sweep_count_); 190 191 // Expect the weak to be cleared. 192 EXPECT_TRUE(cswh.Get().IsNull()); 193 } 194 TEST_F(SystemWeakTest,Remove)195 TEST_F(SystemWeakTest, Remove) { 196 CountingSystemWeakHolder cswh; 197 Runtime::Current()->AddSystemWeakHolder(&cswh); 198 199 ScopedObjectAccess soa(Thread::Current()); 200 201 StackHandleScope<1> hs(soa.Self()); 202 203 // We use Strings because they are very easy to allocate. 204 Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); 205 cswh.Set(GcRoot<mirror::Object>(s.Get())); 206 207 // Trigger a GC. 208 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false); 209 210 // Expect the holder to have been called. 211 ASSERT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_); 212 ASSERT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_); 213 // Userfaultfd GC uses SweepSystemWeaks also for concurrent updation. 214 // TODO: Explore this can be reverted back to unconditionally compare with 1 215 // once concurrent updation of native roots is full implemented in userfaultfd 216 // GC. 217 size_t expected_sweep_count = gUseUserfaultfd ? 2U : 1U; 218 EXPECT_EQ(expected_sweep_count, cswh.sweep_count_); 219 220 // Expect the weak to not be cleared. 221 ASSERT_FALSE(cswh.Get().IsNull()); 222 ASSERT_EQ(cswh.Get().Read(), s.Get()); 223 224 // Remove the holder. 225 Runtime::Current()->RemoveSystemWeakHolder(&cswh); 226 227 // Trigger another GC. 228 Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false); 229 230 // Expectation: no change in the numbers. 231 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_); 232 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_); 233 EXPECT_EQ(expected_sweep_count, cswh.sweep_count_); 234 } 235 236 } // namespace gc 237 } // namespace art 238