• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_INTEROP_JS_ETS_PROXY_SHARED_REFERENCE_STORAGE_H_
17 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_PROXY_SHARED_REFERENCE_STORAGE_H_
18 
19 #include "libpandabase/macros.h"
20 #include "plugins/ets/runtime/ets_vm.h"
21 #include "plugins/ets/runtime/interop_js/ets_proxy/shared_reference.h"
22 #include "plugins/ets/runtime/interop_js/ets_proxy/mem/items_pool.h"
23 #include "plugins/ets/runtime/mem/root_provider.h"
24 #include "plugins/ets/runtime/types/ets_object.h"
25 
26 namespace ark::ets::interop::js {
27 // Forward declarations
28 class InteropCtx;
29 }  // namespace ark::ets::interop::js
30 
31 namespace ark::ets::interop::js::ets_proxy {
32 class SharedReferenceStorageVerifier;
33 namespace testing {
34 class SharedReferenceStorage1GTest;
35 }  // namespace testing
36 
37 using SharedReferencePool = ItemsPool<SharedReference, SharedReference::MAX_MARK_BITS>;
38 
39 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
40 class SharedReferenceStorage : private SharedReferencePool, public mem::RootProvider {
41 public:
42     PANDA_PUBLIC_API static PandaUniquePtr<SharedReferenceStorage> Create(PandaEtsVM *vm);
43     ~SharedReferenceStorage() override;
44 
45     using PreInitJSObjectCallback = std::function<napi_value(SharedReference **)>;
46 
47     /// @return current storage size
Size()48     size_t Size() const
49     {
50         return SharedReferencePool::Size();
51     }
52 
53     /// @return maximum possible storage size
MaxSize()54     size_t MaxSize() const
55     {
56         return SharedReferencePool::MaxSize();
57     }
58 
59     PANDA_PUBLIC_API SharedReference *CreateETSObjectRef(InteropCtx *ctx, EtsObject *etsObject, napi_value jsObject,
60                                                          const PreInitJSObjectCallback &preInitCallback = nullptr);
61     SharedReference *CreateJSObjectRef(InteropCtx *ctx, EtsObject *etsObject, napi_value jsObject);
62 
63     SharedReference *CreateJSObjectRefwithWrap(InteropCtx *ctx, EtsObject *etsObject, napi_value jsObject);
64 
65     SharedReference *CreateHybridObjectRef(InteropCtx *ctx, EtsObject *etsObject, napi_value jsObject);
66 
67     PANDA_PUBLIC_API SharedReference *GetReference(napi_env env, napi_value jsObject) const;
68     PANDA_PUBLIC_API SharedReference *GetReference(EtsObject *etsObject) const;
69 
70     napi_value GetJsObject(EtsObject *etsObject, napi_env env) const;
71     bool HasReference(EtsObject *etsObject, napi_env env);
72 
73     void NotifyXGCStarted();
74     void NotifyXGCFinished();
75 
76     /**
77      * @brief Visit all non-empty refs and call visitor as vm root for EtsObject from the ref
78      * @param visitor gc root visitor
79      */
80     void VisitRoots(const GCRootVisitor &visitor) override;
81 
82     /// Update ref in the storage for EtsObject-s after moving phase
83     void UpdateRefs(const GCRootUpdater &gcRootUpdater) override;
84 
85     /// Remove all unmarked refs after XGC (can be run concurrently)
86     void SweepUnmarkedRefs();
87 
88     /**
89      * Delete all shared references with specific context from the storage
90      * @param ctx interop context
91      * @remark interop context calls the method on destruction
92      */
93     void DeleteAllReferencesWithCtx(const InteropCtx *ctx);
94 
95     /// Clear mark bit for all shared references
96     PANDA_PUBLIC_API void UnmarkAll();
97 
98     /**
99      * Extract one SharedRefrence from set of references allocated during XGC concurrent marking pahse
100      * @return valid SharedReference or nullptr if no more references in the set
101      */
ExtractRefAllocatedDuringXGC()102     SharedReference *ExtractRefAllocatedDuringXGC()
103     {
104         os::memory::WriteLockHolder lock(storageLock_);
105         if (refsAllocatedDuringXGC_.empty()) {
106             return nullptr;
107         }
108         return refsAllocatedDuringXGC_.extract(refsAllocatedDuringXGC_.begin()).value();
109     }
110 
111     static constexpr size_t MAX_POOL_SIZE = (sizeof(void *) > 4) ? 1_GB : 64_MB;
112     static constexpr std::string_view PROXY_NAPI_WRAPPER = "_proxynapiwrapper";
113 
114 private:
SharedReferenceStorage(PandaEtsVM * vm,void * data,size_t size)115     SharedReferenceStorage(PandaEtsVM *vm, void *data, size_t size) : SharedReferencePool(data, size), vm_(vm) {}
116     NO_COPY_SEMANTIC(SharedReferenceStorage);
117     NO_MOVE_SEMANTIC(SharedReferenceStorage);
118 
119     template <SharedReference::InitFn REF_INIT>
120     SharedReference *CreateRefCommon(InteropCtx *ctx, EtsObject *etsObject, napi_value jsObject,
121                                      const PreInitJSObjectCallback &callback = nullptr);
122 
GetCurrent()123     PANDA_PUBLIC_API static SharedReferenceStorage *GetCurrent()
124     {
125         ASSERT(sharedStorage_ != nullptr);
126         return sharedStorage_;
127     }
128 
129     template <SharedReference::InitFn REF_INIT>
130     PANDA_PUBLIC_API inline SharedReference *CreateReference(InteropCtx *ctx, EtsHandle<EtsObject> etsObject,
131                                                              napi_ref jsRef) REQUIRES(storageLock_);
132     PANDA_PUBLIC_API SharedReference *GetReference(void *data) const;
133     PANDA_PUBLIC_API void RemoveReference(SharedReference *sharedRef);
134     /**
135      * Remove all unmarked references from related chain which contains passed shared references
136      * @param sharedRef non-empty shared reference from this storage table
137      * @note the method should be called under the storage write-lock
138      */
139     void DeleteUnmarkedReferences(SharedReference *sharedRef) REQUIRES(storageLock_);
140 
141     /**
142      * Delete napi_ref for passed shared reference and remove the shared reference from the table
143      * @param sharedRef non-empty shared reference from this storage table
144      * @note the method should be called under the storage write-lock
145      */
146     void DeleteJSRefAndRemoveReference(SharedReference *sharedRef) REQUIRES(storageLock_);
147 
148     /**
149      * Delete one reference by predicate from references chain related with passed reference
150      * @param sharedRef non-empty shared reference from processing references chain
151      * @param deletePredicate predicate with condition for a reference deleting
152      * @return true if chain contains reference for removing by predicate and the reference was deleted from the chain,
153      * false - otherwise
154      */
155     bool DeleteReference(SharedReference *sharedRef,
156                          const std::function<bool(const SharedReference *sharedRef)> &deletePredicate)
157         REQUIRES(storageLock_);
158 
159     /// Helper method for DeleteReference
160     void DeleteReferenceFromChain(EtsObject *etsObject, SharedReference *prevRef, SharedReference *removingRef,
161                                   uint32_t nextIndex) REQUIRES(storageLock_);
162 
163     bool HasReferenceWithCtx(SharedReference *ref, InteropCtx *ctx) const;
164 
165     PANDA_PUBLIC_API bool CheckAlive(void *data);
166     friend class SharedReference;
167     friend class SharedReference::Iterator;
168     friend class testing::SharedReferenceStorage1GTest;
169     // Allocator calls our protected ctor
170     friend class mem::Allocator;
171     friend class SharedReferenceStorageVerifier;
172 
173     PANDA_PUBLIC_API static SharedReferenceStorage *sharedStorage_;
174 
175     PandaEtsVM *vm_ {nullptr};
176     mutable os::memory::RWLock storageLock_;
GUARDED_BY(storageLock_)177     bool isXGCinProgress_ GUARDED_BY(storageLock_) {false};  // CC-OFF(G.FMT.03) project code style
178     PandaUnorderedSet<SharedReference *> refsAllocatedDuringXGC_ GUARDED_BY(storageLock_);
179 };
180 
181 }  // namespace ark::ets::interop::js::ets_proxy
182 
183 #endif  // !PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_PROXY_SHARED_REFERENCE_STORAGE_H_
184