Simplify and clean SpaceSplitString
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Aug 2013 22:29:13 +0000 (22:29 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Aug 2013 22:29:13 +0000 (22:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=120385

Patch by Benjamin Poulain <bpoulain@apple.com> on 2013-08-27
Reviewed by Ryosuke Niwa.

Clean up of SpaceSplitString following the cleaning of the DOMTokenList hierarchy.
This brings the following:
- Fix the coding style of the header.
- Remove the concepts of empty and null. The list can now be empty or have something.
  There is no null state.
- Put the tokens directly following SpaceSplitStringData instead of using a Vector in between.

* WebCore.exp.in:
* dom/ElementData.h:
(WebCore::ElementData::hasClass):
* dom/SpaceSplitString.cpp:
(WebCore::tokenizeSpaceSplitString):
(WebCore::SpaceSplitStringData::containsAll):
(WebCore::SpaceSplitString::set):
(WebCore::SpaceSplitString::spaceSplitStringContainsValue):
(WebCore::TokenCounterProcessor::TokenCounterProcessor):
(WebCore::TokenCounterProcessor::processToken):
(WebCore::TokenCounterProcessor::tokenCount):
(WebCore::TokenInitializerProcessor::TokenInitializerProcessor):
(WebCore::TokenInitializerProcessor::processToken):
(WebCore::TokenInitializerProcessor::nextMemoryBucket):
(WebCore::SpaceSplitStringData::create):
(WebCore::SpaceSplitStringData::destroy):
* dom/SpaceSplitString.h:
(WebCore::SpaceSplitStringData::contains):
(WebCore::SpaceSplitStringData::size):
(WebCore::SpaceSplitStringData::operator[]):
(WebCore::SpaceSplitStringData::ref):
(WebCore::SpaceSplitStringData::deref):
(WebCore::SpaceSplitStringData::SpaceSplitStringData):
(WebCore::SpaceSplitStringData::~SpaceSplitStringData):
(WebCore::SpaceSplitStringData::tokenArrayStart):
(WebCore::SpaceSplitString::SpaceSplitString):
(WebCore::SpaceSplitString::operator!=):
(WebCore::SpaceSplitString::clear):
(WebCore::SpaceSplitString::contains):
(WebCore::SpaceSplitString::containsAll):
(WebCore::SpaceSplitString::size):
(WebCore::SpaceSplitString::isEmpty):
(WebCore::SpaceSplitString::operator[]):
(WebCore::SpaceSplitString::spaceSplitStringContainsValue):
* html/ClassList.cpp:
(WebCore::ClassList::classNames):
* page/EventHandler.cpp:
(WebCore::findDropZone):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154780 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/dom/ElementData.h
Source/WebCore/dom/SpaceSplitString.cpp
Source/WebCore/dom/SpaceSplitString.h
Source/WebCore/html/ClassList.cpp
Source/WebCore/page/EventHandler.cpp

index ed04dce..ec4b702 100644 (file)
@@ -1,3 +1,103 @@
+2013-08-27  Benjamin Poulain  <bpoulain@apple.com>
+
+        Simplify and clean SpaceSplitString
+        https://bugs.webkit.org/show_bug.cgi?id=120385
+
+        Reviewed by Ryosuke Niwa.
+
+        Clean up of SpaceSplitString following the cleaning of the DOMTokenList hierarchy.
+        This brings the following:
+        - Fix the coding style of the header.
+        - Remove the concepts of empty and null. The list can now be empty or have something.
+          There is no null state.
+        - Put the tokens directly following SpaceSplitStringData instead of using a Vector in between.
+
+        * WebCore.exp.in:
+        * dom/ElementData.h:
+        (WebCore::ElementData::hasClass):
+        * dom/SpaceSplitString.cpp:
+        (WebCore::tokenizeSpaceSplitString):
+        (WebCore::SpaceSplitStringData::containsAll):
+        (WebCore::SpaceSplitString::set):
+        (WebCore::SpaceSplitString::spaceSplitStringContainsValue):
+        (WebCore::TokenCounterProcessor::TokenCounterProcessor):
+        (WebCore::TokenCounterProcessor::processToken):
+        (WebCore::TokenCounterProcessor::tokenCount):
+        (WebCore::TokenInitializerProcessor::TokenInitializerProcessor):
+        (WebCore::TokenInitializerProcessor::processToken):
+        (WebCore::TokenInitializerProcessor::nextMemoryBucket):
+        (WebCore::SpaceSplitStringData::create):
+        (WebCore::SpaceSplitStringData::destroy):
+        * dom/SpaceSplitString.h:
+        (WebCore::SpaceSplitStringData::contains):
+        (WebCore::SpaceSplitStringData::size):
+        (WebCore::SpaceSplitStringData::operator[]):
+        (WebCore::SpaceSplitStringData::ref):
+        (WebCore::SpaceSplitStringData::deref):
+        (WebCore::SpaceSplitStringData::SpaceSplitStringData):
+        (WebCore::SpaceSplitStringData::~SpaceSplitStringData):
+        (WebCore::SpaceSplitStringData::tokenArrayStart):
+        (WebCore::SpaceSplitString::SpaceSplitString):
+        (WebCore::SpaceSplitString::operator!=):
+        (WebCore::SpaceSplitString::clear):
+        (WebCore::SpaceSplitString::contains):
+        (WebCore::SpaceSplitString::containsAll):
+        (WebCore::SpaceSplitString::size):
+        (WebCore::SpaceSplitString::isEmpty):
+        (WebCore::SpaceSplitString::operator[]):
+        (WebCore::SpaceSplitString::spaceSplitStringContainsValue):
+        * html/ClassList.cpp:
+        (WebCore::ClassList::classNames):
+        * page/EventHandler.cpp:
+        (WebCore::findDropZone):
+
+<<<<<<< .mine
+2013-08-28  Benjamin Poulain  <benjamin@webkit.org>
+
+        Simplify and clean SpaceSplitString
+        https://bugs.webkit.org/show_bug.cgi?id=120385
+
+        Reviewed by Ryosuke Niwa.
+
+        Clean up of SpaceSplitString following the cleaning of the DOMTokenList hierarchy.
+        - Remove the concepts of empty and null. The list can now be empty or have something.
+          There is no null state.
+        - Put the tokens directly following SpaceSplitStringData instead of using a Vector in between.
+
+        * WebCore.exp.in:
+        * dom/ElementData.h:
+        (WebCore::ElementData::hasClass):
+        * dom/SpaceSplitString.cpp:
+        (WebCore::tokenizeSpaceSplitString):
+        (WebCore::SpaceSplitStringData::containsAll):
+        (WebCore::SpaceSplitString::set):
+        (WebCore::SpaceSplitString::spaceSplitStringContainsValue):
+        (WebCore::TokenCounter::TokenCounter):
+        (WebCore::TokenCounter::processToken):
+        (WebCore::TokenCounter::tokenCount):
+        (WebCore::TokenAtomicStringInitializer::TokenAtomicStringInitializer):
+        (WebCore::TokenAtomicStringInitializer::processToken):
+        (WebCore::TokenAtomicStringInitializer::nextMemoryBucket):
+        (WebCore::SpaceSplitStringData::create):
+        (WebCore::SpaceSplitStringData::destroy):
+        * dom/SpaceSplitString.h:
+        (WebCore::SpaceSplitStringData::contains):
+        (WebCore::SpaceSplitStringData::size):
+        (WebCore::SpaceSplitStringData::operator[]):
+        (WebCore::SpaceSplitStringData::ref):
+        (WebCore::SpaceSplitStringData::deref):
+        (WebCore::SpaceSplitStringData::SpaceSplitStringData):
+        (WebCore::SpaceSplitStringData::~SpaceSplitStringData):
+        (WebCore::SpaceSplitStringData::tokenArrayStart):
+        (WebCore::SpaceSplitString::containsAll):
+        (WebCore::SpaceSplitString::isEmpty):
+        (WebCore::SpaceSplitString::operator[]):
+        * html/ClassList.cpp:
+        (WebCore::ClassList::classNames):
+        * page/EventHandler.cpp:
+        (WebCore::findDropZone):
+
+=======
 2013-08-28  Rob Buis  <rwlbuis@webkit.org>
 
         Namespace prefix is blindly followed when serializing
         * platform/qt/LocalizedStringsQt.cpp:
         (WebCore::AXSearchFieldCancelButtonText):
 
+>>>>>>> .r154779
 2013-08-28  Eric Carlson  <eric.carlson@apple.com>
 
         MediaPlayerPrivateAVFoundationObjC is painting video frames under the video layer
index a3cc797..6097335 100644 (file)
@@ -689,7 +689,6 @@ __ZN7WebCore20ResourceResponseBase24setExpectedContentLengthEx
 __ZN7WebCore20ResourceResponseBase6setURLERKNS_4KURLE
 __ZN7WebCore20ResourceResponseBaseC2Ev
 __ZN7WebCore20ResourceResponseBaseC2ERKNS_4KURLERKN3WTF6StringExS7_S7_
-__ZN7WebCore20SpaceSplitStringDataD1Ev
 __ZN7WebCore20UserGestureIndicator7s_stateE
 __ZN7WebCore20UserGestureIndicatorC1ENS_26ProcessingUserGestureStateE
 __ZN7WebCore20UserGestureIndicatorD1Ev
index 76d9a88..9147809 100644 (file)
@@ -66,7 +66,7 @@ public:
     unsigned findAttributeIndexByNameForAttributeNode(const Attr*, bool shouldIgnoreAttributeCase = false) const;
 
     bool hasID() const { return !m_idForStyleResolution.isNull(); }
-    bool hasClass() const { return !m_classNames.isNull(); }
+    bool hasClass() const { return !m_classNames.isEmpty(); }
     bool hasName() const { return m_hasNameAttribute; }
 
     bool isEquivalent(const ElementData* other) const;
index 7806ba0..5c307c6 100644 (file)
 #include <wtf/text/AtomicStringHash.h>
 #include <wtf/text/StringBuilder.h>
 
-using namespace WTF;
-
 namespace WebCore {
 
+COMPILE_ASSERT(!(sizeof(SpaceSplitStringData) % sizeof(uintptr_t)), SpaceSplitStringDataTailIsAlignedToWordSize);
+
 template <typename CharacterType>
 static inline bool hasNonASCIIOrUpper(const CharacterType* characters, unsigned length)
 {
@@ -73,31 +73,16 @@ static inline void tokenizeSpaceSplitString(TokenProcessor& tokenProcessor, cons
     }
 }
 
-class AppendTokenToVectorTokenProcessor {
-public:
-    AppendTokenToVectorTokenProcessor(Vector<AtomicString, 4>& vector) : m_vector(vector) { }
-
-    template <typename CharacterType>
-    bool processToken(const CharacterType* characters, unsigned length)
-    {
-        m_vector.append(AtomicString(characters, length));
-        return true;
-    }
-private:
-    Vector<AtomicString, 4>& m_vector;
-};
-
-void SpaceSplitStringData::createVector(const String& string)
+template<typename TokenProcessor>
+static inline void tokenizeSpaceSplitString(TokenProcessor& tokenProcessor, const String& string)
 {
-    unsigned length = string.length();
-
-    AppendTokenToVectorTokenProcessor tokenProcessor(m_vector);
-    if (string.is8Bit()) {
-        tokenizeSpaceSplitString(tokenProcessor, string.characters8(), length);
-        return;
-    }
+    ASSERT(!string.isNull());
 
-    tokenizeSpaceSplitString(tokenProcessor, string.characters16(), length);
+    const StringImpl* stringImpl = string.impl();
+    if (stringImpl->is8Bit())
+        tokenizeSpaceSplitString(tokenProcessor, stringImpl->characters8(), stringImpl->length());
+    else
+        tokenizeSpaceSplitString(tokenProcessor, stringImpl->characters16(), stringImpl->length());
 }
 
 bool SpaceSplitStringData::containsAll(SpaceSplitStringData& other)
@@ -105,64 +90,25 @@ bool SpaceSplitStringData::containsAll(SpaceSplitStringData& other)
     if (this == &other)
         return true;
 
-    size_t thisSize = m_vector.size();
-    size_t otherSize = other.m_vector.size();
-    for (size_t i = 0; i < otherSize; ++i) {
-        const AtomicString& name = other.m_vector[i];
-        size_t j;
-        for (j = 0; j < thisSize; ++j) {
-            if (m_vector[j] == name)
-                break;
-        }
-        if (j == thisSize)
+    unsigned otherSize = other.m_size;
+    unsigned i = 0;
+    do {
+        if (!contains(other[i]))
             return false;
-    }
+        ++i;
+    } while (i < otherSize);
     return true;
 }
 
-void SpaceSplitStringData::add(const AtomicString& string)
-{
-    ASSERT(hasOneRef());
-    ASSERT(!contains(string));
-    m_vector.append(string);
-}
-
-void SpaceSplitStringData::remove(unsigned index)
+struct SpaceSplitStringDataMapKeyTrait : public HashTraits<AtomicString>
 {
-    ASSERT(hasOneRef());
-    m_vector.remove(index);
-}
-
-void SpaceSplitString::add(const AtomicString& string)
-{
-    // FIXME: add() does not allow duplicates but createVector() does.
-    if (contains(string))
-        return;
-    ensureUnique();
-    if (m_data)
-        m_data->add(string);
-}
-
-bool SpaceSplitString::remove(const AtomicString& string)
-{
-    if (!m_data)
-        return false;
-    unsigned i = 0;
-    bool changed = false;
-    while (i < m_data->size()) {
-        if ((*m_data)[i] == string) {
-            if (!changed)
-                ensureUnique();
-            m_data->remove(i);
-            changed = true;
-            continue;
-        }
-        ++i;
-    }
-    return changed;
-}
+    // The number 200 for typicalNumberOfSpaceSplitString was based on the typical number of unique class names
+    // on typical websites on August 2013.
+    static const unsigned typicalNumberOfSpaceSplitString = 200;
+    static const int minimumTableSize = WTF::HashTableCapacityForSize<typicalNumberOfSpaceSplitString>::value;
+};
 
-typedef HashMap<AtomicString, SpaceSplitStringData*> SpaceSplitStringDataMap;
+typedef HashMap<AtomicString, SpaceSplitStringData*, DefaultHash<AtomicString>::Hash, SpaceSplitStringDataMapKeyTrait> SpaceSplitStringDataMap;
 
 static SpaceSplitStringDataMap& sharedDataMap()
 {
@@ -177,9 +123,9 @@ void SpaceSplitString::set(const AtomicString& inputString, bool shouldFoldCase)
         return;
     }
 
-    String string(inputString.string());
+    AtomicString string(inputString);
     if (shouldFoldCase && hasNonASCIIOrUpper(string))
-        string = string.foldCase();
+        string = string.string().foldCase();
 
     m_data = SpaceSplitStringData::create(string);
 }
