Changeset 275465 in webkit
- Timestamp:
- Apr 5, 2021 6:05:24 PM (3 years ago)
- Location:
- trunk/Source
- Files:
-
- 1 added
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r275463 r275465 1 2021-04-05 Chris Dumez <cdumez@apple.com> 2 3 Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible 4 https://bugs.webkit.org/show_bug.cgi?id=224088 5 6 Reviewed by Yusuke Suzuki. 7 8 To run a worker, we were constructing a ScriptSourceCode from the source String and calling 9 JSC::evaluate. ScriptSourceCode would construct a JSC::StringSourceProvider, which would 10 keep the source String alive for the lifetime of the provider. This is problematic since 11 those worker scripts may be big and keeping heap-allocated version of them in memory is 12 expensive. 13 14 To address the issue, this patch introduces a new JSC::SourceProvider subclass named 15 ScriptBufferSourceProvider, which uses a ScriptBuffer internally. ScriptBuffer has the 16 benefit of being able to hold file-mapped data. We only convert the ScriptBuffer to 17 a String whenever necessary (When the script contains non-ascii characters and JSC 18 requests a StringView to the script). If we do end up converting the ScriptBuffer to 19 a String, this String will get cleared on memory pressure. This is similar to what 20 CachedScriptSourceProvider / CachedScript do on the main thread. 21 22 In the warm case, where the service worker script is coming from disk, we create 23 the ScriptBufferSourceProvider right away from a file-mapped ScriptBuffer, thus 24 greatly reducing dirty memory use. In the cold case, we initially construct the 25 ScriptBufferSourceProvider using a ScriptBuffer that is not file-mapped. However, 26 once the script is saved to disk (via SWScriptStorage), we replace the 27 ScriptBufferSourceProvider's ScriptBuffer with the new file-mapped version in 28 order to reduce dirty memory use in this case too. 29 30 * WebCore.xcodeproj/project.pbxproj: 31 Add ScriptBufferSourceProvider.h to the project. 32 33 * bindings/js/ScriptBufferSourceProvider.h: Added. 34 - Add new ScriptBufferSourceProvider, which is a JSC::SourceProvider subclass that 35 uses a ScriptBuffer as backing instead of a String. This allows us to use file-mapped 36 memory whenever possible, thus reducing dirty memory use. This provider provides 37 similar functionality to CachedScriptSourceProvider / CachedScript but works with 38 a ScriptBuffer and can be used off the main thread. 39 - We only transform the SharedBuffer into a String when strictly necessary, meaning 40 that the ScriptBuffer contains non-ascii characters and JSC is asking for a StringView 41 to the script. 42 - The class supports clearing the String copy of the script (done on memory pressure) 43 and replacing the ScriptBuffer (with a new file-mapped version). 44 45 * bindings/js/ScriptSourceCode.h: 46 (WebCore::ScriptSourceCode::ScriptSourceCode): 47 (WebCore::ScriptSourceCode::m_code): 48 (WebCore::ScriptSourceCode::provider): 49 Add new constructors taking a ScriptBuffer instead of a String for the source code. 50 We then use the new ScriptBufferSourceProvider internally instead of the 51 StringSourceProvider. 52 53 * workers/DedicatedWorkerThread.cpp: 54 (WebCore::DedicatedWorkerThread::DedicatedWorkerThread): 55 * workers/DedicatedWorkerThread.h: 56 Use ScriptBuffer instead of String. 57 58 * workers/ScriptBuffer.cpp: 59 (WebCore::ScriptBuffer::empty): 60 (WebCore::ScriptBuffer::append): 61 (WebCore::operator!=): 62 * workers/ScriptBuffer.h: 63 (WebCore::ScriptBuffer::isEmpty const): 64 Add some functionality to SCriptBuffer to make it more convenient to use. 65 66 * workers/Worker.cpp: 67 (WebCore::Worker::notifyFinished): 68 Convert ScriptBuffer to a String since this is what WebInspector expects. 69 70 * workers/WorkerGlobalScope.cpp: 71 (WebCore::WorkerGlobalScope::importScripts): 72 - When importing a new script, we now construct a ScriptSourceCode from a 73 ScriptBuffer instead of a String. 74 - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode 75 on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects 76 to clear their cached String representation of the script source on memory pressure. It is 77 also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped 78 version when one becomes available. 79 80 (WebCore::WorkerGlobalScope::releaseMemory): 81 In addition to deleting JS code and doing garbage collection, we now also ask the 82 ScriptBufferSourceProvider objects to clear their cached String representation of the script 83 source. 84 85 (WebCore::WorkerGlobalScope::deleteJSCodeAndGC): 86 Moved the logic to delete JS code and doing GC from releaseMemory() to a new function, now 87 that releaseMemory() needs to do more things. 88 89 (WebCore::WorkerGlobalScope::setMainScriptSourceProvider): 90 (WebCore::WorkerGlobalScope::addImportedScriptSourceProvider): 91 Functions used to store the CachedScriptSourceProvider objects for the scripts used by the 92 worker on the WorkerGlobalScope. We keep weak pointers to those. 93 94 (WebCore::WorkerGlobalScope::clearDecodedScriptData): 95 Function used to ask the ScriptBufferSourceProvider objects to clear their cached String 96 representation of the script source on memory pressure. 97 98 (WebCore::WorkerGlobalScope::updateSourceProviderBuffers): 99 Function used to ask the ScriptBufferSourceProvider objects to replace their ScriptBuffers 100 with file-backed versions. 101 102 * workers/WorkerGlobalScope.h: 103 * workers/WorkerGlobalScopeProxy.h: 104 * workers/WorkerMessagingProxy.cpp: 105 (WebCore::WorkerMessagingProxy::startWorkerGlobalScope): 106 * workers/WorkerMessagingProxy.h: 107 Use ScriptBuffer instead of String. 108 109 * workers/WorkerScriptLoader.cpp: 110 (WebCore::WorkerScriptLoader::WorkerScriptLoader): 111 (WebCore::WorkerScriptLoader::loadSynchronously): 112 (WebCore::WorkerScriptLoader::didReceiveData): 113 * workers/WorkerScriptLoader.h: 114 (WebCore::WorkerScriptLoader::script): 115 Use ScriptBuffer instead of String to hold the script source. We eventually need a ScriptBuffer 116 since this is what the Worker now needs to launch. Also, in the service worker case, we may 117 get a ScriptBuffer right away from the scriptResourceMap, without going to the network at all. 118 119 * workers/WorkerThread.cpp: 120 (WebCore::WorkerThreadStartupData::WorkerThreadStartupData): 121 (WebCore::WorkerThread::WorkerThread): 122 Use ScriptBuffer instead of String. 123 124 (WebCore::WorkerThread::evaluateScriptIfNecessary): 125 - When evaluating the main worker script, we now construct a ScriptSourceCode from a 126 ScriptBuffer instead of a String. 127 - We also store a weak pointer to the ScriptBufferSourceProvider used by the ScriptSourceCode 128 on the WorkerGlobalScope. This is so that we can ask those ScriptBufferSourceProvider objects 129 to clear their cached String representation of the script source on memory pressure. It is 130 also needed so we can replace the ScriptBufferSourceProvider's ScriptBuffer with a file-mapped 131 version when one becomes available. 132 133 * workers/WorkerThread.h: 134 * workers/service/ServiceWorkerContainer.cpp: 135 (WebCore::ServiceWorkerContainer::jobFinishedLoadingScript): 136 * workers/service/ServiceWorkerContainer.h: 137 * workers/service/ServiceWorkerFetchResult.h: 138 * workers/service/ServiceWorkerGlobalScope.cpp: 139 (WebCore::ServiceWorkerGlobalScope::didSaveScriptsToDisk): 140 * workers/service/ServiceWorkerJobClient.h: 141 * workers/service/context/ServiceWorkerThread.cpp: 142 (WebCore::ServiceWorkerThread::ServiceWorkerThread): 143 * workers/service/server/SWServer.cpp: 144 (WebCore::SWServer::updateWorker): 145 * workers/service/server/SWServer.h: 146 * workers/service/server/SWServerJobQueue.cpp: 147 (WebCore::SWServerJobQueue::scriptFetchFinished): 148 Use ScriptBuffer instead of String. 149 1 150 2021-04-05 Fujii Hironori <Hironori.Fujii@sony.com> 2 151 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r275459 r275465 1289 1289 46B63F6C1C6E8D19002E914B /* JSEventTargetCustom.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B63F6B1C6E8CDF002E914B /* JSEventTargetCustom.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1290 1290 46B650DD2296262700FD8AA4 /* PageIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B650DB2296262700FD8AA4 /* PageIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1291 46B8593C261672270019EDC6 /* ScriptBufferSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B8593A2616720C0019EDC6 /* ScriptBufferSourceProvider.h */; }; 1291 1292 46B95195207D633400A7D2DD /* AbstractDOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B9518A207D632800A7D2DD /* AbstractDOMWindow.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1292 1293 46B95196207D633A00A7D2DD /* AbstractFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B9518F207D632B00A7D2DD /* AbstractFrame.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 8285 8286 46B63F6B1C6E8CDF002E914B /* JSEventTargetCustom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEventTargetCustom.h; sourceTree = "<group>"; }; 8286 8287 46B650DB2296262700FD8AA4 /* PageIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageIdentifier.h; sourceTree = "<group>"; }; 8288 46B8593A2616720C0019EDC6 /* ScriptBufferSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScriptBufferSourceProvider.h; sourceTree = "<group>"; }; 8287 8289 46B9518A207D632800A7D2DD /* AbstractDOMWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractDOMWindow.h; sourceTree = "<group>"; }; 8288 8290 46B9518C207D632900A7D2DD /* RemoteFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoteFrame.cpp; sourceTree = "<group>"; }; … … 27289 27291 418C395F1C8F0AAB0051C8A3 /* ReadableStreamDefaultController.h */, 27290 27292 51BA946F23AC305000444846 /* RunJavaScriptParameters.h */, 27293 46B8593A2616720C0019EDC6 /* ScriptBufferSourceProvider.h */, 27291 27294 41F1D21E0EF35C2A00DA8753 /* ScriptCachedFrameData.cpp */, 27292 27295 41F1D21D0EF35C2A00DA8753 /* ScriptCachedFrameData.h */, … … 34809 34812 A84D82C111D3474800972990 /* ScriptableDocumentParser.h in Headers */, 34810 34813 462E4C502616A811003A2C67 /* ScriptBuffer.h in Headers */, 34814 46B8593C261672270019EDC6 /* ScriptBufferSourceProvider.h in Headers */, 34811 34815 41F1D21F0EF35C2A00DA8753 /* ScriptCachedFrameData.h in Headers */, 34812 34816 93B70D7009EB0C7C009D8468 /* ScriptController.h in Headers */, -
trunk/Source/WebCore/bindings/js/ScriptSourceCode.h
r273203 r275465 35 35 #include "CachedScriptFetcher.h" 36 36 #include "CachedScriptSourceProvider.h" 37 #include "ScriptBufferSourceProvider.h" 37 38 #include <JavaScriptCore/SourceCode.h> 38 39 #include <JavaScriptCore/SourceProvider.h> … … 47 48 ScriptSourceCode(const String& source, URL&& url = URL(), const TextPosition& startPosition = TextPosition(), JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Program) 48 49 : m_provider(JSC::StringSourceProvider::create(source, JSC::SourceOrigin { url }, url.string(), startPosition, sourceType)) 50 , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) 51 { 52 } 53 54 ScriptSourceCode(const ScriptBuffer& source, URL&& url = URL(), const TextPosition& startPosition = TextPosition(), JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Program) 55 : m_provider(ScriptBufferSourceProvider::create(source, JSC::SourceOrigin { url }, url.string(), startPosition, sourceType)) 49 56 , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) 50 57 { … … 64 71 } 65 72 73 ScriptSourceCode(const ScriptBuffer& source, URL&& url, const TextPosition& startPosition, JSC::SourceProviderSourceType sourceType, Ref<JSC::ScriptFetcher>&& scriptFetcher) 74 : m_provider(ScriptBufferSourceProvider::create(source, JSC::SourceOrigin { url, WTFMove(scriptFetcher) }, url.string(), startPosition, sourceType)) 75 , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()) 76 { 77 } 78 66 79 bool isEmpty() const { return m_code.length() == 0; } 67 80 68 81 const JSC::SourceCode& jsSourceCode() const { return m_code; } 69 82 83 JSC::SourceProvider& provider() { return m_provider.get(); } 70 84 StringView source() const { return m_provider->source(); } 71 85 -
trunk/Source/WebCore/workers/DedicatedWorkerThread.cpp
r268897 r275465 39 39 namespace WebCore { 40 40 41 DedicatedWorkerThread::DedicatedWorkerThread(const WorkerParameters& params, const S tring& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerDebuggerProxy& workerDebuggerProxy, WorkerObjectProxy& workerObjectProxy, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags)41 DedicatedWorkerThread::DedicatedWorkerThread(const WorkerParameters& params, const ScriptBuffer& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerDebuggerProxy& workerDebuggerProxy, WorkerObjectProxy& workerObjectProxy, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags) 42 42 : WorkerThread(params, sourceCode, workerLoaderProxy, workerDebuggerProxy, workerObjectProxy, startMode, topOrigin, connectionProxy, socketProvider, runtimeFlags) 43 43 , m_workerObjectProxy(workerObjectProxy) -
trunk/Source/WebCore/workers/DedicatedWorkerThread.h
r256012 r275465 37 37 38 38 class ContentSecurityPolicyResponseHeaders; 39 class ScriptBuffer; 39 40 class WorkerObjectProxy; 40 41 … … 55 56 56 57 private: 57 DedicatedWorkerThread(const WorkerParameters&, const S tring& sourceCode, WorkerLoaderProxy&, WorkerDebuggerProxy&, WorkerObjectProxy&, WorkerThreadStartMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags);58 DedicatedWorkerThread(const WorkerParameters&, const ScriptBuffer& sourceCode, WorkerLoaderProxy&, WorkerDebuggerProxy&, WorkerObjectProxy&, WorkerThreadStartMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags); 58 59 59 60 WorkerObjectProxy& m_workerObjectProxy; -
trunk/Source/WebCore/workers/ScriptBuffer.cpp
r275443 r275465 42 42 } 43 43 44 ScriptBuffer ScriptBuffer::empty() 45 { 46 return ScriptBuffer { SharedBuffer::create() }; 47 } 48 49 44 50 String ScriptBuffer::toString() const 45 51 { … … 58 64 } 59 65 66 void ScriptBuffer::append(const String& string) 67 { 68 if (!m_buffer) 69 m_buffer = SharedBuffer::create(); 70 auto utf8 = string.utf8(); 71 m_buffer->append(utf8.data(), utf8.length()); 72 } 73 60 74 bool operator==(const ScriptBuffer& a, const ScriptBuffer& b) 61 75 { … … 67 81 } 68 82 83 bool operator!=(const ScriptBuffer& a, const ScriptBuffer& b) 84 { 85 return !(a == b); 86 } 87 69 88 } // namespace WebCore -
trunk/Source/WebCore/workers/ScriptBuffer.h
r275443 r275465 44 44 } 45 45 46 explicit ScriptBuffer(const String&); 46 static ScriptBuffer empty(); 47 48 WEBCORE_EXPORT explicit ScriptBuffer(const String&); 47 49 48 50 String toString() const; … … 51 53 ScriptBuffer isolatedCopy() const { return ScriptBuffer(m_buffer ? RefPtr<SharedBuffer>(m_buffer->copy()) : nullptr); } 52 54 explicit operator bool() const { return !!m_buffer; } 55 bool isEmpty() const { return !m_buffer || !m_buffer->size(); } 53 56 54 57 WEBCORE_EXPORT bool containsSingleFileMappedSegment() const; 58 void append(const String&); 55 59 56 60 private: … … 59 63 60 64 bool operator==(const ScriptBuffer&, const ScriptBuffer&); 65 bool operator!=(const ScriptBuffer&, const ScriptBuffer&); 61 66 62 67 } // namespace WebCore -
trunk/Source/WebCore/workers/Worker.cpp
r274385 r275465 234 234 } 235 235 m_contextProxy.startWorkerGlobalScope(responseURL, m_name, context->userAgent(responseURL), isOnline, m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy, m_workerCreationTime, referrerPolicy, m_type, m_credentials, m_runtimeFlags); 236 InspectorInstrumentation::scriptImported(*context, m_scriptLoader->identifier(), m_scriptLoader->script() );236 InspectorInstrumentation::scriptImported(*context, m_scriptLoader->identifier(), m_scriptLoader->script().toString()); 237 237 } 238 238 -
trunk/Source/WebCore/workers/WorkerGlobalScope.cpp
r275428 r275465 329 329 return WTFMove(*exception); 330 330 331 InspectorInstrumentation::scriptImported(*this, scriptLoader->identifier(), scriptLoader->script()); 332 333 NakedPtr<JSC::Exception> exception; 334 script()->evaluate(ScriptSourceCode(scriptLoader->script(), URL(scriptLoader->responseURL())), exception); 335 if (exception) { 336 script()->setException(exception); 337 return { }; 331 InspectorInstrumentation::scriptImported(*this, scriptLoader->identifier(), scriptLoader->script().toString()); 332 333 WeakPtr<ScriptBufferSourceProvider> sourceProvider; 334 { 335 NakedPtr<JSC::Exception> exception; 336 ScriptSourceCode sourceCode(scriptLoader->script(), URL(scriptLoader->responseURL())); 337 sourceProvider = makeWeakPtr(static_cast<ScriptBufferSourceProvider&>(sourceCode.provider())); 338 script()->evaluate(sourceCode, exception); 339 if (exception) { 340 script()->setException(exception); 341 return { }; 342 } 338 343 } 344 if (sourceProvider) 345 addImportedScriptSourceProvider(url, *sourceProvider); 339 346 } 340 347 … … 530 537 { 531 538 ASSERT(isContextThread()); 539 deleteJSCodeAndGC(synchronous); 540 clearDecodedScriptData(); 541 } 542 543 void WorkerGlobalScope::deleteJSCodeAndGC(Synchronous synchronous) 544 { 545 ASSERT(isContextThread()); 532 546 533 547 JSC::JSLockHolder lock(vm()); … … 564 578 } 565 579 580 void WorkerGlobalScope::setMainScriptSourceProvider(ScriptBufferSourceProvider& provider) 581 { 582 ASSERT(!m_mainScriptSourceProvider); 583 m_mainScriptSourceProvider = makeWeakPtr(provider); 584 } 585 586 void WorkerGlobalScope::addImportedScriptSourceProvider(const URL& url, ScriptBufferSourceProvider& provider) 587 { 588 m_importedScriptsSourceProviders.ensure(url, [] { 589 return WeakHashSet<ScriptBufferSourceProvider> { }; 590 }).iterator->value.add(provider); 591 } 592 593 void WorkerGlobalScope::clearDecodedScriptData() 594 { 595 ASSERT(isContextThread()); 596 597 if (m_mainScriptSourceProvider) 598 m_mainScriptSourceProvider->clearDecodedData(); 599 600 for (auto& sourceProviders : m_importedScriptsSourceProviders.values()) { 601 for (auto& sourceProvider : sourceProviders) 602 sourceProvider.clearDecodedData(); 603 } 604 } 605 606 void WorkerGlobalScope::updateSourceProviderBuffers(const ScriptBuffer& mainScript, const HashMap<URL, ScriptBuffer>& importedScripts) 607 { 608 ASSERT(isContextThread()); 609 610 if (mainScript && m_mainScriptSourceProvider) 611 m_mainScriptSourceProvider->tryReplaceScriptBuffer(mainScript); 612 613 for (auto& pair : importedScripts) { 614 auto it = m_importedScriptsSourceProviders.find(pair.key); 615 if (it == m_importedScriptsSourceProviders.end()) 616 continue; 617 for (auto& sourceProvider : it->value) 618 sourceProvider.tryReplaceScriptBuffer(pair.value); 619 } 620 } 621 566 622 } // namespace WebCore -
trunk/Source/WebCore/workers/WorkerGlobalScope.h
r275428 r275465 30 30 #include "CacheStorageConnection.h" 31 31 #include "ImageBitmap.h" 32 #include "ScriptBufferSourceProvider.h" 32 33 #include "ScriptExecutionContext.h" 33 34 #include "Supplementable.h" 34 35 #include "WorkerOrWorkletGlobalScope.h" 35 36 #include "WorkerOrWorkletScriptController.h" 36 #include <wtf/URL.h>37 37 #include "WorkerCacheStorageConnection.h" 38 38 #include "WorkerMessagePortChannelProvider.h" … … 40 40 #include <JavaScriptCore/ConsoleMessage.h> 41 41 #include <memory> 42 #include <wtf/HashMap.h> 42 43 #include <wtf/MemoryPressureHandler.h> 44 #include <wtf/URL.h> 45 #include <wtf/URLHash.h> 46 #include <wtf/WeakHashSet.h> 43 47 44 48 namespace WebCore { … … 131 135 static void releaseMemoryInWorkers(Synchronous); 132 136 137 void setMainScriptSourceProvider(ScriptBufferSourceProvider&); 138 void addImportedScriptSourceProvider(const URL&, ScriptBufferSourceProvider&); 139 133 140 protected: 134 141 WorkerGlobalScope(WorkerThreadType, const WorkerParameters&, Ref<SecurityOrigin>&&, WorkerThread&, Ref<SecurityOrigin>&& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*); 135 142 136 143 void applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders&); 144 void updateSourceProviderBuffers(const ScriptBuffer& mainScript, const HashMap<URL, ScriptBuffer>& importedScripts); 137 145 138 146 private: … … 146 154 bool isWorkerGlobalScope() const final { return true; } 147 155 156 void deleteJSCodeAndGC(Synchronous); 157 void clearDecodedScriptData(); 158 148 159 URL completeURL(const String&, ForceUTF8 = ForceUTF8::No) const final; 149 160 String userAgent(const URL&) const final; … … 181 192 RefPtr<Performance> m_performance; 182 193 mutable RefPtr<Crypto> m_crypto; 194 195 WeakPtr<ScriptBufferSourceProvider> m_mainScriptSourceProvider; 196 HashMap<URL, WeakHashSet<ScriptBufferSourceProvider>> m_importedScriptsSourceProviders; 183 197 184 198 RefPtr<WorkerCacheStorageConnection> m_cacheStorageConnection; -
trunk/Source/WebCore/workers/WorkerGlobalScopeProxy.h
r273299 r275465 51 51 static WorkerGlobalScopeProxy& create(Worker&); 52 52 53 virtual void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const S tring& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType, FetchRequestCredentials, JSC::RuntimeFlags) = 0;53 virtual void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const ScriptBuffer& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType, FetchRequestCredentials, JSC::RuntimeFlags) = 0; 54 54 virtual void terminateWorkerGlobalScope() = 0; 55 55 virtual void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) = 0; -
trunk/Source/WebCore/workers/WorkerMessagingProxy.cpp
r275151 r275465 76 76 } 77 77 78 void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const S tring& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy referrerPolicy, WorkerType workerType, FetchRequestCredentials credentials, JSC::RuntimeFlags runtimeFlags)78 void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const ScriptBuffer& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy referrerPolicy, WorkerType workerType, FetchRequestCredentials credentials, JSC::RuntimeFlags runtimeFlags) 79 79 { 80 80 // FIXME: This need to be revisited when we support nested worker one day -
trunk/Source/WebCore/workers/WorkerMessagingProxy.h
r274758 r275465 51 51 // Implementations of WorkerGlobalScopeProxy. 52 52 // (Only use these functions in the worker object thread.) 53 void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const S tring& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType, FetchRequestCredentials, JSC::RuntimeFlags) final;53 void startWorkerGlobalScope(const URL& scriptURL, const String& name, const String& userAgent, bool isOnline, const ScriptBuffer& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, ReferrerPolicy, WorkerType, FetchRequestCredentials, JSC::RuntimeFlags) final; 54 54 void terminateWorkerGlobalScope() final; 55 55 void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) final; -
trunk/Source/WebCore/workers/WorkerScriptLoader.cpp
r275443 r275465 45 45 namespace WebCore { 46 46 47 WorkerScriptLoader::WorkerScriptLoader() = default; 47 WorkerScriptLoader::WorkerScriptLoader() 48 : m_script(ScriptBuffer::empty()) 49 { 50 } 48 51 49 52 WorkerScriptLoader::~WorkerScriptLoader() = default; … … 62 65 if (isServiceWorkerGlobalScope) { 63 66 if (auto* scriptResource = downcast<ServiceWorkerGlobalScope>(workerGlobalScope).scriptResource(url)) { 64 m_script .append(scriptResource->script.toString());67 m_script = scriptResource->script; 65 68 m_responseURL = scriptResource->responseURL; 66 69 m_responseMIMEType = scriptResource->mimeType; … … 103 106 return Exception { NetworkError, "mime type is not a supported JavaScript mime type"_s }; 104 107 105 downcast<ServiceWorkerGlobalScope>(workerGlobalScope).setScriptResource(url, ServiceWorkerContextData::ImportedScript { ScriptBuffer { script() }, m_responseURL, m_responseMIMEType });108 downcast<ServiceWorkerGlobalScope>(workerGlobalScope).setScriptResource(url, ServiceWorkerContextData::ImportedScript { script(), m_responseURL, m_responseMIMEType }); 106 109 } 107 110 #endif … … 212 215 if (len == -1) 213 216 len = strlen(data); 214 217 215 218 m_script.append(m_decoder->decode(data, len)); 216 219 } … … 244 247 } 245 248 246 String WorkerScriptLoader::script()247 {248 return m_script.toString();249 }250 251 249 void WorkerScriptLoader::notifyFinished() 252 250 { -
trunk/Source/WebCore/workers/WorkerScriptLoader.h
r273203 r275465 33 33 #include "ResourceRequest.h" 34 34 #include "ResourceResponse.h" 35 #include "ScriptBuffer.h" 35 36 #include "ThreadableLoader.h" 36 37 #include "ThreadableLoaderClient.h" … … 63 64 void notifyError(); 64 65 65 String script();66 const ScriptBuffer& script() { return m_script; } 66 67 const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy() const { return m_contentSecurityPolicy; } 67 68 const String& referrerPolicy() const { return m_referrerPolicy; } … … 99 100 String m_responseEncoding; 100 101 RefPtr<TextResourceDecoder> m_decoder; 101 S tringBuilder m_script;102 ScriptBuffer m_script; 102 103 URL m_url; 103 104 URL m_responseURL; -
trunk/Source/WebCore/workers/WorkerThread.cpp
r275151 r275465 67 67 WTF_MAKE_NONCOPYABLE(WorkerThreadStartupData); WTF_MAKE_FAST_ALLOCATED; 68 68 public: 69 WorkerThreadStartupData(const WorkerParameters& params, const S tring& sourceCode, WorkerThreadStartMode, const SecurityOrigin& topOrigin);69 WorkerThreadStartupData(const WorkerParameters& params, const ScriptBuffer& sourceCode, WorkerThreadStartMode, const SecurityOrigin& topOrigin); 70 70 71 71 WorkerParameters params; 72 72 Ref<SecurityOrigin> origin; 73 S tringsourceCode;73 ScriptBuffer sourceCode; 74 74 WorkerThreadStartMode startMode; 75 75 Ref<SecurityOrigin> topOrigin; 76 76 }; 77 77 78 WorkerThreadStartupData::WorkerThreadStartupData(const WorkerParameters& other, const S tring& sourceCode, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin)78 WorkerThreadStartupData::WorkerThreadStartupData(const WorkerParameters& other, const ScriptBuffer& sourceCode, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin) 79 79 : params(other.isolatedCopy()) 80 80 , origin(SecurityOrigin::create(other.scriptURL)->isolatedCopy()) … … 85 85 } 86 86 87 WorkerThread::WorkerThread(const WorkerParameters& params, const S tring& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerDebuggerProxy& workerDebuggerProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags)87 WorkerThread::WorkerThread(const WorkerParameters& params, const ScriptBuffer& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerDebuggerProxy& workerDebuggerProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags) 88 88 : WorkerOrWorkletThread(params.identifier.isolatedCopy()) 89 89 , m_workerLoaderProxy(workerLoaderProxy) … … 126 126 // We invoke module loader as if we are executing inline module script tag in Document. 127 127 128 WeakPtr<ScriptBufferSourceProvider> sourceProvider; 128 129 if (m_startupData->params.workerType == WorkerType::Classic) { 129 globalScope()->script()->evaluate(ScriptSourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)), &exceptionMessage); 130 ScriptSourceCode sourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)); 131 sourceProvider = makeWeakPtr(static_cast<ScriptBufferSourceProvider&>(sourceCode.provider())); 132 globalScope()->script()->evaluate(sourceCode, &exceptionMessage); 130 133 finishedEvaluatingScript(); 131 134 } else { 132 135 auto scriptFetcher = WorkerScriptFetcher::create(globalScope()->credentials(), globalScope()->destination(), globalScope()->referrerPolicy()); 133 136 ScriptSourceCode sourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL), { }, JSC::SourceProviderSourceType::Module, scriptFetcher.copyRef()); 137 sourceProvider = makeWeakPtr(static_cast<ScriptBufferSourceProvider&>(sourceCode.provider())); 134 138 MessageQueueWaitResult result = globalScope()->script()->loadModuleSynchronously(scriptFetcher.get(), sourceCode); 135 139 if (result != MessageQueueTerminated) { … … 146 150 } 147 151 } 152 if (sourceProvider) 153 globalScope()->setMainScriptSourceProvider(*sourceProvider); 148 154 149 155 // Free the startup data to cause its member variable deref's happen on the worker's thread (since -
trunk/Source/WebCore/workers/WorkerThread.h
r275151 r275465 38 38 39 39 class NotificationClient; 40 class ScriptBuffer; 40 41 class SecurityOrigin; 41 42 class SocketProvider; … … 93 94 94 95 protected: 95 WorkerThread(const WorkerParameters&, const S tring& sourceCode, WorkerLoaderProxy&, WorkerDebuggerProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags);96 WorkerThread(const WorkerParameters&, const ScriptBuffer& sourceCode, WorkerLoaderProxy&, WorkerDebuggerProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags); 96 97 97 98 // Factory method for creating a new worker context for the thread. -
trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp
r273224 r275465 475 475 } 476 476 477 void ServiceWorkerContainer::jobFinishedLoadingScript(ServiceWorkerJob& job, const S tring& script, const CertificateInfo& certificateInfo, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy, const String& referrerPolicy)477 void ServiceWorkerContainer::jobFinishedLoadingScript(ServiceWorkerJob& job, const ScriptBuffer& script, const CertificateInfo& certificateInfo, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy, const String& referrerPolicy) 478 478 { 479 479 #ifndef NDEBUG -
trunk/Source/WebCore/workers/service/ServiceWorkerContainer.h
r273203 r275465 103 103 void jobResolvedWithUnregistrationResult(ServiceWorkerJob&, bool unregistrationResult) final; 104 104 void startScriptFetchForJob(ServiceWorkerJob&, FetchOptions::Cache) final; 105 void jobFinishedLoadingScript(ServiceWorkerJob&, const S tring& script, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy) final;105 void jobFinishedLoadingScript(ServiceWorkerJob&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy) final; 106 106 void jobFailedLoadingScript(ServiceWorkerJob&, const ResourceError&, Exception&&) final; 107 107 -
trunk/Source/WebCore/workers/service/ServiceWorkerFetchResult.h
r264724 r275465 30 30 #include "ContentSecurityPolicyResponseHeaders.h" 31 31 #include "ResourceError.h" 32 #include "ScriptBuffer.h" 32 33 #include "ServiceWorkerRegistrationKey.h" 33 34 #include "ServiceWorkerTypes.h" … … 38 39 ServiceWorkerJobDataIdentifier jobDataIdentifier; 39 40 ServiceWorkerRegistrationKey registrationKey; 40 S tringscript;41 ScriptBuffer script; 41 42 CertificateInfo certificateInfo; 42 43 ContentSecurityPolicyResponseHeaders contentSecurityPolicy; -
trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp
r275443 r275465 159 159 { 160 160 // These scripts should be identical to the ones we have. However, these are mmap'd so using them helps reduce dirty memory usage. 161 updateSourceProviderBuffers(script, importedScripts); 162 161 163 if (script) { 162 164 ASSERT(m_contextData.script == script); -
trunk/Source/WebCore/workers/service/ServiceWorkerJobClient.h
r264724 r275465 36 36 class Exception; 37 37 class ResourceError; 38 class ScriptBuffer; 38 39 class ServiceWorkerJob; 39 class SharedBuffer;40 40 struct ServiceWorkerRegistrationData; 41 41 … … 50 50 virtual void jobResolvedWithUnregistrationResult(ServiceWorkerJob&, bool unregistrationResult) = 0; 51 51 virtual void startScriptFetchForJob(ServiceWorkerJob&, FetchOptions::Cache) = 0; 52 virtual void jobFinishedLoadingScript(ServiceWorkerJob&, const S tring& script, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy) = 0;52 virtual void jobFinishedLoadingScript(ServiceWorkerJob&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy) = 0; 53 53 virtual void jobFailedLoadingScript(ServiceWorkerJob&, const ResourceError&, Exception&&) = 0; 54 54 }; -
trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp
r275443 r275465 75 75 76 76 ServiceWorkerThread::ServiceWorkerThread(ServiceWorkerContextData&& data, String&& userAgent, const Settings::Values& settingsValues, WorkerLoaderProxy& loaderProxy, WorkerDebuggerProxy& debuggerProxy, IDBClient::IDBConnectionProxy* idbConnectionProxy, SocketProvider* socketProvider) 77 : WorkerThread({ data.scriptURL, emptyString(), "serviceworker:" + Inspector::IdentifiersFactory::createIdentifier(), WTFMove(userAgent), platformStrategies()->loaderStrategy()->isOnLine(), data.contentSecurityPolicy, false, MonotonicTime::now(), { }, data.workerType, FetchRequestCredentials::Omit, settingsValues }, data.script .toString(), loaderProxy, debuggerProxy, DummyServiceWorkerThreadProxy::shared(), WorkerThreadStartMode::Normal, data.registration.key.topOrigin().securityOrigin().get(), idbConnectionProxy, socketProvider, JSC::RuntimeFlags::createAllEnabled())77 : WorkerThread({ data.scriptURL, emptyString(), "serviceworker:" + Inspector::IdentifiersFactory::createIdentifier(), WTFMove(userAgent), platformStrategies()->loaderStrategy()->isOnLine(), data.contentSecurityPolicy, false, MonotonicTime::now(), { }, data.workerType, FetchRequestCredentials::Omit, settingsValues }, data.script, loaderProxy, debuggerProxy, DummyServiceWorkerThreadProxy::shared(), WorkerThreadStartMode::Normal, data.registration.key.topOrigin().securityOrigin().get(), idbConnectionProxy, socketProvider, JSC::RuntimeFlags::createAllEnabled()) 78 78 , m_serviceWorkerIdentifier(data.serviceWorkerIdentifier) 79 79 , m_jobDataIdentifier(data.jobDataIdentifier) -
trunk/Source/WebCore/workers/service/server/SWServer.cpp
r275443 r275465 638 638 } 639 639 640 void SWServer::updateWorker(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, SWServerRegistration& registration, const URL& url, const S tring& script, const CertificateInfo& certificateInfo, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy, const String& referrerPolicy, WorkerType type, HashMap<URL, ServiceWorkerContextData::ImportedScript>&& scriptResourceMap)641 { 642 tryInstallContextData(ServiceWorkerContextData { jobDataIdentifier, registration.data(), ServiceWorkerIdentifier::generate(), ScriptBuffer { script }, certificateInfo, contentSecurityPolicy, referrerPolicy, url, type, false, WTFMove(scriptResourceMap) });640 void SWServer::updateWorker(const ServiceWorkerJobDataIdentifier& jobDataIdentifier, SWServerRegistration& registration, const URL& url, const ScriptBuffer& script, const CertificateInfo& certificateInfo, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicy, const String& referrerPolicy, WorkerType type, HashMap<URL, ServiceWorkerContextData::ImportedScript>&& scriptResourceMap) 641 { 642 tryInstallContextData(ServiceWorkerContextData { jobDataIdentifier, registration.data(), ServiceWorkerIdentifier::generate(), script, certificateInfo, contentSecurityPolicy, referrerPolicy, url, type, false, WTFMove(scriptResourceMap) }); 643 643 } 644 644 -
trunk/Source/WebCore/workers/service/server/SWServer.h
r275443 r275465 152 152 void startScriptFetch(const ServiceWorkerJobData&, bool shouldRefreshCache); 153 153 154 void updateWorker(const ServiceWorkerJobDataIdentifier&, SWServerRegistration&, const URL&, const S tring& script, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy, WorkerType, HashMap<URL, ServiceWorkerContextData::ImportedScript>&&);154 void updateWorker(const ServiceWorkerJobDataIdentifier&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const String& referrerPolicy, WorkerType, HashMap<URL, ServiceWorkerContextData::ImportedScript>&&); 155 155 void fireInstallEvent(SWServerWorker&); 156 156 void fireActivateEvent(SWServerWorker&); -
trunk/Source/WebCore/workers/service/server/SWServerJobQueue.cpp
r275443 r275465 101 101 // flag set, and script's source text is a byte-for-byte match with newestWorker's script resource's source 102 102 // text, then: 103 if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && newestWorker->type() == job.workerType && result.script == newestWorker->script() .toString()&& doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) {103 if (newestWorker && equalIgnoringFragmentIdentifier(newestWorker->scriptURL(), job.scriptURL) && newestWorker->type() == job.workerType && result.script == newestWorker->script() && doCertificatesMatch(result.certificateInfo, newestWorker->certificateInfo())) { 104 104 RELEASE_LOG(ServiceWorker, "%p - SWServerJobQueue::scriptFetchFinished, script and certificate are matching for registrationID=%llu", this, registration->identifier().toUInt64()); 105 105 // FIXME: for non classic scripts, check the script’s module record's [[ECMAScriptCode]]. -
trunk/Source/WebKit/ChangeLog
r275463 r275465 1 2021-04-05 Chris Dumez <cdumez@apple.com> 2 3 Make sure service workers use a ScriptSourceCode backed by file-mapped memory when possible 4 https://bugs.webkit.org/show_bug.cgi?id=224088 5 6 Reviewed by Yusuke Suzuki. 7 8 * NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp: 9 (WebKit::ServiceWorkerSoftUpdateLoader::didFinishLoading): 10 1 11 2021-04-05 Fujii Hironori <Hironori.Fujii@sony.com> 2 12 -
trunk/Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerSoftUpdateLoader.cpp
r265150 r275465 189 189 if (m_decoder) 190 190 m_script.append(m_decoder->flush()); 191 m_completionHandler({ m_jobData.identifier(), m_jobData.registrationKey(), m_script.toString(), m_certificateInfo, m_contentSecurityPolicy, m_referrerPolicy, { } });191 m_completionHandler({ m_jobData.identifier(), m_jobData.registrationKey(), ScriptBuffer { m_script.toString() }, m_certificateInfo, m_contentSecurityPolicy, m_referrerPolicy, { } }); 192 192 didComplete(); 193 193 }
Note: See TracChangeset
for help on using the changeset viewer.