1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_PROGRESS_BAR_H_ 6 #define V8_HEAP_PROGRESS_BAR_H_ 7 8 #include <atomic> 9 #include <cstdint> 10 11 #include "src/base/logging.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // The progress bar allows for keeping track of the bytes processed of a single 17 // object. The progress bar itself must be enabled before it's used. 18 // 19 // Only large objects use the progress bar which is stored in their page header. 20 // These objects are scanned in increments and will be kept black while being 21 // scanned. Even if the mutator writes to them they will be kept black and a 22 // white to grey transition is performed in the value. 23 // 24 // The progress bar starts as disabled. After enabling (through `Enable()`), it 25 // can never be disabled again. 26 class ProgressBar final { 27 public: Initialize()28 void Initialize() { value_ = kDisabledSentinel; } Enable()29 void Enable() { value_ = 0; } IsEnabled()30 bool IsEnabled() const { 31 return value_.load(std::memory_order_acquire) != kDisabledSentinel; 32 } 33 Value()34 size_t Value() const { 35 DCHECK(IsEnabled()); 36 return value_.load(std::memory_order_acquire); 37 } 38 TrySetNewValue(size_t old_value,size_t new_value)39 bool TrySetNewValue(size_t old_value, size_t new_value) { 40 DCHECK(IsEnabled()); 41 DCHECK_NE(kDisabledSentinel, new_value); 42 return value_.compare_exchange_strong(old_value, new_value, 43 std::memory_order_acq_rel); 44 } 45 ResetIfEnabled()46 void ResetIfEnabled() { 47 if (IsEnabled()) { 48 value_.store(0, std::memory_order_release); 49 } 50 } 51 52 private: 53 static constexpr size_t kDisabledSentinel = SIZE_MAX; 54 55 std::atomic<size_t> value_; 56 }; 57 58 } // namespace internal 59 } // namespace v8 60 61 #endif // V8_HEAP_PROGRESS_BAR_H_ 62