OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |