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 #ifndef PANDA_RUNTIME_MEM_GC_G1_G1_OBJECT_POINTER_HANDLER_H 16 #define PANDA_RUNTIME_MEM_GC_G1_G1_OBJECT_POINTER_HANDLER_H 17 18 #include "libpandabase/mem/mem.h" 19 #include "runtime/include/coretypes/tagged_value.h" 20 #include "runtime/include/object_accessor.h" 21 #include "runtime/mem/region_allocator.h" 22 #include "runtime/mem/rem_set-inl.h" 23 #include "runtime/mem/gc/g1/g1-gc.h" 24 25 namespace ark::mem { 26 template <LangTypeT LANG_TYPE> 27 struct ObjectReference; 28 29 template <> 30 struct ObjectReference<LANG_TYPE_STATIC> { 31 using Type = ObjectPointerType *; 32 }; 33 34 template <> 35 struct ObjectReference<LANG_TYPE_DYNAMIC> { 36 using Type = coretypes::TaggedType *; 37 }; 38 39 template <typename LanguageConfig> 40 class G1GC; 41 42 template <typename LanguageConfig> 43 class G1EvacuateRegionsWorkerState; 44 45 class RemsetObjectPointerHandler { 46 public: 47 RemsetObjectPointerHandler(Region *fromRegion, size_t regionSizeBits, const std::atomic_bool &deferCards) 48 : fromRemset_(fromRegion->GetRemSet()), regionSizeBits_(regionSizeBits), deferCards_(deferCards) 49 { 50 } 51 52 template <typename T> 53 bool ProcessObjectPointer(T *ref) const 54 { 55 ProcessObjectPointerInternal(ref); 56 // Atomic with relaxed order reason: memory order is not required 57 return !deferCards_.load(std::memory_order_relaxed); 58 } 59 60 private: 61 template <typename T> 62 void ProcessObjectPointerInternal(T *ref) const 63 { 64 // fromRemset_ is not changed while handling one card 65 ASSERT(AddrToRegion(ref)->GetRemSet() == fromRemset_); 66 67 auto o = ObjectAccessor::LoadAtomic(ref); 68 if (!ObjectAccessor::IsHeapObject(o)) { 69 return; 70 } 71 72 auto *obj = ObjectAccessor::DecodeNotNull(o); 73 if (ark::mem::IsSameRegion(ref, obj, regionSizeBits_)) { 74 return; 75 } 76 77 ASSERT_PRINT(IsHeapSpace(PoolManager::GetMmapMemPool()->GetSpaceTypeForAddr(obj)), 78 "Not suitable space for to_obj: " << obj); 79 80 // don't need lock because only one thread changes remsets 81 RemSet<>::AddRefWithAddr<false>(fromRemset_, ref, obj); 82 LOG(DEBUG, GC) << "fill rem set " << ref << " -> " << obj; 83 } 84 RemSetT *fromRemset_; 85 size_t regionSizeBits_; 86 const std::atomic_bool &deferCards_; 87 }; 88 89 template <class LanguageConfig> 90 class EvacuationObjectPointerHandler { 91 public: 92 using Ref = typename ObjectReference<LanguageConfig::LANG_TYPE>::Type; 93 94 explicit EvacuationObjectPointerHandler(G1EvacuateRegionsWorkerState<LanguageConfig> *workerState) 95 : gc_(workerState->GetGC()), workerState_(workerState) 96 { 97 } 98 99 bool ProcessObjectPointer(Ref ref) const 100 { 101 ProcessObjectPointerHelper(ref); 102 return true; 103 } 104 105 private: 106 void ProcessObjectPointerHelper(Ref ref) const 107 { 108 auto o = ObjectAccessor::Load(ref); 109 if (!ObjectAccessor::IsHeapObject(o)) { 110 return; 111 } 112 auto *obj = ObjectAccessor::DecodeNotNull(o); 113 if (gc_->InGCSweepRange(obj)) { 114 workerState_->PushToQueue(ref); 115 } else if (!workerState_->IsSameRegion(ref, obj)) { 116 workerState_->EnqueueCard(ref); 117 } 118 } 119 120 G1GC<LanguageConfig> *gc_; 121 G1EvacuateRegionsWorkerState<LanguageConfig> *workerState_; 122 }; 123 } // namespace ark::mem 124 125 #endif 126