The DOM should have an advancing wavefront opaque root barrier
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Dec 2016 18:19:22 +0000 (18:19 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Dec 2016 18:19:22 +0000 (18:19 +0000)
commitaf35e34b1da2333c052be9e27f8211e3eb8ec6db
tree7b2b166f0236314cf4b6654b1592c8888d704bb7
parent913470c6c4cba369d749c164ba3931f4beaea7ea
The DOM should have an advancing wavefront opaque root barrier
https://bugs.webkit.org/show_bug.cgi?id=165712

Reviewed by Yusuke Suzuki.
Source/JavaScriptCore:

This exposes the ability to fire an advancing wavefront barrier on opaque roots. It also
gives clients the ability to maintain their own cache of whether that barrier needs to
be enabled.

The DOM uses this to enable a very cheap barrier on the DOM. This is neutral on
Speedometer and fixes another concurrent GC crash.

* heap/Heap.cpp:
(JSC::Heap::beginMarking):
(JSC::Heap::endMarking):
(JSC::Heap::writeBarrierOpaqueRootSlow):
(JSC::Heap::addMutatorShouldBeFencedCache):
(JSC::Heap::setMutatorShouldBeFenced):
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::writeBarrierOpaqueRoot):

Source/WebCore:

No new tests because this was covered by crashing tests.

Consider these two cases:

   Removal:
   1) DOM at start: D->X->Y
   2) Mark X, X->visitChildren, addOpaqueRoot(D)
   3) remove X
   4) Y thinks it's not reachable (its opaque root, X, is not in the set).

   Insertion:
   1) DOM at start: D, X->Y
   2) Mark X, X->visitChildren, addOpaqueRoot(X)
   3) insert X into D
   4) Y thinks it's not reachable (its opaque root, D, is not in the set).

We can fix this with two barriers:

   Removal: add X (the removed child) to the opaque root set.
   Insertion: add D (the insertion point) to the opaque root set.

Thanks Rysosuke for coming up with this idea!

Both barriers advance the wavefront. We could consider retreating wavefront barriers in
the future (where we cause visitChildren to be called again on wrappers that belonged to
roots that got affected by insertion/removal) but those would probably require more
bookkeeping.

To make this barrier very fast, the WebCore caches the JSC VM's barrier state in
its own global variable for very fast access. This variable will be false most of the
time. It's false when there is no VM, so triggering the barrier won't cause the VM to be
created. It's only true when GC is running, which is rare by design.

To make that caching more sensible, I finally gave WebCore a central header for
the common VM (CommonVM.h).

