1 /**
2 * Copyright (c) 2023-2025 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 #include "plugins/ets/runtime/mem/mpsc_set.h"
27
28 namespace ark::mem::ets {
29
30 class EtsReferenceProcessor final : public ReferenceProcessor {
31 using RefFinalizer = ark::ets::EtsFinalizableWeakRef::Finalizer;
32
33 public:
34 explicit EtsReferenceProcessor(GC *gc);
35 NO_COPY_SEMANTIC(EtsReferenceProcessor);
36 NO_MOVE_SEMANTIC(EtsReferenceProcessor);
37 ~EtsReferenceProcessor() final = default;
38
39 void Initialize() override;
40
41 bool IsReference(const BaseClass *baseCls, const ObjectHeader *ref,
42 const ReferenceCheckPredicateT &pred) const final;
43
44 void HandleReference(GC *gc, GCMarkingStackType *objectsStack, const BaseClass *cls, const ObjectHeader *object,
45 const ReferenceProcessPredicateT &pred) final;
46 void HandleReference(GC *gc, const BaseClass *cls, const ObjectHeader *object,
47 const ReferenceProcessorT &processor) final;
48
49 void ProcessReferences(bool concurrent, bool clearSoftReferences, GCPhase gcPhase,
50 const mem::GC::ReferenceClearPredicateT &pred) final;
51 void ProcessReferencesAfterCompaction([[maybe_unused]] 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 template <bool USE_OBJECT_REF>
83 void HandleOtherFields(const BaseClass *cls, const ObjectHeader *object, const ReferenceProcessorT &processor);
84
85 mem::MPSCSet<PandaUnorderedSet<ObjectHeader *>> weakReferences_;
86 GC *gc_ {nullptr};
87 ark::ets::EtsObject *nullValue_ {nullptr};
88 PandaDeque<RefFinalizer> finalizerQueue_;
89 };
90
91 template <typename Handler>
ProcessReferences(const mem::GC::ReferenceClearPredicateT & pred,const Handler & handler)92 void EtsReferenceProcessor::ProcessReferences(const mem::GC::ReferenceClearPredicateT &pred, const Handler &handler)
93 {
94 weakReferences_.FlushSets();
95 while (!weakReferences_.IsEmpty()) {
96 auto *weakRefObj = weakReferences_.Extract();
97 ASSERT(ark::ets::EtsClass::FromRuntimeClass(weakRefObj->ClassAddr<Class>())->IsWeakReference());
98 auto *weakRef = static_cast<ark::ets::EtsWeakReference *>(ark::ets::EtsObject::FromCoreType(weakRefObj));
99 auto *referent = weakRef->GetReferent();
100 if (referent == nullptr || referent == nullValue_) {
101 LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
102 << " because referent is nullish";
103 continue;
104 }
105 auto *referentObj = referent->GetCoreType();
106 if (!pred(referentObj)) {
107 LOG(DEBUG, REF_PROC) << "Don't process reference " << GetDebugInfoAboutObject(weakRefObj)
108 << " because referent " << GetDebugInfoAboutObject(referentObj) << " failed predicate";
109 continue;
110 }
111
112 handler(weakRefObj, referentObj);
113 }
114 }
115 } // namespace ark::mem::ets
116
117 #endif // PANDA_PLUGINS_ETS_RUNTIME_MEM_ETS_REFERENCE_PROCESSOR_H
118