1 /** 2 * Copyright (c) 2024 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 PANDA_RUNTIME_MEM_GC_G1_HOT_CARDS_H 17 #define PANDA_RUNTIME_MEM_GC_G1_HOT_CARDS_H 18 19 #include "runtime/include/mem/panda_containers.h" 20 #include "runtime/mem/gc/card_table-inl.h" 21 #include "runtime/arch/memory_helpers.h" 22 23 namespace ark::mem { 24 25 class HotCards { 26 public: 27 using Card = CardTable::Card; 28 using CardPtr = CardTable::CardPtr; 29 30 void PushCard(CardPtr cardPtr); 31 32 void DecrementHotValue(); 33 34 // Should be called when mutator thread is on pause 35 void DrainMarkedCards(PandaUnorderedSet<CardPtr> *markedCards); 36 void ClearHotCards(); 37 38 template <typename CardHandler> HandleCards(CardHandler handler)39 size_t HandleCards(CardHandler handler) 40 { 41 UpdateCardsStatus(); 42 43 // clear card before we process it, because parallel mutator thread can make a write and we would miss it 44 arch::StoreLoadBarrier(); 45 46 size_t processedCardsCnt = 0; 47 auto cardIt = unprocessedCards_.begin(); 48 while (cardIt != unprocessedCards_.end()) { 49 if (!handler.Handle(*cardIt)) { 50 break; 51 } 52 ++processedCardsCnt; 53 cardIt = unprocessedCards_.erase(cardIt); 54 } 55 return processedCardsCnt; 56 } 57 SetHot(CardPtr cardPtr,uint8_t value)58 static ALWAYS_INLINE void SetHot(CardPtr cardPtr, uint8_t value) 59 { 60 cardPtr->SetCard(value | Card::GetHotFlag()); 61 } 62 ResetHot(CardPtr cardPtr,uint8_t value)63 static ALWAYS_INLINE void ResetHot(CardPtr cardPtr, uint8_t value) 64 { 65 cardPtr->SetCard(value & RESET_HOT_MASK); 66 } 67 SetMaxHotValue(CardPtr cardPtr,uint8_t value)68 static ALWAYS_INLINE void SetMaxHotValue(CardPtr cardPtr, uint8_t value) 69 { 70 cardPtr->SetCard(value | Card::GetMaxHotValue()); 71 } 72 SetHotAndMaxHotValue(CardPtr cardPtr,uint8_t value)73 static ALWAYS_INLINE void SetHotAndMaxHotValue(CardPtr cardPtr, uint8_t value) 74 { 75 static constexpr uint8_t HOT_FLAG_MAX_VALUE = Card::GetHotFlag() | Card::GetMaxHotValue(); 76 cardPtr->SetCard(value | HOT_FLAG_MAX_VALUE); 77 } 78 IncrementHotValue(CardPtr cardPtr,uint8_t value)79 static ALWAYS_INLINE void IncrementHotValue(CardPtr cardPtr, uint8_t value) 80 { 81 ASSERT(!Card::IsMaxHotValue(value)); 82 cardPtr->SetCard(value + Card::GetHotValue()); 83 } 84 85 static constexpr uint8_t RESET_HOT_MASK = uint8_t(~Card::GetHotFlag()); 86 static constexpr uint8_t RESET_MARK_MASK = ~CardTable::Card::GetMarkedValue(); 87 88 private: 89 void UpdateCardsStatus(); 90 91 template <typename F> VisitHotCards(F fun)92 void VisitHotCards(F fun) 93 { 94 std::for_each(hotCards_.begin(), hotCards_.end(), std::move(fun)); 95 } 96 97 PandaUnorderedSet<CardPtr> hotCards_; 98 PandaUnorderedSet<CardPtr> unprocessedCards_; 99 }; 100 101 } // namespace ark::mem 102 103 #endif // PANDA_RUNTIME_MEM_GC_G1_HOT_CARDS_H