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_PLUGINS_ETS_RUNTIME_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 16 #define PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 17 18 #include "plugins/ets/runtime/types/ets_object.h" 19 #include "plugins/ets/runtime/types/ets_finalizable_weak_ref.h" 20 21 namespace ark::ets { 22 23 class EtsFinalizableWeakRefList : protected EtsFinalizableWeakRef { 24 public: 25 using Node = EtsFinalizableWeakRef; 26 using List = EtsFinalizableWeakRefList; 27 Push(EtsCoroutine * coro,Node * weakRef)28 void Push(EtsCoroutine *coro, Node *weakRef) 29 { 30 ASSERT(weakRef != nullptr); 31 auto *head = GetHead(); 32 if (head == nullptr) { 33 SetHead(coro, weakRef); 34 return; 35 } 36 head->SetPrev(coro, weakRef); 37 weakRef->SetNext(coro, head); 38 SetHead(coro, weakRef); 39 } 40 Unlink(EtsCoroutine * coro,Node * weakRef)41 void Unlink(EtsCoroutine *coro, Node *weakRef) 42 { 43 ASSERT(weakRef != nullptr); 44 auto *prev = weakRef->GetPrev(); 45 auto *next = weakRef->GetNext(); 46 if (prev != nullptr) { 47 prev->SetNext(coro, next); 48 } 49 if (next != nullptr) { 50 next->SetPrev(coro, prev); 51 } 52 if (weakRef == GetHead()) { 53 SetHead(coro, next); 54 } 55 weakRef->SetPrev(coro, nullptr); 56 weakRef->SetNext(coro, nullptr); 57 } 58 UnlinkClearedReferences(EtsCoroutine * coro)59 void UnlinkClearedReferences(EtsCoroutine *coro) 60 { 61 auto *weakRef = GetHead(); 62 auto *undefinedObj = coro->GetUndefinedObject(); 63 while (weakRef != nullptr) { 64 auto *referent = weakRef->GetReferent(); 65 ASSERT(referent != nullptr); 66 if (referent->GetCoreType() == undefinedObj) { 67 // Finalizer of the cleared reference must be enqueued 68 ASSERT(weakRef->ReleaseFinalizer().IsEmpty()); 69 Unlink(coro, weakRef); 70 } 71 weakRef = weakRef->GetNext(); 72 } 73 } 74 FromCoreType(ObjectHeader * intrusiveList)75 static List *FromCoreType(ObjectHeader *intrusiveList) 76 { 77 return reinterpret_cast<List *>(intrusiveList); 78 } 79 GetCoreType()80 ObjectHeader *GetCoreType() 81 { 82 return reinterpret_cast<ObjectHeader *>(const_cast<EtsObject *>(AsObject())); 83 } 84 GetCoreType()85 const ObjectHeader *GetCoreType() const 86 { 87 return reinterpret_cast<const ObjectHeader *>(AsObject()); 88 } 89 AsObject()90 EtsObject *AsObject() 91 { 92 return this; 93 } 94 AsObject()95 const EtsObject *AsObject() const 96 { 97 return this; 98 } 99 FromEtsObject(EtsObject * intrusiveList)100 static List *FromEtsObject(EtsObject *intrusiveList) 101 { 102 return reinterpret_cast<List *>(intrusiveList); 103 } 104 TraverseAndFinalize()105 void TraverseAndFinalize() 106 { 107 auto *weakRef = GetHead(); 108 while (weakRef != nullptr) { 109 auto finalizer = weakRef->ReleaseFinalizer(); 110 if (!finalizer.IsEmpty()) { 111 finalizer.Run(); 112 } 113 weakRef = weakRef->GetNext(); 114 } 115 } 116 117 private: GetHead()118 Node *GetHead() const 119 { 120 ASSERT(GetPrev() == nullptr); 121 ASSERT(GetReferent() == nullptr); 122 return GetNext(); 123 } 124 SetHead(EtsCoroutine * coro,Node * weakRef)125 void SetHead(EtsCoroutine *coro, Node *weakRef) 126 { 127 ASSERT(GetPrev() == nullptr); 128 ASSERT(GetReferent() == nullptr); 129 return SetNext(coro, weakRef); 130 } 131 }; 132 133 static_assert(sizeof(EtsFinalizableWeakRefList) == sizeof(EtsFinalizableWeakRef)); 134 135 } // namespace ark::ets 136 137 #endif // PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 138