[heap] Make Heap::Contains const

Add const Page iterators to Spaces, and add whichever const methods are
necessary for this to work. This and a couple more const methods allows
us to make Heap::Contains const.

Change-Id: I1b63a10575ccdb8a3979aef4fa63a97b288ff836
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2198975
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67776}
This commit is contained in:
Leszek Swirski 2020-05-13 14:39:56 +02:00 committed by Commit Bot
parent 0062d7594c
commit 9c8a7f84ce
8 changed files with 87 additions and 41 deletions

View File

@ -415,7 +415,7 @@ bool Heap::CanExpandOldGeneration(size_t size) {
return memory_allocator()->Size() + size <= MaxReserved();
}
bool Heap::HasBeenSetUp() {
bool Heap::HasBeenSetUp() const {
// We will always have a new space when the heap is set up.
return new_space_ != nullptr;
}
@ -4079,7 +4079,7 @@ const char* Heap::GarbageCollectionReasonToString(
UNREACHABLE();
}
bool Heap::Contains(HeapObject value) {
bool Heap::Contains(HeapObject value) const {
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) {
return true;
}
@ -4096,7 +4096,7 @@ bool Heap::Contains(HeapObject value) {
new_lo_space_->Contains(value));
}
bool Heap::InSpace(HeapObject value, AllocationSpace space) {
bool Heap::InSpace(HeapObject value, AllocationSpace space) const {
if (memory_allocator()->IsOutsideAllocatedSpace(value.address())) {
return false;
}
@ -4123,7 +4123,7 @@ bool Heap::InSpace(HeapObject value, AllocationSpace space) {
UNREACHABLE();
}
bool Heap::InSpaceSlow(Address addr, AllocationSpace space) {
bool Heap::InSpaceSlow(Address addr, AllocationSpace space) const {
if (memory_allocator()->IsOutsideAllocatedSpace(addr)) {
return false;
}

View File

@ -749,7 +749,7 @@ class Heap {
void TearDown();
// Returns whether SetUp has been called.
bool HasBeenSetUp();
bool HasBeenSetUp() const;
// ===========================================================================
// Getters for spaces. =======================================================
@ -779,6 +779,9 @@ class Heap {
GCTracer* tracer() { return tracer_.get(); }
MemoryAllocator* memory_allocator() { return memory_allocator_.get(); }
const MemoryAllocator* memory_allocator() const {
return memory_allocator_.get();
}
inline Isolate* isolate();
@ -1107,15 +1110,15 @@ class Heap {
// Checks whether an address/object is in the non-read-only heap (including
// auxiliary area and unused area). Use IsValidHeapObject if checking both
// heaps is required.
V8_EXPORT_PRIVATE bool Contains(HeapObject value);
V8_EXPORT_PRIVATE bool Contains(HeapObject value) const;
// Checks whether an address/object in a space.
// Currently used by tests, serialization and heap verification only.
V8_EXPORT_PRIVATE bool InSpace(HeapObject value, AllocationSpace space);
V8_EXPORT_PRIVATE bool InSpace(HeapObject value, AllocationSpace space) const;
// Slow methods that can be used for verification as they can also be used
// with off-heap Addresses.
V8_EXPORT_PRIVATE bool InSpaceSlow(Address addr, AllocationSpace space);
V8_EXPORT_PRIVATE bool InSpaceSlow(Address addr, AllocationSpace space) const;
static inline Heap* FromWritableHeapObject(HeapObject obj);

View File

@ -68,8 +68,8 @@ class List {
element->list_node().set_next(nullptr);
}
bool Contains(T* element) {
T* it = front_;
bool Contains(T* element) const {
const T* it = front_;
while (it) {
if (it == element) return true;
it = it->list_node().next();
@ -77,11 +77,14 @@ class List {
return false;
}
bool Empty() { return !front_ && !back_; }
bool Empty() const { return !front_ && !back_; }
T* front() { return front_; }
T* back() { return back_; }
const T* front() const { return front_; }
const T* back() const { return back_; }
private:
void AddFirstElement(T* element) {
DCHECK(!back_);
@ -129,6 +132,9 @@ class ListNode {
T* next() { return next_; }
T* prev() { return prev_; }
const T* next() const { return next_; }
const T* prev() const { return prev_; }
void Initialize() {
next_ = nullptr;
prev_ = nullptr;

View File

@ -353,6 +353,7 @@ class MemoryChunk : public BasicMemoryChunk {
}
heap::ListNode<MemoryChunk>& list_node() { return list_node_; }
const heap::ListNode<MemoryChunk>& list_node() const { return list_node_; }
CodeObjectRegistry* GetCodeObjectRegistry() { return code_object_registry_; }

View File

@ -123,19 +123,19 @@ void Space::MoveExternalBackingStoreBytes(ExternalBackingStoreType type,
// -----------------------------------------------------------------------------
// SemiSpace
bool SemiSpace::Contains(HeapObject o) {
bool SemiSpace::Contains(HeapObject o) const {
MemoryChunk* memory_chunk = MemoryChunk::FromHeapObject(o);
if (memory_chunk->IsLargePage()) return false;
return id_ == kToSpace ? memory_chunk->IsToPage()
: memory_chunk->IsFromPage();
}
bool SemiSpace::Contains(Object o) {
bool SemiSpace::Contains(Object o) const {
return o.IsHeapObject() && Contains(HeapObject::cast(o));
}
bool SemiSpace::ContainsSlow(Address a) {
for (Page* p : *this) {
bool SemiSpace::ContainsSlow(Address a) const {
for (const Page* p : *this) {
if (p == MemoryChunk::FromAddress(a)) return true;
}
return false;
@ -144,33 +144,35 @@ bool SemiSpace::ContainsSlow(Address a) {
// --------------------------------------------------------------------------
// NewSpace
bool NewSpace::Contains(Object o) {
bool NewSpace::Contains(Object o) const {
return o.IsHeapObject() && Contains(HeapObject::cast(o));
}
bool NewSpace::Contains(HeapObject o) {
bool NewSpace::Contains(HeapObject o) const {
return MemoryChunk::FromHeapObject(o)->InNewSpace();
}
bool NewSpace::ContainsSlow(Address a) {
bool NewSpace::ContainsSlow(Address a) const {
return from_space_.ContainsSlow(a) || to_space_.ContainsSlow(a);
}
bool NewSpace::ToSpaceContainsSlow(Address a) {
bool NewSpace::ToSpaceContainsSlow(Address a) const {
return to_space_.ContainsSlow(a);
}
bool NewSpace::ToSpaceContains(Object o) { return to_space_.Contains(o); }
bool NewSpace::FromSpaceContains(Object o) { return from_space_.Contains(o); }
bool NewSpace::ToSpaceContains(Object o) const { return to_space_.Contains(o); }
bool NewSpace::FromSpaceContains(Object o) const {
return from_space_.Contains(o);
}
bool PagedSpace::Contains(Address addr) {
bool PagedSpace::Contains(Address addr) const {
if (V8_ENABLE_THIRD_PARTY_HEAP_BOOL) {
return true;
}
return Page::FromAddress(addr)->owner() == this;
}
bool PagedSpace::Contains(Object o) {
bool PagedSpace::Contains(Object o) const {
if (!o.IsHeapObject()) return false;
return Page::FromAddress(o.ptr())->owner() == this;
}

View File

@ -1628,9 +1628,9 @@ size_t PagedSpace::CommittedPhysicalMemory() {
return size;
}
bool PagedSpace::ContainsSlow(Address addr) {
bool PagedSpace::ContainsSlow(Address addr) const {
Page* p = Page::FromAddress(addr);
for (Page* page : *this) {
for (const Page* page : *this) {
if (page == p) return true;
}
return false;

View File

@ -499,6 +499,9 @@ class V8_EXPORT_PRIVATE Space : public Malloced {
MemoryChunk* first_page() { return memory_chunk_list_.front(); }
MemoryChunk* last_page() { return memory_chunk_list_.back(); }
const MemoryChunk* first_page() const { return memory_chunk_list_.front(); }
const MemoryChunk* last_page() const { return memory_chunk_list_.back(); }
heap::List<MemoryChunk>& memory_chunk_list() { return memory_chunk_list_; }
FreeList* free_list() { return free_list_.get(); }
@ -609,6 +612,13 @@ class Page : public MemoryChunk {
Page* next_page() { return static_cast<Page*>(list_node_.next()); }
Page* prev_page() { return static_cast<Page*>(list_node_.prev()); }
const Page* next_page() const {
return static_cast<const Page*>(list_node_.next());
}
const Page* prev_page() const {
return static_cast<const Page*>(list_node_.prev());
}
template <typename Callback>
inline void ForAllFreeListCategories(Callback callback) {
for (int i = kFirstCategory;
@ -848,20 +858,20 @@ class MemoryAllocator {
void Free(MemoryChunk* chunk);
// Returns allocated spaces in bytes.
size_t Size() { return size_; }
size_t Size() const { return size_; }
// Returns allocated executable spaces in bytes.
size_t SizeExecutable() { return size_executable_; }
size_t SizeExecutable() const { return size_executable_; }
// Returns the maximum available bytes of heaps.
size_t Available() {
size_t Available() const {
const size_t size = Size();
return capacity_ < size ? 0 : capacity_ - size;
}
// Returns an indication of whether a pointer is in a space that has
// been allocated by this MemoryAllocator.
V8_INLINE bool IsOutsideAllocatedSpace(Address address) {
V8_INLINE bool IsOutsideAllocatedSpace(Address address) const {
return address < lowest_ever_allocated_ ||
address >= highest_ever_allocated_;
}
@ -1107,6 +1117,7 @@ class PageIteratorImpl
};
using PageIterator = PageIteratorImpl<Page>;
using ConstPageIterator = PageIteratorImpl<const Page>;
using LargePageIterator = PageIteratorImpl<LargePage>;
class PageRange {
@ -1815,6 +1826,7 @@ class V8_EXPORT_PRIVATE PagedSpace
: NON_EXPORTED_BASE(public SpaceWithLinearArea) {
public:
using iterator = PageIterator;
using const_iterator = ConstPageIterator;
static const size_t kCompactionMemoryWanted = 500 * KB;
@ -1826,9 +1838,9 @@ class V8_EXPORT_PRIVATE PagedSpace
~PagedSpace() override { TearDown(); }
// Checks whether an object/address is in this space.
inline bool Contains(Address a);
inline bool Contains(Object o);
bool ContainsSlow(Address addr);
inline bool Contains(Address a) const;
inline bool Contains(Object o) const;
bool ContainsSlow(Address addr) const;
// Does the space need executable memory?
Executability executable() { return executable_; }
@ -2034,10 +2046,16 @@ class V8_EXPORT_PRIVATE PagedSpace
inline size_t RelinkFreeListCategories(Page* page);
Page* first_page() { return reinterpret_cast<Page*>(Space::first_page()); }
const Page* first_page() const {
return reinterpret_cast<const Page*>(Space::first_page());
}
iterator begin() { return iterator(first_page()); }
iterator end() { return iterator(nullptr); }
const_iterator begin() const { return const_iterator(first_page()); }
const_iterator end() const { return const_iterator(nullptr); }
// Shrink immortal immovable pages of the space to be exactly the size needed
// using the high water mark.
void ShrinkImmortalImmovablePages();
@ -2158,6 +2176,7 @@ enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 };
class SemiSpace : public Space {
public:
using iterator = PageIterator;
using const_iterator = ConstPageIterator;
static void Swap(SemiSpace* from, SemiSpace* to);
@ -2172,9 +2191,9 @@ class SemiSpace : public Space {
current_page_(nullptr),
pages_used_(0) {}
inline bool Contains(HeapObject o);
inline bool Contains(Object o);
inline bool ContainsSlow(Address a);
inline bool Contains(HeapObject o) const;
inline bool Contains(Object o) const;
inline bool ContainsSlow(Address a) const;
void SetUp(size_t initial_capacity, size_t maximum_capacity);
void TearDown();
@ -2263,9 +2282,19 @@ class SemiSpace : public Space {
Page* first_page() { return reinterpret_cast<Page*>(Space::first_page()); }
Page* last_page() { return reinterpret_cast<Page*>(Space::last_page()); }
const Page* first_page() const {
return reinterpret_cast<const Page*>(Space::first_page());
}
const Page* last_page() const {
return reinterpret_cast<const Page*>(Space::last_page());
}
iterator begin() { return iterator(first_page()); }
iterator end() { return iterator(nullptr); }
const_iterator begin() const { return const_iterator(first_page()); }
const_iterator end() const { return const_iterator(nullptr); }
std::unique_ptr<ObjectIterator> GetObjectIterator(Heap* heap) override;
#ifdef DEBUG
@ -2348,15 +2377,16 @@ class V8_EXPORT_PRIVATE NewSpace
: NON_EXPORTED_BASE(public SpaceWithLinearArea) {
public:
using iterator = PageIterator;
using const_iterator = ConstPageIterator;
NewSpace(Heap* heap, v8::PageAllocator* page_allocator,
size_t initial_semispace_capacity, size_t max_semispace_capacity);
~NewSpace() override { TearDown(); }
inline bool ContainsSlow(Address a);
inline bool Contains(Object o);
inline bool Contains(HeapObject o);
inline bool ContainsSlow(Address a) const;
inline bool Contains(Object o) const;
inline bool Contains(HeapObject o) const;
// Tears down the space. Heap memory was not allocated by the space, so it
// is not deallocated here.
@ -2530,9 +2560,9 @@ class V8_EXPORT_PRIVATE NewSpace
// it in steps to guarantee that the observers are notified periodically.
void UpdateInlineAllocationLimit(size_t size_in_bytes) override;
inline bool ToSpaceContainsSlow(Address a);
inline bool ToSpaceContains(Object o);
inline bool FromSpaceContains(Object o);
inline bool ToSpaceContainsSlow(Address a) const;
inline bool ToSpaceContains(Object o) const;
inline bool FromSpaceContains(Object o) const;
// Try to switch the active semispace to a new, empty, page.
// Returns false if this isn't possible or reasonable (i.e., there
@ -2572,6 +2602,9 @@ class V8_EXPORT_PRIVATE NewSpace
iterator begin() { return to_space_.begin(); }
iterator end() { return to_space_.end(); }
const_iterator begin() const { return to_space_.begin(); }
const_iterator end() const { return to_space_.end(); }
std::unique_ptr<ObjectIterator> GetObjectIterator(Heap* heap) override;
SemiSpace& from_space() { return from_space_; }

View File

@ -12,6 +12,7 @@ namespace heap {
class TestChunk {
public:
heap::ListNode<TestChunk>& list_node() { return list_node_; }
const heap::ListNode<TestChunk>& list_node() const { return list_node_; }
heap::ListNode<TestChunk> list_node_;
};