• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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