[heap] Run cleaning of string table in parallel to other cleaning
Bug: v8:12813 Change-Id: I27bbf5190165a0d919f021bbcf089e203dfed83f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3592955 Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/main@{#80072}
This commit is contained in:
parent
d0c147ab10
commit
7a96ceccb8
@ -908,13 +908,14 @@ void GCTracer::PrintNVP() const {
|
|||||||
"heap.external.epilogue=%.1f "
|
"heap.external.epilogue=%.1f "
|
||||||
"heap.external.weak_global_handles=%.1f "
|
"heap.external.weak_global_handles=%.1f "
|
||||||
"clear=%1.f "
|
"clear=%1.f "
|
||||||
|
"clear.external_string_table=%.1f "
|
||||||
"clear.dependent_code=%.1f "
|
"clear.dependent_code=%.1f "
|
||||||
"clear.maps=%.1f "
|
"clear.maps=%.1f "
|
||||||
"clear.slots_buffer=%.1f "
|
"clear.slots_buffer=%.1f "
|
||||||
"clear.string_table=%.1f "
|
|
||||||
"clear.weak_collections=%.1f "
|
"clear.weak_collections=%.1f "
|
||||||
"clear.weak_lists=%.1f "
|
"clear.weak_lists=%.1f "
|
||||||
"clear.weak_references=%.1f "
|
"clear.weak_references=%.1f "
|
||||||
|
"clear.join_job=%.1f "
|
||||||
"complete.sweep_array_buffers=%.1f "
|
"complete.sweep_array_buffers=%.1f "
|
||||||
"epilogue=%.1f "
|
"epilogue=%.1f "
|
||||||
"evacuate=%.1f "
|
"evacuate=%.1f "
|
||||||
@ -998,13 +999,14 @@ void GCTracer::PrintNVP() const {
|
|||||||
current_scope(Scope::HEAP_EXTERNAL_EPILOGUE),
|
current_scope(Scope::HEAP_EXTERNAL_EPILOGUE),
|
||||||
current_scope(Scope::HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES),
|
current_scope(Scope::HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES),
|
||||||
current_scope(Scope::MC_CLEAR),
|
current_scope(Scope::MC_CLEAR),
|
||||||
|
current_scope(Scope::MC_CLEAR_EXTERNAL_STRING_TABLE),
|
||||||
current_scope(Scope::MC_CLEAR_DEPENDENT_CODE),
|
current_scope(Scope::MC_CLEAR_DEPENDENT_CODE),
|
||||||
current_scope(Scope::MC_CLEAR_MAPS),
|
current_scope(Scope::MC_CLEAR_MAPS),
|
||||||
current_scope(Scope::MC_CLEAR_SLOTS_BUFFER),
|
current_scope(Scope::MC_CLEAR_SLOTS_BUFFER),
|
||||||
current_scope(Scope::MC_CLEAR_STRING_TABLE),
|
|
||||||
current_scope(Scope::MC_CLEAR_WEAK_COLLECTIONS),
|
current_scope(Scope::MC_CLEAR_WEAK_COLLECTIONS),
|
||||||
current_scope(Scope::MC_CLEAR_WEAK_LISTS),
|
current_scope(Scope::MC_CLEAR_WEAK_LISTS),
|
||||||
current_scope(Scope::MC_CLEAR_WEAK_REFERENCES),
|
current_scope(Scope::MC_CLEAR_WEAK_REFERENCES),
|
||||||
|
current_scope(Scope::MC_CLEAR_JOIN_JOB),
|
||||||
current_scope(Scope::MC_COMPLETE_SWEEP_ARRAY_BUFFERS),
|
current_scope(Scope::MC_COMPLETE_SWEEP_ARRAY_BUFFERS),
|
||||||
current_scope(Scope::MC_EPILOGUE), current_scope(Scope::MC_EVACUATE),
|
current_scope(Scope::MC_EPILOGUE), current_scope(Scope::MC_EVACUATE),
|
||||||
current_scope(Scope::MC_EVACUATE_CANDIDATES),
|
current_scope(Scope::MC_EVACUATE_CANDIDATES),
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "src/heap/mark-compact.h"
|
#include "src/heap/mark-compact.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -1314,10 +1315,9 @@ class MarkCompactCollector::SharedHeapObjectVisitor final
|
|||||||
MarkCompactCollector* const collector_;
|
MarkCompactCollector* const collector_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InternalizedStringTableCleaner : public RootVisitor {
|
class InternalizedStringTableCleaner final : public RootVisitor {
|
||||||
public:
|
public:
|
||||||
explicit InternalizedStringTableCleaner(Heap* heap)
|
explicit InternalizedStringTableCleaner(Heap* heap) : heap_(heap) {}
|
||||||
: heap_(heap), pointers_removed_(0) {}
|
|
||||||
|
|
||||||
void VisitRootPointers(Root root, const char* description,
|
void VisitRootPointers(Root root, const char* description,
|
||||||
FullObjectSlot start, FullObjectSlot end) override {
|
FullObjectSlot start, FullObjectSlot end) override {
|
||||||
@ -1329,8 +1329,7 @@ class InternalizedStringTableCleaner : public RootVisitor {
|
|||||||
OffHeapObjectSlot end) override {
|
OffHeapObjectSlot end) override {
|
||||||
DCHECK_EQ(root, Root::kStringTable);
|
DCHECK_EQ(root, Root::kStringTable);
|
||||||
// Visit all HeapObject pointers in [start, end).
|
// Visit all HeapObject pointers in [start, end).
|
||||||
MarkCompactCollector::NonAtomicMarkingState* marking_state =
|
auto* marking_state = heap_->mark_compact_collector()->marking_state();
|
||||||
heap_->mark_compact_collector()->non_atomic_marking_state();
|
|
||||||
Isolate* isolate = heap_->isolate();
|
Isolate* isolate = heap_->isolate();
|
||||||
for (OffHeapObjectSlot p = start; p < end; ++p) {
|
for (OffHeapObjectSlot p = start; p < end; ++p) {
|
||||||
Object o = p.load(isolate);
|
Object o = p.load(isolate);
|
||||||
@ -1346,11 +1345,11 @@ class InternalizedStringTableCleaner : public RootVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int PointersRemoved() { return pointers_removed_; }
|
int PointersRemoved() const { return pointers_removed_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Heap* heap_;
|
Heap* heap_;
|
||||||
int pointers_removed_;
|
int pointers_removed_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExternalStringTableCleaner : public RootVisitor {
|
class ExternalStringTableCleaner : public RootVisitor {
|
||||||
@ -1390,7 +1389,7 @@ class ExternalStringTableCleaner : public RootVisitor {
|
|||||||
class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
|
class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
|
||||||
public:
|
public:
|
||||||
explicit MarkCompactWeakObjectRetainer(
|
explicit MarkCompactWeakObjectRetainer(
|
||||||
MarkCompactCollector::NonAtomicMarkingState* marking_state)
|
MarkCompactCollector::MarkingState* marking_state)
|
||||||
: marking_state_(marking_state) {}
|
: marking_state_(marking_state) {}
|
||||||
|
|
||||||
Object RetainAs(Object object) override {
|
Object RetainAs(Object object) override {
|
||||||
@ -1420,7 +1419,7 @@ class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MarkCompactCollector::NonAtomicMarkingState* marking_state_;
|
MarkCompactCollector::MarkingState* const marking_state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RecordMigratedSlotVisitor : public ObjectVisitorWithCageBases {
|
class RecordMigratedSlotVisitor : public ObjectVisitorWithCageBases {
|
||||||
@ -2495,31 +2494,94 @@ void MarkCompactCollector::MarkLiveObjects() {
|
|||||||
epoch_++;
|
epoch_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ParallelClearingJob final : public v8::JobTask {
|
||||||
|
public:
|
||||||
|
class ClearingItem {
|
||||||
|
public:
|
||||||
|
virtual ~ClearingItem() = default;
|
||||||
|
virtual void Run(JobDelegate* delegate) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ParallelClearingJob() = default;
|
||||||
|
~ParallelClearingJob() override = default;
|
||||||
|
ParallelClearingJob(const ParallelClearingJob&) = delete;
|
||||||
|
ParallelClearingJob& operator=(const ParallelClearingJob&) = delete;
|
||||||
|
|
||||||
|
// v8::JobTask overrides.
|
||||||
|
void Run(JobDelegate* delegate) override {
|
||||||
|
std::unique_ptr<ClearingItem> item;
|
||||||
|
{
|
||||||
|
base::MutexGuard guard(&items_mutex_);
|
||||||
|
item = std::move(items_.back());
|
||||||
|
items_.pop_back();
|
||||||
|
}
|
||||||
|
item->Run(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetMaxConcurrency(size_t worker_count) const override {
|
||||||
|
base::MutexGuard guard(&items_mutex_);
|
||||||
|
return items_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(std::unique_ptr<ClearingItem> item) {
|
||||||
|
items_.push_back(std::move(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable base::Mutex items_mutex_;
|
||||||
|
std::vector<std::unique_ptr<ClearingItem>> items_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClearStringTableJobItem final : public ParallelClearingJob::ClearingItem {
|
||||||
|
public:
|
||||||
|
explicit ClearStringTableJobItem(Isolate* isolate) : isolate_(isolate) {}
|
||||||
|
|
||||||
|
void Run(JobDelegate* delegate) final {
|
||||||
|
if (isolate_->OwnsStringTable()) {
|
||||||
|
TRACE_GC1(isolate_->heap()->tracer(),
|
||||||
|
GCTracer::Scope::MC_CLEAR_STRING_TABLE,
|
||||||
|
delegate->IsJoiningThread() ? ThreadKind::kMain
|
||||||
|
: ThreadKind::kBackground);
|
||||||
|
// Prune the string table removing all strings only pointed to by the
|
||||||
|
// string table. Cannot use string_table() here because the string
|
||||||
|
// table is marked.
|
||||||
|
StringTable* string_table = isolate_->string_table();
|
||||||
|
InternalizedStringTableCleaner internalized_visitor(isolate_->heap());
|
||||||
|
string_table->DropOldData();
|
||||||
|
string_table->IterateElements(&internalized_visitor);
|
||||||
|
string_table->NotifyElementsRemoved(
|
||||||
|
internalized_visitor.PointersRemoved());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Isolate* const isolate_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void MarkCompactCollector::ClearNonLiveReferences() {
|
void MarkCompactCollector::ClearNonLiveReferences() {
|
||||||
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR);
|
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR);
|
||||||
|
|
||||||
if (isolate()->OwnsStringTable()) {
|
auto clearing_job = std::make_unique<ParallelClearingJob>();
|
||||||
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE);
|
clearing_job->Add(std::make_unique<ClearStringTableJobItem>(isolate()));
|
||||||
|
auto clearing_job_handle = V8::GetCurrentPlatform()->PostJob(
|
||||||
|
TaskPriority::kUserBlocking, std::move(clearing_job));
|
||||||
|
|
||||||
// Prune the string table removing all strings only pointed to by the
|
{
|
||||||
// string table. Cannot use string_table() here because the string
|
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_EXTERNAL_STRING_TABLE);
|
||||||
// table is marked.
|
ExternalStringTableCleaner external_visitor(heap());
|
||||||
StringTable* string_table = isolate()->string_table();
|
heap()->external_string_table_.IterateAll(&external_visitor);
|
||||||
InternalizedStringTableCleaner internalized_visitor(heap());
|
heap()->external_string_table_.CleanUpAll();
|
||||||
string_table->DropOldData();
|
|
||||||
string_table->IterateElements(&internalized_visitor);
|
|
||||||
string_table->NotifyElementsRemoved(internalized_visitor.PointersRemoved());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalStringTableCleaner external_visitor(heap());
|
|
||||||
heap()->external_string_table_.IterateAll(&external_visitor);
|
|
||||||
heap()->external_string_table_.CleanUpAll();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_FLUSHABLE_BYTECODE);
|
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_FLUSHABLE_BYTECODE);
|
||||||
// ProcessFlusheBaselineCandidates should be called after clearing bytecode
|
// `ProcessFlusheBaselineCandidates()` must be called after
|
||||||
// so that we flush any bytecode if needed so we could correctly set the
|
// `ProcessOldCodeCandidates()` so that we correctly set the code object on
|
||||||
// code object on the JSFunction.
|
// the JSFunction after flushing.
|
||||||
ProcessOldCodeCandidates();
|
ProcessOldCodeCandidates();
|
||||||
ProcessFlushedBaselineCandidates();
|
ProcessFlushedBaselineCandidates();
|
||||||
}
|
}
|
||||||
@ -2532,8 +2594,7 @@ void MarkCompactCollector::ClearNonLiveReferences() {
|
|||||||
{
|
{
|
||||||
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_LISTS);
|
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_LISTS);
|
||||||
// Process the weak references.
|
// Process the weak references.
|
||||||
MarkCompactWeakObjectRetainer mark_compact_object_retainer(
|
MarkCompactWeakObjectRetainer mark_compact_object_retainer(marking_state());
|
||||||
non_atomic_marking_state());
|
|
||||||
heap()->ProcessAllWeakReferences(&mark_compact_object_retainer);
|
heap()->ProcessAllWeakReferences(&mark_compact_object_retainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2562,6 +2623,11 @@ void MarkCompactCollector::ClearNonLiveReferences() {
|
|||||||
}
|
}
|
||||||
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
|
#endif // V8_SANDBOXED_EXTERNAL_POINTERS
|
||||||
|
|
||||||
|
{
|
||||||
|
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_JOIN_JOB);
|
||||||
|
clearing_job_handle->Join();
|
||||||
|
}
|
||||||
|
|
||||||
DCHECK(weak_objects_.transition_arrays.IsEmpty());
|
DCHECK(weak_objects_.transition_arrays.IsEmpty());
|
||||||
DCHECK(weak_objects_.weak_references.IsEmpty());
|
DCHECK(weak_objects_.weak_references.IsEmpty());
|
||||||
DCHECK(weak_objects_.weak_objects_in_code.IsEmpty());
|
DCHECK(weak_objects_.weak_objects_in_code.IsEmpty());
|
||||||
@ -2676,8 +2742,8 @@ void MarkCompactCollector::FlushBytecodeFromSFI(
|
|||||||
|
|
||||||
// Mark the uncompiled data as black, and ensure all fields have already been
|
// Mark the uncompiled data as black, and ensure all fields have already been
|
||||||
// marked.
|
// marked.
|
||||||
DCHECK(non_atomic_marking_state()->IsBlackOrGrey(inferred_name));
|
DCHECK(marking_state()->IsBlackOrGrey(inferred_name));
|
||||||
non_atomic_marking_state()->WhiteToBlack(uncompiled_data);
|
marking_state()->WhiteToBlack(uncompiled_data);
|
||||||
|
|
||||||
// Use the raw function data setter to avoid validity checks, since we're
|
// Use the raw function data setter to avoid validity checks, since we're
|
||||||
// performing the unusual task of decompiling.
|
// performing the unusual task of decompiling.
|
||||||
|
@ -535,8 +535,10 @@
|
|||||||
F(MARK_COMPACTOR) \
|
F(MARK_COMPACTOR) \
|
||||||
TOP_MC_SCOPES(F) \
|
TOP_MC_SCOPES(F) \
|
||||||
F(MC_CLEAR_DEPENDENT_CODE) \
|
F(MC_CLEAR_DEPENDENT_CODE) \
|
||||||
|
F(MC_CLEAR_EXTERNAL_STRING_TABLE) \
|
||||||
F(MC_CLEAR_FLUSHABLE_BYTECODE) \
|
F(MC_CLEAR_FLUSHABLE_BYTECODE) \
|
||||||
F(MC_CLEAR_FLUSHED_JS_FUNCTIONS) \
|
F(MC_CLEAR_FLUSHED_JS_FUNCTIONS) \
|
||||||
|
F(MC_CLEAR_JOIN_JOB) \
|
||||||
F(MC_CLEAR_MAPS) \
|
F(MC_CLEAR_MAPS) \
|
||||||
F(MC_CLEAR_SLOTS_BUFFER) \
|
F(MC_CLEAR_SLOTS_BUFFER) \
|
||||||
F(MC_CLEAR_STRING_TABLE) \
|
F(MC_CLEAR_STRING_TABLE) \
|
||||||
|
Loading…
Reference in New Issue
Block a user