haikuwebkit/Source/WebCore/workers/ScriptBuffer.h

68 lines
2.5 KiB
C
Raw Permalink Normal View History

Introduce ScriptBuffer class to wrap SharedBuffer containing a script https://bugs.webkit.org/show_bug.cgi?id=224092 Reviewed by Yusuke Suzuki and Geoff Garen. Introduce ScriptBuffer class to wrap SharedBuffer containing a script. We started using SharedBuffer to represent worker scripts instead of String, so that they can hold file mapped data and be shared across processes. This patch introduces a new ScriptBuffer to wrap those SharedBuffers. The type makes it clearer what type of data we're dealing with. The helper functions used to convert between String and SharedBuffer can now simply be member functions on ScriptBuffer. This also simplifies IPC code. Source/WebCore: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: Add new ScriptBuffer class to project files. * inspector/agents/worker/ServiceWorkerAgent.cpp: (WebCore::ServiceWorkerAgent::getInitializationInfo): Use ScriptBuffer::toString() instead of scriptBufferToString(). * workers/ScriptBuffer.cpp: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::toString const): (WebCore::ScriptBuffer::containsSingleFileMappedSegment const): (WebCore::operator==): * workers/ScriptBuffer.h: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::buffer const): (WebCore::ScriptBuffer::isolatedCopy const): (WebCore::ScriptBuffer::operator bool const): New ScriptBuffer class that wraps a SharedBuffer representation of a script. This class helps make it clear what data we're dealing with. It also facilitates conversion to and from a String when needed. The class also has its own IPC coder at WebKit layer to encode the script as a ShareableResource when file mapped. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::loadSynchronously): Use ScriptBuffer::toString() instead of scriptBufferToString(). And use StringBuffer constructor that takes a String instead of stringToScriptBuffer(). * workers/service/SWClientConnection.h: * workers/service/ServiceWorkerContextData.cpp: (WebCore::ServiceWorkerContextData::isolatedCopy const): * workers/service/ServiceWorkerContextData.h: (WebCore::ServiceWorkerContextData::ImportedScript::encode const): (WebCore::ServiceWorkerContextData::ImportedScript::decode): (WebCore::ServiceWorkerContextData::ImportedScript::isolatedCopy const): (WebCore::ServiceWorkerContextData::encode const): (WebCore::ServiceWorkerContextData::decode): - Use ScriptBuffer instead of RefPtr<SharedBuffer> for scripts. - Drop scriptBufferToString() & stringToScriptBuffer() as they are no longer needed. - Move IPC coders for ServiceWorkerContextData back from WebCoreArgumentCoders back to the WebCore class, now that the coders no longer need to deal with ShareableResource directly. We now encode / decode ScriptBuffer objects and its coder takes care of using a ShareableResource whenever possible. * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerGlobalScope.h: * workers/service/context/SWContextManager.cpp: (WebCore::SWContextManager::didSaveScriptsToDisk): * workers/service/context/SWContextManager.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/context/ServiceWorkerThreadProxy.cpp: (WebCore::ServiceWorkerThreadProxy::didSaveScriptsToDisk): * workers/service/context/ServiceWorkerThreadProxy.h: * workers/service/server/RegistrationDatabase.cpp: (WebCore::RegistrationDatabase::doPushChanges): (WebCore::RegistrationDatabase::importRecords): * workers/service/server/RegistrationStore.cpp: (WebCore::RegistrationStore::didSaveWorkerScriptsToDisk): * workers/service/server/RegistrationStore.h: * workers/service/server/SWScriptStorage.cpp: (WebCore::SWScriptStorage::store): (WebCore::SWScriptStorage::retrieve): * workers/service/server/SWScriptStorage.h: * workers/service/server/SWServer.cpp: (WebCore::SWServer::didSaveWorkerScriptsToDisk): (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): * workers/service/server/SWServerToContextConnection.h: * workers/service/server/SWServerWorker.cpp: (WebCore::SWServerWorker::SWServerWorker): (WebCore::SWServerWorker::didSaveScriptsToDisk): * workers/service/server/SWServerWorker.h: (WebCore::SWServerWorker::script const): Use ScriptBuffer instead of SharedBuffer. Source/WebKit: * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: (WebKit::WebSWServerToContextConnection::didSaveScriptsToDisk): * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: Use ScriptBuffer instead SharedBuffer. * Shared/WebCoreArgumentCoders.cpp: (IPC::tryConvertToShareableResourceHandle): (IPC::decodeScriptBufferAsShareableResourceHandle): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::encode): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::decode): * Shared/WebCoreArgumentCoders.h: - Add IPC encoder / decoder for ScriptBuffer which tries to encode / decode as a ShareableResource whenever possible (single segment that is file mapped). This logic used to be in the ServiceWorkerContextData coders. Now that the logic is in the ScriptBuffer coder, the ServiceWorkerContextData encoding / decoding becomes much simpler. - Moved ServiceWorkerContextData coders from WebCoreArgumentCoders back to its class in WebCore, now that they no longer need to deal with ShareableResource directly. * WebProcess/Storage/WebSWContextManagerConnection.cpp: (WebKit::WebSWContextManagerConnection::didSaveScriptsToDisk): * WebProcess/Storage/WebSWContextManagerConnection.h: * WebProcess/Storage/WebSWContextManagerConnection.messages.in: Send scripts over IPC as ScriptBuffer instead of using ShareableResource directly. The new IPC encoder / decoder for ScriptBuffer takes care of using ShareableResource for us. Canonical link: https://commits.webkit.org/236104@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-02 21:53:30 +00:00
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "SharedBuffer.h"
namespace WebCore {
class ScriptBuffer {
public:
ScriptBuffer() = default;
ScriptBuffer(RefPtr<SharedBuffer>&& buffer)
: m_buffer(WTFMove(buffer))
{
}
Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible https://bugs.webkit.org/show_bug.cgi?id=224088 Reviewed by Yusuke Suzuki. Source/WebCore: To run a worker, we were constructing a ScriptSourceCode from the source String and calling JSC::evaluate. ScriptSourceCode would construct a JSC::StringSourceProvider, which would keep the source String alive for the lifetime of the provider. This is problematic since those worker scripts may be big and keeping heap-allocated version of them in memory is expensive. To address the issue, this patch introduces a new JSC::SourceProvider subclass named ScriptBufferSourceProvider, which uses a ScriptBuffer internally. ScriptBuffer has the benefit of being able to hold file-mapped data. We only convert the ScriptBuffer to a String whenever necessary (When the script contains non-ascii characters and JSC requests a StringView to the script). If we do end up converting the ScriptBuffer to a String, this String will get cleared on memory pressure. This is similar to what CachedScriptSourceProvider / CachedScript do on the main thread. In the warm case, where the service worker script is coming from disk, we create the ScriptBufferSourceProvider right away from a file-mapped ScriptBuffer, thus greatly reducing dirty memory use. In the cold case, we initially construct the ScriptBufferSourceProvider using a ScriptBuffer that is not file-mapped. However, once the script is saved to disk (via SWScriptStorage), we replace the ScriptBufferSourceProvider's ScriptBuffer with the new file-mapped version in order to reduce dirty memory use in this case too. * WebCore.xcodeproj/project.pbxproj: Add ScriptBufferSourceProvider.h to the project. * bindings/js/ScriptBufferSourceProvider.h: Added. - Add new ScriptBufferSourceProvider, which is a JSC::SourceProvider subclass that uses a ScriptBuffer as backing instead of a String. This allows us to use file-mapped memory whenever possible, thus reducing dirty memory use. This provider provides similar functionality to CachedScriptSourceProvider / CachedScript but works with a ScriptBuffer and can be used off the main thread. - We only transform the SharedBuffer into a String when strictly necessary, meaning that the ScriptBuffer contains non-ascii characters and JSC is asking for a StringView to the script. - The class supports clearing the String copy of the script (done on memory pressure) and replacing the ScriptBuffer (with a new file-mapped version). * bindings/js/ScriptSourceCode.h: (WebCore::ScriptSourceCode::ScriptSourceCode): (WebCore::ScriptSourceCode::m_code): (WebCore::ScriptSourceCode::provider): Add new constructors taking a ScriptBuffer instead of a String for the source code. We then use the new ScriptBufferSourceProvider internally instead of the StringSourceProvider. * workers/DedicatedWorkerThread.cpp: (WebCore::DedicatedWorkerThread::DedicatedWorkerThread): * workers/DedicatedWorkerThread.h: Use ScriptBuffer instead of String. * workers/ScriptBuffer.cpp: (WebCore::ScriptBuffer::empty): (WebCore::ScriptBuffer::append): (WebCore::operator!=): * workers/ScriptBuffer.h: (WebCore::ScriptBuffer::isEmpty const): Add some functionality to SCriptBuffer to make it more convenient to use. * workers/Worker.cpp: (WebCore::Worker::notifyFinished): Convert ScriptBuffer to a String since this is what WebInspector expects. * workers/WorkerGlobalScope.cpp: (WebCore::WorkerGlobalScope::importScripts): - When importing a new script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. (WebCore::WorkerGlobalScope::releaseMemory): In addition to deleting JS code and doing garbage collection, we now also ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source. (WebCore::WorkerGlobalScope::deleteJSCodeAndGC): Moved the logic to delete JS code and doing GC from releaseMemory() to a new function, now that releaseMemory() needs to do more things. (WebCore::WorkerGlobalScope::setMainScriptSourceProvider): (WebCore::WorkerGlobalScope::addImportedScriptSourceProvider): Functions used to store the CachedScriptSourceProvider objects for the scripts used by the worker on the WorkerGlobalScope. We keep weak pointers to those. (WebCore::WorkerGlobalScope::clearDecodedScriptData): Function used to ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. (WebCore::WorkerGlobalScope::updateSourceProviderBuffers): Function used to ask the ScriptBufferSourceProvider objects to replace their ScriptBuffers with file-backed versions. * workers/WorkerGlobalScope.h: * workers/WorkerGlobalScopeProxy.h: * workers/WorkerMessagingProxy.cpp: (WebCore::WorkerMessagingProxy::startWorkerGlobalScope): * workers/WorkerMessagingProxy.h: Use ScriptBuffer instead of String. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::WorkerScriptLoader): (WebCore::WorkerScriptLoader::loadSynchronously): (WebCore::WorkerScriptLoader::didReceiveData): * workers/WorkerScriptLoader.h: (WebCore::WorkerScriptLoader::script): Use ScriptBuffer instead of String to hold the script source. We eventually need a ScriptBuffer since this is what the Worker now needs to launch. Also, in the service worker case, we may get a ScriptBuffer right away from the scriptResourceMap, without going to the network at all. * workers/WorkerThread.cpp: (WebCore::WorkerThreadStartupData::WorkerThreadStartupData): (WebCore::WorkerThread::WorkerThread): Use ScriptBuffer instead of String. (WebCore::WorkerThread::evaluateScriptIfNecessary): - When evaluating the main worker script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. * workers/WorkerThread.h: * workers/service/ServiceWorkerContainer.cpp: (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript): * workers/service/ServiceWorkerContainer.h: * workers/service/ServiceWorkerFetchResult.h: * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerJobClient.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/server/SWServer.cpp: (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): Use ScriptBuffer instead of String. Source/WebKit: * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp: (WebKit::ServiceWorkerSoftUpdateLoader::didFinishLoading): Canonical link: https://commits.webkit.org/236125@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-06 01:05:24 +00:00
static ScriptBuffer empty();
WEBCORE_EXPORT explicit ScriptBuffer(const String&);
Introduce ScriptBuffer class to wrap SharedBuffer containing a script https://bugs.webkit.org/show_bug.cgi?id=224092 Reviewed by Yusuke Suzuki and Geoff Garen. Introduce ScriptBuffer class to wrap SharedBuffer containing a script. We started using SharedBuffer to represent worker scripts instead of String, so that they can hold file mapped data and be shared across processes. This patch introduces a new ScriptBuffer to wrap those SharedBuffers. The type makes it clearer what type of data we're dealing with. The helper functions used to convert between String and SharedBuffer can now simply be member functions on ScriptBuffer. This also simplifies IPC code. Source/WebCore: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: Add new ScriptBuffer class to project files. * inspector/agents/worker/ServiceWorkerAgent.cpp: (WebCore::ServiceWorkerAgent::getInitializationInfo): Use ScriptBuffer::toString() instead of scriptBufferToString(). * workers/ScriptBuffer.cpp: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::toString const): (WebCore::ScriptBuffer::containsSingleFileMappedSegment const): (WebCore::operator==): * workers/ScriptBuffer.h: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::buffer const): (WebCore::ScriptBuffer::isolatedCopy const): (WebCore::ScriptBuffer::operator bool const): New ScriptBuffer class that wraps a SharedBuffer representation of a script. This class helps make it clear what data we're dealing with. It also facilitates conversion to and from a String when needed. The class also has its own IPC coder at WebKit layer to encode the script as a ShareableResource when file mapped. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::loadSynchronously): Use ScriptBuffer::toString() instead of scriptBufferToString(). And use StringBuffer constructor that takes a String instead of stringToScriptBuffer(). * workers/service/SWClientConnection.h: * workers/service/ServiceWorkerContextData.cpp: (WebCore::ServiceWorkerContextData::isolatedCopy const): * workers/service/ServiceWorkerContextData.h: (WebCore::ServiceWorkerContextData::ImportedScript::encode const): (WebCore::ServiceWorkerContextData::ImportedScript::decode): (WebCore::ServiceWorkerContextData::ImportedScript::isolatedCopy const): (WebCore::ServiceWorkerContextData::encode const): (WebCore::ServiceWorkerContextData::decode): - Use ScriptBuffer instead of RefPtr<SharedBuffer> for scripts. - Drop scriptBufferToString() & stringToScriptBuffer() as they are no longer needed. - Move IPC coders for ServiceWorkerContextData back from WebCoreArgumentCoders back to the WebCore class, now that the coders no longer need to deal with ShareableResource directly. We now encode / decode ScriptBuffer objects and its coder takes care of using a ShareableResource whenever possible. * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerGlobalScope.h: * workers/service/context/SWContextManager.cpp: (WebCore::SWContextManager::didSaveScriptsToDisk): * workers/service/context/SWContextManager.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/context/ServiceWorkerThreadProxy.cpp: (WebCore::ServiceWorkerThreadProxy::didSaveScriptsToDisk): * workers/service/context/ServiceWorkerThreadProxy.h: * workers/service/server/RegistrationDatabase.cpp: (WebCore::RegistrationDatabase::doPushChanges): (WebCore::RegistrationDatabase::importRecords): * workers/service/server/RegistrationStore.cpp: (WebCore::RegistrationStore::didSaveWorkerScriptsToDisk): * workers/service/server/RegistrationStore.h: * workers/service/server/SWScriptStorage.cpp: (WebCore::SWScriptStorage::store): (WebCore::SWScriptStorage::retrieve): * workers/service/server/SWScriptStorage.h: * workers/service/server/SWServer.cpp: (WebCore::SWServer::didSaveWorkerScriptsToDisk): (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): * workers/service/server/SWServerToContextConnection.h: * workers/service/server/SWServerWorker.cpp: (WebCore::SWServerWorker::SWServerWorker): (WebCore::SWServerWorker::didSaveScriptsToDisk): * workers/service/server/SWServerWorker.h: (WebCore::SWServerWorker::script const): Use ScriptBuffer instead of SharedBuffer. Source/WebKit: * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: (WebKit::WebSWServerToContextConnection::didSaveScriptsToDisk): * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: Use ScriptBuffer instead SharedBuffer. * Shared/WebCoreArgumentCoders.cpp: (IPC::tryConvertToShareableResourceHandle): (IPC::decodeScriptBufferAsShareableResourceHandle): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::encode): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::decode): * Shared/WebCoreArgumentCoders.h: - Add IPC encoder / decoder for ScriptBuffer which tries to encode / decode as a ShareableResource whenever possible (single segment that is file mapped). This logic used to be in the ServiceWorkerContextData coders. Now that the logic is in the ScriptBuffer coder, the ServiceWorkerContextData encoding / decoding becomes much simpler. - Moved ServiceWorkerContextData coders from WebCoreArgumentCoders back to its class in WebCore, now that they no longer need to deal with ShareableResource directly. * WebProcess/Storage/WebSWContextManagerConnection.cpp: (WebKit::WebSWContextManagerConnection::didSaveScriptsToDisk): * WebProcess/Storage/WebSWContextManagerConnection.h: * WebProcess/Storage/WebSWContextManagerConnection.messages.in: Send scripts over IPC as ScriptBuffer instead of using ShareableResource directly. The new IPC encoder / decoder for ScriptBuffer takes care of using ShareableResource for us. Canonical link: https://commits.webkit.org/236104@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-02 21:53:30 +00:00
String toString() const;
SharedBuffer* buffer() const { return m_buffer.get(); }
ScriptBuffer isolatedCopy() const { return ScriptBuffer(m_buffer ? RefPtr<SharedBuffer>(m_buffer->copy()) : nullptr); }
explicit operator bool() const { return !!m_buffer; }
Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible https://bugs.webkit.org/show_bug.cgi?id=224088 Reviewed by Yusuke Suzuki. Source/WebCore: To run a worker, we were constructing a ScriptSourceCode from the source String and calling JSC::evaluate. ScriptSourceCode would construct a JSC::StringSourceProvider, which would keep the source String alive for the lifetime of the provider. This is problematic since those worker scripts may be big and keeping heap-allocated version of them in memory is expensive. To address the issue, this patch introduces a new JSC::SourceProvider subclass named ScriptBufferSourceProvider, which uses a ScriptBuffer internally. ScriptBuffer has the benefit of being able to hold file-mapped data. We only convert the ScriptBuffer to a String whenever necessary (When the script contains non-ascii characters and JSC requests a StringView to the script). If we do end up converting the ScriptBuffer to a String, this String will get cleared on memory pressure. This is similar to what CachedScriptSourceProvider / CachedScript do on the main thread. In the warm case, where the service worker script is coming from disk, we create the ScriptBufferSourceProvider right away from a file-mapped ScriptBuffer, thus greatly reducing dirty memory use. In the cold case, we initially construct the ScriptBufferSourceProvider using a ScriptBuffer that is not file-mapped. However, once the script is saved to disk (via SWScriptStorage), we replace the ScriptBufferSourceProvider's ScriptBuffer with the new file-mapped version in order to reduce dirty memory use in this case too. * WebCore.xcodeproj/project.pbxproj: Add ScriptBufferSourceProvider.h to the project. * bindings/js/ScriptBufferSourceProvider.h: Added. - Add new ScriptBufferSourceProvider, which is a JSC::SourceProvider subclass that uses a ScriptBuffer as backing instead of a String. This allows us to use file-mapped memory whenever possible, thus reducing dirty memory use. This provider provides similar functionality to CachedScriptSourceProvider / CachedScript but works with a ScriptBuffer and can be used off the main thread. - We only transform the SharedBuffer into a String when strictly necessary, meaning that the ScriptBuffer contains non-ascii characters and JSC is asking for a StringView to the script. - The class supports clearing the String copy of the script (done on memory pressure) and replacing the ScriptBuffer (with a new file-mapped version). * bindings/js/ScriptSourceCode.h: (WebCore::ScriptSourceCode::ScriptSourceCode): (WebCore::ScriptSourceCode::m_code): (WebCore::ScriptSourceCode::provider): Add new constructors taking a ScriptBuffer instead of a String for the source code. We then use the new ScriptBufferSourceProvider internally instead of the StringSourceProvider. * workers/DedicatedWorkerThread.cpp: (WebCore::DedicatedWorkerThread::DedicatedWorkerThread): * workers/DedicatedWorkerThread.h: Use ScriptBuffer instead of String. * workers/ScriptBuffer.cpp: (WebCore::ScriptBuffer::empty): (WebCore::ScriptBuffer::append): (WebCore::operator!=): * workers/ScriptBuffer.h: (WebCore::ScriptBuffer::isEmpty const): Add some functionality to SCriptBuffer to make it more convenient to use. * workers/Worker.cpp: (WebCore::Worker::notifyFinished): Convert ScriptBuffer to a String since this is what WebInspector expects. * workers/WorkerGlobalScope.cpp: (WebCore::WorkerGlobalScope::importScripts): - When importing a new script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. (WebCore::WorkerGlobalScope::releaseMemory): In addition to deleting JS code and doing garbage collection, we now also ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source. (WebCore::WorkerGlobalScope::deleteJSCodeAndGC): Moved the logic to delete JS code and doing GC from releaseMemory() to a new function, now that releaseMemory() needs to do more things. (WebCore::WorkerGlobalScope::setMainScriptSourceProvider): (WebCore::WorkerGlobalScope::addImportedScriptSourceProvider): Functions used to store the CachedScriptSourceProvider objects for the scripts used by the worker on the WorkerGlobalScope. We keep weak pointers to those. (WebCore::WorkerGlobalScope::clearDecodedScriptData): Function used to ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. (WebCore::WorkerGlobalScope::updateSourceProviderBuffers): Function used to ask the ScriptBufferSourceProvider objects to replace their ScriptBuffers with file-backed versions. * workers/WorkerGlobalScope.h: * workers/WorkerGlobalScopeProxy.h: * workers/WorkerMessagingProxy.cpp: (WebCore::WorkerMessagingProxy::startWorkerGlobalScope): * workers/WorkerMessagingProxy.h: Use ScriptBuffer instead of String. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::WorkerScriptLoader): (WebCore::WorkerScriptLoader::loadSynchronously): (WebCore::WorkerScriptLoader::didReceiveData): * workers/WorkerScriptLoader.h: (WebCore::WorkerScriptLoader::script): Use ScriptBuffer instead of String to hold the script source. We eventually need a ScriptBuffer since this is what the Worker now needs to launch. Also, in the service worker case, we may get a ScriptBuffer right away from the scriptResourceMap, without going to the network at all. * workers/WorkerThread.cpp: (WebCore::WorkerThreadStartupData::WorkerThreadStartupData): (WebCore::WorkerThread::WorkerThread): Use ScriptBuffer instead of String. (WebCore::WorkerThread::evaluateScriptIfNecessary): - When evaluating the main worker script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. * workers/WorkerThread.h: * workers/service/ServiceWorkerContainer.cpp: (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript): * workers/service/ServiceWorkerContainer.h: * workers/service/ServiceWorkerFetchResult.h: * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerJobClient.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/server/SWServer.cpp: (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): Use ScriptBuffer instead of String. Source/WebKit: * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp: (WebKit::ServiceWorkerSoftUpdateLoader::didFinishLoading): Canonical link: https://commits.webkit.org/236125@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-06 01:05:24 +00:00
bool isEmpty() const { return !m_buffer || !m_buffer->size(); }
Introduce ScriptBuffer class to wrap SharedBuffer containing a script https://bugs.webkit.org/show_bug.cgi?id=224092 Reviewed by Yusuke Suzuki and Geoff Garen. Introduce ScriptBuffer class to wrap SharedBuffer containing a script. We started using SharedBuffer to represent worker scripts instead of String, so that they can hold file mapped data and be shared across processes. This patch introduces a new ScriptBuffer to wrap those SharedBuffers. The type makes it clearer what type of data we're dealing with. The helper functions used to convert between String and SharedBuffer can now simply be member functions on ScriptBuffer. This also simplifies IPC code. Source/WebCore: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: Add new ScriptBuffer class to project files. * inspector/agents/worker/ServiceWorkerAgent.cpp: (WebCore::ServiceWorkerAgent::getInitializationInfo): Use ScriptBuffer::toString() instead of scriptBufferToString(). * workers/ScriptBuffer.cpp: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::toString const): (WebCore::ScriptBuffer::containsSingleFileMappedSegment const): (WebCore::operator==): * workers/ScriptBuffer.h: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::buffer const): (WebCore::ScriptBuffer::isolatedCopy const): (WebCore::ScriptBuffer::operator bool const): New ScriptBuffer class that wraps a SharedBuffer representation of a script. This class helps make it clear what data we're dealing with. It also facilitates conversion to and from a String when needed. The class also has its own IPC coder at WebKit layer to encode the script as a ShareableResource when file mapped. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::loadSynchronously): Use ScriptBuffer::toString() instead of scriptBufferToString(). And use StringBuffer constructor that takes a String instead of stringToScriptBuffer(). * workers/service/SWClientConnection.h: * workers/service/ServiceWorkerContextData.cpp: (WebCore::ServiceWorkerContextData::isolatedCopy const): * workers/service/ServiceWorkerContextData.h: (WebCore::ServiceWorkerContextData::ImportedScript::encode const): (WebCore::ServiceWorkerContextData::ImportedScript::decode): (WebCore::ServiceWorkerContextData::ImportedScript::isolatedCopy const): (WebCore::ServiceWorkerContextData::encode const): (WebCore::ServiceWorkerContextData::decode): - Use ScriptBuffer instead of RefPtr<SharedBuffer> for scripts. - Drop scriptBufferToString() & stringToScriptBuffer() as they are no longer needed. - Move IPC coders for ServiceWorkerContextData back from WebCoreArgumentCoders back to the WebCore class, now that the coders no longer need to deal with ShareableResource directly. We now encode / decode ScriptBuffer objects and its coder takes care of using a ShareableResource whenever possible. * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerGlobalScope.h: * workers/service/context/SWContextManager.cpp: (WebCore::SWContextManager::didSaveScriptsToDisk): * workers/service/context/SWContextManager.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/context/ServiceWorkerThreadProxy.cpp: (WebCore::ServiceWorkerThreadProxy::didSaveScriptsToDisk): * workers/service/context/ServiceWorkerThreadProxy.h: * workers/service/server/RegistrationDatabase.cpp: (WebCore::RegistrationDatabase::doPushChanges): (WebCore::RegistrationDatabase::importRecords): * workers/service/server/RegistrationStore.cpp: (WebCore::RegistrationStore::didSaveWorkerScriptsToDisk): * workers/service/server/RegistrationStore.h: * workers/service/server/SWScriptStorage.cpp: (WebCore::SWScriptStorage::store): (WebCore::SWScriptStorage::retrieve): * workers/service/server/SWScriptStorage.h: * workers/service/server/SWServer.cpp: (WebCore::SWServer::didSaveWorkerScriptsToDisk): (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): * workers/service/server/SWServerToContextConnection.h: * workers/service/server/SWServerWorker.cpp: (WebCore::SWServerWorker::SWServerWorker): (WebCore::SWServerWorker::didSaveScriptsToDisk): * workers/service/server/SWServerWorker.h: (WebCore::SWServerWorker::script const): Use ScriptBuffer instead of SharedBuffer. Source/WebKit: * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: (WebKit::WebSWServerToContextConnection::didSaveScriptsToDisk): * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: Use ScriptBuffer instead SharedBuffer. * Shared/WebCoreArgumentCoders.cpp: (IPC::tryConvertToShareableResourceHandle): (IPC::decodeScriptBufferAsShareableResourceHandle): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::encode): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::decode): * Shared/WebCoreArgumentCoders.h: - Add IPC encoder / decoder for ScriptBuffer which tries to encode / decode as a ShareableResource whenever possible (single segment that is file mapped). This logic used to be in the ServiceWorkerContextData coders. Now that the logic is in the ScriptBuffer coder, the ServiceWorkerContextData encoding / decoding becomes much simpler. - Moved ServiceWorkerContextData coders from WebCoreArgumentCoders back to its class in WebCore, now that they no longer need to deal with ShareableResource directly. * WebProcess/Storage/WebSWContextManagerConnection.cpp: (WebKit::WebSWContextManagerConnection::didSaveScriptsToDisk): * WebProcess/Storage/WebSWContextManagerConnection.h: * WebProcess/Storage/WebSWContextManagerConnection.messages.in: Send scripts over IPC as ScriptBuffer instead of using ShareableResource directly. The new IPC encoder / decoder for ScriptBuffer takes care of using ShareableResource for us. Canonical link: https://commits.webkit.org/236104@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-02 21:53:30 +00:00
WEBCORE_EXPORT bool containsSingleFileMappedSegment() const;
Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible https://bugs.webkit.org/show_bug.cgi?id=224088 Reviewed by Yusuke Suzuki. Source/WebCore: To run a worker, we were constructing a ScriptSourceCode from the source String and calling JSC::evaluate. ScriptSourceCode would construct a JSC::StringSourceProvider, which would keep the source String alive for the lifetime of the provider. This is problematic since those worker scripts may be big and keeping heap-allocated version of them in memory is expensive. To address the issue, this patch introduces a new JSC::SourceProvider subclass named ScriptBufferSourceProvider, which uses a ScriptBuffer internally. ScriptBuffer has the benefit of being able to hold file-mapped data. We only convert the ScriptBuffer to a String whenever necessary (When the script contains non-ascii characters and JSC requests a StringView to the script). If we do end up converting the ScriptBuffer to a String, this String will get cleared on memory pressure. This is similar to what CachedScriptSourceProvider / CachedScript do on the main thread. In the warm case, where the service worker script is coming from disk, we create the ScriptBufferSourceProvider right away from a file-mapped ScriptBuffer, thus greatly reducing dirty memory use. In the cold case, we initially construct the ScriptBufferSourceProvider using a ScriptBuffer that is not file-mapped. However, once the script is saved to disk (via SWScriptStorage), we replace the ScriptBufferSourceProvider's ScriptBuffer with the new file-mapped version in order to reduce dirty memory use in this case too. * WebCore.xcodeproj/project.pbxproj: Add ScriptBufferSourceProvider.h to the project. * bindings/js/ScriptBufferSourceProvider.h: Added. - Add new ScriptBufferSourceProvider, which is a JSC::SourceProvider subclass that uses a ScriptBuffer as backing instead of a String. This allows us to use file-mapped memory whenever possible, thus reducing dirty memory use. This provider provides similar functionality to CachedScriptSourceProvider / CachedScript but works with a ScriptBuffer and can be used off the main thread. - We only transform the SharedBuffer into a String when strictly necessary, meaning that the ScriptBuffer contains non-ascii characters and JSC is asking for a StringView to the script. - The class supports clearing the String copy of the script (done on memory pressure) and replacing the ScriptBuffer (with a new file-mapped version). * bindings/js/ScriptSourceCode.h: (WebCore::ScriptSourceCode::ScriptSourceCode): (WebCore::ScriptSourceCode::m_code): (WebCore::ScriptSourceCode::provider): Add new constructors taking a ScriptBuffer instead of a String for the source code. We then use the new ScriptBufferSourceProvider internally instead of the StringSourceProvider. * workers/DedicatedWorkerThread.cpp: (WebCore::DedicatedWorkerThread::DedicatedWorkerThread): * workers/DedicatedWorkerThread.h: Use ScriptBuffer instead of String. * workers/ScriptBuffer.cpp: (WebCore::ScriptBuffer::empty): (WebCore::ScriptBuffer::append): (WebCore::operator!=): * workers/ScriptBuffer.h: (WebCore::ScriptBuffer::isEmpty const): Add some functionality to SCriptBuffer to make it more convenient to use. * workers/Worker.cpp: (WebCore::Worker::notifyFinished): Convert ScriptBuffer to a String since this is what WebInspector expects. * workers/WorkerGlobalScope.cpp: (WebCore::WorkerGlobalScope::importScripts): - When importing a new script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. (WebCore::WorkerGlobalScope::releaseMemory): In addition to deleting JS code and doing garbage collection, we now also ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source. (WebCore::WorkerGlobalScope::deleteJSCodeAndGC): Moved the logic to delete JS code and doing GC from releaseMemory() to a new function, now that releaseMemory() needs to do more things. (WebCore::WorkerGlobalScope::setMainScriptSourceProvider): (WebCore::WorkerGlobalScope::addImportedScriptSourceProvider): Functions used to store the CachedScriptSourceProvider objects for the scripts used by the worker on the WorkerGlobalScope. We keep weak pointers to those. (WebCore::WorkerGlobalScope::clearDecodedScriptData): Function used to ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. (WebCore::WorkerGlobalScope::updateSourceProviderBuffers): Function used to ask the ScriptBufferSourceProvider objects to replace their ScriptBuffers with file-backed versions. * workers/WorkerGlobalScope.h: * workers/WorkerGlobalScopeProxy.h: * workers/WorkerMessagingProxy.cpp: (WebCore::WorkerMessagingProxy::startWorkerGlobalScope): * workers/WorkerMessagingProxy.h: Use ScriptBuffer instead of String. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::WorkerScriptLoader): (WebCore::WorkerScriptLoader::loadSynchronously): (WebCore::WorkerScriptLoader::didReceiveData): * workers/WorkerScriptLoader.h: (WebCore::WorkerScriptLoader::script): Use ScriptBuffer instead of String to hold the script source. We eventually need a ScriptBuffer since this is what the Worker now needs to launch. Also, in the service worker case, we may get a ScriptBuffer right away from the scriptResourceMap, without going to the network at all. * workers/WorkerThread.cpp: (WebCore::WorkerThreadStartupData::WorkerThreadStartupData): (WebCore::WorkerThread::WorkerThread): Use ScriptBuffer instead of String. (WebCore::WorkerThread::evaluateScriptIfNecessary): - When evaluating the main worker script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. * workers/WorkerThread.h: * workers/service/ServiceWorkerContainer.cpp: (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript): * workers/service/ServiceWorkerContainer.h: * workers/service/ServiceWorkerFetchResult.h: * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerJobClient.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/server/SWServer.cpp: (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): Use ScriptBuffer instead of String. Source/WebKit: * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp: (WebKit::ServiceWorkerSoftUpdateLoader::didFinishLoading): Canonical link: https://commits.webkit.org/236125@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-06 01:05:24 +00:00
void append(const String&);
Introduce ScriptBuffer class to wrap SharedBuffer containing a script https://bugs.webkit.org/show_bug.cgi?id=224092 Reviewed by Yusuke Suzuki and Geoff Garen. Introduce ScriptBuffer class to wrap SharedBuffer containing a script. We started using SharedBuffer to represent worker scripts instead of String, so that they can hold file mapped data and be shared across processes. This patch introduces a new ScriptBuffer to wrap those SharedBuffers. The type makes it clearer what type of data we're dealing with. The helper functions used to convert between String and SharedBuffer can now simply be member functions on ScriptBuffer. This also simplifies IPC code. Source/WebCore: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: Add new ScriptBuffer class to project files. * inspector/agents/worker/ServiceWorkerAgent.cpp: (WebCore::ServiceWorkerAgent::getInitializationInfo): Use ScriptBuffer::toString() instead of scriptBufferToString(). * workers/ScriptBuffer.cpp: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::toString const): (WebCore::ScriptBuffer::containsSingleFileMappedSegment const): (WebCore::operator==): * workers/ScriptBuffer.h: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::buffer const): (WebCore::ScriptBuffer::isolatedCopy const): (WebCore::ScriptBuffer::operator bool const): New ScriptBuffer class that wraps a SharedBuffer representation of a script. This class helps make it clear what data we're dealing with. It also facilitates conversion to and from a String when needed. The class also has its own IPC coder at WebKit layer to encode the script as a ShareableResource when file mapped. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::loadSynchronously): Use ScriptBuffer::toString() instead of scriptBufferToString(). And use StringBuffer constructor that takes a String instead of stringToScriptBuffer(). * workers/service/SWClientConnection.h: * workers/service/ServiceWorkerContextData.cpp: (WebCore::ServiceWorkerContextData::isolatedCopy const): * workers/service/ServiceWorkerContextData.h: (WebCore::ServiceWorkerContextData::ImportedScript::encode const): (WebCore::ServiceWorkerContextData::ImportedScript::decode): (WebCore::ServiceWorkerContextData::ImportedScript::isolatedCopy const): (WebCore::ServiceWorkerContextData::encode const): (WebCore::ServiceWorkerContextData::decode): - Use ScriptBuffer instead of RefPtr<SharedBuffer> for scripts. - Drop scriptBufferToString() & stringToScriptBuffer() as they are no longer needed. - Move IPC coders for ServiceWorkerContextData back from WebCoreArgumentCoders back to the WebCore class, now that the coders no longer need to deal with ShareableResource directly. We now encode / decode ScriptBuffer objects and its coder takes care of using a ShareableResource whenever possible. * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerGlobalScope.h: * workers/service/context/SWContextManager.cpp: (WebCore::SWContextManager::didSaveScriptsToDisk): * workers/service/context/SWContextManager.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/context/ServiceWorkerThreadProxy.cpp: (WebCore::ServiceWorkerThreadProxy::didSaveScriptsToDisk): * workers/service/context/ServiceWorkerThreadProxy.h: * workers/service/server/RegistrationDatabase.cpp: (WebCore::RegistrationDatabase::doPushChanges): (WebCore::RegistrationDatabase::importRecords): * workers/service/server/RegistrationStore.cpp: (WebCore::RegistrationStore::didSaveWorkerScriptsToDisk): * workers/service/server/RegistrationStore.h: * workers/service/server/SWScriptStorage.cpp: (WebCore::SWScriptStorage::store): (WebCore::SWScriptStorage::retrieve): * workers/service/server/SWScriptStorage.h: * workers/service/server/SWServer.cpp: (WebCore::SWServer::didSaveWorkerScriptsToDisk): (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): * workers/service/server/SWServerToContextConnection.h: * workers/service/server/SWServerWorker.cpp: (WebCore::SWServerWorker::SWServerWorker): (WebCore::SWServerWorker::didSaveScriptsToDisk): * workers/service/server/SWServerWorker.h: (WebCore::SWServerWorker::script const): Use ScriptBuffer instead of SharedBuffer. Source/WebKit: * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: (WebKit::WebSWServerToContextConnection::didSaveScriptsToDisk): * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: Use ScriptBuffer instead SharedBuffer. * Shared/WebCoreArgumentCoders.cpp: (IPC::tryConvertToShareableResourceHandle): (IPC::decodeScriptBufferAsShareableResourceHandle): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::encode): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::decode): * Shared/WebCoreArgumentCoders.h: - Add IPC encoder / decoder for ScriptBuffer which tries to encode / decode as a ShareableResource whenever possible (single segment that is file mapped). This logic used to be in the ServiceWorkerContextData coders. Now that the logic is in the ScriptBuffer coder, the ServiceWorkerContextData encoding / decoding becomes much simpler. - Moved ServiceWorkerContextData coders from WebCoreArgumentCoders back to its class in WebCore, now that they no longer need to deal with ShareableResource directly. * WebProcess/Storage/WebSWContextManagerConnection.cpp: (WebKit::WebSWContextManagerConnection::didSaveScriptsToDisk): * WebProcess/Storage/WebSWContextManagerConnection.h: * WebProcess/Storage/WebSWContextManagerConnection.messages.in: Send scripts over IPC as ScriptBuffer instead of using ShareableResource directly. The new IPC encoder / decoder for ScriptBuffer takes care of using ShareableResource for us. Canonical link: https://commits.webkit.org/236104@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-02 21:53:30 +00:00
private:
RefPtr<SharedBuffer> m_buffer; // Contains the UTF-8 encoded script.
};
bool operator==(const ScriptBuffer&, const ScriptBuffer&);
Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible https://bugs.webkit.org/show_bug.cgi?id=224088 Reviewed by Yusuke Suzuki. Source/WebCore: To run a worker, we were constructing a ScriptSourceCode from the source String and calling JSC::evaluate. ScriptSourceCode would construct a JSC::StringSourceProvider, which would keep the source String alive for the lifetime of the provider. This is problematic since those worker scripts may be big and keeping heap-allocated version of them in memory is expensive. To address the issue, this patch introduces a new JSC::SourceProvider subclass named ScriptBufferSourceProvider, which uses a ScriptBuffer internally. ScriptBuffer has the benefit of being able to hold file-mapped data. We only convert the ScriptBuffer to a String whenever necessary (When the script contains non-ascii characters and JSC requests a StringView to the script). If we do end up converting the ScriptBuffer to a String, this String will get cleared on memory pressure. This is similar to what CachedScriptSourceProvider / CachedScript do on the main thread. In the warm case, where the service worker script is coming from disk, we create the ScriptBufferSourceProvider right away from a file-mapped ScriptBuffer, thus greatly reducing dirty memory use. In the cold case, we initially construct the ScriptBufferSourceProvider using a ScriptBuffer that is not file-mapped. However, once the script is saved to disk (via SWScriptStorage), we replace the ScriptBufferSourceProvider's ScriptBuffer with the new file-mapped version in order to reduce dirty memory use in this case too. * WebCore.xcodeproj/project.pbxproj: Add ScriptBufferSourceProvider.h to the project. * bindings/js/ScriptBufferSourceProvider.h: Added. - Add new ScriptBufferSourceProvider, which is a JSC::SourceProvider subclass that uses a ScriptBuffer as backing instead of a String. This allows us to use file-mapped memory whenever possible, thus reducing dirty memory use. This provider provides similar functionality to CachedScriptSourceProvider / CachedScript but works with a ScriptBuffer and can be used off the main thread. - We only transform the SharedBuffer into a String when strictly necessary, meaning that the ScriptBuffer contains non-ascii characters and JSC is asking for a StringView to the script. - The class supports clearing the String copy of the script (done on memory pressure) and replacing the ScriptBuffer (with a new file-mapped version). * bindings/js/ScriptSourceCode.h: (WebCore::ScriptSourceCode::ScriptSourceCode): (WebCore::ScriptSourceCode::m_code): (WebCore::ScriptSourceCode::provider): Add new constructors taking a ScriptBuffer instead of a String for the source code. We then use the new ScriptBufferSourceProvider internally instead of the StringSourceProvider. * workers/DedicatedWorkerThread.cpp: (WebCore::DedicatedWorkerThread::DedicatedWorkerThread): * workers/DedicatedWorkerThread.h: Use ScriptBuffer instead of String. * workers/ScriptBuffer.cpp: (WebCore::ScriptBuffer::empty): (WebCore::ScriptBuffer::append): (WebCore::operator!=): * workers/ScriptBuffer.h: (WebCore::ScriptBuffer::isEmpty const): Add some functionality to SCriptBuffer to make it more convenient to use. * workers/Worker.cpp: (WebCore::Worker::notifyFinished): Convert ScriptBuffer to a String since this is what WebInspector expects. * workers/WorkerGlobalScope.cpp: (WebCore::WorkerGlobalScope::importScripts): - When importing a new script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. (WebCore::WorkerGlobalScope::releaseMemory): In addition to deleting JS code and doing garbage collection, we now also ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source. (WebCore::WorkerGlobalScope::deleteJSCodeAndGC): Moved the logic to delete JS code and doing GC from releaseMemory() to a new function, now that releaseMemory() needs to do more things. (WebCore::WorkerGlobalScope::setMainScriptSourceProvider): (WebCore::WorkerGlobalScope::addImportedScriptSourceProvider): Functions used to store the CachedScriptSourceProvider objects for the scripts used by the worker on the WorkerGlobalScope. We keep weak pointers to those. (WebCore::WorkerGlobalScope::clearDecodedScriptData): Function used to ask the ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. (WebCore::WorkerGlobalScope::updateSourceProviderBuffers): Function used to ask the ScriptBufferSourceProvider objects to replace their ScriptBuffers with file-backed versions. * workers/WorkerGlobalScope.h: * workers/WorkerGlobalScopeProxy.h: * workers/WorkerMessagingProxy.cpp: (WebCore::WorkerMessagingProxy::startWorkerGlobalScope): * workers/WorkerMessagingProxy.h: Use ScriptBuffer instead of String. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::WorkerScriptLoader): (WebCore::WorkerScriptLoader::loadSynchronously): (WebCore::WorkerScriptLoader::didReceiveData): * workers/WorkerScriptLoader.h: (WebCore::WorkerScriptLoader::script): Use ScriptBuffer instead of String to hold the script source. We eventually need a ScriptBuffer since this is what the Worker now needs to launch. Also, in the service worker case, we may get a ScriptBuffer right away from the scriptResourceMap, without going to the network at all. * workers/WorkerThread.cpp: (WebCore::WorkerThreadStartupData::WorkerThreadStartupData): (WebCore::WorkerThread::WorkerThread): Use ScriptBuffer instead of String. (WebCore::WorkerThread::evaluateScriptIfNecessary): - When evaluating the main worker script, we now construct a ScriptSourceCode from a ScriptBuffer instead of a String. - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects to clear their cached String representation of the script source on memory pressure. It is also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped version when one becomes available. * workers/WorkerThread.h: * workers/service/ServiceWorkerContainer.cpp: (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript): * workers/service/ServiceWorkerContainer.h: * workers/service/ServiceWorkerFetchResult.h: * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerJobClient.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/server/SWServer.cpp: (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): Use ScriptBuffer instead of String. Source/WebKit: * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp: (WebKit::ServiceWorkerSoftUpdateLoader::didFinishLoading): Canonical link: https://commits.webkit.org/236125@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275465 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-06 01:05:24 +00:00
bool operator!=(const ScriptBuffer&, const ScriptBuffer&);
Introduce ScriptBuffer class to wrap SharedBuffer containing a script https://bugs.webkit.org/show_bug.cgi?id=224092 Reviewed by Yusuke Suzuki and Geoff Garen. Introduce ScriptBuffer class to wrap SharedBuffer containing a script. We started using SharedBuffer to represent worker scripts instead of String, so that they can hold file mapped data and be shared across processes. This patch introduces a new ScriptBuffer to wrap those SharedBuffers. The type makes it clearer what type of data we're dealing with. The helper functions used to convert between String and SharedBuffer can now simply be member functions on ScriptBuffer. This also simplifies IPC code. Source/WebCore: * Sources.txt: * WebCore.xcodeproj/project.pbxproj: Add new ScriptBuffer class to project files. * inspector/agents/worker/ServiceWorkerAgent.cpp: (WebCore::ServiceWorkerAgent::getInitializationInfo): Use ScriptBuffer::toString() instead of scriptBufferToString(). * workers/ScriptBuffer.cpp: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::toString const): (WebCore::ScriptBuffer::containsSingleFileMappedSegment const): (WebCore::operator==): * workers/ScriptBuffer.h: Added. (WebCore::ScriptBuffer::ScriptBuffer): (WebCore::ScriptBuffer::buffer const): (WebCore::ScriptBuffer::isolatedCopy const): (WebCore::ScriptBuffer::operator bool const): New ScriptBuffer class that wraps a SharedBuffer representation of a script. This class helps make it clear what data we're dealing with. It also facilitates conversion to and from a String when needed. The class also has its own IPC coder at WebKit layer to encode the script as a ShareableResource when file mapped. * workers/WorkerScriptLoader.cpp: (WebCore::WorkerScriptLoader::loadSynchronously): Use ScriptBuffer::toString() instead of scriptBufferToString(). And use StringBuffer constructor that takes a String instead of stringToScriptBuffer(). * workers/service/SWClientConnection.h: * workers/service/ServiceWorkerContextData.cpp: (WebCore::ServiceWorkerContextData::isolatedCopy const): * workers/service/ServiceWorkerContextData.h: (WebCore::ServiceWorkerContextData::ImportedScript::encode const): (WebCore::ServiceWorkerContextData::ImportedScript::decode): (WebCore::ServiceWorkerContextData::ImportedScript::isolatedCopy const): (WebCore::ServiceWorkerContextData::encode const): (WebCore::ServiceWorkerContextData::decode): - Use ScriptBuffer instead of RefPtr<SharedBuffer> for scripts. - Drop scriptBufferToString() & stringToScriptBuffer() as they are no longer needed. - Move IPC coders for ServiceWorkerContextData back from WebCoreArgumentCoders back to the WebCore class, now that the coders no longer need to deal with ShareableResource directly. We now encode / decode ScriptBuffer objects and its coder takes care of using a ShareableResource whenever possible. * workers/service/ServiceWorkerGlobalScope.cpp: (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): * workers/service/ServiceWorkerGlobalScope.h: * workers/service/context/SWContextManager.cpp: (WebCore::SWContextManager::didSaveScriptsToDisk): * workers/service/context/SWContextManager.h: * workers/service/context/ServiceWorkerThread.cpp: (WebCore::ServiceWorkerThread::ServiceWorkerThread): * workers/service/context/ServiceWorkerThreadProxy.cpp: (WebCore::ServiceWorkerThreadProxy::didSaveScriptsToDisk): * workers/service/context/ServiceWorkerThreadProxy.h: * workers/service/server/RegistrationDatabase.cpp: (WebCore::RegistrationDatabase::doPushChanges): (WebCore::RegistrationDatabase::importRecords): * workers/service/server/RegistrationStore.cpp: (WebCore::RegistrationStore::didSaveWorkerScriptsToDisk): * workers/service/server/RegistrationStore.h: * workers/service/server/SWScriptStorage.cpp: (WebCore::SWScriptStorage::store): (WebCore::SWScriptStorage::retrieve): * workers/service/server/SWScriptStorage.h: * workers/service/server/SWServer.cpp: (WebCore::SWServer::didSaveWorkerScriptsToDisk): (WebCore::SWServer::updateWorker): * workers/service/server/SWServer.h: * workers/service/server/SWServerJobQueue.cpp: (WebCore::SWServerJobQueue::scriptFetchFinished): * workers/service/server/SWServerToContextConnection.h: * workers/service/server/SWServerWorker.cpp: (WebCore::SWServerWorker::SWServerWorker): (WebCore::SWServerWorker::didSaveScriptsToDisk): * workers/service/server/SWServerWorker.h: (WebCore::SWServerWorker::script const): Use ScriptBuffer instead of SharedBuffer. Source/WebKit: * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp: (WebKit::WebSWServerToContextConnection::didSaveScriptsToDisk): * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h: Use ScriptBuffer instead SharedBuffer. * Shared/WebCoreArgumentCoders.cpp: (IPC::tryConvertToShareableResourceHandle): (IPC::decodeScriptBufferAsShareableResourceHandle): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::encode): (IPC::ArgumentCoder<WebCore::ScriptBuffer>::decode): * Shared/WebCoreArgumentCoders.h: - Add IPC encoder / decoder for ScriptBuffer which tries to encode / decode as a ShareableResource whenever possible (single segment that is file mapped). This logic used to be in the ServiceWorkerContextData coders. Now that the logic is in the ScriptBuffer coder, the ServiceWorkerContextData encoding / decoding becomes much simpler. - Moved ServiceWorkerContextData coders from WebCoreArgumentCoders back to its class in WebCore, now that they no longer need to deal with ShareableResource directly. * WebProcess/Storage/WebSWContextManagerConnection.cpp: (WebKit::WebSWContextManagerConnection::didSaveScriptsToDisk): * WebProcess/Storage/WebSWContextManagerConnection.h: * WebProcess/Storage/WebSWContextManagerConnection.messages.in: Send scripts over IPC as ScriptBuffer instead of using ShareableResource directly. The new IPC encoder / decoder for ScriptBuffer takes care of using ShareableResource for us. Canonical link: https://commits.webkit.org/236104@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@275443 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-02 21:53:30 +00:00
} // namespace WebCore