Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp

Issue 2625093002: [wrapper-tracing] Add heap snapshot generator infrastructure (Closed)
Patch Set: Rework and address comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 #include "core/html/imports/HTMLImportsController.h" 44 #include "core/html/imports/HTMLImportsController.h"
45 #include "core/inspector/InspectorTraceEvents.h" 45 #include "core/inspector/InspectorTraceEvents.h"
46 #include "platform/Histogram.h" 46 #include "platform/Histogram.h"
47 #include "platform/RuntimeEnabledFeatures.h" 47 #include "platform/RuntimeEnabledFeatures.h"
48 #include "platform/instrumentation/tracing/TraceEvent.h" 48 #include "platform/instrumentation/tracing/TraceEvent.h"
49 #include "public/platform/BlameContext.h" 49 #include "public/platform/BlameContext.h"
50 #include "public/platform/Platform.h" 50 #include "public/platform/Platform.h"
51 #include "wtf/Vector.h" 51 #include "wtf/Vector.h"
52 #include "wtf/allocator/Partitions.h" 52 #include "wtf/allocator/Partitions.h"
53 #include <algorithm> 53 #include <algorithm>
54 #include <unordered_map>
55 #include <unordered_set>
54 56
55 namespace blink { 57 namespace blink {
56 58
57 // FIXME: This should use opaque GC roots. 59 // FIXME: This should use opaque GC roots.
58 static void addReferencesForNodeWithEventListeners( 60 static void addReferencesForNodeWithEventListeners(
59 v8::Isolate* isolate, 61 v8::Isolate* isolate,
60 Node* node, 62 Node* node,
61 const v8::Persistent<v8::Object>& wrapper) { 63 const v8::Persistent<v8::Object>& wrapper) {
62 ASSERT(node->hasEventListeners()); 64 ASSERT(node->hasEventListeners());
63 65
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); 143 v8::Persistent<v8::Object>::Cast(*value).MarkActive();
142 return; 144 return;
143 } 145 }
144 } 146 }
145 } 147 }
146 148
147 private: 149 private:
148 v8::Isolate* m_isolate; 150 v8::Isolate* m_isolate;
149 }; 151 };
150 152
153 class HeapSnaphotWrapperVisitor : public ScriptWrappableVisitor,
154 public v8::PersistentHandleVisitor {
155 public:
156 explicit HeapSnaphotWrapperVisitor(v8::Isolate* isolate)
157 : ScriptWrappableVisitor(isolate),
158 m_currentParent(nullptr),
159 m_onlyTraceSingleLevel(false),
160 m_firstTracedScriptWrappable(false) {
161 m_nodesRequiringTracing.clear();
162 }
163
164 void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
165 uint16_t classId) override {
166 if (classId != WrapperTypeInfo::NodeClassId)
167 return;
168
169 DCHECK(!value->IsIndependent());
170 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
171 m_isolate, v8::Persistent<v8::Object>::Cast(*value));
172 DCHECK(V8Node::hasInstance(wrapper, m_isolate));
173 Node* node = V8Node::toImpl(wrapper);
174 Node* root = V8GCController::opaqueRootForGC(m_isolate, node);
175 m_nodesRequiringTracing[root].push_back(node);
haraken 2017/01/16 02:46:56 Why don't you need to push Nodes that are found du
Michael Lippautz 2017/01/16 10:45:06 VisitPersistentHandle visits all persistent handle
haraken 2017/01/16 12:48:13 What happens if there is a pending activity on a D
Michael Lippautz 2017/01/16 13:15:38 Then tracePendingActivities will catch it.
176 }
177
178 // Trace through the blink heap to find all V8 wrappers reachable from
179 // ActiveScriptWrappables. Also collect retainer edges on the way.
180 void tracePendingActivities() {
181 CHECK(m_tempFoundV8Wrappers.empty());
182 m_currentParent = nullptr;
183
184 TracePrologue();
185 ActiveScriptWrappableBase::traceActiveScriptWrappables(m_isolate, this);
186 AdvanceTracing(
187 0,
188 v8::EmbedderHeapTracer::AdvanceTracingActions(
189 v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
190 // Abort instead of Epilogue as we want to finish synchronously.
191 AbortTracing();
haraken 2017/01/16 02:46:56 What's a difference between AbortTracing and Epilo
Michael Lippautz 2017/01/16 10:45:06 Since we finished the line before with FORE_COMPLE
haraken 2017/01/16 12:48:12 Yeah, that looks tidier. (You can address it in a
Michael Lippautz 2017/01/16 13:15:38 Acknowledged.
192
193 m_groups.push_back(
194 std::make_pair(new SuspendableObjectsInfo(m_tempFoundV8Wrappers.size()),
195 std::move(m_tempFoundV8Wrappers)));
196 }
197
198 // Trace through the blink heap to find all V8 wrappers reachable from
199 // the nodes that require tracing. Also collect retainer edges on the way.
200 void traceNodesThatRequireTracing() {
haraken 2017/01/16 02:46:56 I'm not sure why we need the complexity of traceNo
Michael Lippautz 2017/01/16 10:45:06 We cannot do that, as we need a mapping from nodes
201 for (auto& groupPair : m_nodesRequiringTracing) {
202 v8::HeapProfiler::RetainerChildren groupChildren;
203 for (auto& node : groupPair.second) {
204 auto wrappers = findV8WrappersDirectlyReachableFrom(node);
205 groupChildren.insert(wrappers.begin(), wrappers.end());
206 }
207 m_groups.push_back(std::make_pair(new RetainedDOMInfo(groupPair.first),
208 std::move(groupChildren)));
209 }
210 }
211
212 v8::HeapProfiler::RetainerEdges edges() { return std::move(m_edges); }
213 v8::HeapProfiler::RetainerGroups groups() { return std::move(m_groups); }
214
215 void markWrapper(const v8::PersistentBase<v8::Value>* value) const override {
216 if (!m_tracingInProgress)
haraken 2017/01/16 02:46:56 Can this happen?
Michael Lippautz 2017/01/16 10:45:06 Removed as it cannot happen. This was copied over
217 return;
218 if (m_currentParent && m_currentParent != value)
219 m_edges.push_back(std::make_pair(m_currentParent, value));
220 m_tempFoundV8Wrappers.insert(value);
221 }
222
223 void dispatchTraceWrappers(const TraceWrapperBase* traceable) const override {
224 if (!m_onlyTraceSingleLevel || !traceable->isScriptWrappable() ||
225 m_firstTracedScriptWrappable) {
226 m_firstTracedScriptWrappable = false;
227 traceable->traceWrappers(this);
228 }
haraken 2017/01/16 02:46:56 Don't we need to reset m_firstTracedScriptWrappabl
Michael Lippautz 2017/01/16 10:45:06 Yes, that's the intention. It should find wrappers
haraken 2017/01/16 12:48:13 But what happens if there are multiple ScriptWrapp
Michael Lippautz 2017/01/16 13:15:38 They are traced and we insert edges from the v8 wr
haraken 2017/01/17 00:31:25 Imagine the following object graph: Node --> Tr
Michael Lippautz 2017/01/17 09:15:32 Works, and here is why :) My assumptions: - Node
haraken 2017/01/17 09:22:41 Ah, I was missing this point.
229 }
230
231 private:
232 v8::HeapProfiler::RetainerChildren findV8WrappersDirectlyReachableFrom(
233 Node* traceable) {
234 CHECK(m_tempFoundV8Wrappers.empty());
235 WTF::AutoReset<bool>(&m_onlyTraceSingleLevel, true);
236 m_firstTracedScriptWrappable = true;
haraken 2017/01/16 02:46:56 Maybe should we flip true/false? Initially the fi
Michael Lippautz 2017/01/16 10:45:06 Done.
237 m_currentParent =
238 &v8::Persistent<v8::Value>::Cast(*traceable->rawMainWorldWrapper());
239
240 TracePrologue();
241 traceable->wrapperTypeInfo()->traceWrappers(this, traceable);
242 AdvanceTracing(
243 0,
244 v8::EmbedderHeapTracer::AdvanceTracingActions(
245 v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
246 // Abort instead of Epilogue as we want to finish synchronously.
247 AbortTracing();
248
249 return std::move(m_tempFoundV8Wrappers);
250 }
251
252 // Input obtained from |VisitPersistentHandle|.
253 std::unordered_map<Node*, std::vector<Node*>> m_nodesRequiringTracing;
254
255 // Temporaries used for tracing a single Node.
256 const v8::PersistentBase<v8::Value>* m_currentParent;
257 bool m_onlyTraceSingleLevel;
258 mutable bool m_firstTracedScriptWrappable;
259 mutable v8::HeapProfiler::RetainerChildren m_tempFoundV8Wrappers;
haraken 2017/01/16 02:46:56 m_tempFoundV8Wrappers => m_foundV8Wrappers
Michael Lippautz 2017/01/16 10:45:06 Done.
260
261 // Out variables
262 mutable v8::HeapProfiler::RetainerEdges m_edges;
263 mutable v8::HeapProfiler::RetainerGroups m_groups;
264 };
265
266 // The function |getRetainerInfos| processing all handles on the blink heap,
267 // logically grouping together DOM trees (attached and detached) and pending
268 // activities, while at the same time finding parent to child relationships
269 // for non-Node wrappers. Since we are processing *all* handles there is no
270 // way we miss out on a handle. V8 will figure out the liveness information
271 // for the provided information itself.
272 v8::HeapProfiler::RetainerInfos V8GCController::getRetainerInfos(
273 v8::Isolate* isolate) {
274 HeapSnaphotWrapperVisitor tracer(isolate);
haraken 2017/01/16 02:46:56 I guess we should use: std::unique_ptr<HeapSnap
Michael Lippautz 2017/01/16 10:45:06 Done.
275 V8PerIsolateData::TemporaryScriptWrappableVisitorScope scope(isolate,
276 &tracer);
277
278 // Collect which handles need to be processed.
279 isolate->VisitHandlesWithClassIds(&tracer);
haraken 2017/01/16 02:46:56 Nit: I'd prefer writing this as tracer->traceV8Roo
Michael Lippautz 2017/01/16 10:51:01 Done: collectV8Roots.
280
281 tracer.tracePendingActivities();
282 tracer.traceNodesThatRequireTracing();
haraken 2017/01/16 02:46:56 Nit: tracer->traceBlinkRoots().
Michael Lippautz 2017/01/16 10:51:01 This is now traceV8Roots, as it traces exactly wha
283
284 return v8::HeapProfiler::RetainerInfos{tracer.groups(), tracer.edges()};
285 }
286
151 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor { 287 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
152 public: 288 public:
153 explicit MajorGCWrapperVisitor(v8::Isolate* isolate, 289 explicit MajorGCWrapperVisitor(v8::Isolate* isolate,
154 bool constructRetainedObjectInfos) 290 bool constructRetainedObjectInfos)
155 : m_isolate(isolate), 291 : m_isolate(isolate),
156 m_domObjectsWithPendingActivity(0), 292 m_domObjectsWithPendingActivity(0),
157 m_liveRootGroupIdSet(false), 293 m_liveRootGroupIdSet(false),
158 m_constructRetainedObjectInfos(constructRetainedObjectInfos) {} 294 m_constructRetainedObjectInfos(constructRetainedObjectInfos) {}
159 295
160 void VisitPersistentHandle(v8::Persistent<v8::Value>* value, 296 void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 double startTime = WTF::currentTimeMS(); 680 double startTime = WTF::currentTimeMS();
545 v8::HandleScope scope(isolate); 681 v8::HandleScope scope(isolate);
546 PendingActivityVisitor visitor(isolate, executionContext); 682 PendingActivityVisitor visitor(isolate, executionContext);
547 toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor); 683 toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor);
548 scanPendingActivityHistogram.count( 684 scanPendingActivityHistogram.count(
549 static_cast<int>(WTF::currentTimeMS() - startTime)); 685 static_cast<int>(WTF::currentTimeMS() - startTime));
550 return visitor.pendingActivityFound(); 686 return visitor.pendingActivityFound();
551 } 687 }
552 688
553 } // namespace blink 689 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698