• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023 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 "libpandabase/os/mutex.h"
17 #include "runtime/include/object_header.h"
18 #include "runtime/mem/gc/gc_phase.h"
19 #include "runtime/mem/object_helpers.h"
20 #include "plugins/ets/runtime/mem/ets_reference_processor.h"
21 #include "plugins/ets/runtime/types/ets_class.h"
22 #include "plugins/ets/runtime/types/ets_weak_reference.h"
23 
24 namespace panda::mem::ets {
25 
EtsReferenceProcessor(GC * gc)26 EtsReferenceProcessor::EtsReferenceProcessor(GC *gc) : gc_(gc) {}
27 
IsReference(const BaseClass * baseCls,const ObjectHeader * ref,const ReferenceCheckPredicateT & pred) const28 bool EtsReferenceProcessor::IsReference(const BaseClass *baseCls, const ObjectHeader *ref,
29                                         const ReferenceCheckPredicateT &pred) const
30 {
31     ASSERT(baseCls != nullptr);
32     ASSERT(ref != nullptr);
33     ASSERT(baseCls->GetSourceLang() == panda_file::SourceLang::ETS);
34 
35     const auto *objEtsClass = panda::ets::EtsClass::FromRuntimeClass(static_cast<const Class *>(baseCls));
36 
37     if (objEtsClass->IsWeakReference()) {
38         const auto *etsRef = reinterpret_cast<const panda::ets::EtsWeakReference *>(ref);
39 
40         auto *referent = etsRef->GetReferent();
41         if (referent == nullptr) {
42             LOG(DEBUG, REF_PROC) << "Treat " << GetDebugInfoAboutObject(ref)
43                                  << " as normal object, because referent is null";
44             return false;
45         }
46 
47         ASSERT(IsMarking(gc_->GetGCPhase()));
48         bool referentIsMarked = false;
49         if (pred(referent->GetCoreType())) {
50             referentIsMarked = gc_->IsMarked(referent->GetCoreType());
51         } else {
52             LOG(DEBUG, REF_PROC) << "Treat " << GetDebugInfoAboutObject(ref) << " as normal object, because referent "
53                                  << std::hex << GetDebugInfoAboutObject(referent->GetCoreType())
54                                  << " doesn't suit predicate";
55             referentIsMarked = true;
56         }
57         return !referentIsMarked;
58     }
59     return false;
60 }
61 
HandleReference(GC * gc,GCMarkingStackType * objectsStack,const BaseClass * cls,const ObjectHeader * object,const ReferenceProcessPredicateT & pred)62 void EtsReferenceProcessor::HandleReference([[maybe_unused]] GC *gc, [[maybe_unused]] GCMarkingStackType *objectsStack,
63                                             [[maybe_unused]] const BaseClass *cls, const ObjectHeader *object,
64                                             [[maybe_unused]] const ReferenceProcessPredicateT &pred)
65 {
66     os::memory::LockHolder lock(weakRefLock_);
67     LOG(DEBUG, REF_PROC) << GetDebugInfoAboutObject(object) << " is added to weak references set for processing";
68     weakReferences_.insert(const_cast<ObjectHeader *>(object));
69 }
70 
ProcessReferences(bool concurrent,bool clearSoftReferences,GCPhase gcPhase,const mem::GC::ReferenceClearPredicateT & pred)71 void EtsReferenceProcessor::ProcessReferences([[maybe_unused]] bool concurrent,
72                                               [[maybe_unused]] bool clearSoftReferences,
73                                               [[maybe_unused]] GCPhase gcPhase,
74                                               const mem::GC::ReferenceClearPredicateT &pred)
75 {
76     os::memory::LockHolder lock(weakRefLock_);
77     while (!weakReferences_.empty()) {
78         auto *weakRefObj = weakReferences_.extract(weakReferences_.begin()).value();
79         ASSERT(panda::ets::EtsClass::FromRuntimeClass(weakRefObj->ClassAddr<Class>())->IsWeakReference());
80         auto *weakRef = static_cast<panda::ets::EtsWeakReference *>(panda::ets::EtsObject::FromCoreType(weakRefObj));
81         auto *referent = weakRef->GetReferent();
82         if (referent == nullptr) {
83             LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
84                                  << " because referent is null";
85             continue;
86         }
87         auto *referentObj = referent->GetCoreType();
88         if (!pred(referentObj)) {
89             LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
90                                  << " because referent " << GetDebugInfoAboutObject(referentObj) << " failed predicate";
91             continue;
92         }
93         if (gc_->IsMarked(referentObj)) {
94             LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
95                                  << " because referent " << GetDebugInfoAboutObject(referentObj) << " is marked";
96             continue;
97         }
98         LOG(DEBUG, REF_PROC) << "In " << GetDebugInfoAboutObject(weakRefObj) << " clear referent";
99         weakRef->ClearReferent();
100     }
101 }
102 
GetReferenceQueueSize() const103 size_t EtsReferenceProcessor::GetReferenceQueueSize() const
104 {
105     os::memory::LockHolder lock(weakRefLock_);
106     return weakReferences_.size();
107 }
108 
109 }  // namespace panda::mem::ets
110