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