1 /* 2 * Copyright (c) 2021 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 ECMASCRIPT_MEM_CONCURRENT_MARKER_H 17 #define ECMASCRIPT_MEM_CONCURRENT_MARKER_H 18 19 #include <array> 20 #include <atomic> 21 22 #include "ecmascript/mem/space.h" 23 #include "ecmascript/mem/visitor.h" 24 #include "ecmascript/mem/work_manager.h" 25 #include "ecmascript/taskpool/task.h" 26 27 #include "libpandabase/os/mutex.h" 28 29 namespace panda::ecmascript { 30 class EcmaVM; 31 class Heap; 32 // CONFIG_DISABLE means concurrent marker is disabled by options or macros and cannot be changed. 33 // REQUEST_DISABLE means we want to disable concurrent sweeper while it is marking. 34 // REQUEST_DISABLE can be ragarded as enable and will be changed into disable after this GC. 35 enum class EnableConcurrentMarkType : uint8_t { 36 ENABLE, 37 CONFIG_DISABLE, 38 DISABLE, 39 REQUEST_DISABLE 40 }; 41 42 class ConcurrentMarker { 43 public: 44 explicit ConcurrentMarker(Heap *heap, EnableConcurrentMarkType type); 45 ~ConcurrentMarker() = default; 46 TryIncreaseTaskCounts()47 static bool TryIncreaseTaskCounts() 48 { 49 size_t taskPoolSize = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); 50 { 51 os::memory::LockHolder holder(taskCountMutex_); 52 // total counts of running concurrent mark tasks should be less than taskPoolSize 53 if (taskCounts_ + 1 < taskPoolSize) { 54 taskCounts_++; 55 return true; 56 } 57 } 58 LOG_FULL(INFO) << "Concurrent mark tasks in taskPool are full"; 59 return false; 60 } 61 DecreaseTaskCounts()62 static void DecreaseTaskCounts() 63 { 64 os::memory::LockHolder holder(taskCountMutex_); 65 taskCounts_--; 66 } 67 68 /* 69 * Concurrent marking related configurations and utilities. 70 */ 71 void EnableConcurrentMarking(EnableConcurrentMarkType type); 72 IsEnabled()73 bool IsEnabled() const 74 { 75 return !IsDisabled(); 76 } 77 IsDisabled()78 bool IsDisabled() const 79 { 80 return enableMarkType_ == EnableConcurrentMarkType::DISABLE || 81 enableMarkType_ == EnableConcurrentMarkType::CONFIG_DISABLE; 82 } 83 ConfigConcurrentMark(bool enabled)84 void ConfigConcurrentMark(bool enabled) 85 { 86 enableMarkType_ = enabled ? EnableConcurrentMarkType::ENABLE : 87 EnableConcurrentMarkType::CONFIG_DISABLE; 88 } 89 IsRequestDisabled()90 bool IsRequestDisabled() const 91 { 92 return enableMarkType_ == EnableConcurrentMarkType::REQUEST_DISABLE; 93 } 94 IsConfigDisabled()95 bool IsConfigDisabled() const 96 { 97 return enableMarkType_ == EnableConcurrentMarkType::CONFIG_DISABLE; 98 } 99 void Mark(); 100 void Finish(); 101 void ReMark(); 102 103 void HandleMarkingFinished(); // call in vm thread. 104 void WaitMarkingFinished(); // call in main thread 105 void Reset(bool revertCSet = true); 106 GetDuration()107 double GetDuration() const 108 { 109 return duration_; 110 } 111 GetHeapObjectSize()112 double GetHeapObjectSize() const 113 { 114 return heapObjectSize_; 115 } 116 117 private: 118 NO_COPY_SEMANTIC(ConcurrentMarker); 119 NO_MOVE_SEMANTIC(ConcurrentMarker); 120 121 class MarkerTask : public Task { 122 public: MarkerTask(int32_t id,Heap * heap)123 explicit MarkerTask(int32_t id, Heap *heap) : Task(id), heap_(heap) {} 124 ~MarkerTask() override = default; 125 bool Run(uint32_t threadId) override; 126 127 private: 128 NO_COPY_SEMANTIC(MarkerTask); 129 NO_MOVE_SEMANTIC(MarkerTask); 130 131 Heap *heap_ {nullptr}; 132 }; 133 SetDuration(double duration)134 void SetDuration(double duration) 135 { 136 duration_ = duration; 137 } 138 139 void InitializeMarking(); 140 void FinishMarking(float spendTime); 141 142 static size_t taskCounts_; 143 static os::memory::Mutex taskCountMutex_; 144 145 Heap *heap_ {nullptr}; 146 EcmaVM *vm_ {nullptr}; 147 JSThread *thread_ {nullptr}; 148 149 // obtained from the shared heap instance. 150 WorkManager *workManager_ {nullptr}; 151 size_t heapObjectSize_ {0}; 152 double duration_ {0.0}; 153 EnableConcurrentMarkType enableMarkType_ {EnableConcurrentMarkType::CONFIG_DISABLE}; 154 155 bool notifyMarkingFinished_ {false}; // notify js-thread that marking is finished and sweeping is needed 156 bool vmThreadWaitMarkingFinished_ {false}; // jsMainThread waiting for concurrentGC FINISHED 157 os::memory::Mutex waitMarkingFinishedMutex_; 158 os::memory::ConditionVariable waitMarkingFinishedCV_; 159 }; 160 } // namespace panda::ecmascript 161 #endif // ECMASCRIPT_MEM_CONCURRENT_MARKER_H 162