Changeset 52463 in webkit for trunk/JavaScriptCore/runtime/UString.h
- Timestamp:
- Dec 21, 2009, 4:38:24 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.h
r52346 r52463 25 25 26 26 #include "Collector.h" 27 #include "UStringImpl.h" 27 28 #include <stdint.h> 28 29 #include <string.h> … … 41 42 using WTF::PlacementNewAdopt; 42 43 43 class IdentifierTable;44 45 44 class CString { 46 45 public: … … 72 71 }; 73 72 73 bool operator==(const CString&, const CString&); 74 74 75 typedef Vector<char, 32> CStringBuffer; 75 76 … … 78 79 79 80 public: 80 typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; 81 struct BaseString; 82 struct Rep : Noncopyable { 83 friend class JIT; 84 85 static PassRefPtr<Rep> create(UChar* buffer, int length) 86 { 87 return adoptRef(new BaseString(buffer, length)); 88 } 89 90 static PassRefPtr<Rep> createEmptyBuffer(size_t size) 91 { 92 // Guard against integer overflow 93 if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) { 94 void* buf = 0; 95 if (tryFastMalloc(size * sizeof(UChar)).getValue(buf)) 96 return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size)); 97 } 98 return adoptRef(new BaseString(0, 0, 0)); 99 } 100 101 static PassRefPtr<Rep> createCopying(const UChar*, int); 102 static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length); 103 104 // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h). 105 // Returns UString::Rep::null for null input or conversion failure. 106 static PassRefPtr<Rep> createFromUTF8(const char*); 107 108 // Uses SharedUChar to have joint ownership over the UChar*. 109 static PassRefPtr<Rep> create(UChar*, int, PassRefPtr<SharedUChar>); 110 111 SharedUChar* sharedBuffer(); 112 void destroy(); 113 114 bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); } 115 UChar* data() const; 116 int size() const { return len; } 117 118 unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; } 119 unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers 120 void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), len)); _hash = hash; } // fast path for Identifiers 121 122 static unsigned computeHash(const UChar*, int length); 123 static unsigned computeHash(const char*, int length); 124 static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); } 125 126 IdentifierTable* identifierTable() const { return m_identifierTableAndFlags.get(); } 127 void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); } 128 129 bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); } 130 void setStatic(bool); 131 void setBaseString(PassRefPtr<BaseString>); 132 BaseString* baseString(); 133 const BaseString* baseString() const; 134 135 Rep* ref() { ++rc; return this; } 136 ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); } 137 138 void checkConsistency() const; 139 enum UStringFlags { 140 StaticFlag, 141 BaseStringFlag 142 }; 143 144 // unshared data 145 int offset; 146 int len; 147 int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted. 148 mutable unsigned _hash; 149 PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags; 150 151 static BaseString& null() { return *nullBaseString; } 152 static BaseString& empty() { return *emptyBaseString; } 153 154 bool reserveCapacity(int capacity); 155 156 protected: 157 // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose. 158 Rep(int length) 159 : offset(0) 160 , len(length) 161 , rc(1) 162 , _hash(0) 163 , m_baseString(0) 164 { 165 } 166 167 Rep(PassRefPtr<BaseString> base, int offsetInBase, int length) 168 : offset(offsetInBase) 169 , len(length) 170 , rc(1) 171 , _hash(0) 172 , m_baseString(base.releaseRef()) 173 { 174 checkConsistency(); 175 } 176 177 union { 178 // If !baseIsSelf() 179 BaseString* m_baseString; 180 // If baseIsSelf() 181 SharedUChar* m_sharedBuffer; 182 }; 183 184 private: 185 // For SmallStringStorage which allocates an array and does initialization manually. 186 Rep() { } 187 188 friend class SmallStringsStorage; 189 friend void initializeUString(); 190 JS_EXPORTDATA static BaseString* nullBaseString; 191 JS_EXPORTDATA static BaseString* emptyBaseString; 192 }; 193 194 195 struct BaseString : public Rep { 196 bool isShared() { return rc != 1 || isBufferReadOnly(); } 197 void setSharedBuffer(PassRefPtr<SharedUChar>); 198 199 bool isBufferReadOnly() 200 { 201 if (!m_sharedBuffer) 202 return false; 203 return slowIsBufferReadOnly(); 204 } 205 206 // potentially shared data. 207 UChar* buf; 208 int preCapacity; 209 int usedPreCapacity; 210 int capacity; 211 int usedCapacity; 212 213 size_t reportedCost; 214 215 private: 216 BaseString(UChar* buffer, int length, int additionalCapacity = 0) 217 : Rep(length) 218 , buf(buffer) 219 , preCapacity(0) 220 , usedPreCapacity(0) 221 , capacity(length + additionalCapacity) 222 , usedCapacity(length) 223 , reportedCost(0) 224 { 225 m_identifierTableAndFlags.setFlag(BaseStringFlag); 226 checkConsistency(); 227 } 228 229 SharedUChar* sharedBuffer(); 230 bool slowIsBufferReadOnly(); 231 232 friend struct Rep; 233 friend class SmallStringsStorage; 234 friend void initializeUString(); 235 }; 236 81 typedef UStringImpl Rep; 82 237 83 public: 84 // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below. 238 85 UString(); 239 // Constructor for null-terminated ASCII string. 240 UString(const char*); 241 // Constructor for non-null-terminated ASCII string. 86 UString(const char*); // Constructor for null-terminated string. 242 87 UString(const char*, int length); 243 88 UString(const UChar*, int length); … … 261 106 static UString createNonCopying(UChar* c, int length); 262 107 static UString createFromUTF8(const char*); 108 static UString createUninitialized(unsigned length, UChar*& output); 263 109 264 110 static UString from(int); … … 287 133 288 134 UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const; 289 290 UString& append(const UString&);291 UString& append(const char*);292 UString& append(UChar);293 UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }294 UString& append(const UChar*, int size);295 135 296 136 bool getCString(CStringBuffer&) const; … … 312 152 UString& operator=(const char*c); 313 153 314 UString& operator+=(const UString& s) { return append(s); }315 UString& operator+=(const char* s) { return append(s); }316 317 154 const UChar* data() const { return m_rep->data(); } 318 155 319 bool isNull() const { return (m_rep == &Rep::null()); }320 bool isEmpty() const { return (!m_rep->len); }156 bool isNull() const { return m_rep == &Rep::null(); } 157 bool isEmpty() const { return !m_rep->size(); } 321 158 322 159 bool is8Bit() const; … … 354 191 } 355 192 356 size_t cost() const; 357 358 // Attempt to grow this string such that it can grow to a total length of 'capacity' 359 // without reallocation. This may fail a number of reasons - if the BasicString is 360 // shared and another string is using part of the capacity beyond our end point, if 361 // the realloc fails, or if this string is empty and has no storage. 362 // 363 // This method returns a boolean indicating success. 364 bool reserveCapacity(int capacity) 365 { 366 return m_rep->reserveCapacity(capacity); 367 } 193 size_t cost() const { return m_rep->cost(); } 368 194 369 195 private: 370 void expandCapacity(int requiredLength);371 void expandPreCapacity(int requiredPreCap);372 196 void makeNull(); 373 197 … … 377 201 friend void initializeUString(); 378 202 friend bool operator==(const UString&, const UString&); 379 friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory 380 }; 381 PassRefPtr<UString::Rep> concatenate(UString::Rep*, UString::Rep*); 382 PassRefPtr<UString::Rep> concatenate(UString::Rep*, int); 383 PassRefPtr<UString::Rep> concatenate(UString::Rep*, double); 203 }; 384 204 385 205 inline bool operator==(const UString& s1, const UString& s2) … … 429 249 } 430 250 431 bool operator==(const CString&, const CString&);432 433 inline UString operator+(const UString& s1, const UString& s2)434 {435 RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep());436 return UString(result ? result.release() : UString::nullRep());437 }438 439 251 int compare(const UString&, const UString&); 440 441 bool equal(const UString::Rep*, const UString::Rep*);442 443 inline PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<UString::Rep> rep, int offset, int length)444 {445 ASSERT(rep);446 rep->checkConsistency();447 448 int repOffset = rep->offset;449 450 PassRefPtr<BaseString> base = rep->baseString();451 452 ASSERT(-(offset + repOffset) <= base->usedPreCapacity);453 ASSERT(offset + repOffset + length <= base->usedCapacity);454 455 // Steal the single reference this Rep was created with.456 return adoptRef(new Rep(base, repOffset + offset, length));457 }458 459 inline UChar* UString::Rep::data() const460 {461 const BaseString* base = baseString();462 return base->buf + base->preCapacity + offset;463 }464 465 inline void UString::Rep::setStatic(bool v)466 {467 ASSERT(!identifierTable());468 if (v)469 m_identifierTableAndFlags.setFlag(StaticFlag);470 else471 m_identifierTableAndFlags.clearFlag(StaticFlag);472 }473 474 inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base)475 {476 ASSERT(base != this);477 ASSERT(!baseIsSelf());478 m_baseString = base.releaseRef();479 }480 481 inline UString::BaseString* UString::Rep::baseString()482 {483 return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ;484 }485 486 inline const UString::BaseString* UString::Rep::baseString() const487 {488 return const_cast<Rep*>(this)->baseString();489 }490 491 #ifdef NDEBUG492 inline void UString::Rep::checkConsistency() const493 {494 }495 #endif496 252 497 253 inline UString::UString() … … 517 273 static const int minShareSize = Heap::minExtraCost / sizeof(UChar); 518 274 519 inline size_t UString::cost() const520 {521 BaseString* base = m_rep->baseString();522 size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar);523 size_t reportedCost = base->reportedCost;524 ASSERT(capacity >= reportedCost);525 526 size_t capacityDelta = capacity - reportedCost;527 528 if (capacityDelta < static_cast<size_t>(minShareSize))529 return 0;530 531 base->reportedCost = capacity;532 533 return capacityDelta;534 }535 536 275 struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { 537 276 static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); } … … 619 358 UChar* buffer; 620 359 unsigned length = adapter1.length() + adapter2.length(); 621 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 622 return UString(); 623 624 UChar* result = buffer; 625 adapter1.writeTo(result); 626 result += adapter1.length(); 627 adapter2.writeTo(result); 628 629 return UString::createNonCopying(buffer, length); 360 UString resultString = UString::createUninitialized(length, buffer); 361 if (!buffer) 362 return UString(); 363 364 UChar* result = buffer; 365 adapter1.writeTo(result); 366 result += adapter1.length(); 367 adapter2.writeTo(result); 368 369 return resultString; 630 370 } 631 371 … … 639 379 UChar* buffer; 640 380 unsigned length = adapter1.length() + adapter2.length() + adapter3.length(); 641 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 381 UString resultString = UString::createUninitialized(length, buffer); 382 if (!buffer) 642 383 return UString(); 643 384 … … 649 390 adapter3.writeTo(result); 650 391 651 return UString::createNonCopying(buffer, length);392 return resultString; 652 393 } 653 394 … … 662 403 UChar* buffer; 663 404 unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length(); 664 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 405 UString resultString = UString::createUninitialized(length, buffer); 406 if (!buffer) 665 407 return UString(); 666 408 … … 674 416 adapter4.writeTo(result); 675 417 676 return UString::createNonCopying(buffer, length);418 return resultString; 677 419 } 678 420 … … 688 430 UChar* buffer; 689 431 unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length(); 690 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 432 UString resultString = UString::createUninitialized(length, buffer); 433 if (!buffer) 691 434 return UString(); 692 435 … … 702 445 adapter5.writeTo(result); 703 446 704 return UString::createNonCopying(buffer, length);447 return resultString; 705 448 } 706 449 … … 717 460 UChar* buffer; 718 461 unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length(); 719 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 462 UString resultString = UString::createUninitialized(length, buffer); 463 if (!buffer) 720 464 return UString(); 721 465 … … 733 477 adapter6.writeTo(result); 734 478 735 return UString::createNonCopying(buffer, length);479 return resultString; 736 480 } 737 481 … … 749 493 UChar* buffer; 750 494 unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length(); 751 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 495 UString resultString = UString::createUninitialized(length, buffer); 496 if (!buffer) 752 497 return UString(); 753 498 … … 767 512 adapter7.writeTo(result); 768 513 769 return UString::createNonCopying(buffer, length);514 return resultString; 770 515 } 771 516 … … 784 529 UChar* buffer; 785 530 unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length(); 786 if (!tryFastMalloc(length * sizeof(UChar)).getValue(buffer)) 531 UString resultString = UString::createUninitialized(length, buffer); 532 if (!buffer) 787 533 return UString(); 788 534 … … 804 550 adapter8.writeTo(result); 805 551 806 return UString::createNonCopying(buffer, length);552 return resultString; 807 553 } 808 554
Note:
See TracChangeset
for help on using the changeset viewer.