diff options
Diffstat (limited to 'WebCore/platform/text/AtomicString.cpp')
-rw-r--r-- | WebCore/platform/text/AtomicString.cpp | 216 |
1 files changed, 152 insertions, 64 deletions
diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp index c584e6c..dc573e1 100644 --- a/WebCore/platform/text/AtomicString.cpp +++ b/WebCore/platform/text/AtomicString.cpp @@ -20,27 +20,46 @@ #include "config.h" -#ifdef AVOID_STATIC_CONSTRUCTORS +#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC #define ATOMICSTRING_HIDE_GLOBALS 1 #endif #include "AtomicString.h" -#include "DeprecatedString.h" #include "StaticConstructors.h" #include "StringHash.h" #include <kjs/identifier.h> +#include <wtf/Threading.h> #include <wtf/HashSet.h> -using KJS::Identifier; -using KJS::UString; +#if ENABLE(WORKERS) +#include <wtf/ThreadSpecific.h> +using namespace WTF; +#endif + +#if USE(JSC) +using JSC::Identifier; +using JSC::UString; +#endif namespace WebCore { -static HashSet<StringImpl*>* stringTable; +#if ENABLE(WORKERS) +static ThreadSpecific<HashSet<StringImpl*> >* staticStringTable; +#else +static HashSet<StringImpl*>* staticStringTable; +#endif -struct CStringTranslator +static inline HashSet<StringImpl*>* stringTable() { +#if ENABLE(WORKERS) + return *staticStringTable; +#else + return staticStringTable; +#endif +} + +struct CStringTranslator { static unsigned hash(const char* c) { return StringImpl::computeHash(c); @@ -74,13 +93,16 @@ bool operator==(const AtomicString& a, const char* b) return CStringTranslator::equal(impl, b); } -StringImpl* AtomicString::add(const char* c) +PassRefPtr<StringImpl> AtomicString::add(const char* c) { if (!c) return 0; if (!*c) return StringImpl::empty(); - return *stringTable->add<const char*, CStringTranslator>(c).first; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<const char*, CStringTranslator>(c); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); } struct UCharBuffer { @@ -88,6 +110,37 @@ struct UCharBuffer { unsigned length; }; +static inline bool equal(StringImpl* string, const UChar* characters, unsigned length) +{ + if (string->length() != length) + return false; + +#if PLATFORM(ARM) + const UChar* stringCharacters = string->characters(); + for (unsigned i = 0; i != length; ++i) { + if (*stringCharacters++ != *characters++) + return false; + } + return true; +#else + /* Do it 4-bytes-at-a-time on architectures where it's safe */ + + const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters()); + const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters); + + unsigned halfLength = length >> 1; + for (unsigned i = 0; i != halfLength; ++i) { + if (*stringCharacters++ != *bufferCharacters++) + return false; + } + + if (length & 1 && *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters)) + return false; + + return true; +#endif +} + struct UCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { @@ -96,37 +149,7 @@ struct UCharBufferTranslator { static bool equal(StringImpl* const& str, const UCharBuffer& buf) { - unsigned strLength = str->length(); - unsigned bufLength = buf.length; - if (strLength != bufLength) - return false; - -#if PLATFORM(ARM) - const UChar* strChars = str->characters(); - const UChar* bufChars = buf.s; - - for (unsigned i = 0; i != strLength; ++i) { - if (*strChars++ != *bufChars++) - return false; - } - return true; -#else - /* Do it 4-bytes-at-a-time on architectures where it's safe */ - const uint32_t* strChars = reinterpret_cast<const uint32_t*>(str->characters()); - const uint32_t* bufChars = reinterpret_cast<const uint32_t*>(buf.s); - - unsigned halfLength = strLength >> 1; - for (unsigned i = 0; i != halfLength; ++i) { - if (*strChars++ != *bufChars++) - return false; - } - - if (strLength & 1 && - *reinterpret_cast<const uint16_t *>(strChars) != *reinterpret_cast<const uint16_t *>(bufChars)) - return false; - - return true; -#endif + return WebCore::equal(str, buf.s, buf.length); } static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) @@ -135,7 +158,31 @@ struct UCharBufferTranslator { } }; -StringImpl* AtomicString::add(const UChar* s, int length) +struct HashAndCharacters { + unsigned hash; + const UChar* characters; + unsigned length; +}; + +struct HashAndCharactersTranslator { + static unsigned hash(const HashAndCharacters& buffer) + { + ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length)); + return buffer.hash; + } + + static bool equal(StringImpl* const& string, const HashAndCharacters& buffer) + { + return WebCore::equal(string, buffer.characters, buffer.length); + } + + static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash) + { + location = new StringImpl(buffer.characters, buffer.length, hash); + } +}; + +PassRefPtr<StringImpl> AtomicString::add(const UChar* s, int length) { if (!s) return 0; @@ -143,11 +190,14 @@ StringImpl* AtomicString::add(const UChar* s, int length) if (length == 0) return StringImpl::empty(); - UCharBuffer buf = {s, length}; - return *stringTable->add<UCharBuffer, UCharBufferTranslator>(buf).first; + UCharBuffer buf = { s, length }; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); } -StringImpl* AtomicString::add(const UChar* s) +PassRefPtr<StringImpl> AtomicString::add(const UChar* s) { if (!s) return 0; @@ -160,10 +210,13 @@ StringImpl* AtomicString::add(const UChar* s) return StringImpl::empty(); UCharBuffer buf = {s, length}; - return *stringTable->add<UCharBuffer, UCharBufferTranslator>(buf).first; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<UCharBuffer, UCharBufferTranslator>(buf); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); } -StringImpl* AtomicString::add(StringImpl* r) +PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) { if (!r || r->m_inTable) return r; @@ -171,7 +224,7 @@ StringImpl* AtomicString::add(StringImpl* r) if (r->length() == 0) return StringImpl::empty(); - StringImpl* result = *stringTable->add(r).first; + StringImpl* result = *stringTable()->add(r).first; if (result == r) r->m_inTable = true; return result; @@ -179,37 +232,65 @@ StringImpl* AtomicString::add(StringImpl* r) void AtomicString::remove(StringImpl* r) { - stringTable->remove(r); + stringTable()->remove(r); } -StringImpl* AtomicString::add(const KJS::Identifier& str) +#if USE(JSC) +PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier) { - return add(reinterpret_cast<const UChar*>(str.data()), str.size()); -} + if (identifier.isNull()) + return 0; -StringImpl* AtomicString::add(const KJS::UString& str) -{ - return add(reinterpret_cast<const UChar*>(str.data()), str.size()); -} + UString::Rep* string = identifier.ustring().rep(); + unsigned length = string->size(); + if (!length) + return StringImpl::empty(); -AtomicString::operator Identifier() const -{ - return m_string; + HashAndCharacters buffer = { string->computedHash(), string->data(), length }; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); } -AtomicString::operator UString() const +PassRefPtr<StringImpl> AtomicString::add(const JSC::UString& ustring) { - return m_string; + if (ustring.isNull()) + return 0; + + UString::Rep* string = ustring.rep(); + unsigned length = string->size(); + if (!length) + return StringImpl::empty(); + + HashAndCharacters buffer = { string->hash(), string->data(), length }; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable()->add<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); } +#endif -AtomicString::AtomicString(const DeprecatedString& s) - : m_string(add(reinterpret_cast<const UChar*>(s.unicode()), s.length())) +AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) { + if (identifier.isNull()) + return 0; + + UString::Rep* string = identifier.ustring().rep(); + unsigned length = string->size(); + if (!length) + return static_cast<AtomicStringImpl*>(StringImpl::empty()); + + HashAndCharacters buffer = { string->computedHash(), string->data(), length }; + HashSet<StringImpl*>::iterator iterator = stringTable()->find<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (iterator == stringTable()->end()) + return 0; + return static_cast<AtomicStringImpl*>(*iterator); } -DeprecatedString AtomicString::deprecatedString() const +AtomicString::operator UString() const { - return m_string.deprecatedString(); + return m_string; } DEFINE_GLOBAL(AtomicString, nullAtom) @@ -222,7 +303,14 @@ void AtomicString::init() { static bool initialized; if (!initialized) { - stringTable = new HashSet<StringImpl*>; + // Initialization is not thread safe, so this function must be called from the main thread first. + ASSERT(isMainThread()); + +#if ENABLE(WORKERS) + staticStringTable = new ThreadSpecific<HashSet<StringImpl*> >; +#else + staticStringTable = new HashSet<StringImpl*>; +#endif // Use placement new to initialize the globals. new ((void*)&nullAtom) AtomicString; |