• 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 #ifndef COMMON_COMPONENTS_HEAP_COLLECTOR_REGION_RSET_H
17 #define COMMON_COMPONENTS_HEAP_COLLECTOR_REGION_RSET_H
18 
19 #include <atomic>
20 #include <errno.h>
21 
22 namespace common {
23 class RegionRSet {
24 public:
25     static constexpr size_t CARD_SIZE = 512;
26     using CardElement = uint64_t;
27     static_assert(std::atomic<CardElement>::is_always_lock_free);
28     static constexpr size_t CARD_TABLE_DATA_OFFSET = AlignUp<size_t>(sizeof(size_t), sizeof(CardElement));
29 
CreateRegionRSet(size_t regionSize)30     static RegionRSet *CreateRegionRSet(size_t regionSize)
31     {
32         CHECK_CC(regionSize % CARD_SIZE == 0);
33         size_t cardCnt = regionSize / CARD_SIZE;
34         size_t cardSize = cardCnt * sizeof(CardElement);
35         void *ptr = malloc(CARD_TABLE_DATA_OFFSET + cardSize);
36         if (ptr == nullptr) {
37             LOG_COMMON(FATAL) << "malloc failed, regionSize=" << regionSize << ", cardSize=" << cardSize
38                               << ", errnor=" << errno;
39             UNREACHABLE();
40         }
41         RegionRSet *rset = new (ptr) RegionRSet(cardCnt);
42         rset->ClearCardTable();
43         return rset;
44     }
45 
DestroyRegionRSet(RegionRSet * rset)46     static void DestroyRegionRSet(RegionRSet *rset)
47     {
48         free(rset);
49     }
50 
MarkCardTable(size_t offset)51     bool MarkCardTable(size_t offset)
52     {
53         size_t cardIdx = (offset / kMarkedBytesPerBit) / kBitsPerWord;
54         size_t headMaskBitStart = (offset / kMarkedBytesPerBit) % kBitsPerWord;
55         CardElement headMaskBits = static_cast<CardElement>(1ULL << headMaskBitStart);
56         std::atomic<CardElement> *card = reinterpret_cast<std::atomic<CardElement> *>(&GetCardTable()[cardIdx]);
57         bool isMarked = ((card->load(std::memory_order_relaxed) & headMaskBits) != 0);
58         if (!isMarked) {
59             CardElement prev = card->fetch_or(headMaskBits, std::memory_order_relaxed);
60             isMarked = ((prev & headMaskBits) != 0);
61             return isMarked;
62         }
63         return true;
64     }
65 
ClearCardTable()66     void ClearCardTable()
67     {
68         LOGF_CHECK(memset_s(GetCardTable(), cardCnt_ * sizeof(CardElement), 0, cardCnt_ * sizeof(CardElement)) == EOK)
69             << "memset_s fail, cardCnt=" << cardCnt_;
70     }
71 
VisitAllMarkedCardBefore(const std::function<void (BaseObject *)> & func,HeapAddress regionStart,HeapAddress end)72     void VisitAllMarkedCardBefore(const std::function<void(BaseObject*)>& func,
73                                   HeapAddress regionStart, HeapAddress end)
74     {
75         for (size_t i = 0; i < cardCnt_; i++) {
76             CardElement card = GetCardTable()[i];
77             size_t index = kBitsPerWord;
78             while (card != 0) {
79                 index = static_cast<size_t>(__builtin_ctzll(card));
80                 ASSERT(index < kBitsPerWord);
81                 HeapAddress offset = static_cast<HeapAddress>((i * kBitsPerWord) * kBitsPerByte + index * kBitsPerByte);
82                 HeapAddress obj = regionStart + offset;
83                 if (obj >= end) {
84                     return;
85                 }
86                 func(reinterpret_cast<BaseObject*>(obj));
87                 card &= ~(static_cast<CardElement>(1ULL << index));
88             }
89         }
90     }
91 private:
RegionRSet(size_t cardCnt)92     explicit RegionRSet(size_t cardCnt) : cardCnt_(cardCnt) {}
93     ~RegionRSet() = default;
94 
GetCardTable()95     CardElement *GetCardTable() const
96     {
97         return reinterpret_cast<CardElement *>(reinterpret_cast<uintptr_t>(this) + CARD_TABLE_DATA_OFFSET);
98     }
99 
100     size_t cardCnt_ {0};
101 };
102 
103 static_assert(RegionRSet::CARD_TABLE_DATA_OFFSET == AlignUp<size_t>(sizeof(RegionRSet),
104                                                                     sizeof(RegionRSet::CardElement)));
105 }
106 #endif // COMMON_COMPONENTS_HEAP_COLLECTOR_REGION_RSET_H
107