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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 #include "platform/RuntimeEnabledFeatures.h" | 50 #include "platform/RuntimeEnabledFeatures.h" |
51 #include "platform/instrumentation/tracing/TraceEvent.h" | 51 #include "platform/instrumentation/tracing/TraceEvent.h" |
52 #include "platform/wtf/Vector.h" | 52 #include "platform/wtf/Vector.h" |
53 #include "platform/wtf/allocator/Partitions.h" | 53 #include "platform/wtf/allocator/Partitions.h" |
54 #include "public/platform/BlameContext.h" | 54 #include "public/platform/BlameContext.h" |
55 #include "public/platform/Platform.h" | 55 #include "public/platform/Platform.h" |
56 | 56 |
57 namespace blink { | 57 namespace blink { |
58 | 58 |
59 Node* V8GCController::OpaqueRootForGC(v8::Isolate*, Node* node) { | 59 Node* V8GCController::OpaqueRootForGC(v8::Isolate*, Node* node) { |
60 ASSERT(node); | 60 DCHECK(node); |
61 if (node->isConnected()) { | 61 if (node->isConnected()) { |
62 Document& document = node->GetDocument(); | 62 Document& document = node->GetDocument(); |
63 if (HTMLImportsController* controller = document.ImportsController()) | 63 if (HTMLImportsController* controller = document.ImportsController()) |
64 return controller->Master(); | 64 return controller->Master(); |
65 return &document; | 65 return &document; |
66 } | 66 } |
67 | 67 |
68 if (node->IsAttributeNode()) { | 68 if (node->IsAttributeNode()) { |
69 Node* owner_element = ToAttr(node)->ownerElement(); | 69 Node* owner_element = ToAttr(node)->ownerElement(); |
70 if (!owner_element) | 70 if (!owner_element) |
(...skipping 21 matching lines...) Expand all Loading... |
92 | 92 |
93 // MinorGC does not collect objects because it may be expensive to | 93 // MinorGC does not collect objects because it may be expensive to |
94 // update references during minorGC | 94 // update references during minorGC |
95 if (class_id == WrapperTypeInfo::kObjectClassId) { | 95 if (class_id == WrapperTypeInfo::kObjectClassId) { |
96 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); | 96 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); |
97 return; | 97 return; |
98 } | 98 } |
99 | 99 |
100 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New( | 100 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New( |
101 isolate_, v8::Persistent<v8::Object>::Cast(*value)); | 101 isolate_, v8::Persistent<v8::Object>::Cast(*value)); |
102 ASSERT(V8DOMWrapper::HasInternalFieldsSet(wrapper)); | 102 DCHECK(V8DOMWrapper::HasInternalFieldsSet(wrapper)); |
103 if (ToWrapperTypeInfo(wrapper)->IsActiveScriptWrappable() && | 103 if (ToWrapperTypeInfo(wrapper)->IsActiveScriptWrappable() && |
104 ToScriptWrappable(wrapper)->HasPendingActivity()) { | 104 ToScriptWrappable(wrapper)->HasPendingActivity()) { |
105 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); | 105 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); |
106 return; | 106 return; |
107 } | 107 } |
108 | 108 |
109 if (class_id == WrapperTypeInfo::kNodeClassId) { | 109 if (class_id == WrapperTypeInfo::kNodeClassId) { |
110 ASSERT(V8Node::hasInstance(wrapper, isolate_)); | 110 DCHECK(V8Node::hasInstance(wrapper, isolate_)); |
111 Node* node = V8Node::toImpl(wrapper); | 111 Node* node = V8Node::toImpl(wrapper); |
112 if (node->HasEventListeners()) { | 112 if (node->HasEventListeners()) { |
113 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); | 113 v8::Persistent<v8::Object>::Cast(*value).MarkActive(); |
114 return; | 114 return; |
115 } | 115 } |
116 // FIXME: Remove the special handling for SVG elements. | 116 // FIXME: Remove the special handling for SVG elements. |
117 // We currently can't collect SVG Elements from minor gc, as we have | 117 // We currently can't collect SVG Elements from minor gc, as we have |
118 // strong references from SVG property tear-offs keeping context SVG | 118 // strong references from SVG property tear-offs keeping context SVG |
119 // element alive. | 119 // element alive. |
120 if (node->IsSVGElement()) { | 120 if (node->IsSVGElement()) { |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", | 338 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", |
339 "usedHeapSizeBefore", UsedHeapSize(isolate), "type", | 339 "usedHeapSizeBefore", UsedHeapSize(isolate), "type", |
340 "incremental marking"); | 340 "incremental marking"); |
341 break; | 341 break; |
342 case v8::kGCTypeProcessWeakCallbacks: | 342 case v8::kGCTypeProcessWeakCallbacks: |
343 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", | 343 TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", |
344 "usedHeapSizeBefore", UsedHeapSize(isolate), "type", | 344 "usedHeapSizeBefore", UsedHeapSize(isolate), "type", |
345 "weak processing"); | 345 "weak processing"); |
346 break; | 346 break; |
347 default: | 347 default: |
348 ASSERT_NOT_REACHED(); | 348 NOTREACHED(); |
349 } | 349 } |
350 } | 350 } |
351 | 351 |
352 namespace { | 352 namespace { |
353 | 353 |
354 void UpdateCollectedPhantomHandles(v8::Isolate* isolate) { | 354 void UpdateCollectedPhantomHandles(v8::Isolate* isolate) { |
355 ThreadHeapStats& heap_stats = ThreadState::Current()->Heap().HeapStats(); | 355 ThreadHeapStats& heap_stats = ThreadState::Current()->Heap().HeapStats(); |
356 size_t count = isolate->NumberOfPhantomHandleResetsSinceLastCall(); | 356 size_t count = isolate->NumberOfPhantomHandleResetsSinceLastCall(); |
357 heap_stats.DecreaseWrapperCount(count); | 357 heap_stats.DecreaseWrapperCount(count); |
358 heap_stats.IncreaseCollectedWrapperCount(count); | 358 heap_stats.IncreaseCollectedWrapperCount(count); |
(...skipping 23 matching lines...) Expand all Loading... |
382 break; | 382 break; |
383 case v8::kGCTypeIncrementalMarking: | 383 case v8::kGCTypeIncrementalMarking: |
384 TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", | 384 TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", |
385 UsedHeapSize(isolate)); | 385 UsedHeapSize(isolate)); |
386 break; | 386 break; |
387 case v8::kGCTypeProcessWeakCallbacks: | 387 case v8::kGCTypeProcessWeakCallbacks: |
388 TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", | 388 TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", |
389 UsedHeapSize(isolate)); | 389 UsedHeapSize(isolate)); |
390 break; | 390 break; |
391 default: | 391 default: |
392 ASSERT_NOT_REACHED(); | 392 NOTREACHED(); |
393 } | 393 } |
394 | 394 |
395 if (IsMainThread()) | 395 if (IsMainThread()) |
396 ScriptForbiddenScope::Exit(); | 396 ScriptForbiddenScope::Exit(); |
397 | 397 |
398 if (BlameContext* blame_context = | 398 if (BlameContext* blame_context = |
399 Platform::Current()->GetTopLevelBlameContext()) | 399 Platform::Current()->GetTopLevelBlameContext()) |
400 blame_context->Leave(); | 400 blame_context->Leave(); |
401 | 401 |
402 ThreadState* current_thread_state = ThreadState::Current(); | 402 ThreadState* current_thread_state = ThreadState::Current(); |
(...skipping 14 matching lines...) Expand all Loading... |
417 // Regarding (1), we force a precise GC at the end of the current event | 417 // Regarding (1), we force a precise GC at the end of the current event |
418 // loop. So if you want to collect all garbage, you need to wait until the | 418 // loop. So if you want to collect all garbage, you need to wait until the |
419 // next event loop. Regarding (2), it would be OK in practice to trigger | 419 // next event loop. Regarding (2), it would be OK in practice to trigger |
420 // only one GC per gcEpilogue, because GCController.collectAll() forces | 420 // only one GC per gcEpilogue, because GCController.collectAll() forces |
421 // multiple V8's GC. | 421 // multiple V8's GC. |
422 current_thread_state->CollectGarbage(BlinkGC::kHeapPointersOnStack, | 422 current_thread_state->CollectGarbage(BlinkGC::kHeapPointersOnStack, |
423 BlinkGC::kGCWithSweep, | 423 BlinkGC::kGCWithSweep, |
424 BlinkGC::kForcedGC); | 424 BlinkGC::kForcedGC); |
425 | 425 |
426 // Forces a precise GC at the end of the current event loop. | 426 // Forces a precise GC at the end of the current event loop. |
427 RELEASE_ASSERT(!current_thread_state->IsInGC()); | 427 CHECK(!current_thread_state->IsInGC()); |
428 current_thread_state->SetGCState(ThreadState::kFullGCScheduled); | 428 current_thread_state->SetGCState(ThreadState::kFullGCScheduled); |
429 } | 429 } |
430 | 430 |
431 // v8::kGCCallbackFlagCollectAllAvailableGarbage is used when V8 handles | 431 // v8::kGCCallbackFlagCollectAllAvailableGarbage is used when V8 handles |
432 // low memory notifications. | 432 // low memory notifications. |
433 if ((flags & v8::kGCCallbackFlagCollectAllAvailableGarbage) || | 433 if ((flags & v8::kGCCallbackFlagCollectAllAvailableGarbage) || |
434 (flags & v8::kGCCallbackFlagCollectAllExternalMemory)) { | 434 (flags & v8::kGCCallbackFlagCollectAllExternalMemory)) { |
435 // This single GC is not enough. See the above comment. | 435 // This single GC is not enough. See the above comment. |
436 current_thread_state->CollectGarbage(BlinkGC::kHeapPointersOnStack, | 436 current_thread_state->CollectGarbage(BlinkGC::kHeapPointersOnStack, |
437 BlinkGC::kGCWithSweep, | 437 BlinkGC::kGCWithSweep, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 // we don't need to check other wrappers. | 510 // we don't need to check other wrappers. |
511 if (pending_activity_found_) | 511 if (pending_activity_found_) |
512 return; | 512 return; |
513 | 513 |
514 if (class_id != WrapperTypeInfo::kNodeClassId && | 514 if (class_id != WrapperTypeInfo::kNodeClassId && |
515 class_id != WrapperTypeInfo::kObjectClassId) | 515 class_id != WrapperTypeInfo::kObjectClassId) |
516 return; | 516 return; |
517 | 517 |
518 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New( | 518 v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New( |
519 isolate_, v8::Persistent<v8::Object>::Cast(*value)); | 519 isolate_, v8::Persistent<v8::Object>::Cast(*value)); |
520 ASSERT(V8DOMWrapper::HasInternalFieldsSet(wrapper)); | 520 DCHECK(V8DOMWrapper::HasInternalFieldsSet(wrapper)); |
521 // The ExecutionContext check is heavy, so it should be done at the last. | 521 // The ExecutionContext check is heavy, so it should be done at the last. |
522 if (ToWrapperTypeInfo(wrapper)->IsActiveScriptWrappable() && | 522 if (ToWrapperTypeInfo(wrapper)->IsActiveScriptWrappable() && |
523 ToScriptWrappable(wrapper)->HasPendingActivity()) { | 523 ToScriptWrappable(wrapper)->HasPendingActivity()) { |
524 // See the comment in MajorGCWrapperVisitor::VisitPersistentHandle. | 524 // See the comment in MajorGCWrapperVisitor::VisitPersistentHandle. |
525 ExecutionContext* context = | 525 ExecutionContext* context = |
526 ToExecutionContext(wrapper->CreationContext()); | 526 ToExecutionContext(wrapper->CreationContext()); |
527 if (context == execution_context_ && context && | 527 if (context == execution_context_ && context && |
528 !context->IsContextDestroyed()) | 528 !context->IsContextDestroyed()) |
529 pending_activity_found_ = true; | 529 pending_activity_found_ = true; |
530 } | 530 } |
531 } | 531 } |
532 | 532 |
533 bool PendingActivityFound() const { return pending_activity_found_; } | 533 bool PendingActivityFound() const { return pending_activity_found_; } |
534 | 534 |
535 private: | 535 private: |
536 v8::Isolate* isolate_; | 536 v8::Isolate* isolate_; |
537 Persistent<ExecutionContext> execution_context_; | 537 Persistent<ExecutionContext> execution_context_; |
538 bool pending_activity_found_; | 538 bool pending_activity_found_; |
539 }; | 539 }; |
540 | 540 |
541 bool V8GCController::HasPendingActivity(v8::Isolate* isolate, | 541 bool V8GCController::HasPendingActivity(v8::Isolate* isolate, |
542 ExecutionContext* execution_context) { | 542 ExecutionContext* execution_context) { |
543 // V8GCController::hasPendingActivity is used only when a worker checks if | 543 // V8GCController::hasPendingActivity is used only when a worker checks if |
544 // the worker contains any wrapper that has pending activities. | 544 // the worker contains any wrapper that has pending activities. |
545 ASSERT(!IsMainThread()); | 545 DCHECK(!IsMainThread()); |
546 | 546 |
547 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 547 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
548 CustomCountHistogram, scan_pending_activity_histogram, | 548 CustomCountHistogram, scan_pending_activity_histogram, |
549 new CustomCountHistogram("Blink.ScanPendingActivityDuration", 1, 1000, | 549 new CustomCountHistogram("Blink.ScanPendingActivityDuration", 1, 1000, |
550 50)); | 550 50)); |
551 double start_time = WTF::CurrentTimeMS(); | 551 double start_time = WTF::CurrentTimeMS(); |
552 v8::HandleScope scope(isolate); | 552 v8::HandleScope scope(isolate); |
553 PendingActivityVisitor visitor(isolate, execution_context); | 553 PendingActivityVisitor visitor(isolate, execution_context); |
554 ToIsolate(execution_context)->VisitHandlesWithClassIds(&visitor); | 554 ToIsolate(execution_context)->VisitHandlesWithClassIds(&visitor); |
555 scan_pending_activity_histogram.Count( | 555 scan_pending_activity_histogram.Count( |
556 static_cast<int>(WTF::CurrentTimeMS() - start_time)); | 556 static_cast<int>(WTF::CurrentTimeMS() - start_time)); |
557 return visitor.PendingActivityFound(); | 557 return visitor.PendingActivityFound(); |
558 } | 558 } |
559 | 559 |
560 } // namespace blink | 560 } // namespace blink |
OLD | NEW |