Index: third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp |
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp |
index d2b0dcd798ff1217b1bd7057f75b3da8b4ca5fbd..6791466019b649d14872a812fb2f6e98bb89e6a8 100644 |
--- a/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp |
+++ b/third_party/WebKit/Source/bindings/core/v8/V8GCController.cpp |
@@ -30,6 +30,7 @@ |
#include "bindings/core/v8/V8GCController.h" |
+#include "bindings/core/v8/NPV8Object.h" |
#include "bindings/core/v8/RetainedDOMInfo.h" |
#include "bindings/core/v8/V8AbstractEventListener.h" |
#include "bindings/core/v8/V8Binding.h" |
@@ -48,6 +49,7 @@ |
#include "core/html/imports/HTMLImportsController.h" |
#include "core/inspector/InspectorTraceEvents.h" |
#include "core/svg/SVGElement.h" |
+#include "platform/Histogram.h" |
#include "platform/TraceEvent.h" |
#include "wtf/Partitions.h" |
#include "wtf/Vector.h" |
@@ -121,11 +123,8 @@ public: |
v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(m_isolate, v8::Persistent<v8::Object>::Cast(*value)); |
ASSERT(V8DOMWrapper::hasInternalFieldsSet(wrapper)); |
const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); |
- ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(wrapper); |
- if (activeDOMObject && activeDOMObject->hasPendingActivity()) { |
- v8::Persistent<v8::Object>::Cast(*value).MarkActive(); |
+ if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) |
return; |
- } |
if (classId == WrapperTypeInfo::NodeClassId) { |
ASSERT(V8Node::hasInstance(wrapper, m_isolate)); |
@@ -179,8 +178,7 @@ public: |
const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); |
- ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(wrapper); |
- if (activeDOMObject && activeDOMObject->hasPendingActivity()) { |
+ if (type != npObjectTypeInfo() && toScriptWrappable(wrapper)->hasPendingActivity()) { |
m_isolate->SetObjectGroupId(*value, liveRootId()); |
++m_domObjectsWithPendingActivity; |
} |
@@ -430,4 +428,64 @@ void V8GCController::traceDOMWrappers(v8::Isolate* isolate, Visitor* visitor) |
isolate->VisitHandlesWithClassIds(&tracer); |
} |
+class PendingActivityVisitor : public v8::PersistentHandleVisitor { |
+public: |
+ explicit PendingActivityVisitor(ExecutionContext* executionContext) |
+ : m_executionContext(executionContext) |
+ , m_pendingActivityFound(false) |
+ { |
+ } |
+ |
+ void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) override |
+ { |
+ // If we have already found any wrapper that has a pending activity, |
+ // we don't need to check other wrappers. |
+ if (m_pendingActivityFound) |
+ return; |
+ |
+ if (classId != WrapperTypeInfo::NodeClassId && classId != WrapperTypeInfo::ObjectClassId) |
+ return; |
+ |
+ const v8::Persistent<v8::Object>& wrapper = v8::Persistent<v8::Object>::Cast(*value); |
+ const WrapperTypeInfo* type = toWrapperTypeInfo(wrapper); |
+ // The ExecutionContext check is heavy, so it should be done at the last. |
+ if (type != npObjectTypeInfo() |
+ && toScriptWrappable(wrapper)->hasPendingActivity() |
+ // TODO(haraken): Currently we don't have a way to get a creation |
+ // context from a wrapper. We should implement the way and enable |
+ // the following condition. |
+ // |
+ // This condition affects only compositor workers, where one isolate |
+ // is shared by multiple workers. If we don't have the condition, |
+ // a worker object for a compositor worker doesn't get collected |
+ // until all compositor workers in the same isolate lose pending |
+ // activities. In other words, not having the condition delays |
+ // destruction of a worker object of a compositor worker. |
+ // |
+ /* && toExecutionContext(wrapper->creationContext()) == m_executionContext */ |
+ ) |
+ m_pendingActivityFound = true; |
+ } |
+ |
+ bool pendingActivityFound() const { return m_pendingActivityFound; } |
+ |
+private: |
+ RawPtrWillBePersistent<ExecutionContext> m_executionContext; |
+ bool m_pendingActivityFound; |
+}; |
+ |
+bool V8GCController::hasPendingActivity(ExecutionContext* executionContext) |
+{ |
+ // V8GCController::hasPendingActivity is used only when a worker checks if |
+ // the worker contains any wrapper that has pending activities. |
+ ASSERT(!isMainThread()); |
+ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scanPendingActivityHistogram, new CustomCountHistogram("Blink.ScanPendingActivityDuration", 1, 1000, 50)); |
+ double startTime = WTF::currentTimeMS(); |
+ PendingActivityVisitor visitor(executionContext); |
+ toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor); |
+ scanPendingActivityHistogram.count(static_cast<int>(WTF::currentTimeMS() - startTime)); |
+ return visitor.pendingActivityFound(); |
+} |
+ |
} // namespace blink |