Commit 590e91cd authored by benjamin@webkit.org's avatar benjamin@webkit.org

Simplify and clean SpaceSplitString

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: http://svn.webkit.org/repository/webkit/trunk@154780 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 941d8ef6
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
......@@ -80,6 +180,7 @@
* 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
......@@ -689,7 +689,6 @@ __ZN7WebCore20ResourceResponseBase24setExpectedContentLengthEx
__ZN7WebCore20ResourceResponseBase6setURLERKNS_4KURLE
__ZN7WebCore20ResourceResponseBaseC2Ev
__ZN7WebCore20ResourceResponseBaseC2ERKNS_4KURLERKN3WTF6StringExS7_S7_
__ZN7WebCore20SpaceSplitStringDataD1Ev
__ZN7WebCore20UserGestureIndicator7s_stateE
__ZN7WebCore20UserGestureIndicatorC1ENS_26ProcessingUserGestureStateE
__ZN7WebCore20UserGestureIndicatorD1Ev
......
......@@ -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;
......
......@@ -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 @@ 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
/*
* 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 = 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;
};
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment