blob: 7c1ec8af4d06f85d841a74584f221121572c16c5 [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"
29#include "scoped_thread_state_change.h"
30#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
61 void Broadcast() OVERRIDE
62 REQUIRES_SHARED(Locks::mutator_lock_)
63 REQUIRES(!allow_disallow_lock_) {
64 SystemWeakHolder::Broadcast();
65
66 allow_count_++;
67 }
68
69 void Sweep(IsMarkedVisitor* visitor) OVERRIDE
70 REQUIRES_SHARED(Locks::mutator_lock_)
71 REQUIRES(!allow_disallow_lock_) {
72 MutexLock mu(Thread::Current(), allow_disallow_lock_);
73 mirror::Object* old_object = weak_.Read<kWithoutReadBarrier>();
74 mirror::Object* new_object = old_object == nullptr ? nullptr : visitor->IsMarked(old_object);
75 weak_ = GcRoot<mirror::Object>(new_object);
76
77 sweep_count_++;
78 }
79
80 GcRoot<mirror::Object> Get()
81 REQUIRES_SHARED(Locks::mutator_lock_)
82 REQUIRES(!allow_disallow_lock_) {
83 Thread* self = Thread::Current();
84 MutexLock mu(self, allow_disallow_lock_);
85 Wait(self);
86
87 return weak_;
88 }
89
90 void Set(GcRoot<mirror::Object> obj)
91 REQUIRES_SHARED(Locks::mutator_lock_)
92 REQUIRES(!allow_disallow_lock_) {
93 Thread* self = Thread::Current();
94 MutexLock mu(self, allow_disallow_lock_);
95 Wait(self);
96
97 weak_ = obj;
98 }
99
100 size_t allow_count_;
101 size_t disallow_count_;
102 size_t sweep_count_;
103 GcRoot<mirror::Object> weak_ GUARDED_BY(allow_disallow_lock_);
104};
105
106static bool CollectorDoesAllowOrBroadcast() {
107 CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
108 switch (type) {
109 case CollectorType::kCollectorTypeCMS:
110 case CollectorType::kCollectorTypeCC:
111 return true;
112
113 default:
114 return false;
115 }
116}
117
118static bool CollectorDoesDisallow() {
119 CollectorType type = Runtime::Current()->GetHeap()->CurrentCollectorType();
120 switch (type) {
121 case CollectorType::kCollectorTypeCMS:
122 return true;
123
124 default:
125 return false;
126 }
127}
128
129TEST_F(SystemWeakTest, Keep) {
130 CountingSystemWeakHolder cswh;
131 Runtime::Current()->AddSystemWeakHolder(&cswh);
132
133 ScopedObjectAccess soa(Thread::Current());
134
135 StackHandleScope<1> hs(soa.Self());
136
137 // We use Strings because they are very easy to allocate.
138 Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
139 cswh.Set(GcRoot<mirror::Object>(s.Get()));
140
141 // Trigger a GC.
142 Runtime::Current()->GetHeap()->CollectGarbage(false);
143
144 // Expect the holder to have been called.
145 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
146 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
147 EXPECT_EQ(1U, cswh.sweep_count_);
148
149 // Expect the weak to not be cleared.
150 EXPECT_FALSE(cswh.Get().IsNull());
151 EXPECT_EQ(cswh.Get().Read(), s.Get());
152}
153
154TEST_F(SystemWeakTest, Discard) {
155 CountingSystemWeakHolder cswh;
156 Runtime::Current()->AddSystemWeakHolder(&cswh);
157
158 ScopedObjectAccess soa(Thread::Current());
159
160 cswh.Set(GcRoot<mirror::Object>(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
161
162 // Trigger a GC.
163 Runtime::Current()->GetHeap()->CollectGarbage(false);
164
165 // Expect the holder to have been called.
166 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
167 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
168 EXPECT_EQ(1U, cswh.sweep_count_);
169
170 // Expect the weak to be cleared.
171 EXPECT_TRUE(cswh.Get().IsNull());
172}
173
174TEST_F(SystemWeakTest, Remove) {
175 CountingSystemWeakHolder cswh;
176 Runtime::Current()->AddSystemWeakHolder(&cswh);
177
178 ScopedObjectAccess soa(Thread::Current());
179
180 StackHandleScope<1> hs(soa.Self());
181
182 // We use Strings because they are very easy to allocate.
183 Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABC")));
184 cswh.Set(GcRoot<mirror::Object>(s.Get()));
185
186 // Trigger a GC.
187 Runtime::Current()->GetHeap()->CollectGarbage(false);
188
189 // Expect the holder to have been called.
190 ASSERT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
191 ASSERT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
192 ASSERT_EQ(1U, cswh.sweep_count_);
193
194 // Expect the weak to not be cleared.
195 ASSERT_FALSE(cswh.Get().IsNull());
196 ASSERT_EQ(cswh.Get().Read(), s.Get());
197
198 // Remove the holder.
199 Runtime::Current()->RemoveSystemWeakHolder(&cswh);
200
201 // Trigger another GC.
202 Runtime::Current()->GetHeap()->CollectGarbage(false);
203
204 // Expectation: no change in the numbers.
205 EXPECT_EQ(CollectorDoesAllowOrBroadcast() ? 1U : 0U, cswh.allow_count_);
206 EXPECT_EQ(CollectorDoesDisallow() ? 1U : 0U, cswh.disallow_count_);
207 EXPECT_EQ(1U, cswh.sweep_count_);
208}
209
210} // namespace gc
211} // namespace art