Changeset 55878 in webkit for trunk/JavaScriptCore/runtime/UStringImpl.h
- Timestamp:
- Mar 11, 2010, 7:14:17 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UStringImpl.h
r55833 r55878 106 106 107 107 class UStringImpl : public UStringOrRopeImpl { 108 friend class CStringTranslator; 109 friend class UCharBufferTranslator; 110 friend class JIT; 111 friend class SmallStringsStorage; 112 friend class UStringOrRopeImpl; 113 friend void initializeUString(); 114 private: 115 // For SmallStringStorage, which allocates an array and uses an in-place new. 116 UStringImpl() { } 117 118 // Used to construct static strings, which have an special refCount that can never hit zero. 119 // This means that the static string will never be destroyed, which is important because 120 // static strings will be shared across threads & ref-counted in a non-threadsafe manner. 121 UStringImpl(const UChar* characters, unsigned length, StaticStringConstructType) 122 : UStringOrRopeImpl(length, ConstructStaticString) 123 , m_data(characters) 124 , m_buffer(0) 125 , m_hash(0) 126 { 127 hash(); 128 checkConsistency(); 129 } 130 131 // Create a normal string with internal storage (BufferInternal) 132 UStringImpl(unsigned length) 133 : UStringOrRopeImpl(length, BufferInternal) 134 , m_data(reinterpret_cast<UChar*>(this + 1)) 135 , m_buffer(0) 136 , m_hash(0) 137 { 138 ASSERT(m_data); 139 ASSERT(m_length); 140 checkConsistency(); 141 } 142 143 // Create a UStringImpl adopting ownership of the provided buffer (BufferOwned) 144 UStringImpl(const UChar* characters, unsigned length) 145 : UStringOrRopeImpl(length, BufferOwned) 146 , m_data(characters) 147 , m_buffer(0) 148 , m_hash(0) 149 { 150 ASSERT(m_data); 151 ASSERT(m_length); 152 checkConsistency(); 153 } 154 155 // Used to create new strings that are a substring of an existing UStringImpl (BufferSubstring) 156 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<UStringImpl> base) 157 : UStringOrRopeImpl(length, BufferSubstring) 158 , m_data(characters) 159 , m_substringBuffer(base.releaseRef()) 160 , m_hash(0) 161 { 162 ASSERT(m_data); 163 ASSERT(m_length); 164 checkConsistency(); 165 } 166 167 // Used to construct new strings sharing an existing SharedUChar (BufferShared) 168 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) 169 : UStringOrRopeImpl(length, BufferShared) 170 , m_data(characters) 171 , m_sharedBuffer(sharedBuffer.releaseRef()) 172 , m_hash(0) 173 { 174 ASSERT(m_data); 175 ASSERT(m_length); 176 checkConsistency(); 177 } 178 179 // For use only by Identifier's XXXTranslator helpers. 180 void setHash(unsigned hash) 181 { 182 ASSERT(!m_hash); 183 ASSERT(hash == computeHash(m_data, m_length)); 184 m_hash = hash; 185 } 186 108 187 public: 109 template<size_t inlineCapacity> 110 static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) 111 { 112 if (unsigned length = vector.size()) { 113 ASSERT(vector.data()); 114 return adoptRef(new UStringImpl(vector.releaseBuffer(), length)); 115 } 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); 121 static PassRefPtr<UStringImpl> create(const char* c); 122 188 ~UStringImpl(); 189 190 static PassRefPtr<UStringImpl> create(const UChar*, unsigned length); 191 static PassRefPtr<UStringImpl> create(const char*, unsigned length); 192 static PassRefPtr<UStringImpl> create(const char*); 193 static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar>, const UChar*, unsigned length); 123 194 static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned length) 124 195 { 196 if (!length) 197 return empty(); 125 198 ASSERT(rep); 126 199 rep->checkConsistency(); 127 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString())); 128 } 129 130 static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar> sharedBuffer, const UChar* buffer, unsigned length) 131 { 132 return adoptRef(new UStringImpl(buffer, length, sharedBuffer)); 133 } 134 135 static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output) 136 { 137 if (!length) { 138 output = 0; 139 return empty(); 140 } 141 142 if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar))) 143 CRASH(); 144 UStringImpl* resultImpl = static_cast<UStringImpl*>(fastMalloc(sizeof(UChar) * length + sizeof(UStringImpl))); 145 output = reinterpret_cast<UChar*>(resultImpl + 1); 146 return adoptRef(new(resultImpl) UStringImpl(length)); 147 } 148 200 UStringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); 201 return adoptRef(new UStringImpl(rep->m_data + offset, length, ownerRep)); 202 } 203 204 static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output); 149 205 static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output) 150 206 { … … 163 219 } 164 220 221 template<size_t inlineCapacity> 222 static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) 223 { 224 if (size_t size = vector.size()) { 225 ASSERT(vector.data()); 226 return adoptRef(new UStringImpl(vector.releaseBuffer(), size)); 227 } 228 return empty(); 229 } 230 165 231 SharedUChar* sharedBuffer(); 166 232 const UChar* characters() const { return m_data; } 233 167 234 size_t cost() 168 235 { 169 236 // For substrings, return the cost of the base string. 170 237 if (bufferOwnership() == BufferSubstring) 171 return m_ bufferSubstring->cost();238 return m_substringBuffer->cost(); 172 239 173 240 if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) { … … 177 244 return 0; 178 245 } 179 unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } 180 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers 181 void setHash(unsigned hash) { ASSERT(hash == computeHash(m_data, m_length)); m_hash = hash; } // fast path for Identifiers 246 182 247 bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } 183 248 void setIsIdentifier(bool isIdentifier) … … 189 254 } 190 255 256 // SYNC SYNC SYNC 257 // SYNC SYNC SYNC 258 // SYNC SYNC SYNC 259 // SYNC SYNC SYNC 260 // SYNC SYNC SYNC 261 262 unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } 263 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } 264 static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); } 265 static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); } 266 static unsigned computeHash(const char* data) { return WTF::stringHash(data); } 267 191 268 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } 269 270 static UStringImpl* empty(); 192 271 193 272 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) … … 200 279 } 201 280 202 static unsigned computeHash(const UChar* s, unsigned length) { return WTF::stringHash(s, length); }203 static unsigned computeHash(const char* s, unsigned length) { return WTF::stringHash(s, length); }204 static unsigned computeHash(const char* s) { return WTF::stringHash(s); }205 206 static UStringImpl* empty();207 208 281 ALWAYS_INLINE void checkConsistency() const 209 282 { 210 283 // There is no recursion of substrings. 211 ASSERT( bufferOwnerString()->bufferOwnership() != BufferSubstring);284 ASSERT((bufferOwnership() != BufferSubstring) || (m_substringBuffer->bufferOwnership() != BufferSubstring)); 212 285 // Static strings cannot be put in identifier tables, because they are globally shared. 213 286 ASSERT(!isStatic() || !isIdentifier()); … … 215 288 216 289 private: 217 // For SmallStringStorage, which allocates an array and uses an in-place new.218 UStringImpl() { }219 220 // Used to construct normal strings with an internal buffer.221 UStringImpl(unsigned length)222 : UStringOrRopeImpl(length, BufferInternal)223 , m_data(reinterpret_cast<UChar*>(this + 1))224 , m_buffer(0)225 , m_hash(0)226 {227 checkConsistency();228 }229 230 // Used to construct normal strings with an external buffer.231 UStringImpl(const UChar* data, unsigned length)232 : UStringOrRopeImpl(length, BufferOwned)233 , m_data(data)234 , m_buffer(0)235 , m_hash(0)236 {237 checkConsistency();238 }239 240 // Used to construct static strings, which have an special refCount that can never hit zero.241 // This means that the static string will never be destroyed, which is important because242 // static strings will be shared across threads & ref-counted in a non-threadsafe manner.243 UStringImpl(const UChar* data, unsigned length, StaticStringConstructType)244 : UStringOrRopeImpl(length, ConstructStaticString)245 , m_data(data)246 , m_buffer(0)247 , m_hash(0)248 {249 checkConsistency();250 }251 252 // Used to create new strings that are a substring of an existing string.253 UStringImpl(const UChar* data, unsigned length, PassRefPtr<UStringImpl> base)254 : UStringOrRopeImpl(length, BufferSubstring)255 , m_data(data)256 , m_bufferSubstring(base.releaseRef())257 , m_hash(0)258 {259 // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes260 // that all pointers will be at least 8-byte aligned, we cannot guarantee that of261 // UStringImpls that are not heap allocated.262 ASSERT(m_bufferSubstring->length());263 ASSERT(!m_bufferSubstring->isStatic());264 checkConsistency();265 }266 267 // Used to construct new strings sharing an existing shared buffer.268 UStringImpl(const UChar* data, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)269 : UStringOrRopeImpl(length, BufferShared)270 , m_data(data)271 , m_bufferShared(sharedBuffer.releaseRef())272 , m_hash(0)273 {274 checkConsistency();275 }276 277 ~UStringImpl();278 279 290 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 280 static const unsigned s_minLengthToShare = 10;281 291 static const unsigned s_copyCharsInlineCutOff = 20; 282 292 283 UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } 284 const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } 285 SharedUChar* baseSharedBuffer(); 286 unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; } 293 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 287 294 bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } 288 295 … … 291 298 union { 292 299 void* m_buffer; 293 UStringImpl* m_ bufferSubstring;294 SharedUChar* m_ bufferShared;300 UStringImpl* m_substringBuffer; 301 SharedUChar* m_sharedBuffer; 295 302 }; 296 303 mutable unsigned m_hash; 297 298 friend class JIT; 299 friend class SmallStringsStorage; 304 }; 305 306 class URopeImpl : public UStringOrRopeImpl { 300 307 friend class UStringOrRopeImpl; 301 friend void initializeUString();302 };303 304 class URopeImpl : public UStringOrRopeImpl {305 308 public: 306 309 // A URopeImpl is composed from a set of smaller strings called Fibers. … … 340 343 unsigned m_fiberCount; 341 344 Fiber m_fibers[1]; 342 343 friend class UStringOrRopeImpl;344 345 }; 345 346
Note:
See TracChangeset
for help on using the changeset viewer.