Commit 08b8e0ff authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

Clarify roots iteration

Change Heap::IterateStrongRoots to never iterate the read-only roots. In
doing so remove VISIT_ALL_BUT_READ_ONLY and
VISIT_ONLY_STRONG_FOR_SERIALIZATION. All such uses should now use
VISIT_ALL and VISIT_ONLY_STRONG. Where ReadOnlyRoots iteration is
required, this adds ReadOnlyRoots(isolate)->Iterate() at the call site.

Add new begin, end, strong_mutable_roots_begin and
strong_mutable_roots_end methods to RootsTable and try and make the
existing uses a little more consistent.

Bug: v8:8191
Change-Id: Ie9d0f9e5186db418428e2fafd38432b0bd879daa
Reviewed-on: https://chromium-review.googlesource.com/c/1278500
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56672}
parent 6b0bdcdb
...@@ -14,8 +14,8 @@ RootIndexMap::RootIndexMap(Isolate* isolate) { ...@@ -14,8 +14,8 @@ RootIndexMap::RootIndexMap(Isolate* isolate) {
map_ = isolate->root_index_map(); map_ = isolate->root_index_map();
if (map_ != nullptr) return; if (map_ != nullptr) return;
map_ = new HeapObjectToIndexHashMap(); map_ = new HeapObjectToIndexHashMap();
for (RootIndex root_index = RootIndex::kFirstStrongRoot; for (RootIndex root_index = RootIndex::kFirstStrongOrReadOnlyRoot;
root_index <= RootIndex::kLastStrongRoot; ++root_index) { root_index <= RootIndex::kLastStrongOrReadOnlyRoot; ++root_index) {
Object* root = isolate->root(root_index); Object* root = isolate->root(root_index);
if (!root->IsHeapObject()) continue; if (!root->IsHeapObject()) continue;
// Omit root entries that can be written after initialization. They must // Omit root entries that can be written after initialization. They must
......
...@@ -623,13 +623,11 @@ enum Movability { kMovable, kImmovable }; ...@@ -623,13 +623,11 @@ enum Movability { kMovable, kImmovable };
enum VisitMode { enum VisitMode {
VISIT_ALL, VISIT_ALL,
VISIT_ALL_BUT_READ_ONLY,
VISIT_ALL_IN_MINOR_MC_MARK, VISIT_ALL_IN_MINOR_MC_MARK,
VISIT_ALL_IN_MINOR_MC_UPDATE, VISIT_ALL_IN_MINOR_MC_UPDATE,
VISIT_ALL_IN_SCAVENGE, VISIT_ALL_IN_SCAVENGE,
VISIT_ALL_IN_SWEEP_NEWSPACE, VISIT_ALL_IN_SWEEP_NEWSPACE,
VISIT_ONLY_STRONG, VISIT_ONLY_STRONG,
VISIT_ONLY_STRONG_FOR_SERIALIZATION,
VISIT_FOR_SERIALIZATION, VISIT_FOR_SERIALIZATION,
}; };
......
...@@ -2568,6 +2568,7 @@ FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object, ...@@ -2568,6 +2568,7 @@ FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
// Make sure the stack or other roots (e.g., Handles) don't contain pointers // Make sure the stack or other roots (e.g., Handles) don't contain pointers
// to the original FixedArray (which is now the filler object). // to the original FixedArray (which is now the filler object).
LeftTrimmerVerifierRootVisitor root_visitor(object); LeftTrimmerVerifierRootVisitor root_visitor(object);
ReadOnlyRoots(this).Iterate(&root_visitor);
IterateRoots(&root_visitor, VISIT_ALL); IterateRoots(&root_visitor, VISIT_ALL);
} }
#endif // ENABLE_SLOW_DCHECKS #endif // ENABLE_SLOW_DCHECKS
...@@ -3741,12 +3742,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -3741,12 +3742,8 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
const bool isMinorGC = mode == VISIT_ALL_IN_SCAVENGE || const bool isMinorGC = mode == VISIT_ALL_IN_SCAVENGE ||
mode == VISIT_ALL_IN_MINOR_MC_MARK || mode == VISIT_ALL_IN_MINOR_MC_MARK ||
mode == VISIT_ALL_IN_MINOR_MC_UPDATE; mode == VISIT_ALL_IN_MINOR_MC_UPDATE;
// Garbage collection can skip over the read-only roots. v->VisitRootPointers(Root::kStrongRootList, nullptr,
const bool isGC = mode != VISIT_ALL && mode != VISIT_FOR_SERIALIZATION && roots_table().strong_roots_begin(),
mode != VISIT_ONLY_STRONG_FOR_SERIALIZATION;
Object** start = isGC ? roots_table().read_only_roots_end()
: roots_table().strong_roots_begin();
v->VisitRootPointers(Root::kStrongRootList, nullptr, start,
roots_table().strong_roots_end()); roots_table().strong_roots_end());
v->Synchronize(VisitorSynchronization::kStrongRootList); v->Synchronize(VisitorSynchronization::kStrongRootList);
...@@ -3786,7 +3783,6 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -3786,7 +3783,6 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
// global handles need to be added manually. // global handles need to be added manually.
break; break;
case VISIT_ONLY_STRONG: case VISIT_ONLY_STRONG:
case VISIT_ONLY_STRONG_FOR_SERIALIZATION:
isolate_->global_handles()->IterateStrongRoots(v); isolate_->global_handles()->IterateStrongRoots(v);
break; break;
case VISIT_ALL_IN_SCAVENGE: case VISIT_ALL_IN_SCAVENGE:
...@@ -3798,7 +3794,6 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) { ...@@ -3798,7 +3794,6 @@ void Heap::IterateStrongRoots(RootVisitor* v, VisitMode mode) {
case VISIT_ALL_IN_MINOR_MC_UPDATE: case VISIT_ALL_IN_MINOR_MC_UPDATE:
// Global handles are processed manually by the minor MC. // Global handles are processed manually by the minor MC.
break; break;
case VISIT_ALL_BUT_READ_ONLY:
case VISIT_ALL_IN_SWEEP_NEWSPACE: case VISIT_ALL_IN_SWEEP_NEWSPACE:
case VISIT_ALL: case VISIT_ALL:
isolate_->global_handles()->IterateAllRoots(v); isolate_->global_handles()->IterateAllRoots(v);
...@@ -5025,7 +5020,7 @@ class UnreachableObjectsFilter : public HeapObjectsFilter { ...@@ -5025,7 +5020,7 @@ class UnreachableObjectsFilter : public HeapObjectsFilter {
void MarkReachableObjects() { void MarkReachableObjects() {
MarkingVisitor visitor(this); MarkingVisitor visitor(this);
heap_->IterateRoots(&visitor, VISIT_ALL_BUT_READ_ONLY); heap_->IterateRoots(&visitor, VISIT_ALL);
visitor.TransitiveClosure(); visitor.TransitiveClosure();
} }
......
...@@ -744,7 +744,14 @@ class Heap { ...@@ -744,7 +744,14 @@ class Heap {
// Iterators. ================================================================ // Iterators. ================================================================
// =========================================================================== // ===========================================================================
// None of these methods iterate over the read-only roots. To do this use
// ReadOnlyRoots::Iterate. Read-only root iteration is not necessary for
// garbage collection and is usually only performed as part of
// (de)serialization or heap verification.
// Iterates over the strong roots and the weak roots.
void IterateRoots(RootVisitor* v, VisitMode mode); void IterateRoots(RootVisitor* v, VisitMode mode);
// Iterates over the strong roots.
void IterateStrongRoots(RootVisitor* v, VisitMode mode); void IterateStrongRoots(RootVisitor* v, VisitMode mode);
// Iterates over entries in the smi roots list. Only interesting to the // Iterates over entries in the smi roots list. Only interesting to the
// serializer/deserializer, since GC does not care about smis. // serializer/deserializer, since GC does not care about smis.
......
...@@ -2231,8 +2231,8 @@ bool CanLeak(Object* obj, Isolate* isolate) { ...@@ -2231,8 +2231,8 @@ bool CanLeak(Object* obj, Isolate* isolate) {
if (obj->IsContext()) return true; if (obj->IsContext()) return true;
if (obj->IsMap()) { if (obj->IsMap()) {
Map* map = Map::cast(obj); Map* map = Map::cast(obj);
for (RootIndex root_index = RootIndex::kFirstStrongRoot; for (RootIndex root_index = RootIndex::kFirstStrongOrReadOnlyRoot;
root_index <= RootIndex::kLastStrongRoot; ++root_index) { root_index <= RootIndex::kLastStrongOrReadOnlyRoot; ++root_index) {
if (map == isolate->root(root_index)) return false; if (map == isolate->root(root_index)) return false;
} }
return true; return true;
......
...@@ -1427,7 +1427,8 @@ bool V8HeapExplorer::IterateAndExtractReferences( ...@@ -1427,7 +1427,8 @@ bool V8HeapExplorer::IterateAndExtractReferences(
// first. Otherwise a particular JSFunction object could set // first. Otherwise a particular JSFunction object could set
// its custom name to a generic builtin. // its custom name to a generic builtin.
RootsReferencesExtractor extractor(this); RootsReferencesExtractor extractor(this);
heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG_FOR_SERIALIZATION); ReadOnlyRoots(heap_).Iterate(&extractor);
heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
extractor.SetVisitingWeakRoots(); extractor.SetVisitingWeakRoots();
heap_->IterateWeakGlobalHandles(&extractor); heap_->IterateWeakGlobalHandles(&extractor);
...@@ -1676,8 +1677,8 @@ void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description, ...@@ -1676,8 +1677,8 @@ void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description,
const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) { const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) {
if (strong_gc_subroot_names_.empty()) { if (strong_gc_subroot_names_.empty()) {
Isolate* isolate = heap_->isolate(); Isolate* isolate = heap_->isolate();
for (RootIndex root_index = RootIndex::kFirstStrongRoot; for (RootIndex root_index = RootIndex::kFirstStrongOrReadOnlyRoot;
root_index <= RootIndex::kLastStrongRoot; ++root_index) { root_index <= RootIndex::kLastStrongOrReadOnlyRoot; ++root_index) {
const char* name = RootsTable::name(root_index); const char* name = RootsTable::name(root_index);
strong_gc_subroot_names_.emplace(isolate->root(root_index), name); strong_gc_subroot_names_.emplace(isolate->root(root_index), name);
} }
......
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/roots.h" #include "src/roots.h"
#include "src/elements-kind.h" #include "src/elements-kind.h"
#include "src/visitors.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -56,5 +58,12 @@ RootIndex RootsTable::RootIndexForEmptyFixedTypedArray( ...@@ -56,5 +58,12 @@ RootIndex RootsTable::RootIndexForEmptyFixedTypedArray(
} }
} }
void ReadOnlyRoots::Iterate(RootVisitor* visitor) {
visitor->VisitRootPointers(Root::kReadOnlyRootList, nullptr,
roots_table_.read_only_roots_begin(),
roots_table_.read_only_roots_end());
visitor->Synchronize(VisitorSynchronization::kReadOnlyRootList);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -23,6 +23,7 @@ class Isolate; ...@@ -23,6 +23,7 @@ class Isolate;
class Map; class Map;
class String; class String;
class Symbol; class Symbol;
class RootVisitor;
// Defines all the read-only roots in Heap. // Defines all the read-only roots in Heap.
#define STRONG_READ_ONLY_ROOT_LIST(V) \ #define STRONG_READ_ONLY_ROOT_LIST(V) \
...@@ -356,10 +357,6 @@ enum class RootIndex : uint16_t { ...@@ -356,10 +357,6 @@ enum class RootIndex : uint16_t {
kFirstRoot = 0, kFirstRoot = 0,
kLastRoot = kRootListLength - 1, kLastRoot = kRootListLength - 1,
// kStringTable is not a strong root.
kFirstStrongRoot = kFirstRoot,
kLastStrongRoot = kStringTable - 1,
#define ROOT(...) +1 #define ROOT(...) +1
kReadOnlyRootsCount = 0 READ_ONLY_ROOT_LIST(ROOT), kReadOnlyRootsCount = 0 READ_ONLY_ROOT_LIST(ROOT),
kImmortalImmovableRootsCount = kImmortalImmovableRootsCount =
...@@ -368,6 +365,16 @@ enum class RootIndex : uint16_t { ...@@ -368,6 +365,16 @@ enum class RootIndex : uint16_t {
kFirstReadOnlyRoot = kFirstRoot, kFirstReadOnlyRoot = kFirstRoot,
kLastReadOnlyRoot = kFirstReadOnlyRoot + kReadOnlyRootsCount - 1, kLastReadOnlyRoot = kFirstReadOnlyRoot + kReadOnlyRootsCount - 1,
// The strong roots visited by the garbage collector (not including read-only
// roots).
kFirstStrongRoot = kLastReadOnlyRoot + 1,
// (kStringTable is not a strong root).
kLastStrongRoot = kStringTable - 1,
// All of the strong roots plus the read-only roots.
kFirstStrongOrReadOnlyRoot = kFirstRoot,
kLastStrongOrReadOnlyRoot = kLastStrongRoot,
// All immortal immovable roots including read only ones. // All immortal immovable roots including read only ones.
kFirstImmortalImmovableRoot = kFirstReadOnlyRoot, kFirstImmortalImmovableRoot = kFirstReadOnlyRoot,
kLastImmortalImmovableRoot = kLastImmortalImmovableRoot =
...@@ -426,10 +433,30 @@ class RootsTable { ...@@ -426,10 +433,30 @@ class RootsTable {
} }
private: private:
Object** begin() {
return &roots_[static_cast<size_t>(RootIndex::kFirstRoot)];
}
Object** end() {
return &roots_[static_cast<size_t>(RootIndex::kLastRoot) + 1];
}
// Used for iterating over all of the read-only and mutable strong roots.
Object** strong_or_read_only_roots_begin() {
STATIC_ASSERT(static_cast<size_t>(RootIndex::kLastReadOnlyRoot) ==
static_cast<size_t>(RootIndex::kFirstStrongRoot) - 1);
return &roots_[static_cast<size_t>(RootIndex::kFirstStrongOrReadOnlyRoot)];
}
Object** strong_or_read_only_roots_end() {
return &roots_[static_cast<size_t>(RootIndex::kLastStrongOrReadOnlyRoot) +
1];
}
// The read-only, strong and Smi roots as defined by these accessors are all
// disjoint.
Object** read_only_roots_begin() { Object** read_only_roots_begin() {
return &roots_[static_cast<size_t>(RootIndex::kFirstReadOnlyRoot)]; return &roots_[static_cast<size_t>(RootIndex::kFirstReadOnlyRoot)];
} }
inline Object** read_only_roots_end() { Object** read_only_roots_end() {
return &roots_[static_cast<size_t>(RootIndex::kLastReadOnlyRoot) + 1]; return &roots_[static_cast<size_t>(RootIndex::kLastReadOnlyRoot) + 1];
} }
...@@ -460,6 +487,7 @@ class RootsTable { ...@@ -460,6 +487,7 @@ class RootsTable {
friend class Heap; friend class Heap;
friend class Factory; friend class Factory;
friend class ReadOnlyRoots; friend class ReadOnlyRoots;
friend class RootsSerializer;
}; };
class ReadOnlyRoots { class ReadOnlyRoots {
...@@ -478,8 +506,13 @@ class ReadOnlyRoots { ...@@ -478,8 +506,13 @@ class ReadOnlyRoots {
V8_INLINE Map* MapForFixedTypedArray(ElementsKind elements_kind); V8_INLINE Map* MapForFixedTypedArray(ElementsKind elements_kind);
V8_INLINE FixedTypedArrayBase* EmptyFixedTypedArrayForMap(const Map* map); V8_INLINE FixedTypedArrayBase* EmptyFixedTypedArrayForMap(const Map* map);
// Iterate over all the read-only roots. This is not necessary for garbage
// collection and is usually only performed as part of (de)serialization or
// heap verification.
void Iterate(RootVisitor* visitor);
private: private:
const RootsTable& roots_table_; RootsTable& roots_table_;
}; };
} // namespace internal } // namespace internal
......
...@@ -37,8 +37,8 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) { ...@@ -37,8 +37,8 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) {
{ {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
isolate->heap()->IterateSmiRoots(this); isolate->heap()->IterateSmiRoots(this);
isolate->heap()->IterateStrongRoots(this, ReadOnlyRoots(isolate).Iterate(this);
VISIT_ONLY_STRONG_FOR_SERIALIZATION); isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
isolate->heap()->RepairFreeListsAfterDeserialization(); isolate->heap()->RepairFreeListsAfterDeserialization();
isolate->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION); isolate->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION);
DeserializeDeferredObjects(); DeserializeDeferredObjects();
......
...@@ -117,6 +117,7 @@ void StartupSerializer::SerializeStrongReferences() { ...@@ -117,6 +117,7 @@ void StartupSerializer::SerializeStrongReferences() {
isolate->heap()->IterateSmiRoots(this); isolate->heap()->IterateSmiRoots(this);
isolate->heap()->SetStackLimits(); isolate->heap()->SetStackLimits();
// First visit immortal immovables to make sure they end up in the first page. // First visit immortal immovables to make sure they end up in the first page.
ReadOnlyRoots(isolate).Iterate(this);
isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION); isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION);
} }
......
...@@ -17,6 +17,7 @@ class Object; ...@@ -17,6 +17,7 @@ class Object;
#define ROOT_ID_LIST(V) \ #define ROOT_ID_LIST(V) \
V(kStringTable, "(Internalized strings)") \ V(kStringTable, "(Internalized strings)") \
V(kExternalStringsTable, "(External strings)") \ V(kExternalStringsTable, "(External strings)") \
V(kReadOnlyRootList, "(Read-only roots)") \
V(kStrongRootList, "(Strong roots)") \ V(kStrongRootList, "(Strong roots)") \
V(kSmiRootList, "(Smi roots)") \ V(kSmiRootList, "(Smi roots)") \
V(kBootstrapper, "(Bootstrapper)") \ V(kBootstrapper, "(Bootstrapper)") \
......
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