%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
// Copyright 2020 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_OBJECT_START_BITMAP_H_ #define V8_HEAP_OBJECT_START_BITMAP_H_ #include <limits.h> #include <stdint.h> #include <array> #include "include/v8-internal.h" #include "src/base/bits.h" #include "src/base/macros.h" #include "src/common/globals.h" namespace v8 { namespace internal { static constexpr size_t kAllocationGranularity = kTaggedSize; static constexpr size_t kAllocationMask = kAllocationGranularity - 1; static const int kPageSize = 1 << kPageSizeBits; // A bitmap for recording object starts. Objects have to be allocated at // minimum granularity of kGranularity. // // Depends on internals such as: // - kPageSize // - kAllocationGranularity // // ObjectStartBitmap does not support concurrent access and is used only by the // main thread. class V8_EXPORT_PRIVATE ObjectStartBitmap { public: // Granularity of addresses added to the bitmap. static constexpr size_t Granularity() { return kAllocationGranularity; } // Maximum number of entries in the bitmap. static constexpr size_t MaxEntries() { return kReservedForBitmap * kBitsPerCell; } explicit inline ObjectStartBitmap(size_t offset = 0); // Finds an object header based on a maybe_inner_ptr. Will search for an // object start in decreasing address order. // // This must only be used when there exists at least one entry in the bitmap. inline Address FindBasePtr(Address maybe_inner_ptr) const; inline void SetBit(Address); inline void ClearBit(Address); inline bool CheckBit(Address) const; // Iterates all object starts recorded in the bitmap. // // The callback is of type // void(Address) // and is passed the object start address as parameter. template <typename Callback> inline void Iterate(Callback) const; // Clear the object start bitmap. inline void Clear(); private: inline void store(size_t cell_index, uint32_t value); inline uint32_t load(size_t cell_index) const; inline Address offset() const; static constexpr size_t kBitsPerCell = sizeof(uint32_t) * CHAR_BIT; static constexpr size_t kCellMask = kBitsPerCell - 1; static constexpr size_t kBitmapSize = (kPageSize + ((kBitsPerCell * kAllocationGranularity) - 1)) / (kBitsPerCell * kAllocationGranularity); static constexpr size_t kReservedForBitmap = ((kBitmapSize + kAllocationMask) & ~kAllocationMask); inline void ObjectStartIndexAndBit(Address, size_t*, size_t*) const; inline Address StartIndexToAddress(size_t object_start_index) const; size_t offset_; std::array<uint32_t, kReservedForBitmap> object_start_bit_map_; }; ObjectStartBitmap::ObjectStartBitmap(size_t offset) : offset_(offset) { Clear(); } Address ObjectStartBitmap::FindBasePtr(Address maybe_inner_ptr) const { DCHECK_LE(offset(), maybe_inner_ptr); size_t object_offset = maybe_inner_ptr - offset(); size_t object_start_number = object_offset / kAllocationGranularity; size_t cell_index = object_start_number / kBitsPerCell; DCHECK_GT(object_start_bit_map_.size(), cell_index); const size_t bit = object_start_number & kCellMask; // check if maybe_inner_ptr is the base pointer uint32_t byte = load(cell_index) & ((1 << (bit + 1)) - 1); while (!byte && cell_index) { DCHECK_LT(0u, cell_index); byte = load(--cell_index); } const int leading_zeroes = v8::base::bits::CountLeadingZeros(byte); if (leading_zeroes == kBitsPerCell) { return kNullAddress; } object_start_number = (cell_index * kBitsPerCell) + (kBitsPerCell - 1) - leading_zeroes; Address base_ptr = StartIndexToAddress(object_start_number); return base_ptr; } void ObjectStartBitmap::SetBit(Address base_ptr) { size_t cell_index, object_bit; ObjectStartIndexAndBit(base_ptr, &cell_index, &object_bit); store(cell_index, static_cast<uint32_t>(load(cell_index) | (1 << object_bit))); } void ObjectStartBitmap::ClearBit(Address base_ptr) { size_t cell_index, object_bit; ObjectStartIndexAndBit(base_ptr, &cell_index, &object_bit); store(cell_index, static_cast<uint32_t>(load(cell_index) & ~(1 << object_bit))); } bool ObjectStartBitmap::CheckBit(Address base_ptr) const { size_t cell_index, object_bit; ObjectStartIndexAndBit(base_ptr, &cell_index, &object_bit); return load(cell_index) & (1 << object_bit); } void ObjectStartBitmap::store(size_t cell_index, uint32_t value) { object_start_bit_map_[cell_index] = value; return; } uint32_t ObjectStartBitmap::load(size_t cell_index) const { return object_start_bit_map_[cell_index]; } Address ObjectStartBitmap::offset() const { return offset_; } void ObjectStartBitmap::ObjectStartIndexAndBit(Address base_ptr, size_t* cell_index, size_t* bit) const { const size_t object_offset = base_ptr - offset(); DCHECK(!(object_offset & kAllocationMask)); const size_t object_start_number = object_offset / kAllocationGranularity; *cell_index = object_start_number / kBitsPerCell; DCHECK_GT(kBitmapSize, *cell_index); *bit = object_start_number & kCellMask; } Address ObjectStartBitmap::StartIndexToAddress( size_t object_start_index) const { return offset() + (kAllocationGranularity * object_start_index); } template <typename Callback> inline void ObjectStartBitmap::Iterate(Callback callback) const { for (size_t cell_index = 0; cell_index < kReservedForBitmap; cell_index++) { uint32_t value = object_start_bit_map_[cell_index]; while (value) { const int trailing_zeroes = v8::base::bits::CountTrailingZeros(value); const size_t object_start_number = (cell_index * kBitsPerCell) + trailing_zeroes; const Address object_address = StartIndexToAddress(object_start_number); callback(object_address); // Clear current object bit in temporary value to advance iteration. value &= ~(1 << (object_start_number & kCellMask)); } } } void ObjectStartBitmap::Clear() { std::fill(object_start_bit_map_.begin(), object_start_bit_map_.end(), 0); } } // namespace internal } // namespace v8 #endif // V8_HEAP_OBJECT_START_BITMAP_H_