Changeset 53400 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Jan 18, 2010, 4:14:49 AM (15 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.cpp
r53392 r53400 349 349 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const 350 350 { 351 m_rep->checkConsistency(); 352 351 353 if (rangeCount == 1 && separatorCount == 0) { 352 354 int thisSize = size(); … … 390 392 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const 391 393 { 394 m_rep->checkConsistency(); 395 392 396 int replacementLength = replacement.size(); 393 397 int totalLength = size() - rangeLength + replacementLength; -
trunk/JavaScriptCore/runtime/UString.h
r53391 r53400 32 32 #include <wtf/OwnFastMallocPtr.h> 33 33 #include <wtf/PassRefPtr.h> 34 #include <wtf/PtrAndFlags.h> 34 35 #include <wtf/RefPtr.h> 35 36 #include <wtf/Vector.h> -
trunk/JavaScriptCore/runtime/UStringImpl.cpp
r53392 r53400 36 36 namespace JSC { 37 37 38 SharedUChar* UStringImpl::baseSharedBuffer() 39 { 40 ASSERT((bufferOwnership() == BufferShared) 41 || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>())); 42 43 if (bufferOwnership() != BufferShared) 44 m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared); 45 46 return m_dataBuffer.asPtr<SharedUChar*>(); 47 } 48 38 49 SharedUChar* UStringImpl::sharedBuffer() 39 50 { 40 if (m_length < s_minLengthToShare || isStatic()) 51 if (m_length < s_minLengthToShare) 52 return 0; 53 ASSERT(!isStatic()); 54 55 UStringImpl* owner = bufferOwnerString(); 56 if (owner->bufferOwnership() == BufferInternal) 41 57 return 0; 42 58 43 switch (bufferOwnership()) { 44 case BufferInternal: 45 return 0; 46 case BufferOwned: 47 m_bufferShared = SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(); 48 m_refCountAndFlags &= ~s_refCountMaskBufferOwnership; 49 m_refCountAndFlags |= BufferShared; 50 return m_bufferShared; 51 case BufferSubstring: 52 return m_bufferSubstring->sharedBuffer(); 53 case BufferShared: 54 return m_bufferShared; 55 } 56 57 ASSERT_NOT_REACHED(); 58 return 0; 59 return owner->baseSharedBuffer(); 59 60 } 60 61 … … 62 63 { 63 64 ASSERT(!isStatic()); 65 checkConsistency(); 64 66 65 67 if (isIdentifier()) 66 68 Identifier::remove(this); 67 69 68 switch (bufferOwnership()) { 69 case BufferInternal: 70 return; 71 case BufferOwned: 72 fastFree(m_data); 73 return; 74 case BufferSubstring: 75 m_bufferSubstring->deref(); 76 return; 77 case BufferShared: 78 m_bufferSubstring->deref(); 70 if (bufferOwnership() != BufferInternal) { 71 if (bufferOwnership() == BufferOwned) 72 fastFree(m_data); 73 else if (bufferOwnership() == BufferSubstring) 74 m_dataBuffer.asPtr<UStringImpl*>()->deref(); 75 else { 76 ASSERT(bufferOwnership() == BufferShared); 77 m_dataBuffer.asPtr<SharedUChar*>()->deref(); 78 } 79 79 } 80 80 } 81 81 82 } // namespace JSC82 } -
trunk/JavaScriptCore/runtime/UStringImpl.h
r53392 r53400 41 41 typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; 42 42 43 class UntypedPtrAndBitfield { 44 public: 45 UntypedPtrAndBitfield() {} 46 47 UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue) 48 : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue) 49 #ifndef NDEBUG 50 , m_leaksPtr(ptrValue) 51 #endif 52 { 53 ASSERT(ptrValue == asPtr<void*>()); 54 ASSERT((*this & ~s_alignmentMask) == bitValue); 55 } 56 57 template<typename T> 58 T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); } 59 60 UntypedPtrAndBitfield& operator&=(uintptr_t bits) 61 { 62 m_value &= bits | s_alignmentMask; 63 return *this; 64 } 65 66 UntypedPtrAndBitfield& operator|=(uintptr_t bits) 67 { 68 m_value |= bits & ~s_alignmentMask; 69 return *this; 70 } 71 72 uintptr_t operator&(uintptr_t mask) const 73 { 74 return m_value & mask & ~s_alignmentMask; 75 } 76 77 private: 78 static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7); 79 uintptr_t m_value; 80 #ifndef NDEBUG 81 void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced. 82 #endif 83 }; 84 43 85 class UStringImpl : Noncopyable { 44 86 public: … … 64 106 { 65 107 ASSERT(rep); 66 if (rep->bufferOwnership() == BufferSubstring) 67 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->m_bufferSubstring)); 68 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep)); 108 rep->checkConsistency(); 109 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString())); 69 110 } 70 111 … … 111 152 // For substrings, return the cost of the base string. 112 153 if (bufferOwnership() == BufferSubstring) 113 return m_bufferSubstring->cost(); 114 if (m_refCountAndFlags & s_refCountFlagHasReportedCost) 154 return m_dataBuffer.asPtr<UStringImpl*>()->cost(); 155 156 if (m_dataBuffer & s_reportedCostBit) 115 157 return 0; 116 ASSERT(!isStatic()); 117 m_refCountAndFlags |= s_refCountFlagHasReportedCost; 158 m_dataBuffer |= s_reportedCostBit; 118 159 return m_length; 119 160 } … … 121 162 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers 122 163 void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers 123 bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } 124 void setIsIdentifier(bool isIdentifier) 125 { 126 ASSERT(!isStatic()); 127 if (isIdentifier) 128 m_refCountAndFlags |= s_refCountFlagIsIdentifier; 129 else 130 m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; 131 } 132 133 UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } 134 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } 164 bool isIdentifier() const { return m_isIdentifier; } 165 void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; } 166 167 UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; } 168 ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; } 135 169 136 170 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) … … 149 183 static UStringImpl& null() { return *s_null; } 150 184 static UStringImpl& empty() { return *s_empty; } 185 186 ALWAYS_INLINE void checkConsistency() const 187 { 188 // There is no recursion of substrings. 189 ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring); 190 // Static strings cannot be put in identifier tables, because they are globally shared. 191 ASSERT(!isStatic() || !isIdentifier()); 192 } 151 193 152 194 private: … … 164 206 UStringImpl(UChar* data, int length, BufferOwnership ownership) 165 207 : m_data(data) 166 , m_buffer(0)167 208 , m_length(length) 168 , m_refCount AndFlags(s_refCountIncrement | ownership)209 , m_refCount(s_refCountIncrement) 169 210 , m_hash(0) 211 , m_isIdentifier(false) 212 , m_dataBuffer(0, ownership) 170 213 { 171 214 ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); 215 checkConsistency(); 172 216 } 173 217 … … 178 222 UStringImpl(UChar* data, int length, StaticStringConstructType) 179 223 : m_data(data) 180 , m_buffer(0)181 224 , m_length(length) 182 , m_refCount AndFlags(s_refCountFlagStatic | s_refCountFlagHasReportedCost | BufferOwned)225 , m_refCount(s_staticRefCountInitialValue) 183 226 , m_hash(0) 184 { 227 , m_isIdentifier(false) 228 , m_dataBuffer(0, BufferOwned) 229 { 230 checkConsistency(); 185 231 } 186 232 … … 188 234 UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base) 189 235 : m_data(data) 190 , m_bufferSubstring(base.releaseRef())191 236 , m_length(length) 192 , m_refCount AndFlags(s_refCountIncrement | BufferSubstring)237 , m_refCount(s_refCountIncrement) 193 238 , m_hash(0) 239 , m_isIdentifier(false) 240 , m_dataBuffer(base.releaseRef(), BufferSubstring) 194 241 { 195 242 // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes 196 243 // that all pointers will be at least 8-byte aligned, we cannot guarantee that of 197 244 // UStringImpls that are not heap allocated. 198 ASSERT(m_ bufferSubstring->size());199 ASSERT(!m_ bufferSubstring->isStatic());200 ASSERT(m_bufferSubstring->bufferOwnership() != BufferSubstring);245 ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size()); 246 ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic()); 247 checkConsistency(); 201 248 } 202 249 … … 204 251 UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer) 205 252 : m_data(data) 206 , m_bufferShared(sharedBuffer.releaseRef())207 253 , m_length(length) 208 , m_refCount AndFlags(s_refCountIncrement | BufferShared)254 , m_refCount(s_refCountIncrement) 209 255 , m_hash(0) 210 { 256 , m_isIdentifier(false) 257 , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) 258 { 259 checkConsistency(); 211 260 } 212 261 … … 217 266 218 267 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 219 static const unsigneds_minLengthToShare = 10;268 static const int s_minLengthToShare = 10; 220 269 static const unsigned s_copyCharsInlineCutOff = 20; 221 222 bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } 223 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 224 270 static const uintptr_t s_bufferOwnershipMask = 3; 271 static const uintptr_t s_reportedCostBit = 4; 225 272 // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. 226 273 // 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 274 static const int s_refCountIncrement = 2; 275 static const int s_staticRefCountInitialValue = 1; 276 277 UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } 278 const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } 279 SharedUChar* baseSharedBuffer(); 280 unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; } 281 bool isStatic() const { return m_refCount & 1; } 282 283 // unshared data 234 284 UChar* m_data; 235 union { 236 void* m_buffer; 237 UStringImpl* m_bufferSubstring; 238 SharedUChar* m_bufferShared; 239 }; 240 unsigned m_length; 241 unsigned m_refCountAndFlags; 242 mutable unsigned m_hash; 285 int m_length; 286 unsigned m_refCount; 287 mutable unsigned m_hash : 31; 288 mutable unsigned m_isIdentifier : 1; 289 UntypedPtrAndBitfield m_dataBuffer; 243 290 244 291 JS_EXPORTDATA static UStringImpl* s_null;
Note:
See TracChangeset
for help on using the changeset viewer.