| Index: Source/WTF/wtf/text/AtomicString.cpp
|
| diff --git a/Source/WTF/wtf/text/AtomicString.cpp b/Source/WTF/wtf/text/AtomicString.cpp
|
| deleted file mode 100644
|
| index 56f7df60cb110d0b1968a4d13fd4d6d299ee30b8..0000000000000000000000000000000000000000
|
| --- a/Source/WTF/wtf/text/AtomicString.cpp
|
| +++ /dev/null
|
| @@ -1,505 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
|
| - * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
|
| - * Copyright (C) 2012 Google 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
|
| - * License as published by the Free Software Foundation; either
|
| - * version 2 of the License, or (at your option) any later version.
|
| - *
|
| - * This library is distributed in the hope that it will be useful,
|
| - * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| - * Library General Public License for more details.
|
| - *
|
| - * You should have received a copy of the GNU Library General Public License
|
| - * along with this library; see the file COPYING.LIB. If not, write to
|
| - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
| - * Boston, MA 02110-1301, USA.
|
| - *
|
| - */
|
| -
|
| -#include "config.h"
|
| -
|
| -#include "AtomicString.h"
|
| -
|
| -#include "StringHash.h"
|
| -#include <wtf/HashSet.h>
|
| -#include <wtf/Threading.h>
|
| -#include <wtf/WTFThreadData.h>
|
| -#include <wtf/unicode/UTF8.h>
|
| -
|
| -#if USE(WEB_THREAD)
|
| -#include <wtf/MainThread.h>
|
| -#include <wtf/TCSpinLock.h>
|
| -#endif
|
| -
|
| -namespace WTF {
|
| -
|
| -using namespace Unicode;
|
| -
|
| -COMPILE_ASSERT(sizeof(AtomicString) == sizeof(String), atomic_string_and_string_must_be_same_size);
|
| -
|
| -#if USE(WEB_THREAD)
|
| -class AtomicStringTableLocker : public SpinLockHolder {
|
| - WTF_MAKE_NONCOPYABLE(AtomicStringTableLocker);
|
| -
|
| - static SpinLock s_stringTableLock;
|
| -public:
|
| - AtomicStringTableLocker()
|
| - : SpinLockHolder(&s_stringTableLock)
|
| - {
|
| - }
|
| -};
|
| -
|
| -SpinLock AtomicStringTableLocker::s_stringTableLock = SPINLOCK_INITIALIZER;
|
| -#else
|
| -
|
| -class AtomicStringTableLocker {
|
| - WTF_MAKE_NONCOPYABLE(AtomicStringTableLocker);
|
| -public:
|
| - AtomicStringTableLocker() { }
|
| - ~AtomicStringTableLocker() { }
|
| -};
|
| -#endif // USE(WEB_THREAD)
|
| -
|
| -class AtomicStringTable {
|
| - WTF_MAKE_FAST_ALLOCATED;
|
| -public:
|
| - static AtomicStringTable* create(WTFThreadData& data)
|
| - {
|
| -#if USE(WEB_THREAD)
|
| - // On iOS, one AtomicStringTable is shared between the main UI thread and the WebThread.
|
| - static AtomicStringTable* sharedStringTable = new AtomicStringTable;
|
| -
|
| - bool currentThreadIsWebThread = isWebThread();
|
| - if (currentThreadIsWebThread || isUIThread())
|
| - data.m_atomicStringTable = sharedStringTable;
|
| - else
|
| - data.m_atomicStringTable = new AtomicStringTable;
|
| -
|
| - // We do the following so that its destruction happens only
|
| - // once - on the main UI thread.
|
| - if (!currentThreadIsWebThread)
|
| - data.m_atomicStringTableDestructor = AtomicStringTable::destroy;
|
| -#else
|
| - data.m_atomicStringTable = new AtomicStringTable;
|
| - data.m_atomicStringTableDestructor = AtomicStringTable::destroy;
|
| -#endif // USE(WEB_THREAD)
|
| - return data.m_atomicStringTable;
|
| - }
|
| -
|
| - HashSet<StringImpl*>& table()
|
| - {
|
| - return m_table;
|
| - }
|
| -
|
| -private:
|
| - static void destroy(AtomicStringTable* table)
|
| - {
|
| - HashSet<StringImpl*>::iterator end = table->m_table.end();
|
| - for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter)
|
| - (*iter)->setIsAtomic(false);
|
| - delete table;
|
| - }
|
| -
|
| - HashSet<StringImpl*> m_table;
|
| -};
|
| -
|
| -static inline HashSet<StringImpl*>& stringTable()
|
| -{
|
| - // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor).
|
| - WTFThreadData& data = wtfThreadData();
|
| - AtomicStringTable* table = data.atomicStringTable();
|
| - if (UNLIKELY(!table))
|
| - table = AtomicStringTable::create(data);
|
| - return table->table();
|
| -}
|
| -
|
| -template<typename T, typename HashTranslator>
|
| -static inline PassRefPtr<StringImpl> addToStringTable(const T& value)
|
| -{
|
| - AtomicStringTableLocker locker;
|
| -
|
| - HashSet<StringImpl*>::AddResult addResult = stringTable().add<T, HashTranslator>(value);
|
| -
|
| - // If the string is newly-translated, then we need to adopt it.
|
| - // The boolean in the pair tells us if that is so.
|
| - return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
|
| -}
|
| -
|
| -struct CStringTranslator {
|
| - static unsigned hash(const LChar* c)
|
| - {
|
| - return StringHasher::computeHashAndMaskTop8Bits(c);
|
| - }
|
| -
|
| - static inline bool equal(StringImpl* r, const LChar* s)
|
| - {
|
| - return WTF::equal(r, s);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const LChar* const& c, unsigned hash)
|
| - {
|
| - location = StringImpl::create(c).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(const LChar* c)
|
| -{
|
| - if (!c)
|
| - return 0;
|
| - if (!*c)
|
| - return StringImpl::empty();
|
| -
|
| - return addToStringTable<const LChar*, CStringTranslator>(c);
|
| -}
|
| -
|
| -template<typename CharacterType>
|
| -struct HashTranslatorCharBuffer {
|
| - const CharacterType* s;
|
| - unsigned length;
|
| -};
|
| -
|
| -typedef HashTranslatorCharBuffer<UChar> UCharBuffer;
|
| -struct UCharBufferTranslator {
|
| - static unsigned hash(const UCharBuffer& buf)
|
| - {
|
| - return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& str, const UCharBuffer& buf)
|
| - {
|
| - return WTF::equal(str, buf.s, buf.length);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
|
| - {
|
| - location = StringImpl::create8BitIfPossible(buf.s, buf.length).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -template<typename CharacterType>
|
| -struct HashAndCharacters {
|
| - unsigned hash;
|
| - const CharacterType* characters;
|
| - unsigned length;
|
| -};
|
| -
|
| -template<typename CharacterType>
|
| -struct HashAndCharactersTranslator {
|
| - static unsigned hash(const HashAndCharacters<CharacterType>& buffer)
|
| - {
|
| - ASSERT(buffer.hash == StringHasher::computeHashAndMaskTop8Bits(buffer.characters, buffer.length));
|
| - return buffer.hash;
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& string, const HashAndCharacters<CharacterType>& buffer)
|
| - {
|
| - return WTF::equal(string, buffer.characters, buffer.length);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const HashAndCharacters<CharacterType>& buffer, unsigned hash)
|
| - {
|
| - location = StringImpl::create(buffer.characters, buffer.length).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -struct HashAndUTF8Characters {
|
| - unsigned hash;
|
| - const char* characters;
|
| - unsigned length;
|
| - unsigned utf16Length;
|
| -};
|
| -
|
| -struct HashAndUTF8CharactersTranslator {
|
| - static unsigned hash(const HashAndUTF8Characters& buffer)
|
| - {
|
| - return buffer.hash;
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& string, const HashAndUTF8Characters& buffer)
|
| - {
|
| - if (buffer.utf16Length != string->length())
|
| - return false;
|
| -
|
| - // If buffer contains only ASCII characters UTF-8 and UTF16 length are the same.
|
| - if (buffer.utf16Length != buffer.length) {
|
| - const UChar* stringCharacters = string->characters();
|
| -
|
| - return equalUTF16WithUTF8(stringCharacters, stringCharacters + string->length(), buffer.characters, buffer.characters + buffer.length);
|
| - }
|
| -
|
| - if (string->is8Bit()) {
|
| - const LChar* stringCharacters = string->characters8();
|
| -
|
| - for (unsigned i = 0; i < buffer.length; ++i) {
|
| - ASSERT(isASCII(buffer.characters[i]));
|
| - if (stringCharacters[i] != buffer.characters[i])
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| - }
|
| -
|
| - const UChar* stringCharacters = string->characters16();
|
| -
|
| - for (unsigned i = 0; i < buffer.length; ++i) {
|
| - ASSERT(isASCII(buffer.characters[i]));
|
| - if (stringCharacters[i] != buffer.characters[i])
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const HashAndUTF8Characters& buffer, unsigned hash)
|
| - {
|
| - UChar* target;
|
| - RefPtr<StringImpl> newString = StringImpl::createUninitialized(buffer.utf16Length, target);
|
| -
|
| - bool isAllASCII;
|
| - const char* source = buffer.characters;
|
| - if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII) != conversionOK)
|
| - ASSERT_NOT_REACHED();
|
| -
|
| - if (isAllASCII)
|
| - newString = StringImpl::create(buffer.characters, buffer.length);
|
| -
|
| - location = newString.release().leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
|
| -{
|
| - if (!s)
|
| - return 0;
|
| -
|
| - if (!length)
|
| - return StringImpl::empty();
|
| -
|
| - UCharBuffer buffer = { s, length };
|
| - return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
|
| -}
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash)
|
| -{
|
| - ASSERT(s);
|
| - ASSERT(existingHash);
|
| -
|
| - if (!length)
|
| - return StringImpl::empty();
|
| -
|
| - HashAndCharacters<UChar> buffer = { existingHash, s, length };
|
| - return addToStringTable<HashAndCharacters<UChar>, HashAndCharactersTranslator<UChar> >(buffer);
|
| -}
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
|
| -{
|
| - if (!s)
|
| - return 0;
|
| -
|
| - unsigned length = 0;
|
| - while (s[length] != UChar(0))
|
| - ++length;
|
| -
|
| - if (!length)
|
| - return StringImpl::empty();
|
| -
|
| - UCharBuffer buffer = { s, length };
|
| - return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
|
| -}
|
| -
|
| -struct SubstringLocation {
|
| - StringImpl* baseString;
|
| - unsigned start;
|
| - unsigned length;
|
| -};
|
| -
|
| -struct SubstringTranslator {
|
| - static unsigned hash(const SubstringLocation& buffer)
|
| - {
|
| - return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->characters() + buffer.start, buffer.length);
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& string, const SubstringLocation& buffer)
|
| - {
|
| - return WTF::equal(string, buffer.baseString->characters() + buffer.start, buffer.length);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const SubstringLocation& buffer, unsigned hash)
|
| - {
|
| - location = StringImpl::create(buffer.baseString, buffer.start, buffer.length).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length)
|
| -{
|
| - if (!baseString)
|
| - return 0;
|
| -
|
| - if (!length || start >= baseString->length())
|
| - return StringImpl::empty();
|
| -
|
| - unsigned maxLength = baseString->length() - start;
|
| - if (length >= maxLength) {
|
| - if (!start)
|
| - return add(baseString);
|
| - length = maxLength;
|
| - }
|
| -
|
| - SubstringLocation buffer = { baseString, start, length };
|
| - return addToStringTable<SubstringLocation, SubstringTranslator>(buffer);
|
| -}
|
| -
|
| -typedef HashTranslatorCharBuffer<LChar> LCharBuffer;
|
| -struct LCharBufferTranslator {
|
| - static unsigned hash(const LCharBuffer& buf)
|
| - {
|
| - return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& str, const LCharBuffer& buf)
|
| - {
|
| - return WTF::equal(str, buf.s, buf.length);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const LCharBuffer& buf, unsigned hash)
|
| - {
|
| - location = StringImpl::create(buf.s, buf.length).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -typedef HashTranslatorCharBuffer<char> CharBuffer;
|
| -struct CharBufferFromLiteralDataTranslator {
|
| - static unsigned hash(const CharBuffer& buf)
|
| - {
|
| - return StringHasher::computeHashAndMaskTop8Bits(reinterpret_cast<const LChar*>(buf.s), buf.length);
|
| - }
|
| -
|
| - static bool equal(StringImpl* const& str, const CharBuffer& buf)
|
| - {
|
| - return WTF::equal(str, buf.s, buf.length);
|
| - }
|
| -
|
| - static void translate(StringImpl*& location, const CharBuffer& buf, unsigned hash)
|
| - {
|
| - location = StringImpl::createFromLiteral(buf.s, buf.length).leakRef();
|
| - location->setHash(hash);
|
| - location->setIsAtomic(true);
|
| - }
|
| -};
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::add(const LChar* s, unsigned length)
|
| -{
|
| - if (!s)
|
| - return 0;
|
| -
|
| - if (!length)
|
| - return StringImpl::empty();
|
| -
|
| - LCharBuffer buffer = { s, length };
|
| - return addToStringTable<LCharBuffer, LCharBufferTranslator>(buffer);
|
| -}
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::addFromLiteralData(const char* characters, unsigned length)
|
| -{
|
| - ASSERT(characters);
|
| - ASSERT(length);
|
| -
|
| - CharBuffer buffer = { characters, length };
|
| - return addToStringTable<CharBuffer, CharBufferFromLiteralDataTranslator>(buffer);
|
| -}
|
| -
|
| -PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
|
| -{
|
| - if (!r->length())
|
| - return StringImpl::empty();
|
| -
|
| - AtomicStringTableLocker locker;
|
| - StringImpl* result = *stringTable().add(r).iterator;
|
| - if (result == r)
|
| - r->setIsAtomic(true);
|
| - ASSERT(!r->isStatic() || result->isStatic());
|
| - return result;
|
| -}
|
| -
|
| -template<typename CharacterType>
|
| -static inline HashSet<StringImpl*>::iterator findString(const StringImpl* stringImpl)
|
| -{
|
| - HashAndCharacters<CharacterType> buffer = { stringImpl->existingHash(), stringImpl->getCharacters<CharacterType>(), stringImpl->length() };
|
| - return stringTable().find<HashAndCharacters<CharacterType>, HashAndCharactersTranslator<CharacterType> >(buffer);
|
| -}
|
| -
|
| -AtomicStringImpl* AtomicString::find(const StringImpl* stringImpl)
|
| -{
|
| - ASSERT(stringImpl);
|
| - ASSERT(stringImpl->existingHash());
|
| -
|
| - if (!stringImpl->length())
|
| - return static_cast<AtomicStringImpl*>(StringImpl::empty());
|
| -
|
| - AtomicStringTableLocker locker;
|
| - HashSet<StringImpl*>::iterator iterator;
|
| - if (stringImpl->is8Bit())
|
| - iterator = findString<LChar>(stringImpl);
|
| - else
|
| - iterator = findString<UChar>(stringImpl);
|
| - if (iterator == stringTable().end())
|
| - return 0;
|
| - return static_cast<AtomicStringImpl*>(*iterator);
|
| -}
|
| -
|
| -void AtomicString::remove(StringImpl* r)
|
| -{
|
| - AtomicStringTableLocker locker;
|
| - stringTable().remove(r);
|
| -}
|
| -
|
| -AtomicString AtomicString::lower() const
|
| -{
|
| - // Note: This is a hot function in the Dromaeo benchmark.
|
| - StringImpl* impl = this->impl();
|
| - if (UNLIKELY(!impl))
|
| - return *this;
|
| - RefPtr<StringImpl> newImpl = impl->lower();
|
| - if (LIKELY(newImpl == impl))
|
| - return *this;
|
| - return AtomicString(newImpl);
|
| -}
|
| -
|
| -AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
|
| -{
|
| - HashAndUTF8Characters buffer;
|
| - buffer.characters = charactersStart;
|
| - buffer.hash = calculateStringHashAndLengthFromUTF8MaskingTop8Bits(charactersStart, charactersEnd, buffer.length, buffer.utf16Length);
|
| -
|
| - if (!buffer.hash)
|
| - return nullAtom;
|
| -
|
| - AtomicString atomicString;
|
| - atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer);
|
| - return atomicString;
|
| -}
|
| -
|
| -#ifndef NDEBUG
|
| -void AtomicString::show() const
|
| -{
|
| - m_string.show();
|
| -}
|
| -#endif
|
| -
|
| -} // namespace WTF
|
|
|