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

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

Issue 2640963007: [wrapper-tracing] Remove flag and object grouping entry points (Closed)
Patch Set: Fix merge artifact Created 3 years, 10 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
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> 54 #include <unordered_map>
55 #include <unordered_set> 55 #include <unordered_set>
56 56
57 namespace blink { 57 namespace blink {
58 58
59 // FIXME: This should use opaque GC roots.
60 static void addReferencesForNodeWithEventListeners(
61 v8::Isolate* isolate,
62 Node* node,
63 const v8::Persistent<v8::Object>& wrapper) {
64 ASSERT(node->hasEventListeners());
65
66 EventListenerIterator iterator(node);
67 while (EventListener* listener = iterator.nextListener()) {
68 if (listener->type() != EventListener::JSEventListenerType)
69 continue;
70 V8AbstractEventListener* v8listener =
71 static_cast<V8AbstractEventListener*>(listener);
72 if (!v8listener->hasExistingListenerObject())
73 continue;
74
75 isolate->SetReference(
76 wrapper, v8::Persistent<v8::Value>::Cast(
77 v8listener->existingListenerObjectPersistentHandle()));
78 }
79 }
80
81 Node* V8GCController::opaqueRootForGC(v8::Isolate*, Node* node) { 59 Node* V8GCController::opaqueRootForGC(v8::Isolate*, Node* node) {
82 ASSERT(node); 60 ASSERT(node);
83 if (node->isConnected()) { 61 if (node->isConnected()) {
84 Document& document = node->document(); 62 Document& document = node->document();
85 if (HTMLImportsController* controller = document.importsController()) 63 if (HTMLImportsController* controller = document.importsController())
86 return controller->master(); 64 return controller->master();
87 return &document; 65 return &document;
88 } 66 }
89 67
90 if (node->isAttributeNode()) { 68 if (node->isAttributeNode()) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 new HeapSnaphotWrapperVisitor(isolate))); 263 new HeapSnaphotWrapperVisitor(isolate)));
286 264
287 HeapSnaphotWrapperVisitor* tracer = 265 HeapSnaphotWrapperVisitor* tracer =
288 reinterpret_cast<HeapSnaphotWrapperVisitor*>(scope.currentVisitor()); 266 reinterpret_cast<HeapSnaphotWrapperVisitor*>(scope.currentVisitor());
289 tracer->collectV8Roots(); 267 tracer->collectV8Roots();
290 tracer->traceV8Roots(); 268 tracer->traceV8Roots();
291 tracer->tracePendingActivities(); 269 tracer->tracePendingActivities();
292 return v8::HeapProfiler::RetainerInfos{tracer->groups(), tracer->edges()}; 270 return v8::HeapProfiler::RetainerInfos{tracer->groups(), tracer->edges()};
293 } 271 }
294 272
295 class MajorGCWrapperVisitor : public v8::PersistentHandleVisitor {
296 public:
297 explicit MajorGCWrapperVisitor(v8::Isolate* isolate,
298 bool constructRetainedObjectInfos)
299 : m_isolate(isolate),
300 m_domObjectsWithPendingActivity(0),
301 m_liveRootGroupIdSet(false),
302 m_constructRetainedObjectInfos(constructRetainedObjectInfos) {}
303
304 void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
305 uint16_t classId) override {
306 if (classId != WrapperTypeInfo::NodeClassId &&
307 classId != WrapperTypeInfo::ObjectClassId)
308 return;
309
310 if (value->IsIndependent())
311 return;
312
313 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
314 m_isolate, v8::Persistent<v8::Object>::Cast(*value));
315 DCHECK(V8DOMWrapper::hasInternalFieldsSet(wrapper));
316
317 const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper);
318 if (type->isActiveScriptWrappable() &&
319 toScriptWrappable(wrapper)->hasPendingActivity()) {
320 // Enable hasPendingActivity only when the associated
321 // ExecutionContext is not yet detached. This is a work-around
322 // to avoid memory leaks caused by hasPendingActivity that keeps
323 // returning true forever. This will be okay in practice because
324 // the spec requires to stop almost all DOM activities when the
325 // associated browsing context is detached. However, the real
326 // problem is that some hasPendingActivity's are wrongly implemented
327 // and never return false.
328 // TODO(haraken): Implement correct lifetime using traceWrapper.
329 ExecutionContext* context =
330 toExecutionContext(wrapper->CreationContext());
331 if (context && !context->isContextDestroyed()) {
332 m_isolate->SetObjectGroupId(*value, liveRootId());
333 ++m_domObjectsWithPendingActivity;
334 }
335 }
336
337 if (classId == WrapperTypeInfo::NodeClassId) {
338 DCHECK(V8Node::hasInstance(wrapper, m_isolate));
339 Node* node = V8Node::toImpl(wrapper);
340 if (node->hasEventListeners())
341 addReferencesForNodeWithEventListeners(
342 m_isolate, node, v8::Persistent<v8::Object>::Cast(*value));
343 Node* root = V8GCController::opaqueRootForGC(m_isolate, node);
344 m_isolate->SetObjectGroupId(
345 *value, v8::UniqueId(reinterpret_cast<intptr_t>(root)));
346 if (m_constructRetainedObjectInfos)
347 m_groupsWhichNeedRetainerInfo.push_back(root);
348 } else if (classId == WrapperTypeInfo::ObjectClassId) {
349 if (!RuntimeEnabledFeatures::traceWrappablesEnabled()) {
350 type->visitDOMWrapper(m_isolate, toScriptWrappable(wrapper),
351 v8::Persistent<v8::Object>::Cast(*value));
352 }
353 } else {
354 NOTREACHED();
355 }
356 }
357
358 void notifyFinished() {
359 if (!m_constructRetainedObjectInfos)
360 return;
361 std::sort(m_groupsWhichNeedRetainerInfo.begin(),
362 m_groupsWhichNeedRetainerInfo.end());
363 Node* alreadyAdded = 0;
364 v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
365 for (size_t i = 0; i < m_groupsWhichNeedRetainerInfo.size(); ++i) {
366 Node* root = m_groupsWhichNeedRetainerInfo[i];
367 if (root != alreadyAdded) {
368 profiler->SetRetainedObjectInfo(
369 v8::UniqueId(reinterpret_cast<intptr_t>(root)),
370 new RetainedDOMInfo(root));
371 alreadyAdded = root;
372 }
373 }
374 if (m_liveRootGroupIdSet) {
375 profiler->SetRetainedObjectInfo(
376 liveRootId(),
377 new SuspendableObjectsInfo(m_domObjectsWithPendingActivity));
378 }
379 }
380
381 private:
382 v8::UniqueId liveRootId() {
383 const v8::Persistent<v8::Value>& liveRoot =
384 V8PerIsolateData::from(m_isolate)->ensureLiveRoot();
385 const intptr_t* idPointer = reinterpret_cast<const intptr_t*>(&liveRoot);
386 v8::UniqueId id(*idPointer);
387 if (!m_liveRootGroupIdSet) {
388 m_isolate->SetObjectGroupId(liveRoot, id);
389 m_liveRootGroupIdSet = true;
390 ++m_domObjectsWithPendingActivity;
391 }
392 return id;
393 }
394
395 v8::Isolate* m_isolate;
396 // v8 guarantees that Blink will not regain control while a v8 GC runs
397 // (=> no Oilpan GCs will be triggered), hence raw, untraced members
398 // can safely be kept here.
399 Vector<UntracedMember<Node>> m_groupsWhichNeedRetainerInfo;
400 int m_domObjectsWithPendingActivity;
401 bool m_liveRootGroupIdSet;
402 bool m_constructRetainedObjectInfos;
403 };
404
405 static unsigned long long usedHeapSize(v8::Isolate* isolate) { 273 static unsigned long long usedHeapSize(v8::Isolate* isolate) {
406 v8::HeapStatistics heapStatistics; 274 v8::HeapStatistics heapStatistics;
407 isolate->GetHeapStatistics(&heapStatistics); 275 isolate->GetHeapStatistics(&heapStatistics);
408 return heapStatistics.used_heap_size(); 276 return heapStatistics.used_heap_size();
409 } 277 }
410 278
411 namespace { 279 namespace {
412 280
413 void visitWeakHandlesForMinorGC(v8::Isolate* isolate) { 281 void visitWeakHandlesForMinorGC(v8::Isolate* isolate) {
414 MinorGCUnmodifiedWrapperVisitor visitor(isolate); 282 MinorGCUnmodifiedWrapperVisitor visitor(isolate);
415 isolate->VisitWeakHandles(&visitor); 283 isolate->VisitWeakHandles(&visitor);
416 } 284 }
417 285
418 void objectGroupingForMajorGC(v8::Isolate* isolate,
419 bool constructRetainedObjectInfos) {
420 MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
421 isolate->VisitHandlesWithClassIds(&visitor);
422 visitor.notifyFinished();
423 }
424
425 void gcPrologueForMajorGC(v8::Isolate* isolate,
426 bool constructRetainedObjectInfos) {
427 if (!RuntimeEnabledFeatures::traceWrappablesEnabled() ||
428 constructRetainedObjectInfos) {
429 objectGroupingForMajorGC(isolate, constructRetainedObjectInfos);
430 }
431 }
432
433 } // namespace 286 } // namespace
434 287
435 void V8GCController::gcPrologue(v8::Isolate* isolate, 288 void V8GCController::gcPrologue(v8::Isolate* isolate,
436 v8::GCType type, 289 v8::GCType type,
437 v8::GCCallbackFlags flags) { 290 v8::GCCallbackFlags flags) {
438 if (isMainThread()) 291 if (isMainThread())
439 ScriptForbiddenScope::enter(); 292 ScriptForbiddenScope::enter();
440 293
441 // Attribute garbage collection to the all frames instead of a specific 294 // Attribute garbage collection to the all frames instead of a specific
442 // frame. 295 // frame.
(...skipping 16 matching lines...) Expand all
459 "usedHeapSizeBefore", usedHeapSize(isolate)); 312 "usedHeapSizeBefore", usedHeapSize(isolate));
460 visitWeakHandlesForMinorGC(isolate); 313 visitWeakHandlesForMinorGC(isolate);
461 break; 314 break;
462 case v8::kGCTypeMarkSweepCompact: 315 case v8::kGCTypeMarkSweepCompact:
463 if (ThreadState::current()) 316 if (ThreadState::current())
464 ThreadState::current()->willStartV8GC(BlinkGC::V8MajorGC); 317 ThreadState::current()->willStartV8GC(BlinkGC::V8MajorGC);
465 318
466 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", 319 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC",
467 "usedHeapSizeBefore", usedHeapSize(isolate), "type", 320 "usedHeapSizeBefore", usedHeapSize(isolate), "type",
468 "atomic pause"); 321 "atomic pause");
469 gcPrologueForMajorGC(
470 isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
471 break; 322 break;
472 case v8::kGCTypeIncrementalMarking: 323 case v8::kGCTypeIncrementalMarking:
473 if (ThreadState::current()) 324 if (ThreadState::current())
474 ThreadState::current()->willStartV8GC(BlinkGC::V8MajorGC); 325 ThreadState::current()->willStartV8GC(BlinkGC::V8MajorGC);
475 326
476 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", 327 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC",
477 "usedHeapSizeBefore", usedHeapSize(isolate), "type", 328 "usedHeapSizeBefore", usedHeapSize(isolate), "type",
478 "incremental marking"); 329 "incremental marking");
479 gcPrologueForMajorGC(
480 isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
481 break; 330 break;
482 case v8::kGCTypeProcessWeakCallbacks: 331 case v8::kGCTypeProcessWeakCallbacks:
483 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", 332 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC",
484 "usedHeapSizeBefore", usedHeapSize(isolate), "type", 333 "usedHeapSizeBefore", usedHeapSize(isolate), "type",
485 "weak processing"); 334 "weak processing");
486 break; 335 break;
487 default: 336 default:
488 ASSERT_NOT_REACHED(); 337 ASSERT_NOT_REACHED();
489 } 338 }
490 } 339 }
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 double startTime = WTF::currentTimeMS(); 537 double startTime = WTF::currentTimeMS();
689 v8::HandleScope scope(isolate); 538 v8::HandleScope scope(isolate);
690 PendingActivityVisitor visitor(isolate, executionContext); 539 PendingActivityVisitor visitor(isolate, executionContext);
691 toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor); 540 toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor);
692 scanPendingActivityHistogram.count( 541 scanPendingActivityHistogram.count(
693 static_cast<int>(WTF::currentTimeMS() - startTime)); 542 static_cast<int>(WTF::currentTimeMS() - startTime));
694 return visitor.pendingActivityFound(); 543 return visitor.pendingActivityFound();
695 } 544 }
696 545
697 } // namespace blink 546 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698