// Copyright 2021 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_HEAP_PROGRESS_BAR_H_ #define V8_HEAP_PROGRESS_BAR_H_ #include <atomic> #include <cstdint> #include "src/base/logging.h" namespace v8 { namespace internal { // The progress bar allows for keeping track of the bytes processed of a single // object. The progress bar itself must be enabled before it's used. // // Only large objects use the progress bar which is stored in their page header. // These objects are scanned in increments and will be kept black while being // scanned. Even if the mutator writes to them they will be kept black and a // white to grey transition is performed in the value. // // The progress bar starts as disabled. After enabling (through `Enable()`), it // can never be disabled again. class ProgressBar final { public: void Initialize() { value_ = kDisabledSentinel; } void Enable() { value_ = 0; } bool IsEnabled() const { return value_.load(std::memory_order_acquire) != kDisabledSentinel; } size_t Value() const { DCHECK(IsEnabled()); return value_.load(std::memory_order_acquire); } bool TrySetNewValue(size_t old_value, size_t new_value) { DCHECK(IsEnabled()); DCHECK_NE(kDisabledSentinel, new_value); return value_.compare_exchange_strong(old_value, new_value, std::memory_order_acq_rel); } void ResetIfEnabled() { if (IsEnabled()) { value_.store(0, std::memory_order_release); } } private: static constexpr size_t kDisabledSentinel = SIZE_MAX; std::atomic<size_t> value_; }; } // namespace internal } // namespace v8 #endif // V8_HEAP_PROGRESS_BAR_H_