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

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: Addressed 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_firstTracedScriptWrappableTraced(false) {
haraken 2017/01/17 00:31:25 m_firstTracedScriptWrappableTraced => m_firstScrip
Michael Lippautz 2017/01/17 09:15:32 Done.
161 m_nodesRequiringTracing.clear();
haraken 2017/01/17 00:31:26 Remove this.
Michael Lippautz 2017/01/17 09:15:32 Whoops, done.
162 }
163
164 // Collect interesting V8 roots for the heap snapshot. Currently these are
165 // DOM nodes.
166 void collectV8Roots() { m_isolate->VisitHandlesWithClassIds(this); }
167
168 void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
169 uint16_t classId) override {
170 if (classId != WrapperTypeInfo::NodeClassId)
171 return;
172
173 DCHECK(!value->IsIndependent());
174 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
175 m_isolate, v8::Persistent<v8::Object>::Cast(*value));
176 DCHECK(V8Node::hasInstance(wrapper, m_isolate));
177 Node* node = V8Node::toImpl(wrapper);
178 Node* root = V8GCController::opaqueRootForGC(m_isolate, node);
179 m_nodesRequiringTracing[root].push_back(node);
180 }
181
182 // Trace through the blink heap to find all V8 wrappers reachable from
183 // ActiveScriptWrappables. Also collect retainer edges on the way.
184 void tracePendingActivities() {
185 CHECK(m_foundV8Wrappers.empty());
186 m_currentParent = nullptr;
187
188 TracePrologue();
189 ActiveScriptWrappableBase::traceActiveScriptWrappables(m_isolate, this);
190 AdvanceTracing(
191 0,
192 v8::EmbedderHeapTracer::AdvanceTracingActions(
193 v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
194 // Abort instead of Epilogue as we want to finish synchronously.
195 AbortTracing();
196
197 m_groups.push_back(
198 std::make_pair(new SuspendableObjectsInfo(m_foundV8Wrappers.size()),
199 std::move(m_foundV8Wrappers)));
200 }
201
202 // Trace through the blink heap to find all V8 wrappers reachable from any
203 // of the collected roots. Also collect retainer edges on the way.
204 void traceV8Roots() {
205 for (auto& groupPair : m_nodesRequiringTracing) {
206 v8::HeapProfiler::RetainerChildren groupChildren;
207 for (auto& node : groupPair.second) {
208 auto wrappers = findV8WrappersDirectlyReachableFrom(node);
209 groupChildren.insert(wrappers.begin(), wrappers.end());
210 }
211 m_groups.push_back(std::make_pair(new RetainedDOMInfo(groupPair.first),
212 std::move(groupChildren)));
213 }
214 }
215
216 v8::HeapProfiler::RetainerEdges edges() { return std::move(m_edges); }
217 v8::HeapProfiler::RetainerGroups groups() { return std::move(m_groups); }
218
219 void markWrapper(const v8::PersistentBase<v8::Value>* value) const override {
220 if (m_currentParent && m_currentParent != value)
221 m_edges.push_back(std::make_pair(m_currentParent, value));
222 m_foundV8Wrappers.insert(value);
223 }
224
225 void dispatchTraceWrappers(const TraceWrapperBase* traceable) const override {
226 if (!m_onlyTraceSingleLevel || !traceable->isScriptWrappable() ||
227 !m_firstTracedScriptWrappableTraced) {
228 m_firstTracedScriptWrappableTraced = true;
229 traceable->traceWrappers(this);
230 }
231 }
232
233 private:
234 v8::HeapProfiler::RetainerChildren findV8WrappersDirectlyReachableFrom(
235 Node* traceable) {
236 CHECK(m_foundV8Wrappers.empty());
237 WTF::AutoReset<bool>(&m_onlyTraceSingleLevel, true);
238 m_firstTracedScriptWrappableTraced = false;
239 m_currentParent =
240 &v8::Persistent<v8::Value>::Cast(*traceable->rawMainWorldWrapper());
241
242 TracePrologue();
243 traceable->wrapperTypeInfo()->traceWrappers(this, traceable);
244 AdvanceTracing(
245 0,
246 v8::EmbedderHeapTracer::AdvanceTracingActions(
247 v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
248 // Abort instead of Epilogue as we want to finish synchronously.
249 AbortTracing();
250
251 return std::move(m_foundV8Wrappers);
252 }
253
254 // Input obtained from |VisitPersistentHandle|.
255 std::unordered_map<Node*, std::vector<Node*>> m_nodesRequiringTracing;
256
257 // Temporaries used for tracing a single Node.
258 const v8::PersistentBase<v8::Value>* m_currentParent;
259 bool m_onlyTraceSingleLevel;
260 mutable bool m_firstTracedScriptWrappableTraced;
261 mutable v8::HeapProfiler::RetainerChildren m_foundV8Wrappers;
262
263 // Out variables
264 mutable v8::HeapProfiler::RetainerEdges m_edges;
265 mutable v8::HeapProfiler::RetainerGroups m_groups;
266 };
267
268 // The function |getRetainerInfos| processing all handles on the blink heap,
269 // logically grouping together DOM trees (attached and detached) and pending
270 // activities, while at the same time finding parent to child relationships
271 // for non-Node wrappers. Since we are processing *all* handles there is no
272 // way we miss out on a handle. V8 will figure out the liveness information
273 // for the provided information itself.
274 v8::HeapProfiler::RetainerInfos V8GCController::getRetainerInfos(
275 v8::Isolate* isolate) {
276 std::unique_ptr<HeapSnaphotWrapperVisitor> tracer(
277 new HeapSnaphotWrapperVisitor(isolate));
278 V8PerIsolateData::TemporaryScriptWrappableVisitorScope scope(
279 isolate, std::move(tracer));
280
281 tracer->collectV8Roots();
282 tracer->traceV8Roots();
283 tracer->tracePendingActivities();
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