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