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