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