@@ -221,48 +167,107 @@ bool SpaceSplitString::spaceSplitStringContainsValue(const String& inputString,
         string = string.foldCase();
 
     TokenIsEqualToCStringTokenProcessor tokenProcessor(value, valueLength);
-    unsigned length = string.length();
-    if (string.is8Bit())
-        tokenizeSpaceSplitString(tokenProcessor, string.characters8(), length);
-    else
-        tokenizeSpaceSplitString(tokenProcessor, string.characters16(), length);
+    tokenizeSpaceSplitString(tokenProcessor, string);
     return tokenProcessor.referenceStringWasFound();
 }
 
-SpaceSplitStringData::~SpaceSplitStringData()
-{
-    if (!m_keyString.isNull())
-        sharedDataMap().remove(m_keyString);
-}
+class TokenCounter {
+    WTF_MAKE_NONCOPYABLE(TokenCounter);
+public:
+    TokenCounter() : m_tokenCount(0) { }
 
-PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::create(const AtomicString& string)
-{
-    SpaceSplitStringData*& data = sharedDataMap().add(string, 0).iterator->value;
-    if (!data) {
-        data = new SpaceSplitStringData(string);
-        return adoptRef(data);
+    template <typename CharacterType>
+    bool processToken(const CharacterType*, unsigned)
+    {
+        ++m_tokenCount;
+        return true;
+    }
+
+    unsigned tokenCount() const { return m_tokenCount; }
+
+private:
+    unsigned m_tokenCount;
+};
+
+class TokenAtomicStringInitializer {
+    WTF_MAKE_NONCOPYABLE(TokenAtomicStringInitializer);
+public:
+    TokenAtomicStringInitializer(AtomicString* memory) : m_memoryBucket(memory) { }
+
+    template <typename CharacterType>
+    bool processToken(const CharacterType* characters, unsigned length)
+    {
+        new (NotNull, m_memoryBucket) AtomicString(characters, length);
+        ++m_memoryBucket;
+        return true;
     }
-    return data;
-}
 
-PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::createUnique(const SpaceSplitStringData& other)
+    const AtomicString* nextMemoryBucket() const { return m_memoryBucket; }
+private:
+    AtomicString* m_memoryBucket;
+};
+
+PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::create(const AtomicString& keyString, unsigned tokenCount)
 {
-    return adoptRef(new SpaceSplitStringData(other));
+    ASSERT(tokenCount);
+
+    RELEASE_ASSERT(tokenCount < (std::numeric_limits<unsigned>::max() - sizeof(SpaceSplitStringData)) / sizeof(AtomicString));
+    unsigned sizeToAllocate = sizeof(SpaceSplitStringData) + tokenCount * sizeof(AtomicString);
+    SpaceSplitStringData* spaceSplitStringData = static_cast<SpaceSplitStringData*>(fastMalloc(sizeToAllocate));
+
+    new (NotNull, spaceSplitStringData) SpaceSplitStringData(keyString, tokenCount);
+    AtomicString* tokenArrayStart = spaceSplitStringData->tokenArrayStart();
+    TokenAtomicStringInitializer tokenInitializer(tokenArrayStart);
+    tokenizeSpaceSplitString(tokenInitializer, keyString);
+    ASSERT(tokenInitializer.nextMemoryBucket() - tokenArrayStart == tokenCount);
+    ASSERT(reinterpret_cast<const char*>(tokenInitializer.nextMemoryBucket()) == reinterpret_cast<const char*>(spaceSplitStringData) + sizeToAllocate);
+
+    return adoptRef(spaceSplitStringData);
 }
 
-SpaceSplitStringData::SpaceSplitStringData(const AtomicString& string)
-    : m_keyString(string)
+PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::create(const AtomicString& keyString)
 {
-    ASSERT(!string.isNull());
-    createVector(string);
+    ASSERT(isMainThread());
+    ASSERT(!keyString.isNull());
+
+    SpaceSplitStringDataMap& spaceSplitStringDataCache = sharedDataMap();
+    SpaceSplitStringDataMap::iterator iterator = spaceSplitStringDataCache.find(keyString);
+    if (iterator != spaceSplitStringDataCache.end())
+        return iterator->value;
+
+    // Nothing in the cache? Let's create a new SpaceSplitStringData if the input has something useful.
+    // 1) We find the number of strings in the input to know how much size we need to allocate.
+    TokenCounter tokenCounter;
+    tokenizeSpaceSplitString(tokenCounter, keyString);
+    unsigned tokenCount = tokenCounter.tokenCount();
+
+    if (!tokenCount)
+        return nullptr;
+
+    RefPtr<SpaceSplitStringData> spaceSplitStringData = create(keyString, tokenCount);
+    spaceSplitStringDataCache.add(keyString, spaceSplitStringData.get());
+    return spaceSplitStringData.release();
 }
 
-SpaceSplitStringData::SpaceSplitStringData(const SpaceSplitStringData& other)
-    : RefCounted<SpaceSplitStringData>()
-    , m_vector(other.m_vector)
+
+void SpaceSplitStringData::destroy(SpaceSplitStringData* spaceSplitString)
 {
-    // Note that we don't copy m_keyString to indicate to the destructor that there's nothing
-    // to be removed from the sharedDataMap().
+    ASSERT(isMainThread());
+
+    if (!spaceSplitString->m_keyString.isNull())
+        sharedDataMap().remove(spaceSplitString->m_keyString);
+
+    unsigned i = 0;
+    unsigned size = spaceSplitString->size();
+    const AtomicString* data = spaceSplitString->tokenArrayStart();
+    do {
+        data[i].~AtomicString();
+        ++i;
+    } while (i < size);
+
+    spaceSplitString->~SpaceSplitStringData();
+
+    fastFree(spaceSplitString);
 }
 
 } // namespace WebCore
