| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MarkingVisitor_h | 5 #ifndef MarkingVisitor_h |
| 6 #define MarkingVisitor_h | 6 #define MarkingVisitor_h |
| 7 | 7 |
| 8 #include "platform/heap/MarkingVisitorImpl.h" | 8 #include "platform/heap/MarkingVisitorImpl.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| 11 | 11 |
| 12 template <Visitor::MarkingMode Mode> | 12 template <Visitor::MarkingMode Mode> |
| 13 class MarkingVisitor final : public Visitor, public MarkingVisitorImpl<MarkingVi
sitor<Mode>> { | 13 class MarkingVisitor final : public Visitor, public MarkingVisitorImpl<MarkingVi
sitor<Mode>> { |
| 14 public: | 14 public: |
| 15 using Impl = MarkingVisitorImpl<MarkingVisitor<Mode>>; | 15 using Impl = MarkingVisitorImpl<MarkingVisitor<Mode>>; |
| 16 friend class MarkingVisitorImpl<MarkingVisitor<Mode>>; | 16 friend class MarkingVisitorImpl<MarkingVisitor<Mode>>; |
| 17 | 17 |
| 18 #if ENABLE(GC_PROFILING) | |
| 19 using LiveObjectSet = HashSet<uintptr_t>; | |
| 20 using LiveObjectMap = HashMap<String, LiveObjectSet>; | |
| 21 using ObjectGraph = HashMap<uintptr_t, std::pair<uintptr_t, String>>; | |
| 22 #endif | |
| 23 | |
| 24 MarkingVisitor() | 18 MarkingVisitor() |
| 25 : Visitor(Mode) | 19 : Visitor(Mode) |
| 26 { | 20 { |
| 27 } | 21 } |
| 28 | 22 |
| 29 virtual void markHeader(HeapObjectHeader* header, TraceCallback callback) ov
erride | 23 virtual void markHeader(HeapObjectHeader* header, TraceCallback callback) ov
erride |
| 30 { | 24 { |
| 31 Impl::markHeader(header, header->payload(), callback); | 25 Impl::markHeader(header, header->payload(), callback); |
| 32 } | 26 } |
| 33 | 27 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 56 { | 50 { |
| 57 return Impl::weakTableRegistered(closure); | 51 return Impl::weakTableRegistered(closure); |
| 58 } | 52 } |
| 59 #endif | 53 #endif |
| 60 | 54 |
| 61 virtual bool ensureMarked(const void* objectPointer) override | 55 virtual bool ensureMarked(const void* objectPointer) override |
| 62 { | 56 { |
| 63 return Impl::ensureMarked(objectPointer); | 57 return Impl::ensureMarked(objectPointer); |
| 64 } | 58 } |
| 65 | 59 |
| 66 #if ENABLE(GC_PROFILING) | |
| 67 virtual void recordObjectGraphEdge(const void* objectPointer) override | |
| 68 { | |
| 69 MutexLocker locker(objectGraphMutex()); | |
| 70 String className(classOf(objectPointer)); | |
| 71 { | |
| 72 LiveObjectMap::AddResult result = currentlyLive().add(className, Liv
eObjectSet()); | |
| 73 result.storedValue->value.add(reinterpret_cast<uintptr_t>(objectPoin
ter)); | |
| 74 } | |
| 75 ObjectGraph::AddResult result = objectGraph().add(reinterpret_cast<uintp
tr_t>(objectPointer), std::make_pair(reinterpret_cast<uintptr_t>(m_hostObject),
m_hostName)); | |
| 76 ASSERT(result.isNewEntry); | |
| 77 // fprintf(stderr, "%s[%p] -> %s[%p]\n", m_hostName.ascii().data(), m_ho
stObject, className.ascii().data(), objectPointer); | |
| 78 } | |
| 79 | |
| 80 void reportStats() | |
| 81 { | |
| 82 fprintf(stderr, "\n---------- AFTER MARKING -------------------\n"); | |
| 83 for (LiveObjectMap::iterator it = currentlyLive().begin(), end = current
lyLive().end(); it != end; ++it) { | |
| 84 fprintf(stderr, "%s %u", it->key.ascii().data(), it->value.size()); | |
| 85 | |
| 86 if (it->key == "blink::Document") | |
| 87 reportStillAlive(it->value, previouslyLive().get(it->key)); | |
| 88 | |
| 89 fprintf(stderr, "\n"); | |
| 90 } | |
| 91 | |
| 92 previouslyLive().swap(currentlyLive()); | |
| 93 currentlyLive().clear(); | |
| 94 | |
| 95 for (uintptr_t object : objectsToFindPath()) { | |
| 96 dumpPathToObjectFromObjectGraph(objectGraph(), object); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 static void reportStillAlive(LiveObjectSet current, LiveObjectSet previous) | |
| 101 { | |
| 102 int count = 0; | |
| 103 | |
| 104 fprintf(stderr, " [previously %u]", previous.size()); | |
| 105 for (uintptr_t object : current) { | |
| 106 if (previous.find(object) == previous.end()) | |
| 107 continue; | |
| 108 count++; | |
| 109 } | |
| 110 | |
| 111 if (!count) | |
| 112 return; | |
| 113 | |
| 114 fprintf(stderr, " {survived 2GCs %d: ", count); | |
| 115 for (uintptr_t object : current) { | |
| 116 if (previous.find(object) == previous.end()) | |
| 117 continue; | |
| 118 fprintf(stderr, "%ld", object); | |
| 119 if (--count) | |
| 120 fprintf(stderr, ", "); | |
| 121 } | |
| 122 ASSERT(!count); | |
| 123 fprintf(stderr, "}"); | |
| 124 } | |
| 125 | |
| 126 static void dumpPathToObjectFromObjectGraph(const ObjectGraph& graph, uintpt
r_t target) | |
| 127 { | |
| 128 ObjectGraph::const_iterator it = graph.find(target); | |
| 129 if (it == graph.end()) | |
| 130 return; | |
| 131 fprintf(stderr, "Path to %lx of %s\n", target, classOf(reinterpret_cast<
const void*>(target)).ascii().data()); | |
| 132 while (it != graph.end()) { | |
| 133 fprintf(stderr, "<- %lx of %s\n", it->value.first, it->value.second.
utf8().data()); | |
| 134 it = graph.find(it->value.first); | |
| 135 } | |
| 136 fprintf(stderr, "\n"); | |
| 137 } | |
| 138 | |
| 139 static void dumpPathToObjectOnNextGC(void* p) | |
| 140 { | |
| 141 objectsToFindPath().add(reinterpret_cast<uintptr_t>(p)); | |
| 142 } | |
| 143 | |
| 144 static Mutex& objectGraphMutex() | |
| 145 { | |
| 146 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); | |
| 147 return mutex; | |
| 148 } | |
| 149 | |
| 150 static LiveObjectMap& previouslyLive() | |
| 151 { | |
| 152 DEFINE_STATIC_LOCAL(LiveObjectMap, map, ()); | |
| 153 return map; | |
| 154 } | |
| 155 | |
| 156 static LiveObjectMap& currentlyLive() | |
| 157 { | |
| 158 DEFINE_STATIC_LOCAL(LiveObjectMap, map, ()); | |
| 159 return map; | |
| 160 } | |
| 161 | |
| 162 static ObjectGraph& objectGraph() | |
| 163 { | |
| 164 DEFINE_STATIC_LOCAL(ObjectGraph, graph, ()); | |
| 165 return graph; | |
| 166 } | |
| 167 | |
| 168 static HashSet<uintptr_t>& objectsToFindPath() | |
| 169 { | |
| 170 DEFINE_STATIC_LOCAL(HashSet<uintptr_t>, set, ()); | |
| 171 return set; | |
| 172 } | |
| 173 #endif | |
| 174 | |
| 175 protected: | 60 protected: |
| 176 virtual void registerWeakCellWithCallback(void** cell, WeakCallback callback
) override | 61 virtual void registerWeakCellWithCallback(void** cell, WeakCallback callback
) override |
| 177 { | 62 { |
| 178 Impl::registerWeakCellWithCallback(cell, callback); | 63 Impl::registerWeakCellWithCallback(cell, callback); |
| 179 } | 64 } |
| 180 | 65 |
| 181 inline bool shouldMarkObject(const void* objectPointer) | 66 inline bool shouldMarkObject(const void* objectPointer) |
| 182 { | 67 { |
| 183 if (Mode != ThreadLocalMarking) | 68 if (Mode != ThreadLocalMarking) |
| 184 return true; | 69 return true; |
| 185 | 70 |
| 186 BasePage* page = pageFromObject(objectPointer); | 71 BasePage* page = pageFromObject(objectPointer); |
| 187 ASSERT(!page->orphaned()); | 72 ASSERT(!page->orphaned()); |
| 188 // When doing a thread local GC, the marker checks if | 73 // When doing a thread local GC, the marker checks if |
| 189 // the object resides in another thread's heap. If it | 74 // the object resides in another thread's heap. If it |
| 190 // does, the object should not be marked & traced. | 75 // does, the object should not be marked & traced. |
| 191 return page->terminating(); | 76 return page->terminating(); |
| 192 } | 77 } |
| 193 }; | 78 }; |
| 194 | 79 |
| 195 } // namespace blink | 80 } // namespace blink |
| 196 | 81 |
| 197 #endif | 82 #endif |
| OLD | NEW |