Title: [276659] trunk/Source
Revision
276659
Author
[email protected]
Date
2021-04-27 13:55:02 -0700 (Tue, 27 Apr 2021)

Log Message

Copy-on-write semantics should be an internal implementation detail of StorageMap
https://bugs.webkit.org/show_bug.cgi?id=225108

Reviewed by Alex Christensen.

Source/WebCore:

Instead of making the StorageMap RefCounted and requiring the client to potentially
replace its StorageMap whenever it calls functions that modify the StorageMap, the
copy-on-write semantics in now an internal implementation detail of StorageMap.

To achieve this, the following changes were made:
- StorageMap is no longer RefCounted. Instead, it has an internal Impl data member
  that is RefCounted.
- The internal Impl data member is the one that gets copied on write.
- Functions that modify the StorageMap no longer need to return a StorageMap.
- Add a clear() function for convenience.

* storage/StorageMap.cpp:
(WebCore::StorageMap::StorageMap):
(WebCore::StorageMap::invalidateIterator):
(WebCore::StorageMap::setIteratorToIndex):
(WebCore::StorageMap::length const):
(WebCore::StorageMap::key):
(WebCore::StorageMap::getItem const):
(WebCore::StorageMap::setItem):
(WebCore::StorageMap::setItemIgnoringQuota):
(WebCore::StorageMap::removeItem):
(WebCore::StorageMap::clear):
(WebCore::StorageMap::contains const):
(WebCore::StorageMap::importItems):
(WebCore::StorageMap::Impl::copy const):
* storage/StorageMap.h:
(WebCore::StorageMap::items const):
(WebCore::StorageMap::Impl::create):

Source/WebKit:

Update StorageArea due to StorageMap API changes.

* NetworkProcess/WebStorage/StorageArea.cpp:
(WebKit::StorageArea::StorageArea):
(WebKit::StorageArea::setItem):
(WebKit::StorageArea::removeItem):
(WebKit::StorageArea::clear):
(WebKit::StorageArea::items const):
(WebKit::StorageArea::openDatabaseAndImportItemsIfNeeded const):
* NetworkProcess/WebStorage/StorageArea.h:

Source/WebKitLegacy:

Update StorageAreaImpl due to StorageMap API changes.

* Storage/StorageAreaImpl.cpp:
(WebKit::StorageAreaImpl::StorageAreaImpl):
(WebKit::StorageAreaImpl::length):
(WebKit::StorageAreaImpl::key):
(WebKit::StorageAreaImpl::item):
(WebKit::StorageAreaImpl::setItem):
(WebKit::StorageAreaImpl::removeItem):
(WebKit::StorageAreaImpl::clear):
(WebKit::StorageAreaImpl::contains):
(WebKit::StorageAreaImpl::importItems):
(WebKit::StorageAreaImpl::clearForOriginDeletion):
(WebKit::StorageAreaImpl::sessionChanged):
* Storage/StorageAreaImpl.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (276658 => 276659)


--- trunk/Source/WebCore/ChangeLog	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebCore/ChangeLog	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,3 +1,39 @@
+2021-04-27  Chris Dumez  <[email protected]>
+
+        Copy-on-write semantics should be an internal implementation detail of StorageMap
+        https://bugs.webkit.org/show_bug.cgi?id=225108
+
+        Reviewed by Alex Christensen.
+
+        Instead of making the StorageMap RefCounted and requiring the client to potentially
+        replace its StorageMap whenever it calls functions that modify the StorageMap, the
+        copy-on-write semantics in now an internal implementation detail of StorageMap.
+
+        To achieve this, the following changes were made:
+        - StorageMap is no longer RefCounted. Instead, it has an internal Impl data member
+          that is RefCounted.
+        - The internal Impl data member is the one that gets copied on write.
+        - Functions that modify the StorageMap no longer need to return a StorageMap.
+        - Add a clear() function for convenience.
+
+        * storage/StorageMap.cpp:
+        (WebCore::StorageMap::StorageMap):
+        (WebCore::StorageMap::invalidateIterator):
+        (WebCore::StorageMap::setIteratorToIndex):
+        (WebCore::StorageMap::length const):
+        (WebCore::StorageMap::key):
+        (WebCore::StorageMap::getItem const):
+        (WebCore::StorageMap::setItem):
+        (WebCore::StorageMap::setItemIgnoringQuota):
+        (WebCore::StorageMap::removeItem):
+        (WebCore::StorageMap::clear):
+        (WebCore::StorageMap::contains const):
+        (WebCore::StorageMap::importItems):
+        (WebCore::StorageMap::Impl::copy const):
+        * storage/StorageMap.h:
+        (WebCore::StorageMap::items const):
+        (WebCore::StorageMap::Impl::create):
+
 2021-04-27  Aditya Keerthi  <[email protected]>
 
         [iOS][FCR] Add borders for better control visibility

Modified: trunk/Source/WebCore/storage/StorageMap.cpp (276658 => 276659)


--- trunk/Source/WebCore/storage/StorageMap.cpp	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebCore/storage/StorageMap.cpp	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-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
@@ -30,29 +30,16 @@
 
 namespace WebCore {
 
-Ref<StorageMap> StorageMap::create(unsigned quota)
-{
-    return adoptRef(*new StorageMap(quota));
-}
-
 StorageMap::StorageMap(unsigned quota)
-    : m_iterator(m_map.end())
-    , m_quotaSize(quota)  // quota measured in bytes
+    : m_impl(Impl::create())
+    , m_quotaSize(quota) // quota measured in bytes
 {
 }
 
-Ref<StorageMap> StorageMap::copy()
-{
-    Ref<StorageMap> newMap = create(m_quotaSize);
-    newMap->m_map = m_map;
-    newMap->m_currentLength = m_currentLength;
-    return newMap;
-}
-
 void StorageMap::invalidateIterator()
 {
-    m_iterator = m_map.end();
-    m_iteratorIndex = UINT_MAX;
+    m_impl->iterator = m_impl->map.end();
+    m_impl->iteratorIndex = UINT_MAX;
 }
 
 void StorageMap::setIteratorToIndex(unsigned index)
@@ -62,25 +49,25 @@
     // can take the shortest route.
     // Until that mechanism is available, we'll always increment our iterator from begin() or current.
 
-    if (m_iteratorIndex == index)
+    if (m_impl->iteratorIndex == index)
         return;
 
-    if (index < m_iteratorIndex) {
-        m_iteratorIndex = 0;
-        m_iterator = m_map.begin();
-        ASSERT(m_iterator != m_map.end());
+    if (index < m_impl->iteratorIndex) {
+        m_impl->iteratorIndex = 0;
+        m_impl->iterator = m_impl->map.begin();
+        ASSERT(m_impl->iterator != m_impl->map.end());
     }
 
-    while (m_iteratorIndex < index) {
-        ++m_iteratorIndex;
-        ++m_iterator;
-        ASSERT(m_iterator != m_map.end());
+    while (m_impl->iteratorIndex < index) {
+        ++m_impl->iteratorIndex;
+        ++m_impl->iterator;
+        ASSERT(m_impl->iterator != m_impl->map.end());
     }
 }
 
 unsigned StorageMap::length() const
 {
-    return m_map.size();
+    return m_impl->map.size();
 }
 
 String StorageMap::key(unsigned index)
@@ -89,33 +76,29 @@
         return String();
 
     setIteratorToIndex(index);
-    return m_iterator->key;
+    return m_impl->iterator->key;
 }
 
 String StorageMap::getItem(const String& key) const
 {
-    return m_map.get(key);
+    return m_impl->map.get(key);
 }
 
-RefPtr<StorageMap> StorageMap::setItem(const String& key, const String& value, String& oldValue, bool& quotaException)
+void StorageMap::setItem(const String& key, const String& value, String& oldValue, bool& quotaException)
 {
     ASSERT(!value.isNull());
     quotaException = false;
 
-    // Implement copy-on-write semantics here.  We're guaranteed that the only refs of StorageMaps belong to Storage objects
-    // so if more than one Storage object refs this map, copy it before mutating it.
-    if (refCount() > 1) {
-        RefPtr<StorageMap> newStorageMap = copy();
-        newStorageMap->setItem(key, value, oldValue, quotaException);
-        return newStorageMap;
-    }
+    // Implement copy-on-write semantics.
+    if (m_impl->refCount() > 1)
+        m_impl = m_impl->copy();
 
     // Quota tracking.  This is done in a couple of steps to keep the overflow tracking simple.
-    unsigned newLength = m_currentLength;
+    unsigned newLength = m_impl->currentLength;
     bool overflow = newLength + value.length() < newLength;
     newLength += value.length();
 
-    oldValue = m_map.get(key);
+    oldValue = m_impl->map.get(key);
     overflow |= newLength - oldValue.length() > newLength;
     newLength -= oldValue.length();
 
@@ -127,79 +110,66 @@
     bool overQuota = newLength > m_quotaSize / sizeof(UChar);
     if (m_quotaSize != noQuota && (overflow || overQuota)) {
         quotaException = true;
-        return nullptr;
+        return;
     }
-    m_currentLength = newLength;
+    m_impl->currentLength = newLength;
 
-    HashMap<String, String>::AddResult addResult = m_map.add(key, value);
+    HashMap<String, String>::AddResult addResult = m_impl->map.add(key, value);
     if (!addResult.isNewEntry)
         addResult.iterator->value = value;
 
     invalidateIterator();
-
-    return nullptr;
 }
 
-RefPtr<StorageMap> StorageMap::setItemIgnoringQuota(const String& key, const String& value)
+void StorageMap::setItemIgnoringQuota(const String& key, const String& value)
 {
     SetForScope<unsigned> quotaSizeChange(m_quotaSize, static_cast<unsigned>(noQuota));
 
     String oldValue;
     bool quotaException;
-
-    RefPtr<StorageMap> map = setItem(key, value, oldValue, quotaException);
+    setItem(key, value, oldValue, quotaException);
     ASSERT(!quotaException);
-
-    return map;
 }
 
-RefPtr<StorageMap> StorageMap::removeItem(const String& key, String& oldValue)
+void StorageMap::removeItem(const String& key, String& oldValue)
 {
-    // Implement copy-on-write semantics here.  We're guaranteed that the only refs of StorageMaps belong to Storage objects
-    // so if more than one Storage object refs this map, copy it before mutating it.
-    if (refCount() > 1) {
-        RefPtr<StorageMap> newStorage = copy();
-        newStorage->removeItem(key, oldValue);
-        return newStorage;
-    }
+    // Implement copy-on-write semantics.
+    if (m_impl->refCount() > 1)
+        m_impl = m_impl->copy();
 
-    oldValue = m_map.take(key);
+    oldValue = m_impl->map.take(key);
     if (!oldValue.isNull()) {
         invalidateIterator();
-        ASSERT(m_currentLength - key.length() <= m_currentLength);
-        m_currentLength -= key.length();
+        ASSERT(m_impl->currentLength - key.length() <= m_impl->currentLength);
+        m_impl->currentLength -= key.length();
     }
-    ASSERT(m_currentLength - oldValue.length() <= m_currentLength);
-    m_currentLength -= oldValue.length();
-
-    return nullptr;
+    ASSERT(m_impl->currentLength - oldValue.length() <= m_impl->currentLength);
+    m_impl->currentLength -= oldValue.length();
 }
 
-RefPtr<StorageMap> StorageMap::clear()
+void StorageMap::clear()
 {
-    // Implement copy-on-write semantics here. We're guaranteed that the only refs of StorageMaps belong to Storage objects
-    // so if more than one Storage object refs this map, copy it before mutating it.
-    if (refCount() > 1 && !m_map.isEmpty())
-        return StorageMap::create(m_quotaSize);
-
-    m_map.clear();
-    m_currentLength = 0;
-    return nullptr;
+    if (m_impl->refCount() > 1 && length()) {
+        m_impl = Impl::create();
+        return;
+    }
+    m_impl->map.clear();
+    m_impl->currentLength = 0;
 }
 
 bool StorageMap::contains(const String& key) const
 {
-    return m_map.contains(key);
+    return m_impl->map.contains(key);
 }
 
 void StorageMap::importItems(HashMap<String, String>&& items)
 {
-    if (m_map.isEmpty()) {
+    if (m_impl->map.isEmpty()) {
         // Fast path.
-        m_map = WTFMove(items);
-        for (auto& pair : m_map) {
-            ASSERT(m_currentLength + pair.key.length() + pair.value.length() >= m_currentLength);
-            m_currentLength += (pair.key.length() + pair.value.length());
+        m_impl->map = WTFMove(items);
+        for (auto& pair : m_impl->map) {
+            ASSERT(m_impl->currentLength + pair.key.length() + pair.value.length() >= m_impl->currentLength);
+            m_impl->currentLength += (pair.key.length() + pair.value.length());
         }
         return;
     }
@@ -208,12 +178,20 @@
         auto& key = item.key;
         auto& value = item.value;
 
-        ASSERT(m_currentLength + key.length() + value.length() >= m_currentLength);
-        m_currentLength += (key.length() + value.length());
+        ASSERT(m_impl->currentLength + key.length() + value.length() >= m_impl->currentLength);
+        m_impl->currentLength += (key.length() + value.length());
         
-        auto result = m_map.add(WTFMove(key), WTFMove(value));
+        auto result = m_impl->map.add(WTFMove(key), WTFMove(value));
         ASSERT_UNUSED(result, result.isNewEntry); // True if the key didn't exist previously.
     }
 }
 
+Ref<StorageMap::Impl> StorageMap::Impl::copy() const
+{
+    auto copy = Impl::create();
+    copy->map = map;
+    copy->currentLength = currentLength;
+    return copy;
 }
+
+}

Modified: trunk/Source/WebCore/storage/StorageMap.h (276658 => 276659)


--- trunk/Source/WebCore/storage/StorageMap.h	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebCore/storage/StorageMap.h	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-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
@@ -32,41 +32,52 @@
 
 namespace WebCore {
 
-class StorageMap : public RefCounted<StorageMap> {
+// This class uses copy-on-write semantics.
+class StorageMap {
+    WTF_MAKE_FAST_ALLOCATED;
 public:
     // Quota size measured in bytes.
-    WEBCORE_EXPORT static Ref<StorageMap> create(unsigned quotaSize);
+    WEBCORE_EXPORT explicit StorageMap(unsigned quotaSize);
 
     WEBCORE_EXPORT unsigned length() const;
     WEBCORE_EXPORT String key(unsigned index);
     WEBCORE_EXPORT String getItem(const String&) const;
-    WEBCORE_EXPORT RefPtr<StorageMap> setItem(const String& key, const String& value, String& oldValue, bool& quotaException);
-    WEBCORE_EXPORT RefPtr<StorageMap> setItemIgnoringQuota(const String& key, const String& value);
-    WEBCORE_EXPORT RefPtr<StorageMap> removeItem(const String&, String& oldValue);
-    WEBCORE_EXPORT RefPtr<StorageMap> clear();
+    WEBCORE_EXPORT void setItem(const String& key, const String& value, String& oldValue, bool& quotaException);
+    WEBCORE_EXPORT void setItemIgnoringQuota(const String& key, const String& value);
+    WEBCORE_EXPORT void removeItem(const String&, String& oldValue);
+    WEBCORE_EXPORT void clear();
 
     WEBCORE_EXPORT bool contains(const String& key) const;
 
     WEBCORE_EXPORT void importItems(HashMap<String, String>&&);
-    const HashMap<String, String>& items() const { return m_map; }
+    const HashMap<String, String>& items() const { return m_impl->map; }
 
     unsigned quota() const { return m_quotaSize; }
 
-    WEBCORE_EXPORT Ref<StorageMap> copy();
+    bool isShared() const { return !m_impl->hasOneRef(); }
 
-    static const constexpr unsigned noQuota = UINT_MAX;
+    static constexpr unsigned noQuota = UINT_MAX;
 
 private:
-    explicit StorageMap(unsigned quota);
     void invalidateIterator();
     void setIteratorToIndex(unsigned);
 
-    HashMap<String, String> m_map;
-    HashMap<String, String>::iterator m_iterator;
-    unsigned m_iteratorIndex { std::numeric_limits<unsigned>::max() };
+    struct Impl : public RefCounted<Impl> {
+        static Ref<Impl> create()
+        {
+            return adoptRef(*new Impl);
+        }
 
-    unsigned m_quotaSize; // Measured in bytes.
-    unsigned m_currentLength { 0 }; // Measured in UChars.
+        Ref<Impl> copy() const;
+
+        HashMap<String, String> map;
+        HashMap<String, String>::iterator iterator { map.end() };
+        unsigned iteratorIndex { std::numeric_limits<unsigned>::max() };
+        unsigned currentLength { 0 }; // Measured in UChars.
+    };
+
+    Ref<Impl> m_impl;
+    unsigned m_quotaSize { noQuota }; // Measured in bytes.
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (276658 => 276659)


--- trunk/Source/WebKit/ChangeLog	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKit/ChangeLog	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,3 +1,21 @@
+2021-04-27  Chris Dumez  <[email protected]>
+
+        Copy-on-write semantics should be an internal implementation detail of StorageMap
+        https://bugs.webkit.org/show_bug.cgi?id=225108
+
+        Reviewed by Alex Christensen.
+
+        Update StorageArea due to StorageMap API changes.
+
+        * NetworkProcess/WebStorage/StorageArea.cpp:
+        (WebKit::StorageArea::StorageArea):
+        (WebKit::StorageArea::setItem):
+        (WebKit::StorageArea::removeItem):
+        (WebKit::StorageArea::clear):
+        (WebKit::StorageArea::items const):
+        (WebKit::StorageArea::openDatabaseAndImportItemsIfNeeded const):
+        * NetworkProcess/WebStorage/StorageArea.h:
+
 2021-04-27  Per Arne  <[email protected]>
 
         Enforce IOKit filtering

Modified: trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp (276658 => 276659)


--- trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.cpp	2021-04-27 20:55:02 UTC (rev 276659)
@@ -30,8 +30,6 @@
 #include "LocalStorageNamespace.h"
 #include "StorageAreaMapMessages.h"
 #include "StorageManager.h"
-#include <WebCore/StorageMap.h>
-#include <wtf/Scope.h>
 
 namespace WebKit {
 
@@ -46,7 +44,7 @@
 {
     ASSERT(!RunLoop::isMain());
     if (isEphemeral())
-        m_storageMap = StorageMap::create(m_quotaInBytes);
+        m_sessionStorageMap = makeUnique<StorageMap>(m_quotaInBytes);
 }
 
 StorageArea::~StorageArea()
@@ -92,7 +90,7 @@
     ASSERT(!m_localStorageNamespace);
 
     auto storageArea = makeUnique<StorageArea>(nullptr, m_securityOrigin, m_quotaInBytes, m_queue.copyRef());
-    storageArea->m_storageMap = m_storageMap;
+    *storageArea->m_sessionStorageMap = *m_sessionStorageMap;
 
     return storageArea;
 }
@@ -102,11 +100,9 @@
     ASSERT(!RunLoop::isMain());
 
     String oldValue;
-    if (isEphemeral()) {
-        auto newStorageMap = m_storageMap->setItem(key, value, oldValue, quotaException);
-        if (newStorageMap)
-            m_storageMap = WTFMove(newStorageMap);
-    } else
+    if (isEphemeral())
+        m_sessionStorageMap->setItem(key, value, oldValue, quotaException);
+    else
         ensureDatabase().setItem(key, value, oldValue, quotaException);
 
     if (quotaException)
@@ -120,11 +116,9 @@
     ASSERT(!RunLoop::isMain());
 
     String oldValue;
-    if (isEphemeral()) {
-        auto newStorageMap = m_storageMap->removeItem(key, oldValue);
-        if (newStorageMap)
-            m_storageMap = WTFMove(newStorageMap);
-    } else
+    if (isEphemeral())
+        m_sessionStorageMap->removeItem(key, oldValue);
+    else
         ensureDatabase().removeItem(key, oldValue);
     if (oldValue.isNull())
         return;
@@ -137,10 +131,9 @@
     ASSERT(!RunLoop::isMain());
 
     if (isEphemeral()) {
-        if (!m_storageMap->length())
+        if (!m_sessionStorageMap->length())
             return;
-        if (auto newStorageMap = m_storageMap->clear())
-            m_storageMap = WTFMove(newStorageMap);
+        m_sessionStorageMap->clear();
     } else {
         if (!ensureDatabase().clear())
             return;
@@ -153,7 +146,7 @@
 {
     ASSERT(!RunLoop::isMain());
     if (isEphemeral())
-        return m_storageMap->items();
+        return m_sessionStorageMap->items();
 
     return ensureDatabase().items();
 }
@@ -161,10 +154,9 @@
 void StorageArea::clear()
 {
     ASSERT(!RunLoop::isMain());
-    if (isEphemeral()) {
-        if (auto newStorageMap = m_storageMap->clear())
-            m_storageMap = WTFMove(newStorageMap);
-    } else {
+    if (isEphemeral())
+        m_sessionStorageMap->clear();
+    else {
         if (m_localStorageDatabase) {
             m_localStorageDatabase->close();
             m_localStorageDatabase = nullptr;

Modified: trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h (276658 => 276659)


--- trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKit/NetworkProcess/WebStorage/StorageArea.h	2021-04-27 20:55:02 UTC (rev 276659)
@@ -29,6 +29,7 @@
 #include "StorageAreaIdentifier.h"
 #include "StorageAreaImplIdentifier.h"
 #include <WebCore/SecurityOriginData.h>
+#include <WebCore/StorageMap.h>
 #include <wtf/Forward.h>
 #include <wtf/WeakPtr.h>
 
@@ -84,7 +85,7 @@
     WebCore::SecurityOriginData m_securityOrigin;
     unsigned m_quotaInBytes { 0 };
 
-    RefPtr<WebCore::StorageMap> m_storageMap;
+    mutable std::unique_ptr<WebCore::StorageMap> m_sessionStorageMap;
     HashSet<IPC::Connection::UniqueID> m_eventListeners;
 
     Identifier m_identifier;

Modified: trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp (276658 => 276659)


--- trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.cpp	2021-04-27 20:55:02 UTC (rev 276659)
@@ -81,7 +81,7 @@
 void StorageAreaMap::setItem(Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key, const String& value, bool& quotaException)
 {
     auto& map = ensureMap();
-    ASSERT(map.hasOneRef());
+    ASSERT(!map.isShared());
 
     String oldValue;
     quotaException = false;
@@ -103,7 +103,7 @@
 void StorageAreaMap::removeItem(WebCore::Frame* sourceFrame, StorageAreaImpl* sourceArea, const String& key)
 {
     auto& map = ensureMap();
-    ASSERT(map.hasOneRef());
+    ASSERT(!map.isShared());
 
     String oldValue;
     map.removeItem(key, oldValue);
@@ -126,7 +126,7 @@
     resetValues();
 
     m_hasPendingClear = true;
-    m_map = StorageMap::create(m_quotaInBytes);
+    m_map = makeUnique<StorageMap>(m_quotaInBytes);
 
     if (m_mapID)
         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::StorageManagerSet::Clear(*m_mapID, sourceArea->identifier(), m_currentSeed, sourceFrame->document()->url().string()), 0);
@@ -153,7 +153,7 @@
     connect();
 
     if (!m_map) {
-        m_map = StorageMap::create(m_quotaInBytes);
+        m_map = makeUnique<StorageMap>(m_quotaInBytes);
 
         if (m_mapID) {
             // We need to use a IPC::UnboundedSynchronousIPCScope to prevent UIProcess hangs in case we receive a synchronous IPC from the UIProcess while we're waiting for a response
@@ -218,7 +218,7 @@
 
 void StorageAreaMap::applyChange(const String& key, const String& newValue)
 {
-    ASSERT(!m_map || m_map->hasOneRef());
+    ASSERT(!m_map || !m_map->isShared());
 
     // There is at least one clear pending we don't want to apply any changes until we get the corresponding DidClear messages.
     if (m_hasPendingClear)
@@ -226,7 +226,7 @@
 
     if (!key) {
         // A null key means clear.
-        auto newMap = StorageMap::create(m_quotaInBytes);
+        auto newMap = makeUnique<StorageMap>(m_quotaInBytes);
 
         // Any changes that were made locally after the clear must still be kept around in the new map.
         for (auto& change : m_pendingValueChanges) {

Modified: trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h (276658 => 276659)


--- trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKit/WebProcess/WebStorage/StorageAreaMap.h	2021-04-27 20:55:02 UTC (rev 276659)
@@ -94,7 +94,7 @@
 
     StorageNamespaceImpl& m_namespace;
     Ref<WebCore::SecurityOrigin> m_securityOrigin;
-    RefPtr<WebCore::StorageMap> m_map;
+    std::unique_ptr<WebCore::StorageMap> m_map;
     Optional<StorageAreaIdentifier> m_mapID;
     HashCountedSet<String> m_pendingValueChanges;
     uint64_t m_currentSeed { 0 };

Modified: trunk/Source/WebKitLegacy/ChangeLog (276658 => 276659)


--- trunk/Source/WebKitLegacy/ChangeLog	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKitLegacy/ChangeLog	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,5 +1,28 @@
 2021-04-27  Chris Dumez  <[email protected]>
 
+        Copy-on-write semantics should be an internal implementation detail of StorageMap
+        https://bugs.webkit.org/show_bug.cgi?id=225108
+
+        Reviewed by Alex Christensen.
+
+        Update StorageAreaImpl due to StorageMap API changes.
+
+        * Storage/StorageAreaImpl.cpp:
+        (WebKit::StorageAreaImpl::StorageAreaImpl):
+        (WebKit::StorageAreaImpl::length):
+        (WebKit::StorageAreaImpl::key):
+        (WebKit::StorageAreaImpl::item):
+        (WebKit::StorageAreaImpl::setItem):
+        (WebKit::StorageAreaImpl::removeItem):
+        (WebKit::StorageAreaImpl::clear):
+        (WebKit::StorageAreaImpl::contains):
+        (WebKit::StorageAreaImpl::importItems):
+        (WebKit::StorageAreaImpl::clearForOriginDeletion):
+        (WebKit::StorageAreaImpl::sessionChanged):
+        * Storage/StorageAreaImpl.h:
+
+2021-04-27  Chris Dumez  <[email protected]>
+
         Don't keep local storage data in memory in the NetworkProcess
         https://bugs.webkit.org/show_bug.cgi?id=225065
 

Modified: trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.cpp (276658 => 276659)


--- trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.cpp	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.cpp	2021-04-27 20:55:02 UTC (rev 276659)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-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
@@ -32,7 +32,6 @@
 #include <WebCore/SecurityOrigin.h>
 #include <WebCore/SecurityOriginData.h>
 #include <WebCore/StorageEventDispatcher.h>
-#include <WebCore/StorageMap.h>
 #include <WebCore/StorageType.h>
 #include <wtf/MainThread.h>
 
@@ -48,13 +47,12 @@
 inline StorageAreaImpl::StorageAreaImpl(StorageType storageType, const SecurityOriginData& origin, RefPtr<StorageSyncManager>&& syncManager, unsigned quota)
     : m_storageType(storageType)
     , m_securityOrigin(origin)
-    , m_storageMap(StorageMap::create(quota))
+    , m_storageMap(quota)
     , m_storageSyncManager(WTFMove(syncManager))
     , m_accessCount(0)
     , m_closeDatabaseTimer(*this, &StorageAreaImpl::closeDatabaseTimerFired)
 {
     ASSERT(isMainThread());
-    ASSERT(m_storageMap);
     
     // Accessing the shared global StorageTracker when a StorageArea is created 
     // ensures that the tracker is properly initialized before anyone actually needs to use it.
@@ -91,7 +89,6 @@
     , m_closeDatabaseTimer(*this, &StorageAreaImpl::closeDatabaseTimerFired)
 {
     ASSERT(isMainThread());
-    ASSERT(m_storageMap);
     ASSERT(!m_isShutdown);
 }
 
@@ -105,7 +102,7 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
 
-    return m_storageMap->length();
+    return m_storageMap.length();
 }
 
 String StorageAreaImpl::key(unsigned index)
@@ -113,7 +110,7 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
 
-    return m_storageMap->key(index);
+    return m_storageMap.key(index);
 }
 
 String StorageAreaImpl::item(const String& key)
@@ -121,7 +118,7 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
 
-    return m_storageMap->getItem(key);
+    return m_storageMap.getItem(key);
 }
 
 void StorageAreaImpl::setItem(Frame* sourceFrame, const String& key, const String& value, bool& quotaException)
@@ -131,10 +128,7 @@
     blockUntilImportComplete();
 
     String oldValue;
-    auto newMap = m_storageMap->setItem(key, value, oldValue, quotaException);
-    if (newMap)
-        m_storageMap = WTFMove(newMap);
-
+    m_storageMap.setItem(key, value, oldValue, quotaException);
     if (quotaException)
         return;
 
@@ -153,10 +147,7 @@
     blockUntilImportComplete();
 
     String oldValue;
-    auto newMap = m_storageMap->removeItem(key, oldValue);
-    if (newMap)
-        m_storageMap = WTFMove(newMap);
-
+    m_storageMap.removeItem(key, oldValue);
     if (oldValue.isNull())
         return;
 
@@ -171,11 +162,10 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
 
-    if (!m_storageMap->length())
+    if (!m_storageMap.length())
         return;
 
-    if (auto newStorageMap = m_storageMap->clear())
-        m_storageMap = WTFMove(newStorageMap);
+    m_storageMap.clear();
 
     if (m_storageAreaSync)
         m_storageAreaSync->scheduleClear();
@@ -188,7 +178,7 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
 
-    return m_storageMap->contains(key);
+    return m_storageMap.contains(key);
 }
 
 void StorageAreaImpl::importItems(HashMap<String, String>&& items)
@@ -196,7 +186,7 @@
     ASSERT(!m_isShutdown);
     ASSERT(!isMainThread());
 
-    m_storageMap->importItems(WTFMove(items));
+    m_storageMap.importItems(WTFMove(items));
 }
 
 void StorageAreaImpl::close()
@@ -214,8 +204,7 @@
     ASSERT(!m_isShutdown);
     blockUntilImportComplete();
     
-    if (auto newStorageMap = m_storageMap->clear())
-        m_storageMap = WTFMove(newStorageMap);
+    m_storageMap.clear();
 
     if (m_storageAreaSync) {
         m_storageAreaSync->scheduleClear();
@@ -295,8 +284,7 @@
     // If import is not completed, background storage thread may be modifying m_storageMap.
     blockUntilImportComplete();
 
-    unsigned quota = m_storageMap->quota();
-    m_storageMap = StorageMap::create(quota);
+    m_storageMap.clear();
 
     if (isNewSessionPersistent && !m_storageAreaSync && m_storageSyncManager) {
         m_storageAreaSync = StorageAreaSync::create(m_storageSyncManager.get(), *this, m_securityOrigin.databaseIdentifier());

Modified: trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.h (276658 => 276659)


--- trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.h	2021-04-27 20:37:56 UTC (rev 276658)
+++ trunk/Source/WebKitLegacy/Storage/StorageAreaImpl.h	2021-04-27 20:55:02 UTC (rev 276659)
@@ -27,6 +27,7 @@
 
 #include <WebCore/SecurityOriginData.h>
 #include <WebCore/StorageArea.h>
+#include <WebCore/StorageMap.h>
 #include <WebCore/Timer.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefPtr.h>
@@ -85,7 +86,7 @@
 
     WebCore::StorageType m_storageType;
     WebCore::SecurityOriginData m_securityOrigin;
-    RefPtr<WebCore::StorageMap> m_storageMap;
+    WebCore::StorageMap m_storageMap;
 
     RefPtr<StorageAreaSync> m_storageAreaSync;
     RefPtr<WebCore::StorageSyncManager> m_storageSyncManager;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to