| 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 |