index 80bb5e6..ebcea2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #ifndef SpaceSplitString_h
 #define SpaceSplitString_h
 
-#include <wtf/RefCounted.h>
-#include <wtf/Vector.h>
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
+#include <wtf/Noncopyable.h>
 #include <wtf/text/AtomicString.h>
 
 namespace WebCore {
 
-class SpaceSplitStringData : public RefCounted<SpaceSplitStringData> {
+class SpaceSplitStringData {
+    WTF_MAKE_NONCOPYABLE(SpaceSplitStringData);
+    WTF_MAKE_FAST_ALLOCATED;
 public:
     static PassRefPtr<SpaceSplitStringData> create(const AtomicString&);
-    static PassRefPtr<SpaceSplitStringData> createUnique(const SpaceSplitStringData&);
-
-    ~SpaceSplitStringData();
 
     bool contains(const AtomicString& string)
     {
-        size_t size = m_vector.size();
-        for (size_t i = 0; i < size; ++i) {
-            if (m_vector[i] == string)
+        const AtomicString* data = tokenArrayStart();
+        unsigned i = 0;
+        do {
+            if (data[i] == string)
                 return true;
-        }
+            ++i;
+        } while (i < m_size);
         return false;
     }
 
     bool containsAll(SpaceSplitStringData&);
 
-    void add(const AtomicString&);
-    void remove(unsigned index);
+    unsigned size() const { return m_size; }
+    const AtomicString& operator[](size_t i)
+    {
+        RELEASE_ASSERT(i < m_size);
+        return tokenArrayStart()[i];
+    }
 
-    bool isUnique() const { return m_keyString.isNull(); } 
-    size_t size() const { return m_vector.size(); }
-    const AtomicString& operator[](size_t i) { ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return m_vector[i]; }
+    inline void ref()
+    {
+        ASSERT(isMainThread());
+        ASSERT(m_refCount);
+        ++m_refCount;
+    }
+
+    inline void deref()
+    {
+        ASSERT(isMainThread());
+        ASSERT(m_refCount);
+        unsigned tempRefCount = m_refCount - 1;
+        if (!tempRefCount) {
+            SpaceSplitStringData::destroy(this);
+            return;
+        }
+        m_refCount = tempRefCount;
+    }
 
 private:
-    explicit SpaceSplitStringData(const AtomicString&);
-    explicit SpaceSplitStringData(const SpaceSplitStringData&);
+    static PassRefPtr<SpaceSplitStringData> create(const AtomicString&, unsigned tokenCount);
+    SpaceSplitStringData(const AtomicString& string, unsigned size)
+        : m_keyString(string)
+        , m_refCount(1)
+        , m_size(size)
+    {
+        ASSERT(!string.isEmpty());
+        ASSERT_WITH_MESSAGE(m_size, "SpaceSplitStringData should never be empty by definition. There is no difference between empty and null.");
+    }
+
+    inline ~SpaceSplitStringData() { }
+    static void destroy(SpaceSplitStringData*);
 
-    void createVector(const String&);
-    template <typename CharacterType>
-    inline void createVector(const CharacterType*, unsigned);
+    AtomicString* tokenArrayStart() { return reinterpret_cast<AtomicString*>(this + 1); }
 
     AtomicString m_keyString;
-    Vector<AtomicString, 4> m_vector;
+    unsigned m_refCount;
+    unsigned m_size;
 };
 
 class SpaceSplitString {
@@ -77,12 +107,14 @@ public:
 
     bool contains(const AtomicString& string) const { return m_data && m_data->contains(string); }
     bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); }
-    void add(const AtomicString&);
-    bool remove(const AtomicString&);
 
     size_t size() const { return m_data ? m_data->size() : 0; }
-    bool isNull() const { return !m_data; }
-    const AtomicString& operator[](size_t i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < size()); return (*m_data)[i]; }
+    bool isEmpty() const { return !m_data; }
+    const AtomicString& operator[](size_t i) const
+    {
+        ASSERT_WITH_SECURITY_IMPLICATION(m_data);
+        return (*m_data)[i];
+    }
 
     static bool spaceSplitStringContainsValue(const String& spaceSplitString, const char* value, unsigned length, bool shouldFoldCase);
     template<size_t length>
@@ -92,11 +124,6 @@ public:
     }
 
 private:
-    void ensureUnique()
-    {
-        if (m_data && !m_data->isUnique())
-            m_data = SpaceSplitStringData::createUnique(*m_data);
-    }
 
     RefPtr<SpaceSplitStringData> m_data;
 };
index d6e9006..0d62098 100644 (file)
@@ -83,7 +83,7 @@ const SpaceSplitString& ClassList::classNames() const
 {
     ASSERT(m_element->hasClass());
     if (m_element->document()->inQuirksMode()) {
-        if (!m_classNamesForQuirksMode.size())
+        if (m_classNamesForQuirksMode.isEmpty())
             m_classNamesForQuirksMode.set(value(), false);
         return m_classNamesForQuirksMode;
     }
index f3338ba..1e0b629 100644 (file)
@@ -2074,7 +2074,7 @@ static bool findDropZone(Node* target, Clipboard* clipboard)
         dropZoneStr.makeLower();
         
         SpaceSplitString keywords(dropZoneStr, false);
-        if (keywords.isNull())
+        if (keywords.isEmpty())
             continue;
         
         DragOperation dragOperation = DragOperationNone;