Commit f3e0ee23 authored by Dominik Inführ's avatar Dominik Inführ Committed by V8 LUCI CQ

[heap] Simplify Sweeper::CleanupInvalidTypedSlotsOfFreeRanges

This CL only refactors code in the sweeper without changing behavior.

This method can be simplified by moving duplicate code into new methods.
Also move definition of FreeRangesMap into TypedSlotSet and replace all
usages of that raw map type with that type-alias.

Since we are already here, remove the unused argument in
Sweeper::FreeAndProcessFreedMemory.

Bug: v8:12760
Change-Id: Ifa1848b456aef7955eccbaafc00df55fbcbc385c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3574542Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79822}
parent 25c69ecb
...@@ -61,14 +61,12 @@ TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, size_t capacity) { ...@@ -61,14 +61,12 @@ TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, size_t capacity) {
return chunk; return chunk;
} }
void TypedSlotSet::ClearInvalidSlots( void TypedSlotSet::ClearInvalidSlots(const FreeRangesMap& invalid_ranges) {
const std::map<uint32_t, uint32_t>& invalid_ranges) {
IterateSlotsInRanges([](TypedSlot* slot) { *slot = ClearedTypedSlot(); }, IterateSlotsInRanges([](TypedSlot* slot) { *slot = ClearedTypedSlot(); },
invalid_ranges); invalid_ranges);
} }
void TypedSlotSet::AssertNoInvalidSlots( void TypedSlotSet::AssertNoInvalidSlots(const FreeRangesMap& invalid_ranges) {
const std::map<uint32_t, uint32_t>& invalid_ranges) {
IterateSlotsInRanges( IterateSlotsInRanges(
[](TypedSlot* slot) { [](TypedSlot* slot) {
CHECK_WITH_MSG(false, "No slot in ranges expected."); CHECK_WITH_MSG(false, "No slot in ranges expected.");
...@@ -77,8 +75,8 @@ void TypedSlotSet::AssertNoInvalidSlots( ...@@ -77,8 +75,8 @@ void TypedSlotSet::AssertNoInvalidSlots(
} }
template <typename Callback> template <typename Callback>
void TypedSlotSet::IterateSlotsInRanges( void TypedSlotSet::IterateSlotsInRanges(Callback callback,
Callback callback, const std::map<uint32_t, uint32_t>& ranges) { const FreeRangesMap& ranges) {
if (ranges.empty()) return; if (ranges.empty()) return;
Chunk* chunk = LoadHead(); Chunk* chunk = LoadHead();
...@@ -87,8 +85,7 @@ void TypedSlotSet::IterateSlotsInRanges( ...@@ -87,8 +85,7 @@ void TypedSlotSet::IterateSlotsInRanges(
SlotType type = TypeField::decode(slot.type_and_offset); SlotType type = TypeField::decode(slot.type_and_offset);
if (type == SlotType::kCleared) continue; if (type == SlotType::kCleared) continue;
uint32_t offset = OffsetField::decode(slot.type_and_offset); uint32_t offset = OffsetField::decode(slot.type_and_offset);
std::map<uint32_t, uint32_t>::const_iterator upper_bound = FreeRangesMap::const_iterator upper_bound = ranges.upper_bound(offset);
ranges.upper_bound(offset);
if (upper_bound == ranges.begin()) continue; if (upper_bound == ranges.begin()) continue;
// upper_bounds points to the invalid range after the given slot. Hence, // upper_bounds points to the invalid range after the given slot. Hence,
// we have to go to the previous element. // we have to go to the previous element.
......
...@@ -681,6 +681,8 @@ class V8_EXPORT_PRIVATE TypedSlots { ...@@ -681,6 +681,8 @@ class V8_EXPORT_PRIVATE TypedSlots {
// clearing of invalid slots. // clearing of invalid slots.
class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots { class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots {
public: public:
using FreeRangesMap = std::map<uint32_t, uint32_t>;
enum IterationMode { FREE_EMPTY_CHUNKS, KEEP_EMPTY_CHUNKS }; enum IterationMode { FREE_EMPTY_CHUNKS, KEEP_EMPTY_CHUNKS };
explicit TypedSlotSet(Address page_start) : page_start_(page_start) {} explicit TypedSlotSet(Address page_start) : page_start_(page_start) {}
...@@ -737,10 +739,10 @@ class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots { ...@@ -737,10 +739,10 @@ class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots {
// Clears all slots that have the offset in the specified ranges. // Clears all slots that have the offset in the specified ranges.
// This can run concurrently to Iterate(). // This can run concurrently to Iterate().
void ClearInvalidSlots(const std::map<uint32_t, uint32_t>& invalid_ranges); void ClearInvalidSlots(const FreeRangesMap& invalid_ranges);
// Asserts that there are no recorded slots in the specified ranges. // Asserts that there are no recorded slots in the specified ranges.
void AssertNoInvalidSlots(const std::map<uint32_t, uint32_t>& invalid_ranges); void AssertNoInvalidSlots(const FreeRangesMap& invalid_ranges);
// Frees empty chunks accumulated by PREFREE_EMPTY_CHUNKS. // Frees empty chunks accumulated by PREFREE_EMPTY_CHUNKS.
void FreeToBeFreedChunks(); void FreeToBeFreedChunks();
...@@ -748,7 +750,7 @@ class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots { ...@@ -748,7 +750,7 @@ class V8_EXPORT_PRIVATE TypedSlotSet : public TypedSlots {
private: private:
template <typename Callback> template <typename Callback>
void IterateSlotsInRanges(Callback callback, void IterateSlotsInRanges(Callback callback,
const std::map<uint32_t, uint32_t>& invalid_ranges); const FreeRangesMap& invalid_ranges);
// Atomic operations used by Iterate and ClearInvalidSlots; // Atomic operations used by Iterate and ClearInvalidSlots;
Chunk* LoadNext(Chunk* chunk) { Chunk* LoadNext(Chunk* chunk) {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "src/heap/list.h" #include "src/heap/list.h"
#include "src/heap/memory-chunk-layout.h" #include "src/heap/memory-chunk-layout.h"
#include "src/heap/memory-chunk.h" #include "src/heap/memory-chunk.h"
#include "src/heap/slot-set.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
#include "src/utils/allocation.h" #include "src/utils/allocation.h"
#include "src/utils/utils.h" #include "src/utils/utils.h"
...@@ -311,6 +312,24 @@ class Page : public MemoryChunk { ...@@ -311,6 +312,24 @@ class Page : public MemoryChunk {
ActiveSystemPages* active_system_pages() { return &active_system_pages_; } ActiveSystemPages* active_system_pages() { return &active_system_pages_; }
template <RememberedSetType remembered_set>
void ClearInvalidTypedSlots(const TypedSlotSet::FreeRangesMap& ranges) {
TypedSlotSet* typed_slot_set = this->typed_slot_set<remembered_set>();
if (typed_slot_set != nullptr) {
typed_slot_set->ClearInvalidSlots(ranges);
}
}
template <RememberedSetType remembered_set>
void AssertNoInvalidTypedSlots(const TypedSlotSet::FreeRangesMap& ranges) {
#if DEBUG
TypedSlotSet* typed_slot_set = this->typed_slot_set<OLD_TO_OLD>();
if (typed_slot_set != nullptr) {
typed_slot_set->AssertNoInvalidSlots(ranges);
}
#endif // DEBUG
}
private: private:
friend class MemoryAllocator; friend class MemoryAllocator;
}; };
......
...@@ -227,7 +227,7 @@ bool Sweeper::AreSweeperTasksRunning() { ...@@ -227,7 +227,7 @@ bool Sweeper::AreSweeperTasksRunning() {
V8_INLINE size_t Sweeper::FreeAndProcessFreedMemory( V8_INLINE size_t Sweeper::FreeAndProcessFreedMemory(
Address free_start, Address free_end, Page* page, Space* space, Address free_start, Address free_end, Page* page, Space* space,
bool record_free_ranges, FreeListRebuildingMode free_list_mode, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode) { FreeSpaceTreatmentMode free_space_mode) {
CHECK_GT(free_end, free_start); CHECK_GT(free_end, free_start);
size_t freed_bytes = 0; size_t freed_bytes = 0;
...@@ -252,7 +252,7 @@ V8_INLINE size_t Sweeper::FreeAndProcessFreedMemory( ...@@ -252,7 +252,7 @@ V8_INLINE size_t Sweeper::FreeAndProcessFreedMemory(
V8_INLINE void Sweeper::CleanupRememberedSetEntriesForFreedMemory( V8_INLINE void Sweeper::CleanupRememberedSetEntriesForFreedMemory(
Address free_start, Address free_end, Page* page, bool record_free_ranges, Address free_start, Address free_end, Page* page, bool record_free_ranges,
FreeRangesMap* free_ranges_map, SweepingMode sweeping_mode, TypedSlotSet::FreeRangesMap* free_ranges_map, SweepingMode sweeping_mode,
InvalidatedSlotsCleanup* old_to_new_cleanup) { InvalidatedSlotsCleanup* old_to_new_cleanup) {
DCHECK_LE(free_start, free_end); DCHECK_LE(free_start, free_end);
if (sweeping_mode == SweepingMode::kEagerDuringGC) { if (sweeping_mode == SweepingMode::kEagerDuringGC) {
...@@ -282,37 +282,23 @@ V8_INLINE void Sweeper::CleanupRememberedSetEntriesForFreedMemory( ...@@ -282,37 +282,23 @@ V8_INLINE void Sweeper::CleanupRememberedSetEntriesForFreedMemory(
} }
void Sweeper::CleanupInvalidTypedSlotsOfFreeRanges( void Sweeper::CleanupInvalidTypedSlotsOfFreeRanges(
Page* page, const FreeRangesMap& free_ranges_map, Page* page, const TypedSlotSet::FreeRangesMap& free_ranges_map,
SweepingMode sweeping_mode) { SweepingMode sweeping_mode) {
if (sweeping_mode == SweepingMode::kEagerDuringGC) { if (sweeping_mode == SweepingMode::kEagerDuringGC) {
TypedSlotSet* old_to_new = page->typed_slot_set<OLD_TO_NEW>(); page->ClearInvalidTypedSlots<OLD_TO_NEW>(free_ranges_map);
if (old_to_new != nullptr) {
old_to_new->ClearInvalidSlots(free_ranges_map);
}
#if DEBUG // Typed old-to-old slot sets are only ever recorded in live code objects.
TypedSlotSet* old_to_old = page->typed_slot_set<OLD_TO_OLD>(); // Also code objects are never right-trimmed, so there cannot be any slots
if (old_to_old != nullptr) { // in a free range.
// Typed old-to-old slot sets are only ever recorded in live code objects. page->AssertNoInvalidTypedSlots<OLD_TO_OLD>(free_ranges_map);
// Also code objects are never right-trimmed, so there cannot be any slots
// in a free range.
old_to_old->AssertNoInvalidSlots(free_ranges_map);
}
#endif // DEBUG
return; return;
} }
DCHECK_EQ(sweeping_mode, SweepingMode::kLazyOrConcurrent); DCHECK_EQ(sweeping_mode, SweepingMode::kLazyOrConcurrent);
#if DEBUG // After a full GC there are no old-to-new typed slots. The main thread
TypedSlotSet* old_to_new = page->typed_slot_set<OLD_TO_NEW>(); // could create new slots but not in a free range.
if (old_to_new != nullptr) { page->AssertNoInvalidTypedSlots<OLD_TO_NEW>(free_ranges_map);
// After a full GC there are no old-to-new typed slots. The main thread
// could create new slots but not in a free range.
old_to_new->AssertNoInvalidSlots(free_ranges_map);
}
#endif // DEBUG
DCHECK_NULL(page->typed_slot_set<OLD_TO_OLD>()); DCHECK_NULL(page->typed_slot_set<OLD_TO_OLD>());
} }
...@@ -380,7 +366,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode, ...@@ -380,7 +366,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
old_to_new_cleanup = InvalidatedSlotsCleanup::OldToNew(p); old_to_new_cleanup = InvalidatedSlotsCleanup::OldToNew(p);
// The free ranges map is used for filtering typed slots. // The free ranges map is used for filtering typed slots.
FreeRangesMap free_ranges_map; TypedSlotSet::FreeRangesMap free_ranges_map;
#ifdef V8_ENABLE_CONSERVATIVE_STACK_SCANNING #ifdef V8_ENABLE_CONSERVATIVE_STACK_SCANNING
p->object_start_bitmap()->Clear(); p->object_start_bitmap()->Clear();
...@@ -401,8 +387,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode, ...@@ -401,8 +387,7 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
max_freed_bytes = max_freed_bytes =
std::max(max_freed_bytes, std::max(max_freed_bytes,
FreeAndProcessFreedMemory(free_start, free_end, p, space, FreeAndProcessFreedMemory(free_start, free_end, p, space,
record_free_ranges, free_list_mode, free_list_mode, free_space_mode));
free_space_mode));
CleanupRememberedSetEntriesForFreedMemory( CleanupRememberedSetEntriesForFreedMemory(
free_start, free_end, p, record_free_ranges, &free_ranges_map, free_start, free_end, p, record_free_ranges, &free_ranges_map,
sweeping_mode, &old_to_new_cleanup); sweeping_mode, &old_to_new_cleanup);
...@@ -428,10 +413,10 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode, ...@@ -428,10 +413,10 @@ int Sweeper::RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
// If there is free memory after the last live object also free that. // If there is free memory after the last live object also free that.
Address free_end = p->area_end(); Address free_end = p->area_end();
if (free_end != free_start) { if (free_end != free_start) {
max_freed_bytes = std::max( max_freed_bytes =
max_freed_bytes, FreeAndProcessFreedMemory( std::max(max_freed_bytes,
free_start, free_end, p, space, record_free_ranges, FreeAndProcessFreedMemory(free_start, free_end, p, space,
free_list_mode, free_space_mode)); free_list_mode, free_space_mode));
CleanupRememberedSetEntriesForFreedMemory( CleanupRememberedSetEntriesForFreedMemory(
free_start, free_end, p, record_free_ranges, &free_ranges_map, free_start, free_end, p, record_free_ranges, &free_ranges_map,
sweeping_mode, &old_to_new_cleanup); sweeping_mode, &old_to_new_cleanup);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "src/base/platform/condition-variable.h" #include "src/base/platform/condition-variable.h"
#include "src/base/platform/semaphore.h" #include "src/base/platform/semaphore.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/heap/slot-set.h"
#include "src/tasks/cancelable-task.h" #include "src/tasks/cancelable-task.h"
namespace v8 { namespace v8 {
...@@ -29,7 +30,6 @@ class Sweeper { ...@@ -29,7 +30,6 @@ class Sweeper {
using IterabilityList = std::vector<Page*>; using IterabilityList = std::vector<Page*>;
using SweepingList = std::vector<Page*>; using SweepingList = std::vector<Page*>;
using SweptList = std::vector<Page*>; using SweptList = std::vector<Page*>;
using FreeRangesMap = std::map<uint32_t, uint32_t>;
// Pauses the sweeper tasks. // Pauses the sweeper tasks.
class V8_NODISCARD PauseScope final { class V8_NODISCARD PauseScope final {
...@@ -136,7 +136,6 @@ class Sweeper { ...@@ -136,7 +136,6 @@ class Sweeper {
// the operating system. // the operating system.
size_t FreeAndProcessFreedMemory(Address free_start, Address free_end, size_t FreeAndProcessFreedMemory(Address free_start, Address free_end,
Page* page, Space* space, Page* page, Space* space,
bool record_free_ranges,
FreeListRebuildingMode free_list_mode, FreeListRebuildingMode free_list_mode,
FreeSpaceTreatmentMode free_space_mode); FreeSpaceTreatmentMode free_space_mode);
...@@ -144,13 +143,13 @@ class Sweeper { ...@@ -144,13 +143,13 @@ class Sweeper {
// memory which require clearing. // memory which require clearing.
void CleanupRememberedSetEntriesForFreedMemory( void CleanupRememberedSetEntriesForFreedMemory(
Address free_start, Address free_end, Page* page, bool record_free_ranges, Address free_start, Address free_end, Page* page, bool record_free_ranges,
FreeRangesMap* free_ranges_map, SweepingMode sweeping_mode, TypedSlotSet::FreeRangesMap* free_ranges_map, SweepingMode sweeping_mode,
InvalidatedSlotsCleanup* old_to_new_cleanup); InvalidatedSlotsCleanup* old_to_new_cleanup);
// Helper function for RawSweep. Clears invalid typed slots in the given free // Helper function for RawSweep. Clears invalid typed slots in the given free
// ranges. // ranges.
void CleanupInvalidTypedSlotsOfFreeRanges( void CleanupInvalidTypedSlotsOfFreeRanges(
Page* page, const FreeRangesMap& free_ranges_map, Page* page, const TypedSlotSet::FreeRangesMap& free_ranges_map,
SweepingMode sweeping_mode); SweepingMode sweeping_mode);
// Helper function for RawSweep. Clears the mark bits and ensures consistency // Helper function for RawSweep. Clears the mark bits and ensures consistency
......
...@@ -278,14 +278,14 @@ TEST(TypedSlotSet, ClearInvalidSlots) { ...@@ -278,14 +278,14 @@ TEST(TypedSlotSet, ClearInvalidSlots) {
set.Insert(type, i * kHostDelta); set.Insert(type, i * kHostDelta);
} }
std::map<uint32_t, uint32_t> invalid_ranges; TypedSlotSet::FreeRangesMap invalid_ranges;
for (uint32_t i = 1; i < entries; i += 2) { for (uint32_t i = 1; i < entries; i += 2) {
invalid_ranges.insert( invalid_ranges.insert(
std::pair<uint32_t, uint32_t>(i * kHostDelta, i * kHostDelta + 1)); std::pair<uint32_t, uint32_t>(i * kHostDelta, i * kHostDelta + 1));
} }
set.ClearInvalidSlots(invalid_ranges); set.ClearInvalidSlots(invalid_ranges);
for (std::map<uint32_t, uint32_t>::iterator it = invalid_ranges.begin(); for (TypedSlotSet::FreeRangesMap::iterator it = invalid_ranges.begin();
it != invalid_ranges.end(); ++it) { it != invalid_ranges.end(); ++it) {
uint32_t start = it->first; uint32_t start = it->first;
uint32_t end = it->second; uint32_t end = it->second;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment