• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "common_components/heap/allocator/region_desc.h"
17 #include "common_components/heap/allocator/region_space.h"
18 #include "common_components/mutator/satb_buffer.h"
19 #include "common_components/tests/test_helper.h"
20 #include "common_interfaces/base_runtime.h"
21 
22 using namespace common;
23 namespace common::test {
24 
25 class SatbBufferTest : public BaseTestWithScope {
26 protected:
SetUpTestCase()27     static void SetUpTestCase()
28     {
29         BaseRuntime::GetInstance()->Init();
30     }
31 
TearDownTestCase()32     static void TearDownTestCase()
33     {
34         BaseRuntime::GetInstance()->Fini();
35     }
36 
SetUp()37     void SetUp() override
38     {
39         holder_ = ThreadHolder::CreateAndRegisterNewThreadHolder(nullptr);
40         scope_ = new ThreadHolder::TryBindMutatorScope(holder_);
41     }
42 
TearDown()43     void TearDown() override
44     {
45         if (scope_ != nullptr) {
46             delete scope_;
47             scope_ = nullptr;
48         }
49     }
50 
51     ThreadHolder *holder_ {nullptr};
52     ThreadHolder::TryBindMutatorScope *scope_ {nullptr};
53 };
54 
HWTEST_F_L0(SatbBufferTest,NullptrReturnsFalse)55 HWTEST_F_L0(SatbBufferTest, NullptrReturnsFalse)
56 {
57     EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(nullptr));
58 }
59 
HWTEST_F_L0(SatbBufferTest,IsYoungSpaceObject1)60 HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject1)
61 {
62     auto* mutator = common::Mutator::GetMutator();
63     mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM);
64     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
65     uintptr_t addr = theAllocator.AllocOldRegion();
66     ASSERT_NE(addr, 0);
67     RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
68     region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST);
69     Heap::GetHeap().SetGCReason(GC_REASON_YOUNG);
70 
71     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
72     EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(obj));
73 }
74 
HWTEST_F_L0(SatbBufferTest,IsYoungSpaceObject2)75 HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject2)
76 {
77     auto* mutator = common::Mutator::GetMutator();
78     mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM);
79     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
80     uintptr_t addr = theAllocator.AllocOldRegion();
81     ASSERT_NE(addr, 0);
82     RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
83     region->SetRegionType(RegionDesc::RegionType::FROM_REGION);
84     Heap::GetHeap().SetGCReason(GC_REASON_HEU);
85 
86     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
87     EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(obj));
88 }
89 
HWTEST_F_L0(SatbBufferTest,IsYoungSpaceObject3)90 HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject3)
91 {
92     auto* mutator = common::Mutator::GetMutator();
93     mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM);
94     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
95     uintptr_t addr = theAllocator.AllocOldRegion();
96     ASSERT_NE(addr, 0);
97     RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
98     region->SetRegionType(RegionDesc::RegionType::FROM_REGION);
99     Heap::GetHeap().SetGCReason(GC_REASON_YOUNG);
100 
101     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
102     EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(obj));
103 }
104 
HWTEST_F_L0(SatbBufferTest,IsYoungSpaceObject4)105 HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject4)
106 {
107     auto* mutator = common::Mutator::GetMutator();
108     mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM);
109     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
110     uintptr_t addr = theAllocator.AllocOldRegion();
111     ASSERT_NE(addr, 0);
112     RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
113     region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST);
114     Heap::GetHeap().SetGCReason(GC_REASON_HEU);
115     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
116     EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(obj));
117 }
118 
HWTEST_F_L0(SatbBufferTest,IsMarkedObject)119 HWTEST_F_L0(SatbBufferTest, IsMarkedObject)
120 {
121     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
122     uintptr_t addr = theAllocator.AllocOldRegion();
123     ASSERT_NE(addr, 0U);
124     BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
125     Heap::GetHeap().SetGCReason(GC_REASON_HEU);
126 
127     RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast<uintptr_t>(obj));
128     region->SetMarkedRegionFlag(1);
129 
130     size_t offset = region->GetAddressOffset(reinterpret_cast<HeapAddress>(obj));
131     RegionBitmap* markBitmap = region->GetOrAllocMarkBitmap();
132     markBitmap->MarkBits(offset);
133 
134     bool result = SatbBuffer::Instance().ShouldEnqueue(obj);
135     EXPECT_FALSE(result);
136 }
137 
ClearMarkBit(RegionBitmap * bitmap,size_t offset)138 void ClearMarkBit(RegionBitmap* bitmap, size_t offset)
139 {
140     uintptr_t* bits = *reinterpret_cast<uintptr_t**>(bitmap);
141 
142     size_t wordIndex = offset / (sizeof(uintptr_t) * 8);
143     size_t bitIndex = offset % (sizeof(uintptr_t) * 8);
144 
145     uintptr_t mask = ~(static_cast<uintptr_t>(1) << bitIndex);
146 
147     uintptr_t* addr = const_cast<uintptr_t*>(bits + wordIndex);
148     uintptr_t oldVal;
149     uintptr_t newVal;
150 
151     do {
152         oldVal = __atomic_load_n(addr, __ATOMIC_ACQUIRE);
153         newVal = oldVal & mask;
154         if (oldVal == newVal) {
155             return;
156         }
157     } while (!__atomic_compare_exchange_n(addr, &oldVal, newVal, false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE));
158 }
159 
HWTEST_F_L0(SatbBufferTest,EnqueueObject)160 HWTEST_F_L0(SatbBufferTest, EnqueueObject)
161 {
162     RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
163     uintptr_t addr = theAllocator.AllocOldRegion();
164     ASSERT_NE(addr, 0U);
165 
166     uintptr_t objAddress = addr + 0x100;
167     BaseObject* obj = reinterpret_cast<BaseObject*>(objAddress);
168     Heap::GetHeap().SetGCReason(GC_REASON_HEU);
169 
170     RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast<uintptr_t>(obj));
171     region->SetRegionType(RegionDesc::RegionType::FROM_REGION);
172     region->SetMarkingLine();
173     region->SetMarkedRegionFlag(0);
174     RegionBitmap* markBitmap = region->GetMarkBitmap();
175     size_t offset = region->GetAddressOffset(reinterpret_cast<HeapAddress>(obj));
176     if (markBitmap != nullptr) {
177         ClearMarkBit(markBitmap, offset);
178     }
179 
180     region->SetEnqueuedRegionFlag(1);
181     RegionBitmap* enqueueBitmap = region->GetOrAllocEnqueueBitmap();
182     enqueueBitmap->MarkBits(offset);
183 
184     bool result = SatbBuffer::Instance().ShouldEnqueue(obj);
185     EXPECT_FALSE(result);
186 }
187 }  // namespace common::test
188