Changeset 54843 in webkit for trunk/JavaScriptCore/runtime/UStringImpl.h
- Timestamp:
- Feb 16, 2010, 4:01:58 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UStringImpl.h
r54789 r54843 41 41 typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; 42 42 43 class UStringImpl : Noncopyable { 43 class UStringOrRopeImpl : public Noncopyable { 44 public: 45 bool isRope() { return (m_refCountAndFlags & s_refCountIsRope) == s_refCountIsRope; } 46 unsigned length() const { return m_length; } 47 48 void ref() { m_refCountAndFlags += s_refCountIncrement; } 49 inline void deref(); 50 51 protected: 52 enum BufferOwnership { 53 BufferInternal, 54 BufferOwned, 55 BufferSubstring, 56 BufferShared, 57 }; 58 59 using Noncopyable::operator new; 60 void* operator new(size_t, void* inPlace) { return inPlace; } 61 62 // For SmallStringStorage, which allocates an array and uses an in-place new. 63 UStringOrRopeImpl() { } 64 65 UStringOrRopeImpl(unsigned length, BufferOwnership ownership) 66 : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership) 67 , m_length(length) 68 { 69 ASSERT(!isRope()); 70 } 71 72 enum StaticStringConstructType { ConstructStaticString }; 73 UStringOrRopeImpl(unsigned length, StaticStringConstructType) 74 : m_refCountAndFlags(s_refCountFlagStatic | BufferOwned) 75 , m_length(length) 76 { 77 ASSERT(!isRope()); 78 } 79 80 enum RopeConstructType { ConstructRope }; 81 UStringOrRopeImpl(RopeConstructType) 82 : m_refCountAndFlags(s_refCountIncrement | s_refCountIsRope) 83 , m_length(0) 84 { 85 ASSERT(isRope()); 86 } 87 88 // The bottom 5 bits hold flags, the top 27 bits hold the ref count. 89 // When dereferencing UStringImpls we check for the ref count AND the 90 // static bit both being zero - static strings are never deleted. 91 static const unsigned s_refCountMask = 0xFFFFFFE0; 92 static const unsigned s_refCountIncrement = 0x20; 93 static const unsigned s_refCountFlagStatic = 0x10; 94 static const unsigned s_refCountFlagShouldReportedCost = 0x8; 95 static const unsigned s_refCountFlagIsIdentifier = 0x4; 96 static const unsigned s_refCountMaskBufferOwnership = 0x3; 97 // Use an otherwise invalid permutation of flags (static & shouldReportedCost - 98 // static strings do not set shouldReportedCost in the constructor, and this bit 99 // is only ever cleared, not set) to identify objects that are ropes. 100 static const unsigned s_refCountIsRope = s_refCountFlagStatic | s_refCountFlagShouldReportedCost; 101 102 unsigned m_refCountAndFlags; 103 unsigned m_length; 104 }; 105 106 class UStringImpl : public UStringOrRopeImpl { 44 107 public: 45 108 template<size_t inlineCapacity> … … 48 111 if (unsigned length = vector.size()) { 49 112 ASSERT(vector.data()); 50 return adoptRef(new UStringImpl(vector.releaseBuffer(), length , BufferOwned));113 return adoptRef(new UStringImpl(vector.releaseBuffer(), length)); 51 114 } 52 115 return &empty(); … … 80 143 UStringImpl* resultImpl = static_cast<UStringImpl*>(fastMalloc(sizeof(UChar) * length + sizeof(UStringImpl))); 81 144 output = reinterpret_cast<UChar*>(resultImpl + 1); 82 return adoptRef(new(resultImpl) UStringImpl( output, length, BufferInternal));145 return adoptRef(new(resultImpl) UStringImpl(length)); 83 146 } 84 147 … … 96 159 return 0; 97 160 output = reinterpret_cast<UChar*>(resultImpl + 1); 98 return adoptRef(new(resultImpl) UStringImpl( output, length, BufferInternal));161 return adoptRef(new(resultImpl) UStringImpl(length)); 99 162 } 100 163 101 164 SharedUChar* sharedBuffer(); 102 165 UChar* data() const { return m_data; } 103 unsigned size() const { return m_length; }104 166 size_t cost() 105 167 { … … 108 170 return m_bufferSubstring->cost(); 109 171 110 if (m_refCountAndFlags & s_refCountFlagHasReportedCost) 111 return 0; 112 m_refCountAndFlags |= s_refCountFlagHasReportedCost; 113 return m_length; 172 if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) { 173 m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost; 174 return m_length; 175 } 176 return 0; 114 177 } 115 178 unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; } … … 125 188 } 126 189 127 UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } 128 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } 190 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } 129 191 130 192 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) … … 152 214 153 215 private: 154 enum BufferOwnership {155 BufferInternal,156 BufferOwned,157 BufferSubstring,158 BufferShared,159 };160 161 216 // For SmallStringStorage, which allocates an array and uses an in-place new. 162 217 UStringImpl() { } 163 218 164 // Used to construct normal strings with an internal or external buffer. 165 UStringImpl(UChar* data, unsigned length, BufferOwnership ownership) 166 : m_data(data) 219 // Used to construct normal strings with an internal buffer. 220 UStringImpl(unsigned length) 221 : UStringOrRopeImpl(length, BufferInternal) 222 , m_data(reinterpret_cast<UChar*>(this + 1)) 167 223 , m_buffer(0) 168 , m_length(length) 169 , m_refCountAndFlags(s_refCountIncrement | ownership) 170 , m_hash(0) 171 { 172 ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); 224 , m_hash(0) 225 { 226 checkConsistency(); 227 } 228 229 // Used to construct normal strings with an external buffer. 230 UStringImpl(UChar* data, unsigned length) 231 : UStringOrRopeImpl(length, BufferOwned) 232 , m_data(data) 233 , m_buffer(0) 234 , m_hash(0) 235 { 173 236 checkConsistency(); 174 237 } … … 177 240 // This means that the static string will never be destroyed, which is important because 178 241 // static strings will be shared across threads & ref-counted in a non-threadsafe manner. 179 enum StaticStringConstructType { ConstructStaticString };180 242 UStringImpl(UChar* data, unsigned length, StaticStringConstructType) 181 : m_data(data) 243 : UStringOrRopeImpl(length, ConstructStaticString) 244 , m_data(data) 182 245 , m_buffer(0) 183 , m_length(length)184 , m_refCountAndFlags(s_refCountFlagStatic | BufferOwned)185 246 , m_hash(0) 186 247 { … … 190 251 // Used to create new strings that are a substring of an existing string. 191 252 UStringImpl(UChar* data, unsigned length, PassRefPtr<UStringImpl> base) 192 : m_data(data) 253 : UStringOrRopeImpl(length, BufferSubstring) 254 , m_data(data) 193 255 , m_bufferSubstring(base.releaseRef()) 194 , m_length(length)195 , m_refCountAndFlags(s_refCountIncrement | BufferSubstring)196 256 , m_hash(0) 197 257 { … … 199 259 // that all pointers will be at least 8-byte aligned, we cannot guarantee that of 200 260 // UStringImpls that are not heap allocated. 201 ASSERT(m_bufferSubstring-> size());261 ASSERT(m_bufferSubstring->length()); 202 262 ASSERT(!m_bufferSubstring->isStatic()); 203 263 checkConsistency(); … … 206 266 // Used to construct new strings sharing an existing shared buffer. 207 267 UStringImpl(UChar* data, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) 208 : m_data(data) 268 : UStringOrRopeImpl(length, BufferShared) 269 , m_data(data) 209 270 , m_bufferShared(sharedBuffer.releaseRef()) 210 , m_length(length) 211 , m_refCountAndFlags(s_refCountIncrement | BufferShared) 212 , m_hash(0) 213 { 214 checkConsistency(); 215 } 216 217 using Noncopyable::operator new; 218 void* operator new(size_t, void* inPlace) { return inPlace; } 271 , m_hash(0) 272 { 273 checkConsistency(); 274 } 219 275 220 276 ~UStringImpl(); … … 223 279 static const unsigned s_minLengthToShare = 10; 224 280 static const unsigned s_copyCharsInlineCutOff = 20; 225 // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2.226 // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero.227 static const unsigned s_refCountMask = 0xFFFFFFF0;228 static const unsigned s_refCountIncrement = 0x20;229 static const unsigned s_refCountFlagStatic = 0x10;230 static const unsigned s_refCountFlagHasReportedCost = 0x8;231 static const unsigned s_refCountFlagIsIdentifier = 0x4;232 static const unsigned s_refCountMaskBufferOwnership = 0x3;233 281 234 282 UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } … … 245 293 SharedUChar* m_bufferShared; 246 294 }; 247 unsigned m_length;248 unsigned m_refCountAndFlags;249 295 mutable unsigned m_hash; 250 296 … … 253 299 friend class JIT; 254 300 friend class SmallStringsStorage; 301 friend class UStringOrRopeImpl; 255 302 friend void initializeUString(); 256 303 }; 257 304 305 class URopeImpl : public UStringOrRopeImpl { 306 public: 307 // A URopeImpl is composed from a set of smaller strings called Fibers. 308 // Each Fiber in a rope is either UStringImpl or another URopeImpl. 309 typedef UStringOrRopeImpl* Fiber; 310 311 // Creates a URopeImpl comprising of 'fiberCount' Fibers. 312 // The URopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the URopeImpl. 313 static PassRefPtr<URopeImpl> tryCreateUninitialized(unsigned fiberCount) 314 { 315 void* allocation; 316 if (tryFastMalloc(sizeof(URopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) 317 return adoptRef(new (allocation) URopeImpl(fiberCount)); 318 return 0; 319 } 320 321 void initializeFiber(unsigned &index, Fiber fiber) 322 { 323 m_fibers[index++] = fiber; 324 fiber->ref(); 325 m_length += fiber->length(); 326 } 327 328 unsigned fiberCount() { return m_fiberCount; } 329 Fiber& fibers(unsigned index) { return m_fibers[index]; } 330 331 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); } 332 333 private: 334 URopeImpl(unsigned fiberCount) : UStringOrRopeImpl(ConstructRope), m_fiberCount(fiberCount) {} 335 336 void destructNonRecursive(); 337 void derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue); 338 339 bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } 340 341 unsigned m_fiberCount; 342 Fiber m_fibers[1]; 343 }; 344 345 inline void UStringOrRopeImpl::deref() 346 { 347 m_refCountAndFlags -= s_refCountIncrement; 348 if (!(m_refCountAndFlags & s_refCountMask)) { 349 if (isRope()) 350 delete static_cast<URopeImpl*>(this); 351 else if (!s_refCountFlagStatic) 352 delete static_cast<UStringImpl*>(this); 353 } 354 } 355 258 356 bool equal(const UStringImpl*, const UStringImpl*); 259 357
Note:
See TracChangeset
for help on using the changeset viewer.