| // Copyright 2019 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ | 
 | #define BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ | 
 |  | 
 | #include <atomic> | 
 | #include <vector> | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/memory/raw_ptr_exclusion.h" | 
 | #include "base/no_destructor.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | namespace android { | 
 |  | 
 | // ReachedAddressesBitset is a set that stores addresses for the | 
 | // ReachedCodeProfiler in compact form. Its main features are lock-free | 
 | // thread-safety and fast adding of elements. | 
 | // | 
 | // The addresses are kept with |kBytesGranularity| to save the storage space. | 
 | // | 
 | // Once insterted, elements cannot be erased from the set. | 
 | // | 
 | // All methods can be called from any thread. | 
 | class BASE_EXPORT ReachedAddressesBitset { | 
 |  public: | 
 |   // Returns an instance of ReachedAddressesBitset having enough storage space | 
 |   // to keep all addresses from the .text section. | 
 |   // Returns nullptr if SUPPORTS_CODE_ORDERING isn't defined. | 
 |   // This instance is stored in the .bss section of the binary, meaning that it | 
 |   // doesn't incur the binary size overhead and it doesn't increase the resident | 
 |   // memory footprint when not used. | 
 |   static ReachedAddressesBitset* GetTextBitset(); | 
 |  | 
 |   // Inserts |address| into the bitset iff |address| lies in the range between | 
 |   // |start_address_| and |end_address_|. | 
 |   void RecordAddress(uintptr_t address); | 
 |  | 
 |   // Returns a list of recorded addresses in the form of offsets from | 
 |   // |start_address_|. | 
 |   std::vector<uint32_t> GetReachedOffsets() const; | 
 |  | 
 |  private: | 
 |   friend class ReachedAddressesBitsetTest; | 
 |   friend class NoDestructor<ReachedAddressesBitset>; | 
 |  | 
 |   // Represents the number of bytes that are mapped into the same bit in the | 
 |   // bitset. | 
 |   static constexpr size_t kBytesGranularity = 4; | 
 |  | 
 |   // Constructs a ReachedAddressesBitset on top of an external storage of | 
 |   // |storage_size| pointed by |storage_ptr|. This external storage must outlive | 
 |   // the constructed bitset instance. The size of storage must be large enough | 
 |   // to fit all addresses in the range between |start_address| and | 
 |   // |end_address|. | 
 |   ReachedAddressesBitset(uintptr_t start_address, | 
 |                          uintptr_t end_address, | 
 |                          std::atomic<uint32_t>* storage_ptr, | 
 |                          size_t storage_size); | 
 |  | 
 |   size_t NumberOfReachableElements() const; | 
 |  | 
 |   uintptr_t start_address_; | 
 |   uintptr_t end_address_; | 
 |   // This field is not a raw_ptr<> because the rewriter couldn't handle the | 
 |   // global variable in a build configuration specific code. | 
 |   RAW_PTR_EXCLUSION std::atomic<uint32_t>* reached_; | 
 | }; | 
 |  | 
 | }  // namespace android | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_ANDROID_REACHED_ADDRESSES_BITSET_H_ |