Changeset 277343 in webkit
- Timestamp:
- May 11, 2021, 4:41:22 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.cpp (modified) (6 diffs)
-
Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.h (modified) (3 diffs)
-
Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp (modified) (1 diff)
-
Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp (modified) (1 diff)
-
Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/IndexedDBDatabaseProcessKill.mm (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r277341 r277343 1 2021-05-11 Sihui Liu <sihui_liu@apple.com> 2 3 Use one VM per thread for IDB serialization work 4 https://bugs.webkit.org/show_bug.cgi?id=225658 5 6 Reviewed by Chris Dumez. 7 8 The vm map in IDBSerializationContext uses sessionID as key instead of thread identifier. Normally IDB has one 9 thread per session (see WebIDBServer and CrossThreadTaskHandler), so we are using one vm per thread. With 10 r275799, we remove WebIDBServer more aggressively (when no web process is not using IDB) to make sure its thread 11 does not stay around, and WebIDBServer will be destroyed after it finishes scheduled tasks on the background 12 thread. Then, it's possible that while a WebIDBServer for some session is removed and finishing last tasks, 13 a new IDB request for the same session comes in and we create a new WebIDBServer for the session. In this case, 14 two threads ends up using the same VM. 15 16 VM is generally not designed to be used on multiple threads, otherwise we need to acquire lock for each 17 WTF::String operation to get correct AtomStringTable. So let's just make sure we are using one VM per thread by 18 making the map in IDBSerializationContext keyed by thread pointer. 19 20 New API test: IndexedDB.OneVMPerThread 21 22 * Modules/indexeddb/server/IDBSerializationContext.cpp: 23 (WebCore::IDBServer::IDBSerializationContext::getOrCreateIDBSerializationContext): 24 (WebCore::IDBServer::IDBSerializationContext::~IDBSerializationContext): 25 (WebCore::IDBServer::IDBSerializationContext::vm): 26 (WebCore::IDBServer::IDBSerializationContext::globalObject): 27 (WebCore::IDBServer::IDBSerializationContext::IDBSerializationContext): 28 * Modules/indexeddb/server/IDBSerializationContext.h: 29 * Modules/indexeddb/server/MemoryIDBBackingStore.cpp: 30 (WebCore::IDBServer::MemoryIDBBackingStore::MemoryIDBBackingStore): 31 * Modules/indexeddb/server/MemoryObjectStore.cpp: 32 (WebCore::IDBServer::MemoryObjectStore::MemoryObjectStore): 33 * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp: 34 (WebCore::IDBServer::SQLiteIDBBackingStore::SQLiteIDBBackingStore): 35 1 36 2021-05-11 Chris Dumez <cdumez@apple.com> 2 37 -
trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.cpp
r275151 r277343 30 30 #include "WebCoreJSClientData.h" 31 31 #include <JavaScriptCore/JSObjectInlines.h> 32 #include <pal/SessionID.h>33 32 34 33 namespace WebCore { … … 38 37 static Lock serializationContextMapMutex; 39 38 40 static HashMap< PAL::SessionID, IDBSerializationContext*>& serializationContextMap()39 static HashMap<Thread*, IDBSerializationContext*>& serializationContextMap(Locker<Lock>&) 41 40 { 42 static NeverDestroyed<HashMap< PAL::SessionID, IDBSerializationContext*>> map;41 static NeverDestroyed<HashMap<Thread*, IDBSerializationContext*>> map; 43 42 return map; 44 43 } 45 44 46 Ref<IDBSerializationContext> IDBSerializationContext::getOrCreate IDBSerializationContext(PAL::SessionID sessionID)45 Ref<IDBSerializationContext> IDBSerializationContext::getOrCreateForCurrentThread() 47 46 { 47 auto& thread = Thread::current(); 48 48 Locker<Lock> locker(serializationContextMapMutex); 49 auto[iter, isNewEntry] = serializationContextMap( ).add(sessionID, nullptr);49 auto[iter, isNewEntry] = serializationContextMap(locker).add(&thread, nullptr); 50 50 if (isNewEntry) { 51 Ref<IDBSerializationContext> protectedContext = adoptRef(*new IDBSerializationContext( sessionID));51 Ref<IDBSerializationContext> protectedContext = adoptRef(*new IDBSerializationContext(thread)); 52 52 iter->value = protectedContext.ptr(); 53 53 return protectedContext; … … 60 60 { 61 61 Locker<Lock> locker(serializationContextMapMutex); 62 ASSERT(this == serializationContextMap( ).get(m_sessionID));62 ASSERT(this == serializationContextMap(locker).get(&m_thread)); 63 63 64 64 if (m_vm) { … … 67 67 m_vm = nullptr; 68 68 } 69 serializationContextMap( ).remove(m_sessionID);69 serializationContextMap(locker).remove(&m_thread); 70 70 } 71 71 … … 86 86 JSC::VM& IDBSerializationContext::vm() 87 87 { 88 ASSERT(&m_thread == &Thread::current()); 89 88 90 initializeVM(); 89 91 return *m_vm; … … 92 94 JSC::JSGlobalObject& IDBSerializationContext::globalObject() 93 95 { 96 ASSERT(&m_thread == &Thread::current()); 97 94 98 initializeVM(); 95 99 return *m_globalObject.get(); 96 100 } 97 101 98 IDBSerializationContext::IDBSerializationContext( PAL::SessionID sessionID)99 : m_ sessionID(sessionID)102 IDBSerializationContext::IDBSerializationContext(Thread& thread) 103 : m_thread(thread) 100 104 { 101 105 } -
trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.h
r275151 r277343 29 29 #include <JavaScriptCore/StrongInlines.h> 30 30 #include <JavaScriptCore/StructureInlines.h> 31 #include <pal/SessionID.h>32 31 33 32 namespace JSC { … … 42 41 class IDBSerializationContext : public RefCounted<IDBSerializationContext> { 43 42 public: 44 static Ref<IDBSerializationContext> getOrCreate IDBSerializationContext(PAL::SessionID);43 static Ref<IDBSerializationContext> getOrCreateForCurrentThread(); 45 44 46 45 ~IDBSerializationContext(); … … 50 49 51 50 private: 52 IDBSerializationContext(PAL::SessionID);51 explicit IDBSerializationContext(Thread&); 53 52 void initializeVM(); 54 53 55 54 RefPtr<JSC::VM> m_vm; 56 55 JSC::Strong<JSIDBSerializationGlobalObject> m_globalObject; 57 PAL::SessionID m_sessionID;56 Thread& m_thread; 58 57 }; 59 58 -
trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.cpp
r275583 r277343 49 49 : m_identifier(identifier) 50 50 , m_sessionID(sessionID) 51 , m_serializationContext(IDBSerializationContext::getOrCreate IDBSerializationContext(sessionID))51 , m_serializationContext(IDBSerializationContext::getOrCreateForCurrentThread()) 52 52 { 53 53 } -
trunk/Source/WebCore/Modules/indexeddb/server/MemoryObjectStore.cpp
r275151 r277343 50 50 } 51 51 52 MemoryObjectStore::MemoryObjectStore(PAL::SessionID sessionID, const IDBObjectStoreInfo& info)52 MemoryObjectStore::MemoryObjectStore(PAL::SessionID, const IDBObjectStoreInfo& info) 53 53 : m_info(info) 54 , m_serializationContext(IDBSerializationContext::getOrCreate IDBSerializationContext(sessionID))54 , m_serializationContext(IDBSerializationContext::getOrCreateForCurrentThread()) 55 55 { 56 56 } -
trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
r277269 r277343 248 248 , m_identifier(identifier) 249 249 , m_databaseRootDirectory(databaseRootDirectory) 250 , m_serializationContext(IDBSerializationContext::getOrCreate IDBSerializationContext(sessionID))250 , m_serializationContext(IDBSerializationContext::getOrCreateForCurrentThread()) 251 251 { 252 252 m_databaseDirectory = fullDatabaseDirectoryWithUpgrade(); -
trunk/Tools/ChangeLog
r277341 r277343 1 2021-05-11 Sihui Liu <sihui_liu@apple.com> 2 3 Use one VM per thread for IDB serialization work 4 https://bugs.webkit.org/show_bug.cgi?id=225658 5 6 Reviewed by Chris Dumez. 7 8 * TestWebKitAPI/Tests/WebKitCocoa/IndexedDBDatabaseProcessKill.mm: 9 (-[DatabaseProcessKillMessageHandler userContentController:didReceiveScriptMessage:]): 10 (TEST): 11 1 12 2021-05-11 Chris Dumez <cdumez@apple.com> 2 13 -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/IndexedDBDatabaseProcessKill.mm
r275890 r277343 28 28 #import "PlatformUtilities.h" 29 29 #import "Test.h" 30 #import "Test NavigationDelegate.h"30 #import "TestWKWebView.h" 31 31 #import <WebKit/WKProcessPoolPrivate.h> 32 32 #import <WebKit/WKUserContentControllerPrivate.h> 33 33 #import <WebKit/WKWebViewConfigurationPrivate.h> 34 #import <WebKit/WKWebViewPrivate.h> 34 35 #import <WebKit/WKWebsiteDataStorePrivate.h> 35 36 #import <WebKit/WebKit.h> … … 42 43 static bool openRequestUpgradeNeeded; 43 44 static bool databaseErrorReceived; 45 static RetainPtr<NSString> lastScriptMessage; 44 46 45 47 @interface DatabaseProcessKillMessageHandler : NSObject <WKScriptMessageHandler> … … 67 69 } 68 70 69 if ([[message body] isEqualToString:@"OpenRequestError"]) 71 if ([[message body] isEqualToString:@"OpenRequestError"]) { 70 72 receivedAtLeastOneOpenError = true; 73 return; 74 } 75 76 lastScriptMessage = [message body]; 71 77 } 72 78 … … 75 81 TEST(IndexedDB, DatabaseProcessKill) 76 82 { 77 RetainPtr<DatabaseProcessKillMessageHandler>handler = adoptNS([[DatabaseProcessKillMessageHandler alloc] init]);78 RetainPtr<WKWebViewConfiguration>configuration = adoptNS([[WKWebViewConfiguration alloc] init]);83 auto handler = adoptNS([[DatabaseProcessKillMessageHandler alloc] init]); 84 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 79 85 [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"]; 80 86 … … 101 107 EXPECT_EQ(databaseErrorReceived, true); 102 108 } 109 110 TEST(IndexedDB, OneVMPerThread) 111 { 112 RetainPtr<DatabaseProcessKillMessageHandler> handler = adoptNS([[DatabaseProcessKillMessageHandler alloc] init]); 113 RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 114 [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"]; 115 configuration.get().websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore]; 116 117 118 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]); 119 auto secondWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]); 120 121 NSString *htmlString = @"<script> \ 122 function openDatabase() { \ 123 var request = indexedDB.open('testDB'); \ 124 request.onupgradeneeded = function(event) { \ 125 let db = event.target.result; \ 126 let os = db.createObjectStore('testOS');\ 127 for (let i = 0; i < 10000; i++) \ 128 os.put(i, i); \ 129 webkit.messageHandlers.testHandler.postMessage('Opened');\ 130 }; \ 131 }\ 132 </script>"; 133 134 [webView synchronouslyLoadHTMLString:htmlString baseURL:[NSURL URLWithString:@"https://webkit.org"]]; 135 [secondWebView synchronouslyLoadHTMLString:htmlString baseURL:[NSURL URLWithString:@"https://apple.com"]]; 136 137 receivedScriptMessage = false; 138 [webView evaluateJavaScript:@"openDatabase()" completionHandler:nil]; 139 TestWebKitAPI::Util::run(&receivedScriptMessage); 140 EXPECT_WK_STREQ(@"Opened", lastScriptMessage.get()); 141 142 kill([webView _webProcessIdentifier], SIGKILL); 143 144 receivedScriptMessage = false; 145 [secondWebView evaluateJavaScript:@"openDatabase()" completionHandler:nil]; 146 lastScriptMessage = nil; 147 TestWebKitAPI::Util::run(&receivedScriptMessage); 148 EXPECT_WK_STREQ(@"Opened", lastScriptMessage.get()); 149 }
Note:
See TracChangeset
for help on using the changeset viewer.