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/string.h"
30 #include "scoped_thread_state_change-inl.h"
31 #include "thread_list.h"
32 
33 namespace art {
34 namespace gc {
35 
36 class SystemWeakTest : public CommonRuntimeTest {
37 };
38 
39 struct CountingSystemWeakHolder : public SystemWeakHolder {
CountingSystemWeakHolderart::gc::CountingSystemWeakHolder40   CountingSystemWeakHolder()
41       : SystemWeakHolder(kAllocTrackerLock),
42         allow_count_(0),
43         disallow_count_(0),
44         sweep_count_(0) {}
45 
Allowart::gc::CountingSystemWeakHolder46   void Allow() OVERRIDE
47       REQUIRES_SHARED(Locks::mutator_lock_)
48       REQUIRES(!allow_disallow_lock_) {
49     SystemWeakHolder::Allow();
50 
51     allow_count_++;
52   }
53 
Disallowart::gc::CountingSystemWeakHolder54   void Disallow() OVERRIDE
55       REQUIRES_SHARED(Locks::mutator_lock_)
56       REQUIRES(!allow_disallow_lock_) {
57     SystemWeakHolder::Disallow();
58 
59     disallow_count_++;
60   }
61 
Broadcastart::gc::CountingSystemWeakHolder62   void Broadcast(bool broadcast_for_checkpoint) OVERRIDE
63       REQUIRES(!allow_disallow_lock_) {
64     SystemWeakHolder::Broadcast(broadcast_for_checkpoint);
65 
66     if (!broadcast_for_checkpoint) {
67       // Don't count the broadcasts for running checkpoints.
68       allow_count_++;
69     }
70   }
71 
Sweepart::gc::CountingSystemWeakHolder72   void Sweep(IsMarkedVisitor* visitor) OVERRIDE
73       REQUIRES_SHARED(Locks::mutator_lock_)
74       REQUIRES(!allow_disallow_lock_) {
75     MutexLock mu(Thread::Current(), allow_disallow_lock_);
76     mirror::Object* old_object = weak_.Read<kWithoutReadBarrier>();
77     mirror::Object* new_object = old_object == nullptr ? nullptr : visitor->IsMarked(old_object);
78     weak_ = GcRoot<mirror::Object>(new_object);
79 
80     sweep_count_++;
81   }
82 
Getart::gc::CountingSystemWeakHolder83   GcRoot<mirror::Object> Get()
84       REQUIRES_SHARED(Locks::mutator_lock_)
85       REQUIRES(!allow_disallow_lock_) {
86     Thread* self = Thread::Current();
87     MutexLock mu(self, allow_disallow_lock_);
88     Wait(self);
89 
90     return weak_;
91   }
92 
Setart::gc::CountingSystemWeakHolder93   void Set(GcRoot<mirror::Object> obj)
94       REQUIRES_SHARED(Locks::mutator_lock_)
95       REQUIRES(!allow_disallow_lock_) {
96     Thread* self = Thread::Current();
97     MutexLock mu(self, allow_disallow_lock_);
98     Wait(self);
99 
100     weak_ = obj;
101   }
102 
103   size_t allow_count_;
104   size_t disallow_count_;
105   size_t sweep_count_;
106   GcRoot<mirror::Object> weak_ GUARDED_BY(allow_disallow_lock_);
107 };
108 
CollectorDoesAllowOrBroadcast()109 static bool CollectorDoesAllowOrBroadcast() {
110   CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
111   switch (type) {
112     case CollectorType::kCollectorTypeCMS:
113     case CollectorType::kCollectorTypeCC:
114       return true;
115 
116     default:
117       return false;
118   }
119 }
120 
CollectorDoesDisallow()121 static bool CollectorDoesDisallow() {
122   CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
123   switch (type) {
124     case CollectorType::kCollectorTypeCMS:
125       return true;
126 
127     default:
128       return false;
129   }
130 }
131 
TEST_F(SystemWeakTest,Keep)132 TEST_F(SystemWeakTest, Keep) {
133   CountingSystemWeakHolder cswh;
134   Runtime::Current()->AddSystemWeakHolder(&cswh);
135 
136   ScopedObjectAccess soa(Thread::Current());
137 
138   StackHandleScope<1> hs(soa.Self());
139 
140   // We use Strings because they are very easy to allocate.
141   Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
142   cswh.Set(GcRoot<mirror::Object>(s.Get()));
143 
144   // Trigger a GC.
145   Runtime::Current()->GetHeap()->CollectGarbage(false);
146 
147   // Expect the holder to have been called.
148   EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
149   EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
150   EXPECT_EQ(1U, cswh.sweep_count_);
151 
152   // Expect the weak to not be cleared.
153   EXPECT_FALSE(cswh.Get().IsNull());
154   EXPECT_EQ(cswh.Get().Read(), s.Get());
155 }
156 
TEST_F(SystemWeakTest,Discard)157 TEST_F(SystemWeakTest, Discard) {
158   CountingSystemWeakHolder cswh;
159   Runtime::Current()->AddSystemWeakHolder(&cswh);
160 
161   ScopedObjectAccess soa(Thread::Current());
162 
163   cswh.Set(GcRoot<mirror::Object>(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
164 
165   // Trigger a GC.
166   Runtime::Current()->GetHeap()->CollectGarbage(false);
167 
168   // Expect the holder to have been called.
169   EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
170   EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
171   EXPECT_EQ(1U, cswh.sweep_count_);
172 
173   // Expect the weak to be cleared.
174   EXPECT_TRUE(cswh.Get().IsNull());
175 }
176 
TEST_F(SystemWeakTest,Remove)177 TEST_F(SystemWeakTest, Remove) {
178   CountingSystemWeakHolder cswh;
179   Runtime::Current()->AddSystemWeakHolder(&cswh);
180 
181   ScopedObjectAccess soa(Thread::Current());
182 
183   StackHandleScope<1> hs(soa.Self());
184 
185   // We use Strings because they are very easy to allocate.
186   Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
187   cswh.Set(GcRoot<mirror::Object>(s.Get()));
188 
189   // Trigger a GC.
190   Runtime::Current()->GetHeap()->CollectGarbage(false);
191 
192   // Expect the holder to have been called.
193   ASSERT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
194   ASSERT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
195   ASSERT_EQ(1U, cswh.sweep_count_);
196 
197   // Expect the weak to not be cleared.
198   ASSERT_FALSE(cswh.Get().IsNull());
199   ASSERT_EQ(cswh.Get().Read(), s.Get());
200 
201   // Remove the holder.
202   Runtime::Current()->RemoveSystemWeakHolder(&cswh);
203 
204   // Trigger another GC.
205   Runtime::Current()->GetHeap()->CollectGarbage(false);
206 
207   // Expectation: no change in the numbers.
208   EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
209   EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
210   EXPECT_EQ(1U, cswh.sweep_count_);
211 }
212 
213 }  // namespace gc
214 }  // namespace art
215