Changeset 53392 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Jan 17, 2010, 11:36:45 PM (15 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.cpp
r53320 r53392 349 349 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const 350 350 { 351 m_rep->checkConsistency();352 353 351 if (rangeCount == 1 && separatorCount == 0) { 354 352 int thisSize = size(); … … 392 390 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const 393 391 { 394 m_rep->checkConsistency();395 396 392 int replacementLength = replacement.size(); 397 393 int totalLength = size() - rangeLength + replacementLength; -
trunk/JavaScriptCore/runtime/UStringImpl.cpp
r53221 r53392 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 49 38 SharedUChar* UStringImpl::sharedBuffer() 50 39 { 51 if (m_length < s_minLengthToShare) 52 return 0; 53 ASSERT(!isStatic()); 54 55 UStringImpl* owner = bufferOwnerString(); 56 if (owner->bufferOwnership() == BufferInternal) 40 if (m_length < s_minLengthToShare || isStatic()) 57 41 return 0; 58 42 59 return owner->baseSharedBuffer(); 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; 60 59 } 61 60 … … 63 62 { 64 63 ASSERT(!isStatic()); 65 checkConsistency();66 64 67 65 if (isIdentifier()) 68 66 Identifier::remove(this); 69 67 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 } 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(); 79 79 } 80 80 } 81 81 82 } 82 } // namespace JSC -
trunk/JavaScriptCore/runtime/UStringImpl.h
r53323 r53392 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 NDEBUG50 , m_leaksPtr(ptrValue)51 #endif52 {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) const73 {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 NDEBUG81 void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced.82 #endif83 };84 85 43 class UStringImpl : Noncopyable { 86 44 public: … … 106 64 { 107 65 ASSERT(rep); 108 rep->checkConsistency(); 109 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString())); 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)); 110 69 } 111 70 … … 152 111 // For substrings, return the cost of the base string. 153 112 if (bufferOwnership() == BufferSubstring) 154 return m_dataBuffer.asPtr<UStringImpl*>()->cost(); 155 156 if (m_dataBuffer & s_reportedCostBit) 113 return m_bufferSubstring->cost(); 114 if (m_refCountAndFlags & s_refCountFlagHasReportedCost) 157 115 return 0; 158 m_dataBuffer |= s_reportedCostBit; 116 ASSERT(!isStatic()); 117 m_refCountAndFlags |= s_refCountFlagHasReportedCost; 159 118 return m_length; 160 119 } … … 162 121 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers 163 122 void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers 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; } 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; } 169 135 170 136 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) … … 183 149 static UStringImpl& null() { return *s_null; } 184 150 static UStringImpl& empty() { return *s_empty; } 185 186 ALWAYS_INLINE void checkConsistency() const187 {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 }193 151 194 152 private: … … 206 164 UStringImpl(UChar* data, int length, BufferOwnership ownership) 207 165 : m_data(data) 208 , m_length(length) 209 , m_refCount(s_refCountIncrement) 210 , m_hash(0) 211 , m_isIdentifier(false) 212 , m_dataBuffer(0, ownership) 166 , m_buffer(0) 167 , m_length(length) 168 , m_refCountAndFlags(s_refCountIncrement | ownership) 169 , m_hash(0) 213 170 { 214 171 ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); 215 checkConsistency();216 172 } 217 173 … … 222 178 UStringImpl(UChar* data, int length, StaticStringConstructType) 223 179 : m_data(data) 224 , m_length(length) 225 , m_refCount(s_staticRefCountInitialValue) 226 , m_hash(0) 227 , m_isIdentifier(false) 228 , m_dataBuffer(0, BufferOwned) 229 { 230 checkConsistency(); 180 , m_buffer(0) 181 , m_length(length) 182 , m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagHasReportedCost | BufferOwned) 183 , m_hash(0) 184 { 231 185 } 232 186 … … 234 188 UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base) 235 189 : m_data(data) 236 , m_length(length) 237 , m_refCount(s_refCountIncrement) 238 , m_hash(0) 239 , m_isIdentifier(false) 240 , m_dataBuffer(base.releaseRef(), BufferSubstring) 190 , m_bufferSubstring(base.releaseRef()) 191 , m_length(length) 192 , m_refCountAndFlags(s_refCountIncrement | BufferSubstring) 193 , m_hash(0) 241 194 { 242 195 // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes 243 196 // that all pointers will be at least 8-byte aligned, we cannot guarantee that of 244 197 // UStringImpls that are not heap allocated. 245 ASSERT(m_ dataBuffer.asPtr<UStringImpl*>()->size());246 ASSERT(!m_ dataBuffer.asPtr<UStringImpl*>()->isStatic());247 checkConsistency();198 ASSERT(m_bufferSubstring->size()); 199 ASSERT(!m_bufferSubstring->isStatic()); 200 ASSERT(m_bufferSubstring->bufferOwnership() != BufferSubstring); 248 201 } 249 202 … … 251 204 UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer) 252 205 : m_data(data) 253 , m_length(length) 254 , m_refCount(s_refCountIncrement) 255 , m_hash(0) 256 , m_isIdentifier(false) 257 , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) 258 { 259 checkConsistency(); 206 , m_bufferShared(sharedBuffer.releaseRef()) 207 , m_length(length) 208 , m_refCountAndFlags(s_refCountIncrement | BufferShared) 209 , m_hash(0) 210 { 260 211 } 261 212 … … 266 217 267 218 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 268 static const ints_minLengthToShare = 10;219 static const unsigned s_minLengthToShare = 10; 269 220 static const unsigned s_copyCharsInlineCutOff = 20; 270 static const uintptr_t s_bufferOwnershipMask = 3; 271 static const uintptr_t s_reportedCostBit = 4; 221 222 bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } 223 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 224 272 225 // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. 273 226 // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero. 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 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 284 234 UChar* m_data; 285 int m_length; 286 unsigned m_refCount; 287 mutable unsigned m_hash : 31; 288 mutable unsigned m_isIdentifier : 1; 289 UntypedPtrAndBitfield m_dataBuffer; 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; 290 243 291 244 JS_EXPORTDATA static UStringImpl* s_null;
Note:
See TracChangeset
for help on using the changeset viewer.