| Index: Source/bindings/core/v8/V8GCController.cpp
|
| diff --git a/Source/bindings/core/v8/V8GCController.cpp b/Source/bindings/core/v8/V8GCController.cpp
|
| index ffe8eb04f2687a7ce951b2f2bd301b789c7e2912..3ff9478cb22f9758b5368984a131205a6bbec904 100644
|
| --- a/Source/bindings/core/v8/V8GCController.cpp
|
| +++ b/Source/bindings/core/v8/V8GCController.cpp
|
| @@ -331,72 +331,124 @@ static unsigned long long usedHeapSize(v8::Isolate* isolate)
|
| return heapStatistics.used_heap_size();
|
| }
|
|
|
| -void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
|
| +namespace {
|
| +
|
| +void objectGroupingForMinorGC(v8::Isolate* isolate)
|
| {
|
| - // FIXME: It would be nice if the GC callbacks passed the Isolate directly....
|
| - v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| - if (type == v8::kGCTypeScavenge) {
|
| - // Finish Oilpan's complete sweeping before running a V8 minor GC.
|
| - // This will let the minor GC collect more V8 objects.
|
| - ThreadState::current()->completeSweep();
|
| - minorGCPrologue(isolate);
|
| - } else if (type == v8::kGCTypeMarkSweepCompact) {
|
| - majorGCPrologue(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
|
| - }
|
| + ASSERT(isMainThread());
|
| + MinorGCWrapperVisitor visitor(isolate);
|
| + v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
|
| + visitor.notifyFinished();
|
| }
|
|
|
| -void V8GCController::minorGCPrologue(v8::Isolate* isolate)
|
| +void objectGroupingForMajorGC(v8::Isolate* isolate, bool constructRetainedObjectInfos)
|
| +{
|
| + MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
|
| + v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
|
| + visitor.notifyFinished();
|
| +}
|
| +
|
| +void gcPrologueForMajorGC(v8::Isolate* isolate, bool constructRetainedObjectInfos)
|
| {
|
| - TRACE_EVENT_BEGIN1("devtools.timeline,v8", "MinorGC", "usedHeapSizeBefore", usedHeapSize(isolate));
|
| if (isMainThread()) {
|
| - ScriptForbiddenScope::enter();
|
| {
|
| - TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "DOMMinorGC");
|
| - v8::HandleScope scope(isolate);
|
| - MinorGCWrapperVisitor visitor(isolate);
|
| - v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
|
| - visitor.notifyFinished();
|
| + TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "DOMMajorGC");
|
| + objectGroupingForMajorGC(isolate, constructRetainedObjectInfos);
|
| }
|
| V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
|
| - TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8MinorGC");
|
| + TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8MajorGC");
|
| + } else {
|
| + objectGroupingForMajorGC(isolate, constructRetainedObjectInfos);
|
| }
|
| }
|
|
|
| -// Create object groups for DOM tree nodes.
|
| -void V8GCController::majorGCPrologue(v8::Isolate* isolate, bool constructRetainedObjectInfos)
|
| +}
|
| +
|
| +void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags)
|
| {
|
| - v8::HandleScope scope(isolate);
|
| - TRACE_EVENT_BEGIN1("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate));
|
| if (isMainThread()) {
|
| ScriptForbiddenScope::enter();
|
| - {
|
| - TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "DOMMajorGC");
|
| - MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
|
| - v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
|
| - visitor.notifyFinished();
|
| + }
|
| +
|
| + // TODO(haraken): It would be nice if the GC callbacks passed the Isolate
|
| + // directly.
|
| + v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| + v8::HandleScope scope(isolate);
|
| + switch (type) {
|
| + case v8::kGCTypeScavenge:
|
| + // Finish Oilpan's complete sweeping before running a V8 minor GC.
|
| + // This will let the minor GC collect more V8 objects.
|
| + ThreadState::current()->completeSweep();
|
| +
|
| + TRACE_EVENT_BEGIN1("devtools.timeline,v8", "MinorGC", "usedHeapSizeBefore", usedHeapSize(isolate));
|
| + if (isMainThread()) {
|
| + {
|
| + TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "DOMMinorGC");
|
| + objectGroupingForMinorGC(isolate);
|
| + }
|
| + V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
|
| + TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8MinorGC");
|
| }
|
| - V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
|
| - TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8MajorGC");
|
| - } else {
|
| - MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos);
|
| - v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
|
| - visitor.notifyFinished();
|
| + break;
|
| + case v8::kGCTypeMarkSweepCompact:
|
| + TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate), "type", "atomic pause");
|
| + gcPrologueForMajorGC(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
|
| + break;
|
| + case v8::kGCTypeIncrementalMarking:
|
| + TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate), "type", "incremental marking");
|
| + gcPrologueForMajorGC(isolate, flags & v8::kGCCallbackFlagConstructRetainedObjectInfos);
|
| + break;
|
| + case v8::kGCTypeProcessWeakCallbacks:
|
| + TRACE_EVENT_BEGIN2("devtools.timeline,v8", "MajorGC", "usedHeapSizeBefore", usedHeapSize(isolate), "type", "weak processing");
|
| + if (isMainThread()) {
|
| + V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE());
|
| + TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMMajorGC");
|
| + }
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| }
|
| }
|
|
|
| void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags)
|
| {
|
| - // FIXME: It would be nice if the GC callbacks passed the Isolate directly....
|
| + // TODO(haraken): It would be nice if the GC callbacks passed the Isolate
|
| + // directly.
|
| v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
| - if (type == v8::kGCTypeScavenge) {
|
| - minorGCEpilogue(isolate);
|
| + switch (type) {
|
| + case v8::kGCTypeScavenge:
|
| + TRACE_EVENT_END1("devtools.timeline,v8", "MinorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| + if (isMainThread()) {
|
| + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| + }
|
| ThreadState::current()->scheduleV8FollowupGCIfNeeded();
|
| - } else if (type == v8::kGCTypeMarkSweepCompact) {
|
| - majorGCEpilogue(isolate);
|
| - } else if (type == v8::kGCTypeProcessWeakCallbacks) {
|
| + break;
|
| + case v8::kGCTypeMarkSweepCompact:
|
| + TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| + if (isMainThread()) {
|
| + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| + }
|
| + break;
|
| + case v8::kGCTypeIncrementalMarking:
|
| + TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| + if (isMainThread()) {
|
| + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| + }
|
| + break;
|
| + case v8::kGCTypeProcessWeakCallbacks:
|
| + TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| + if (isMainThread()) {
|
| + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| + }
|
| ThreadState::current()->scheduleV8FollowupGCIfNeeded();
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| }
|
|
|
| + if (isMainThread())
|
| + ScriptForbiddenScope::exit();
|
| +
|
| // v8::kGCCallbackFlagForced forces a Blink heap garbage collection
|
| // when a garbage collection was forced from V8. This is either used
|
| // for tests that force GCs from JavaScript to verify that objects die
|
| @@ -421,24 +473,6 @@ void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags)
|
| TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());
|
| }
|
|
|
| -void V8GCController::minorGCEpilogue(v8::Isolate* isolate)
|
| -{
|
| - TRACE_EVENT_END1("devtools.timeline,v8", "MinorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| - if (isMainThread()) {
|
| - TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| - ScriptForbiddenScope::exit();
|
| - }
|
| -}
|
| -
|
| -void V8GCController::majorGCEpilogue(v8::Isolate* isolate)
|
| -{
|
| - TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter", usedHeapSize(isolate));
|
| - if (isMainThread()) {
|
| - TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState());
|
| - ScriptForbiddenScope::exit();
|
| - }
|
| -}
|
| -
|
| void V8GCController::collectGarbage(v8::Isolate* isolate)
|
| {
|
| v8::HandleScope handleScope(isolate);
|
|
|