• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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_PLUGINGS_ETS_RUNTIME_INTEROP_JS_HYBRID_XGC_XGC_H
17 #define PANDA_PLUGINGS_ETS_RUNTIME_INTEROP_JS_HYBRID_XGC_XGC_H
18 
19 #include "hybrid/ecma_vm_interface.h"
20 #include "plugins/ets/runtime/interop_js/app_state_manager.h"
21 #include "plugins/ets/runtime/interop_js/sts_vm_interface_impl.h"
22 #include "runtime/mem/gc/gc_trigger.h"
23 
24 namespace ark::ets {
25 class PandaEtsVM;
26 }  // namespace ark::ets
27 
28 namespace ark::ets::interop::js {
29 
30 class InteropCtx;
31 namespace ets_proxy {
32 class SharedReferenceStorage;
33 class SharedReferenceStorageVerifier;
34 enum class XgcStatus;
35 }  // namespace ets_proxy
36 
37 /**
38  * Cross-reference garbage collector.
39  * Implements logic to collect cross-references between JS and ETS in SharedReferenceStorage.
40  */
41 class XGC final : public mem::GCTrigger {
42 public:
43     NO_COPY_SEMANTIC(XGC);
44     NO_MOVE_SEMANTIC(XGC);
45     ~XGC() override = default;
46 
47     /// @enum represents XGC trigger policy types
48     enum class TriggerPolicy : uint8_t {
49         INVALID,  // Invalid trigger, it should not be used
50         DEFAULT,  // Default trigger
51         FORCE,    // Run on each allocation
52         NEVER,    // Never trigger XGC (disable)
53     };
54 
55     /**
56      * Create instance of XGC if it was not created before. Runtime should be existed before the XGC creation
57      * @param mainCoro main coroutine
58      * @return true if the instance successfully created, false - otherwise
59      */
60     [[nodiscard]] PANDA_PUBLIC_API static bool Create(PandaEtsVM *vm, ets_proxy::SharedReferenceStorage *storage,
61                                                       STSVMInterfaceImpl *stsVmIface);
62 
63     /// @return current instance of XGC
64     static XGC *GetInstance();
65 
66     /**
67      * Destroy the current instance of XGC if the instance is existed. Runtime should be existed before the XGC
68      * destruction
69      * @return true if the instance successfully destroyed, false - otherwise
70      */
71     PANDA_PUBLIC_API static bool Destroy();
72 
73     /**
74      * Check trigger condition and post XGC task to gc queue and
75      * trigger XMark for all related JS virtual machines if needed
76      * @param gc GC using in the current VM
77      */
78     void TriggerGcIfNeeded(mem::GC *gc) override;
79 
80     /**
81      * Notify XGC about the new interop context attached to STS VM
82      * @param context attached interop context
83      * @remark the passed interop context must not be registered (attached) in XGC
84      */
85     void OnAttach(const InteropCtx *context);
86 
87     /**
88      * Notify XGC about the interop context detached from STS VM
89      * @param context detached interop context
90      * @remark the passed interop context must be registered (attached) in XGC
91      * @see OnAttach
92      */
93     void OnDetach(const InteropCtx *context);
94 
95     /**
96      * Post XGC task to gc queue and trigger XMark for all related JS virtual machines
97      * @param gc GC using in the current VM
98      * @return true if XGC successfully triggered, false - otherwise
99      */
100     bool Trigger(mem::GC *gc, PandaUniquePtr<GCTask> task);
101 
102     /// @return XGC trigger type value
GetType()103     mem::GCTriggerType GetType() const override
104     {
105         return mem::GCTriggerType::XGC;
106     }
107 
108     /// GCListener specific public methods ///
109 
110     void GCStarted(const GCTask &task, size_t heapSize) override;
111     void GCFinished(const GCTask &task, size_t heapSizeBeforeGc, size_t heapSize) override;
112     void GCPhaseStarted(mem::GCPhase phase) override;
113     void GCPhaseFinished(mem::GCPhase phase) override;
114 
115 private:
116     // For allocation of XGC with the private constructor by internal allocator
117     friend mem::Allocator;
118     friend void STSVMInterfaceImpl::MarkFromObject([[maybe_unused]] void *obj);
119 
120     XGC(PandaEtsVM *vm, STSVMInterfaceImpl *stsVmIface, ets_proxy::SharedReferenceStorage *storage);
121     static XGC *instance_;
122 
123     /// @return true if need to trigger XGC by policy and special conditions, false - otherwise
124     bool NeedToTriggerXGC(const mem::GC *gc) const;
125 
126     /// @return new target threshold storage size for XGC trigger
127     size_t ComputeNewSize();
128 
129     /// Unmark all cross references before initial mark
130     void UnmarkAll();
131 
132     /**
133      * Start marking from specific cross reference object
134      * @param data native data from a JS VM with cross reference data
135      */
136     void MarkFromObject(void *data);
137 
138     /// Remark cross references allocated during concurrent mark phase
139     void Remark();
140 
141     /// Sweep unmarked cross references on STW
142     void Sweep();
143 
144     /// Finish XGC process (on the end of Remark phase or the end of GC)
145     void Finish();
146 
147     /**
148      * Notify all related waiters that the XGC process has been finished
149      * @see WaitForFinishXGC
150      * @see Finish
151      */
152     void NotifyToFinishXGC();
153 
154     /**
155      * Wait until XGC process completed
156      * @see NotifyToFinishXGC
157      * @see OnDetach
158      */
159     void WaitForFinishXGC();
160 
161     void VerifySharedReferences(ets_proxy::XgcStatus status);
162 
163     /// External specific fields ///
164 
165     PandaEtsVM *vm_ {nullptr};
166     ets_proxy::SharedReferenceStorage *storage_ {nullptr};
167     STSVMInterfaceImpl *stsVmIface_ {nullptr};
168 
169     /// XGC current state specific fields ///
170 
171     os::memory::Mutex finishXgcLock_;
172     os::memory::ConditionVariable finishXgcCV_ GUARDED_BY(finishXgcLock_);
173     std::atomic_bool isXGcInProgress_ {false};
174     bool remarkFinished_ {false};  // GUARDED_BY(mutatorLock)
175 
176     /// Trigger specific fields ///
177 
178     size_t beforeGCStorageSize_ {0U};
179     const size_t minimalThresholdSize_ {0U};
180     const size_t increaseThresholdPercent_ {0U};
181     // We can load a value of the variable from several threads, so need to use atomic
182     std::atomic<size_t> targetThreasholdSize_ {0U};
183     const TriggerPolicy treiggerPolicy_ {TriggerPolicy::INVALID};
184     const bool enableXgcVerifier_ {false};
185 };
186 
187 }  // namespace ark::ets::interop::js
188 
189 #endif  // PANDA_PLUGINGS_ETS_RUNTIME_INTEROP_JS_HYBRID_XGC_XGC_H
190