Changeset 55825 in webkit
- Timestamp:
- Mar 10, 2010 6:36:08 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r55817 r55825 1 2010-03-10 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Darin Adler, Geoffrey Garen, Maciej Stachowiak. 4 5 https://bugs.webkit.org/show_bug.cgi?id=35991 6 Would be faster to not use a thread specific to implement StringImpl::empty() 7 8 Change JSC::UStringImpl's implementation of empty() match to match StringImpl's new implementation 9 (use a static defined within the empty() method), and change the interface to match too (return 10 a pointer not a reference). 11 12 ~0% performance impact (possible minor progression from moving empty() from .h to .cpp). 13 14 * JavaScriptCore.exp: 15 * runtime/Identifier.cpp: 16 (JSC::Identifier::add): 17 (JSC::Identifier::addSlowCase): 18 * runtime/PropertyNameArray.cpp: 19 (JSC::PropertyNameArray::add): 20 * runtime/UString.cpp: 21 (JSC::initializeUString): 22 (JSC::UString::UString): 23 * runtime/UStringImpl.cpp: 24 (JSC::UStringImpl::empty): 25 (JSC::UStringImpl::create): 26 * runtime/UStringImpl.h: 27 (JSC::UStringImpl::adopt): 28 (JSC::UStringImpl::createUninitialized): 29 (JSC::UStringImpl::tryCreateUninitialized): 30 1 31 2010-03-10 Dmitry Titov <dimich@chromium.org> 2 32 -
trunk/JavaScriptCore/JavaScriptCore.exp
r55811 r55825 107 107 __ZN3JSC11ParserArena5resetEv 108 108 __ZN3JSC11UStringImpl12sharedBufferEv 109 __ZN3JSC11UStringImpl 7s_emptyE109 __ZN3JSC11UStringImpl5emptyEv 110 110 __ZN3JSC11UStringImplD1Ev 111 111 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE -
trunk/JavaScriptCore/runtime/Identifier.cpp
r55751 r55825 131 131 } 132 132 if (!c[0]) { 133 UString::Rep::empty() .hash();134 return &UString::Rep::empty();133 UString::Rep::empty()->hash(); 134 return UString::Rep::empty(); 135 135 } 136 136 if (!c[1]) … … 195 195 } 196 196 if (!length) { 197 UString::Rep::empty() .hash();198 return &UString::Rep::empty();197 UString::Rep::empty()->hash(); 198 return UString::Rep::empty(); 199 199 } 200 200 UCharBuffer buf = {s, length}; … … 226 226 } 227 227 if (!r->length()) { 228 UString::Rep::empty() .hash();229 return &UString::Rep::empty();228 UString::Rep::empty()->hash(); 229 return UString::Rep::empty(); 230 230 } 231 231 return *globalData->identifierTable->add(r).first; -
trunk/JavaScriptCore/runtime/PropertyNameArray.cpp
r55751 r55825 31 31 void PropertyNameArray::add(UString::Rep* identifier) 32 32 { 33 ASSERT(identifier == UString::null().rep() || identifier == &UString::Rep::empty() || identifier->isIdentifier());33 ASSERT(identifier == UString::null().rep() || identifier == UString::Rep::empty() || identifier->isIdentifier()); 34 34 35 35 size_t size = m_data->propertyNameVector().size(); -
trunk/JavaScriptCore/runtime/UString.cpp
r54843 r55825 147 147 } 148 148 149 // These static strings are immutable, except for rc, whose initial value is chosen to 150 // reduce the possibility of it becoming zero due to ref/deref not being thread-safe. 151 static UChar sharedEmptyChar; 152 UStringImpl* UStringImpl::s_empty; 153 149 // The null string is immutable, except for refCount. 154 150 UString::Rep* UString::s_nullRep; 155 151 UString* UString::s_nullUString; … … 157 153 void initializeUString() 158 154 { 159 UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString); 155 // UStringImpl::empty() does not construct its static string in a threadsafe fashion, 156 // so ensure it has been initialized from here. 157 UStringImpl::empty(); 160 158 161 159 UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString); … … 174 172 175 173 UString::UString(const UChar* c, unsigned length) 176 { 177 if (length == 0) 178 m_rep = &Rep::empty(); 179 else 180 m_rep = Rep::create(c, length); 174 : m_rep(Rep::create(c, length)) 175 { 181 176 } 182 177 -
trunk/JavaScriptCore/runtime/UStringImpl.cpp
r55679 r55825 28 28 29 29 #include "Identifier.h" 30 #include "StdLibExtras.h" 30 31 #include "UString.h" 31 32 #include <wtf/unicode/UTF8.h> … … 36 37 namespace JSC { 37 38 38 PassRefPtr<UStringImpl> UStringImpl::create(const char* c)39 UStringImpl* UStringImpl::empty() 39 40 { 40 ASSERT(c); 41 42 if (!c[0]) 43 return &UStringImpl::empty(); 44 45 size_t length = strlen(c); 46 UChar* d; 47 PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); 48 for (size_t i = 0; i < length; i++) 49 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend 50 return result; 41 // A non-null pointer at an invalid address (in page zero) so that if it were to be accessed we 42 // should catch the error with fault (however it should be impossible to access, since length is zero). 43 static const UChar* invalidNonNullUCharPtr = reinterpret_cast<UChar*>(static_cast<intptr_t>(1)); 44 DEFINE_STATIC_LOCAL(UStringImpl, emptyString, (invalidNonNullUCharPtr, 0, ConstructStaticString)); 45 return &emptyString; 51 46 } 52 47 53 PassRefPtr<UStringImpl> UStringImpl::create(const char* c, unsigned length)48 PassRefPtr<UStringImpl> UStringImpl::create(const UChar* characters, unsigned length) 54 49 { 55 ASSERT(c); 50 if (!characters || !length) 51 return empty(); 56 52 57 if (!length) 58 return &UStringImpl::empty(); 59 60 UChar* d; 61 PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); 62 for (unsigned i = 0; i < length; i++) 63 d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend 64 return result; 53 UChar* data; 54 PassRefPtr<UStringImpl> string = createUninitialized(length, data); 55 memcpy(data, characters, length * sizeof(UChar)); 56 return string; 65 57 } 66 58 67 PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, unsigned length)59 PassRefPtr<UStringImpl> UStringImpl::create(const char* characters, unsigned length) 68 60 { 69 UChar* newBuffer; 70 PassRefPtr<UStringImpl> impl = createUninitialized(length, newBuffer); 71 copyChars(newBuffer, buffer, length); 72 return impl; 61 if (!characters || !length) 62 return empty(); 63 64 UChar* data; 65 PassRefPtr<UStringImpl> string = createUninitialized(length, data); 66 for (unsigned i = 0; i != length; ++i) { 67 unsigned char c = characters[i]; 68 data[i] = c; 69 } 70 return string; 71 } 72 73 PassRefPtr<UStringImpl> UStringImpl::create(const char* string) 74 { 75 if (!string) 76 return empty(); 77 return create(string, strlen(string)); 73 78 } 74 79 -
trunk/JavaScriptCore/runtime/UStringImpl.h
r55679 r55825 114 114 return adoptRef(new UStringImpl(vector.releaseBuffer(), length)); 115 115 } 116 return &empty(); 117 } 118 116 return empty(); 117 } 118 119 static PassRefPtr<UStringImpl> create(const UChar* buffer, unsigned length); 120 static PassRefPtr<UStringImpl> create(const char* c, unsigned length); 119 121 static PassRefPtr<UStringImpl> create(const char* c); 120 static PassRefPtr<UStringImpl> create(const char* c, unsigned length);121 static PassRefPtr<UStringImpl> create(const UChar* buffer, unsigned length);122 122 123 123 static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned length) … … 137 137 if (!length) { 138 138 output = 0; 139 return &empty();139 return empty(); 140 140 } 141 141 … … 151 151 if (!length) { 152 152 output = 0; 153 return &empty();153 return empty(); 154 154 } 155 155 … … 204 204 static unsigned computeHash(const char* s) { return WTF::stringHash(s); } 205 205 206 static UStringImpl & empty() { return *s_empty; }206 static UStringImpl* empty(); 207 207 208 208 ALWAYS_INLINE void checkConsistency() const … … 296 296 mutable unsigned m_hash; 297 297 298 JS_EXPORTDATA static UStringImpl* s_empty;299 300 298 friend class JIT; 301 299 friend class SmallStringsStorage; -
trunk/WebCore/ChangeLog
r55823 r55825 1 2010-03-10 Gavin Barraclough <barraclough@apple.com> 2 3 Reviewed by Darin Adler, Geoffrey Garen, Maciej Stachowiak. 4 5 https://bugs.webkit.org/show_bug.cgi?id=35991 6 Would be faster to not use a thread specific to implement StringImpl::empty() 7 8 Copy JavaScriptCore in making 'static' strings threadsafe, make the empty string a static, 9 shared by all threads. 10 11 ~2% progression on Dromaeo DOM core & JS lib tests. 12 13 * platform/ThreadGlobalData.cpp: 14 (WebCore::ThreadGlobalData::ThreadGlobalData): 15 (WebCore::ThreadGlobalData::~ThreadGlobalData): 16 * platform/ThreadGlobalData.h: 17 (WebCore::ThreadGlobalData::eventNames): 18 * platform/text/StringImpl.cpp: 19 (WebCore::StringImpl::StringImpl): 20 (WebCore::StringImpl::empty): 21 * platform/text/StringImpl.h: 22 (WebCore::StringImpl::deref): 23 (WebCore::StringImpl::hasOneRef): 24 1 25 2010-03-08 Dumitru Daniliuc <dumi@chromium.org> 2 26 -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r55823 r55825 14713 14713 1432E8480C51493F00B1500F /* GCController.cpp */, 14714 14714 1432E8460C51493800B1500F /* GCController.h */, 14715 14716 14715 B5D3601E112F8BA80048DEA8 /* JSDatabaseCallback.cpp */, 14716 B5D3601C112F8BA00048DEA8 /* JSDatabaseCallback.h */, 14717 14717 BC53DAC411432FD9000D817E /* JSDebugWrapperSet.cpp */, 14718 14718 BC53DAC111432EEE000D817E /* JSDebugWrapperSet.h */, -
trunk/WebCore/platform/ThreadGlobalData.cpp
r53514 r55825 56 56 57 57 ThreadGlobalData::ThreadGlobalData() 58 : m_emptyString(new StringImpl) 59 , m_atomicStringTable(new HashSet<StringImpl*>) 58 : m_atomicStringTable(new HashSet<StringImpl*>) 60 59 , m_eventNames(new EventNames) 61 60 , m_threadTimers(new ThreadTimers) … … 70 69 #endif 71 70 { 71 // StringImpl::empty() does not construct its static string in a threadsafe fashion, 72 // so ensure it has been initialized from here. 73 // 74 // This constructor will have been called on the main thread before being called on 75 // any other thread, and is only called once per thread. 76 StringImpl::empty(); 72 77 } 73 78 … … 83 88 delete m_atomicStringTable; 84 89 delete m_threadTimers; 85 86 // Using member variable m_isMainThread instead of calling WTF::isMainThread() directly87 // to avoid issues described in https://bugs.webkit.org/show_bug.cgi?id=25973.88 // In short, some pthread-based platforms and ports can not use WTF::CurrentThread() and WTF::isMainThread()89 // in destructors of thread-specific data.90 ASSERT(m_isMainThread || m_emptyString->hasOneRef()); // We intentionally don't clean up static data on application quit, so there will be many strings remaining on the main thread.91 92 delete m_emptyString;93 90 } 94 91 -
trunk/WebCore/platform/ThreadGlobalData.h
r55524 r55825 52 52 53 53 EventNames& eventNames() { return *m_eventNames; } 54 StringImpl* emptyString() { return m_emptyString; }55 54 HashSet<StringImpl*>& atomicStringTable() { return *m_atomicStringTable; } 56 55 ThreadTimers& threadTimers() { return *m_threadTimers; } … … 65 64 66 65 private: 67 StringImpl* m_emptyString;68 66 HashSet<StringImpl*>* m_atomicStringTable; 69 67 EventNames* m_eventNames; -
trunk/WebCore/platform/text/StringImpl.cpp
r55069 r55825 58 58 , m_sharedBuffer(0) 59 59 , m_length(0) 60 , m_refCountAndFlags(s_refCount Increment| BufferInternal)60 , m_refCountAndFlags(s_refCountFlagStatic | BufferInternal) 61 61 , m_hash(0) 62 62 { … … 121 121 StringImpl* StringImpl::empty() 122 122 { 123 return threadGlobalData().emptyString(); 123 DEFINE_STATIC_LOCAL(StringImpl, emptyString, ()); 124 return &emptyString; 124 125 } 125 126 -
trunk/WebCore/platform/text/StringImpl.h
r55069 r55825 120 120 121 121 StringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } 122 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; }123 ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; }122 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } 123 ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; } 124 124 125 125 // Returns a StringImpl suitable for use on another thread. … … 202 202 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 203 203 204 static const unsigned s_refCountMask = 0xFFFFFFF0; 205 static const unsigned s_refCountIncrement = 0x10; 204 static const unsigned s_refCountMask = 0xFFFFFFE0; 205 static const unsigned s_refCountIncrement = 0x20; 206 static const unsigned s_refCountFlagStatic = 0x10; 206 207 static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x8; 207 208 static const unsigned s_refCountFlagInTable = 0x4;
Note: See TracChangeset
for help on using the changeset viewer.