* CMakeLists.txt:
* Modules/mediastream/SDPProcessor.cpp:
(WebCore::SDPProcessor::callScript):
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/CommonVM.cpp: Added.
(WebCore::commonVMSlow):
(WebCore::writeBarrierOpaqueRootSlow):
* bindings/js/CommonVM.h: Added.
(WebCore::commonVM):
(WebCore::writeBarrierOpaqueRoot):
* bindings/js/DOMWrapperWorld.cpp:
(WebCore::mainThreadNormalWorld):
* bindings/js/GCController.cpp:
(WebCore::collect):
(WebCore::GCController::garbageCollectSoon):
(WebCore::GCController::garbageCollectNow):
(WebCore::GCController::garbageCollectNowIfNotDoneRecently):
(WebCore::GCController::setJavaScriptGarbageCollectorTimerEnabled):
(WebCore::GCController::deleteAllCode):
(WebCore::GCController::deleteAllLinkedCode):
* bindings/js/JSCustomXPathNSResolver.cpp:
(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
* bindings/js/JSDOMBinding.cpp:
(WebCore::addImpureProperty):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowBase::fireFrameClearedWatchpointsForWindow):
(WebCore::JSDOMWindowBase::commonVM): Deleted.
* bindings/js/JSDOMWindowBase.h:
* bindings/js/JSDOMWindowShell.cpp:
(WebCore::JSDOMWindowShell::setWindow):
* bindings/js/JSNodeCustom.h:
(WebCore::root):
* bindings/js/ScriptCachedFrameData.cpp:
(WebCore::ScriptCachedFrameData::ScriptCachedFrameData):
(WebCore::ScriptCachedFrameData::restore):
(WebCore::ScriptCachedFrameData::clear):
* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::~ScriptController):
(WebCore::ScriptController::createWorld):
(WebCore::ScriptController::getAllWorlds):
(WebCore::ScriptController::clearWindowShell):
(WebCore::ScriptController::cacheableBindingRootObject):
(WebCore::ScriptController::bindingRootObject):
(WebCore::ScriptController::windowScriptNPObject):
(WebCore::ScriptController::jsObjectForPluginElement):
(WebCore::ScriptController::clearScriptObjects):
* dom/CollectionIndexCache.cpp:
(WebCore::reportExtraMemoryAllocatedForCollectionIndexCache):
* dom/ContainerNode.cpp:
* dom/ContainerNodeAlgorithms.cpp:
(WebCore::notifyChildNodeInserted):
(WebCore::notifyChildNodeRemoved):
* dom/Document.cpp:
(WebCore::Document::shouldBypassMainWorldContentSecurityPolicy):
* dom/Node.h:
(WebCore::Node::opaqueRoot):
* dom/ScriptExecutionContext.cpp:
(WebCore::ScriptExecutionContext::vm):
* html/HTMLImageLoader.cpp:
(WebCore::HTMLImageLoader::notifyFinished):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::pauseAfterDetachedTask):
(WebCore::HTMLMediaElement::ensureIsolatedWorld):
* html/HTMLPlugInImageElement.cpp:
(WebCore::plugInImageElementIsolatedWorld):
* inspector/InspectorController.cpp:
(WebCore::InspectorController::vm):
* inspector/PageScriptDebugServer.cpp:
(WebCore::PageScriptDebugServer::PageScriptDebugServer):
* page/PerformanceLogging.cpp:
(WebCore::PerformanceLogging::memoryUsageStatistics):
(WebCore::PerformanceLogging::javaScriptObjectCounts):
* page/ResourceUsageThread.cpp:
(WebCore::ResourceUsageThread::createThreadIfNeeded):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::reportApproximateMemoryCost):
* testing/MemoryInfo.h:
(WebCore::MemoryInfo::MemoryInfo):

Source/WebKit/mac:

Propagate the JSDOMWindowBase::commonVM() -> commonVM() change.

* Misc/WebCoreStatistics.mm:
(+[WebCoreStatistics javaScriptObjectsCount]):
(+[WebCoreStatistics javaScriptGlobalObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedGlobalObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedObjectTypeCounts]):
(+[WebCoreStatistics javaScriptObjectTypeCounts]):
(+[WebCoreStatistics shouldPrintExceptions]):
(+[WebCoreStatistics setShouldPrintExceptions:]):
(+[WebCoreStatistics memoryStatistics]):
(+[WebCoreStatistics javaScriptReferencedObjectsCount]):
* Plugins/Hosted/NetscapePluginHostProxy.mm:
(identifierFromIdentifierRep):
* Plugins/Hosted/ProxyInstance.mm:
(WebKit::ProxyInstance::getPropertyNames):
* Plugins/WebNetscapePluginStream.mm:
(WebNetscapePluginStream::wantsAllStreams):
* Plugins/WebNetscapePluginView.mm:
(-[WebNetscapePluginView sendEvent:isDrawRect:]):
(-[WebNetscapePluginView privateBrowsingModeDidChange]):
(-[WebNetscapePluginView setWindowIfNecessary]):
(-[WebNetscapePluginView createPluginScriptableObject]):
(-[WebNetscapePluginView getFormValue:]):
(-[WebNetscapePluginView evaluateJavaScriptPluginRequest:]):
(-[WebNetscapePluginView webFrame:didFinishLoadWithReason:]):
(-[WebNetscapePluginView loadPluginRequest:]):
(-[WebNetscapePluginView _printedPluginBitmap]):
* Plugins/WebPluginController.mm:
(-[WebPluginController plugInViewWithArguments:fromPluginPackage:]):
(-[WebPluginController stopOnePlugin:]):
(-[WebPluginController stopOnePluginForPageCache:]):
(-[WebPluginController destroyOnePlugin:]):
(-[WebPluginController startAllPlugins]):
(-[WebPluginController addPlugin:]):

Source/WebKit/win:

Propagate the JSDOMWindowBase::commonVM() -> commonVM() change.

