• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023-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_PLUGINS_ETS_RUNTIME_MEM_ETS_REFERENCE_PROCESSOR_H
17 #define PANDA_PLUGINS_ETS_RUNTIME_MEM_ETS_REFERENCE_PROCESSOR_H
18 
19 #include "plugins/ets/runtime/types/ets_object.h"
20 #include "runtime/mem/gc/reference-processor/reference_processor.h"
21 
22 #include "plugins/ets/runtime/types/ets_class.h"
23 #include "plugins/ets/runtime/types/ets_weak_reference.h"
24 #include "plugins/ets/runtime/types/ets_finalizable_weak_ref.h"
25 
26 namespace ark::mem::ets {
27 
28 class EtsReferenceProcessor final : public ReferenceProcessor {
29     using RefFinalizer = ark::ets::EtsFinalizableWeakRef::Finalizer;
30 
31 public:
32     explicit EtsReferenceProcessor(GC *gc);
33     NO_COPY_SEMANTIC(EtsReferenceProcessor);
34     NO_MOVE_SEMANTIC(EtsReferenceProcessor);
35     ~EtsReferenceProcessor() final = default;
36 
37     void Initialize() override;
38 
39     bool IsReference(const BaseClass *baseCls, const ObjectHeader *ref,
40                      const ReferenceCheckPredicateT &pred) const final;
41     bool IsReference(const BaseClass *baseCls, const ObjectHeader *ref) const final;
42 
43     void HandleReference(GC *gc, GCMarkingStackType *objectsStack, const BaseClass *cls, const ObjectHeader *object,
44                          const ReferenceProcessPredicateT &pred) final;
45     void HandleReference(GC *gc, const BaseClass *cls, const ObjectHeader *object,
46                          const ReferenceProcessorT &processor) final;
47 
48     void ProcessReferences(bool concurrent, bool clearSoftReferences, GCPhase gcPhase,
49                            const mem::GC::ReferenceClearPredicateT &pred) final;
50     void ProcessReferencesAfterCompaction(bool clearSoftReferences,
51                                           const mem::GC::ReferenceClearPredicateT &pred) final;
52 
CollectClearedReferences()53     ark::mem::Reference *CollectClearedReferences() final
54     {
55         return nullptr;
56     }
57 
ScheduleForEnqueue(Reference * clearedReferences)58     void ScheduleForEnqueue([[maybe_unused]] Reference *clearedReferences) final
59     {
60         UNREACHABLE();
61     }
62 
Enqueue(ark::mem::Reference * clearedReferences)63     void Enqueue([[maybe_unused]] ark::mem::Reference *clearedReferences) final
64     {
65         UNREACHABLE();
66     }
67 
68     /// @return size of the queue of weak references
69     size_t GetReferenceQueueSize() const final;
70 
71     /// Process native finalizers of FinalizableWeakRef
72     void ProcessFinalizers() final;
73 
74 private:
75     template <typename Handler>
76     void ProcessReferences(const mem::GC::ReferenceClearPredicateT &pred, const Handler &handler);
77 
78     /// Add finalizer of dead referent of FinalizableWeakRef to the queue
79     void EnqueueFinalizer(ark::ets::EtsWeakReference *weakRef);
80 
81     /// Handle fields of references
82     void HandleOtherFields(const BaseClass *cls, const ObjectHeader *object, const ReferenceProcessorT &processor)
83         REQUIRES(weakRefLock_);
84 
85     mutable os::memory::Mutex weakRefLock_;
86     PandaUnorderedSet<ObjectHeader *> weakReferences_ GUARDED_BY(weakRefLock_);
87     GC *gc_ {nullptr};
88     ark::ets::EtsObject *undefinedObject_ {nullptr};
89     PandaDeque<RefFinalizer> finalizerQueue_;
90 };
91 
92 template <typename Handler>
ProcessReferences(const mem::GC::ReferenceClearPredicateT & pred,const Handler & handler)93 void EtsReferenceProcessor::ProcessReferences(const mem::GC::ReferenceClearPredicateT &pred, const Handler &handler)
94 {
95     os::memory::LockHolder lock(weakRefLock_);
96     while (!weakReferences_.empty()) {
97         auto *weakRefObj = weakReferences_.extract(weakReferences_.begin()).value();
98         ASSERT(ark::ets::EtsClass::FromRuntimeClass(weakRefObj->ClassAddr<Class>())->IsWeakReference());
99         auto *weakRef = static_cast<ark::ets::EtsWeakReference *>(ark::ets::EtsObject::FromCoreType(weakRefObj));
100         auto *referent = weakRef->GetReferent();
101         if (referent == nullptr || referent == undefinedObject_) {
102             LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
103                                  << " because referent is nullish";
104             continue;
105         }
106         auto *referentObj = referent->GetCoreType();
107         if (!pred(referentObj)) {
108             LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
109                                  << " because referent " << GetDebugInfoAboutObject(referentObj) << " failed predicate";
110             continue;
111         }
112 
113         handler(weakRefObj, referentObj);
114     }
115 }
116 }  // namespace ark::mem::ets
117 
118 #endif  // PANDA_PLUGINS_ETS_RUNTIME_MEM_ETS_REFERENCE_PROCESSOR_H
119