Diff
Modified: trunk/Source/WebCore/ChangeLog (154779 => 154780)
--- trunk/Source/WebCore/ChangeLog 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/ChangeLog 2013-08-28 22:29:13 UTC (rev 154780)
@@ -1,3 +1,103 @@
+2013-08-27 Benjamin Poulain <[email protected]>
+
+ 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 <[email protected]>
+
+ 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 <[email protected]>
Namespace prefix is blindly followed when serializing
@@ -80,6 +180,7 @@
* platform/qt/LocalizedStringsQt.cpp:
(WebCore::AXSearchFieldCancelButtonText):
+>>>>>>> .r154779
2013-08-28 Eric Carlson <[email protected]>
MediaPlayerPrivateAVFoundationObjC is painting video frames under the video layer
Modified: trunk/Source/WebCore/WebCore.exp.in (154779 => 154780)
--- trunk/Source/WebCore/WebCore.exp.in 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/WebCore.exp.in 2013-08-28 22:29:13 UTC (rev 154780)
@@ -689,7 +689,6 @@
__ZN7WebCore20ResourceResponseBase6setURLERKNS_4KURLE
__ZN7WebCore20ResourceResponseBaseC2Ev
__ZN7WebCore20ResourceResponseBaseC2ERKNS_4KURLERKN3WTF6StringExS7_S7_
-__ZN7WebCore20SpaceSplitStringDataD1Ev
__ZN7WebCore20UserGestureIndicator7s_stateE
__ZN7WebCore20UserGestureIndicatorC1ENS_26ProcessingUserGestureStateE
__ZN7WebCore20UserGestureIndicatorD1Ev
Modified: trunk/Source/WebCore/dom/ElementData.h (154779 => 154780)
--- trunk/Source/WebCore/dom/ElementData.h 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/dom/ElementData.h 2013-08-28 22:29:13 UTC (rev 154780)
@@ -66,7 +66,7 @@
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;
Modified: trunk/Source/WebCore/dom/SpaceSplitString.cpp (154779 => 154780)
--- trunk/Source/WebCore/dom/SpaceSplitString.cpp 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/dom/SpaceSplitString.cpp 2013-08-28 22:29:13 UTC (rev 154780)
@@ -27,10 +27,10 @@
#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 @@
}
}
-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();
+ ASSERT(!string.isNull());
- AppendTokenToVectorTokenProcessor tokenProcessor(m_vector);
- if (string.is8Bit()) {
- tokenizeSpaceSplitString(tokenProcessor, string.characters8(), length);
- return;
- }
-
- 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,65 +90,26 @@
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)
+struct SpaceSplitStringDataMapKeyTrait : public HashTraits<AtomicString>
{
- ASSERT(hasOneRef());
- ASSERT(!contains(string));
- m_vector.append(string);
-}
+ // 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;
+};
-void SpaceSplitStringData::remove(unsigned index)
-{
- ASSERT(hasOneRef());
- m_vector.remove(index);
-}
+typedef HashMap<AtomicString, SpaceSplitStringData*, DefaultHash<AtomicString>::Hash, SpaceSplitStringDataMapKeyTrait> SpaceSplitStringDataMap;
-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;
-}
-
-typedef HashMap<AtomicString, SpaceSplitStringData*> SpaceSplitStringDataMap;
-
static SpaceSplitStringDataMap& sharedDataMap()
{
DEFINE_STATIC_LOCAL(SpaceSplitStringDataMap, map, ());
@@ -177,9 +123,9 @@
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 @@
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 = "" 0).iterator->value;
- if (!data) {
- data = "" SpaceSplitStringData(string);
- return adoptRef(data);
+ template <typename CharacterType>
+ bool processToken(const CharacterType*, unsigned)
+ {
+ ++m_tokenCount;
+ return true;
}
- return data;
-}
-PassRefPtr<SpaceSplitStringData> SpaceSplitStringData::createUnique(const SpaceSplitStringData& other)
+ 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;
+ }
+
+ 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 = ""
+ do {
+ data[i].~AtomicString();
+ ++i;
+ } while (i < size);
+
+ spaceSplitString->~SpaceSplitStringData();
+
+ fastFree(spaceSplitString);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/SpaceSplitString.h (154779 => 154780)
--- trunk/Source/WebCore/dom/SpaceSplitString.h 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/dom/SpaceSplitString.h 2013-08-28 22:29:13 UTC (rev 154780)
@@ -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
@@ -21,48 +21,78 @@
#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 = ""
+ 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.");
+ }
- void createVector(const String&);
- template <typename CharacterType>
- inline void createVector(const CharacterType*, unsigned);
+ inline ~SpaceSplitStringData() { }
+ static void destroy(SpaceSplitStringData*);
+ 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 @@
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 @@
}
private:
- void ensureUnique()
- {
- if (m_data && !m_data->isUnique())
- m_data = SpaceSplitStringData::createUnique(*m_data);
- }
RefPtr<SpaceSplitStringData> m_data;
};
Modified: trunk/Source/WebCore/html/ClassList.cpp (154779 => 154780)
--- trunk/Source/WebCore/html/ClassList.cpp 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/html/ClassList.cpp 2013-08-28 22:29:13 UTC (rev 154780)
@@ -83,7 +83,7 @@
{
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;
}
Modified: trunk/Source/WebCore/page/EventHandler.cpp (154779 => 154780)
--- trunk/Source/WebCore/page/EventHandler.cpp 2013-08-28 22:25:19 UTC (rev 154779)
+++ trunk/Source/WebCore/page/EventHandler.cpp 2013-08-28 22:29:13 UTC (rev 154780)
@@ -2074,7 +2074,7 @@
dropZoneStr.makeLower();
SpaceSplitString keywords(dropZoneStr, false);
- if (keywords.isNull())
+ if (keywords.isEmpty())
continue;
DragOperation dragOperation = DragOperationNone;