* Plugins/PluginView.cpp:
(WebCore::PluginView::start):
(WebCore::PluginView::stop):
(WebCore::PluginView::performRequest):
(WebCore::PluginView::npObject):
(WebCore::PluginView::privateBrowsingStateChanged):
* Plugins/PluginViewWin.cpp:
(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::handleKeyboardEvent):
(WebCore::PluginView::handleMouseEvent):
(WebCore::PluginView::setNPWindowRect):
* WebCoreStatistics.cpp:
(WebCoreStatistics::javaScriptObjectsCount):
(WebCoreStatistics::javaScriptGlobalObjectsCount):
(WebCoreStatistics::javaScriptProtectedObjectsCount):
(WebCoreStatistics::javaScriptProtectedGlobalObjectsCount):
(WebCoreStatistics::javaScriptProtectedObjectTypeCounts):
(WebCoreStatistics::javaScriptObjectTypeCounts):
(WebCoreStatistics::shouldPrintExceptions):
(WebCoreStatistics::setShouldPrintExceptions):
(WebCoreStatistics::memoryStatistics):
* WebJavaScriptCollector.cpp:
(WebJavaScriptCollector::objectCount):

Source/WebKit2:

Propagate the JSDOMWindowBase::commonVM() -> commonVM() change.

* Shared/linux/WebMemorySamplerLinux.cpp:
(WebKit::WebMemorySampler::sampleWebKit):
* Shared/mac/WebMemorySampler.mac.mm:
(WebKit::WebMemorySampler::sampleWebKit):
* WebProcess/InjectedBundle/InjectedBundle.cpp:
(WebKit::InjectedBundle::javaScriptObjectsCount):
* WebProcess/Plugins/Netscape/JSNPObject.cpp:
(WebKit::JSNPObject::callMethod):
(WebKit::JSNPObject::callObject):
(WebKit::JSNPObject::callConstructor):
(WebKit::JSNPObject::put):
(WebKit::JSNPObject::deleteProperty):
(WebKit::JSNPObject::getOwnPropertyNames):
(WebKit::JSNPObject::propertyGetter):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::runJavaScriptInMainFrame):
(WebKit::WebPage::getBytecodeProfile):
(WebKit::WebPage::getSamplingProfilerOutput):
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::getWebCoreStatistics):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209683 268f45cc-cd09-0410-ab3c-d52691b4dbfc
60 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/heap/Heap.h
Source/JavaScriptCore/heap/HeapInlines.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/SDPProcessor.cpp
Source/WebCore/Modules/plugins/QuickTimePluginReplacement.mm
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/CommonVM.cpp [new file with mode: 0644]
Source/WebCore/bindings/js/CommonVM.h [new file with mode: 0644]
Source/WebCore/bindings/js/DOMWrapperWorld.cpp
Source/WebCore/bindings/js/GCController.cpp
Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
Source/WebCore/bindings/js/JSDOMBinding.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.h
Source/WebCore/bindings/js/JSDOMWindowShell.cpp
Source/WebCore/bindings/js/JSNodeCustom.h
Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptControllerMac.mm
Source/WebCore/dom/CollectionIndexCache.cpp
Source/WebCore/dom/ContainerNode.cpp
Source/WebCore/dom/ContainerNodeAlgorithms.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/ScriptExecutionContext.cpp
Source/WebCore/html/HTMLImageLoader.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLPlugInImageElement.cpp
Source/WebCore/inspector/InspectorController.cpp
Source/WebCore/inspector/PageScriptDebugServer.cpp
Source/WebCore/page/PerformanceLogging.cpp
Source/WebCore/page/ResourceUsageThread.cpp
Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm
Source/WebCore/page/ios/FrameIOS.mm
Source/WebCore/platform/ios/wak/WebCoreThread.mm
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/testing/MemoryInfo.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/Misc/WebCoreStatistics.mm
Source/WebKit/mac/Plugins/Hosted/NetscapePluginHostProxy.mm
Source/WebKit/mac/Plugins/Hosted/ProxyInstance.mm
Source/WebKit/mac/Plugins/WebNetscapePluginStream.mm
Source/WebKit/mac/Plugins/WebNetscapePluginView.mm
Source/WebKit/mac/Plugins/WebPluginController.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/Plugins/PluginView.cpp
Source/WebKit/win/Plugins/PluginViewWin.cpp
Source/WebKit/win/WebCoreStatistics.cpp
Source/WebKit/win/WebJavaScriptCollector.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/linux/WebMemorySamplerLinux.cpp
Source/WebKit2/Shared/mac/WebMemorySampler.mac.mm
Source/WebKit2/WebProcess/InjectedBundle/InjectedBundle.cpp
Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebProcess.cpp