1// Copyright 2022 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/heap/reference-summarizer.h" 6 7#include "src/heap/mark-compact-inl.h" 8#include "src/heap/marking-visitor-inl.h" 9#include "src/objects/embedder-data-array-inl.h" 10#include "src/objects/js-array-buffer-inl.h" 11 12namespace v8 { 13namespace internal { 14 15namespace { 16 17// A class which acts as a MarkingState but does not actually update any marking 18// bits. It reports all objects as white and all transitions as successful. It 19// also tracks which objects are retained by the primary object according to the 20// marking visitor. 21class ReferenceSummarizerMarkingState final { 22 public: 23 // Declares that this marking state is collecting retainers, so the marking 24 // visitor must fully visit each object and can't update on-heap state. 25 static constexpr bool kCollectRetainers = true; 26 27 explicit ReferenceSummarizerMarkingState(HeapObject object) 28 : primary_object_(object), 29 local_marking_worklists_(&marking_worklists_), 30 local_weak_objects_(&weak_objects_) {} 31 32 ~ReferenceSummarizerMarkingState() { 33 // Clean up temporary state. 34 local_weak_objects_.Publish(); 35 weak_objects_.Clear(); 36 local_marking_worklists_.Publish(); 37 marking_worklists_.Clear(); 38 } 39 40 // Retrieves the references that were collected by this marker. This operation 41 // transfers ownership of the set, so calling it again would yield an empty 42 // result. 43 ReferenceSummary DestructivelyRetrieveReferences() { 44 ReferenceSummary tmp = std::move(references_); 45 references_.Clear(); 46 return tmp; 47 } 48 49 // Standard marking visitor functions: 50 51 bool IsWhite(HeapObject obj) const { return true; } 52 53 bool IsBlackOrGrey(HeapObject obj) const { return false; } 54 55 bool WhiteToGrey(HeapObject obj) { return true; } 56 57 bool GreyToBlack(HeapObject obj) { return true; } 58 59 // Adds a retaining relationship found by the marking visitor. 60 void AddStrongReferenceForReferenceSummarizer(HeapObject host, 61 HeapObject obj) { 62 AddReference(host, obj, references_.strong_references()); 63 } 64 65 // Adds a non-retaining weak reference found by the marking visitor. The value 66 // in an ephemeron hash table entry is also included here, since it is not 67 // known to be strong without further information about the key. 68 void AddWeakReferenceForReferenceSummarizer(HeapObject host, HeapObject obj) { 69 AddReference(host, obj, references_.weak_references()); 70 } 71 72 // Other member functions, not part of the marking visitor contract: 73 74 MarkingWorklists::Local* local_marking_worklists() { 75 return &local_marking_worklists_; 76 } 77 WeakObjects::Local* local_weak_objects() { return &local_weak_objects_; } 78 79 private: 80 void AddReference( 81 HeapObject host, HeapObject obj, 82 std::unordered_set<HeapObject, Object::Hasher>& references) { 83 // It's possible that the marking visitor handles multiple objects at once, 84 // such as a Map and its DescriptorArray, but we're only interested in 85 // references from the primary object. 86 if (host == primary_object_) { 87 references.insert(obj); 88 } 89 } 90 91 ReferenceSummary references_; 92 HeapObject primary_object_; 93 MarkingWorklists marking_worklists_; 94 MarkingWorklists::Local local_marking_worklists_; 95 WeakObjects weak_objects_; 96 WeakObjects::Local local_weak_objects_; 97}; 98 99} // namespace 100 101ReferenceSummary ReferenceSummary::SummarizeReferencesFrom(Heap* heap, 102 HeapObject obj) { 103 ReferenceSummarizerMarkingState marking_state(obj); 104 105 MainMarkingVisitor<ReferenceSummarizerMarkingState> visitor( 106 &marking_state, marking_state.local_marking_worklists(), 107 marking_state.local_weak_objects(), heap, 0 /*mark_compact_epoch*/, 108 {} /*code_flush_mode*/, false /*embedder_tracing_enabled*/, 109 true /*should_keep_ages_unchanged*/); 110 visitor.Visit(obj.map(heap->isolate()), obj); 111 112 return marking_state.DestructivelyRetrieveReferences(); 113} 114 115} // namespace internal 116} // namespace v8 117