* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_MEM_RSET_WORKLIST_HANDLER_H
#define ECMASCRIPT_MEM_RSET_WORKLIST_HANDLER_H
#include "ecmascript/platform/mutex.h"
namespace panda::ecmascript {
class Heap;
class Region;
class RememberedSet;
class RSetItem {
public:
explicit RSetItem(Region *region, RememberedSet *rSet) : region_(region), rSet_(rSet) {}
~RSetItem() = default;
template<class Visitor>
inline void Process(const Visitor &visitor);
inline void MergeBack();
private:
Region *region_ {nullptr};
RememberedSet *rSet_ {nullptr};
};
class RSetWorkListHandler {
public:
explicit RSetWorkListHandler(Heap *heap, JSThread *thread);
~RSetWorkListHandler() = default;
inline void Initialize();
template<class Visitor>
inline void ProcessAll(const Visitor &visitor);
inline void WaitFinishedThenMergeBack();
inline bool MergeBack();
inline Heap *GetHeap();
inline void EnumerateRegions(const Heap *heap);
template<class Visitor>
inline void ProcessAllVisitor(const Visitor &visitor, int done);
inline void MergeBackForAllItem();
JSThread *GetOwnerThreadUnsafe() const
{
return ownerThread_;
}
private:
inline void CollectRSetItemsInHeap(const Heap *heap);
template<class Visitor>
inline bool ProcessNext(const Visitor &visitor);
inline bool TryMergeBack();
Heap *heap_ {nullptr};
JSThread *ownerThread_ {nullptr};
* This value represent whether there are some items to process, this is set to true in Initialize when collecting
* the RSet in heap(call from daemon thread in SuspendAll), and use CAS to set to false when try to merge back and
* clear(call maybe from daemon thread in SuspendAll, or from bound js thread in RUNNING state).
* Only two ways to modify this value:
* 1. Initialzie, from daemon thread in SuspendAll, and the modification must be visible to the bound js thread.
* 2. MergeBackAndReset, maybe from daemon thread when SuspendAll, or from js thread which region
* belonged to in RUNNING state.
* So the bound js thread can always see the lastest value without using atomic.
* And thus WaitFinishedThenMergeBack should ONLY be called from the bound js thread in RUNNING state.
*/
bool initialized_ {false};
std::vector<RSetItem> items_;
std::atomic<int> nextItemIndex_ {-1};
int remainItems_ {0};
Mutex mutex_;
ConditionVariable cv_;
};
}
#endif