• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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