Changeset 39815 in webkit for trunk/JavaScriptCore/runtime/UString.cpp
- Timestamp:
- Jan 11, 2009, 7:19:23 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.cpp
r39747 r39815 188 188 // reduce the possibility of it becoming zero due to ref/deref not being thread-safe. 189 189 static UChar sharedEmptyChar; 190 UString:: Rep* UString::Rep::nullBaseString;191 UString:: Rep* UString::Rep::emptyBaseString;190 UString::BaseString* UString::Rep::nullBaseString; 191 UString::BaseString* UString::Rep::emptyBaseString; 192 192 UString* UString::nullUString; 193 193 194 void initializeStaticBaseString(int len, UChar* buf, UString:: Rep& base)194 void initializeStaticBaseString(int len, UChar* buf, UString::BaseString& base) 195 195 { 196 196 base.offset = 0; … … 199 199 base._hash = 0; 200 200 base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag); 201 base. baseString = &base;201 base.m_baseString = 0; 202 202 base.buf = buf; 203 203 base.preCapacity = 0; … … 206 206 base.usedCapacity = 0; 207 207 base.reportedCost = 0; 208 base.checkConsistency(); 208 209 } 209 210 210 211 void initializeUString() 211 212 { 212 UString::Rep::nullBaseString = new UString:: Rep;213 UString::Rep::nullBaseString = new UString::BaseString; 213 214 initializeStaticBaseString(0, 0, *UString::Rep::nullBaseString); 214 215 215 UString::Rep::emptyBaseString = new UString:: Rep;216 UString::Rep::emptyBaseString = new UString::BaseString; 216 217 initializeStaticBaseString(0, &sharedEmptyChar, *UString::Rep::emptyBaseString); 217 218 … … 230 231 PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l) 231 232 { 232 Rep* r = new Rep;233 BaseString* r = new BaseString; 233 234 r->offset = 0; 234 235 r->len = l; 235 236 r->rc = 1; 236 237 r->_hash = 0; 237 r-> baseString = r;238 r->m_baseString = 0; 238 239 r->reportedCost = 0; 239 240 r->buf = d; … … 249 250 } 250 251 251 PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)252 { 253 ASSERT( base);254 base->checkConsistency();255 256 int baseOffset = base->offset;257 258 base = base->baseString;259 260 ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);261 ASSERT(offset + baseOffset + length <= base->usedCapacity);252 PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> rep, int offset, int length) 253 { 254 ASSERT(rep); 255 rep->checkConsistency(); 256 257 int repOffset = rep->offset; 258 259 PassRefPtr<BaseString> base = rep->baseString(); 260 261 ASSERT(-(offset + repOffset) <= base->usedPreCapacity); 262 ASSERT(offset + repOffset + length <= base->usedCapacity); 262 263 263 264 Rep* r = new Rep; 264 r->offset = baseOffset + offset;265 r->offset = repOffset + offset; 265 266 r->len = length; 266 267 r->rc = 1; 267 268 r->_hash = 0; 268 r->baseString = base.releaseRef(); 269 r->reportedCost = 0; 270 r->buf = 0; 271 r->usedCapacity = 0; 272 r->capacity = 0; 273 r->usedPreCapacity = 0; 274 r->preCapacity = 0; 269 r->setBaseString(base); 275 270 276 271 r->checkConsistency(); … … 303 298 if (identifierTable()) 304 299 Identifier::remove(this); 305 if (baseString == this) 306 fastFree(buf); 300 UString::BaseString* base = baseString(); 301 if (base == this) 302 fastFree(base->buf); 307 303 else 308 base String->deref();304 base->deref(); 309 305 310 306 delete this; … … 408 404 void UString::Rep::checkConsistency() const 409 405 { 410 // Only base strings have non-zero shared data. 411 if (this != baseString) { 412 ASSERT(!buf); 413 ASSERT(!usedCapacity); 414 ASSERT(!capacity); 415 ASSERT(!usedPreCapacity); 416 ASSERT(!preCapacity); 417 } 406 const UString::BaseString* base = baseString(); 418 407 419 408 // There is no recursion for base strings. 420 ASSERT(base String == baseString->baseString);409 ASSERT(base == base->baseString()); 421 410 422 411 if (isStatic()) { … … 429 418 430 419 // The string fits in buffer. 431 ASSERT(base String->usedPreCapacity <= baseString->preCapacity);432 ASSERT(base String->usedCapacity <= baseString->capacity);433 ASSERT(-offset <= base String->usedPreCapacity);434 ASSERT(offset + len <= base String->usedCapacity);420 ASSERT(base->usedPreCapacity <= base->preCapacity); 421 ASSERT(base->usedCapacity <= base->capacity); 422 ASSERT(-offset <= base->usedPreCapacity); 423 ASSERT(offset + len <= base->usedCapacity); 435 424 } 436 425 #endif … … 452 441 } 453 442 454 inline int UString::usedCapacity() const455 {456 return m_rep->baseString->usedCapacity;457 }458 459 inline int UString::usedPreCapacity() const460 {461 return m_rep->baseString->usedPreCapacity;462 }463 464 465 443 static inline bool expandCapacity(UString::Rep* rep, int requiredLength) 466 444 { 467 445 rep->checkConsistency(); 468 446 469 UString:: Rep* r = rep->baseString;470 471 if (requiredLength > r->capacity) {472 size_t newCapacity = expandedSize(requiredLength, r->preCapacity);473 UChar* oldBuf = r->buf;474 r->buf = reallocChars(r->buf, newCapacity);475 if (! r->buf) {476 r->buf = oldBuf;447 UString::BaseString* base = rep->baseString(); 448 449 if (requiredLength > base->capacity) { 450 size_t newCapacity = expandedSize(requiredLength, base->preCapacity); 451 UChar* oldBuf = base->buf; 452 base->buf = reallocChars(base->buf, newCapacity); 453 if (!base->buf) { 454 base->buf = oldBuf; 477 455 return false; 478 456 } 479 r->capacity = newCapacity - r->preCapacity;480 } 481 if (requiredLength > r->usedCapacity)482 r->usedCapacity = requiredLength;457 base->capacity = newCapacity - base->preCapacity; 458 } 459 if (requiredLength > base->usedCapacity) 460 base->usedCapacity = requiredLength; 483 461 484 462 rep->checkConsistency(); … … 496 474 m_rep->checkConsistency(); 497 475 498 Rep* r = m_rep->baseString;499 500 if (requiredPreCap > r->preCapacity) {501 size_t newCapacity = expandedSize(requiredPreCap, r->capacity);502 int delta = newCapacity - r->capacity - r->preCapacity;476 BaseString* base = m_rep->baseString(); 477 478 if (requiredPreCap > base->preCapacity) { 479 size_t newCapacity = expandedSize(requiredPreCap, base->capacity); 480 int delta = newCapacity - base->capacity - base->preCapacity; 503 481 504 482 UChar* newBuf = allocChars(newCapacity); … … 507 485 return; 508 486 } 509 copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity);510 fastFree( r->buf);511 r->buf = newBuf;512 513 r->preCapacity = newCapacity - r->capacity;514 } 515 if (requiredPreCap > r->usedPreCapacity)516 r->usedPreCapacity = requiredPreCap;487 copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity); 488 fastFree(base->buf); 489 base->buf = newBuf; 490 491 base->preCapacity = newCapacity - base->capacity; 492 } 493 if (requiredPreCap > base->usedPreCapacity) 494 base->usedPreCapacity = requiredPreCap; 517 495 518 496 m_rep->checkConsistency(); … … 579 557 int thisOffset = rep->offset; 580 558 int length = thisSize + tSize; 559 UString::BaseString* base = rep->baseString(); 581 560 582 561 // possible cases: … … 586 565 // this is empty 587 566 rep = UString::Rep::createCopying(tData, tSize); 588 } else if (rep ->baseIsSelf()&& rep->rc == 1) {567 } else if (rep == base && rep->rc == 1) { 589 568 // this is direct and has refcount of 1 (so we can just alter it directly) 590 569 if (!expandCapacity(rep.get(), thisOffset + length)) … … 595 574 rep->_hash = 0; 596 575 } 597 } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {576 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { 598 577 // this reaches the end of the buffer - extend it if it's long enough to append to 599 578 if (!expandCapacity(rep.get(), thisOffset + length)) … … 613 592 copyChars(d + thisSize, tData, tSize); 614 593 rep = UString::Rep::create(d, length); 615 rep-> capacity = newCapacity;594 rep->baseString()->capacity = newCapacity; 616 595 } 617 596 } … … 632 611 int tSize = static_cast<int>(strlen(t)); 633 612 int length = thisSize + tSize; 613 UString::BaseString* base = rep->baseString(); 634 614 635 615 // possible cases: … … 639 619 } else if (tSize == 0) { 640 620 // t is empty, we'll just return *this below. 641 } else if (rep ->baseIsSelf()&& rep->rc == 1) {621 } else if (rep == base && rep->rc == 1) { 642 622 // this is direct and has refcount of 1 (so we can just alter it directly) 643 623 expandCapacity(rep.get(), thisOffset + length); … … 649 629 rep->_hash = 0; 650 630 } 651 } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {631 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { 652 632 // this string reaches the end of the buffer - extend it 653 633 expandCapacity(rep.get(), thisOffset + length); … … 669 649 d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend 670 650 rep = UString::Rep::create(d, length); 671 rep-> capacity = newCapacity;651 rep->baseString()->capacity = newCapacity; 672 652 } 673 653 } … … 698 678 return a; 699 679 700 if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) { 680 UString::BaseString* aBase = a->baseString(); 681 if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + length <= aBase->capacity) { 701 682 // b is a single character (common fast case) 702 a ->baseString->usedCapacity = aOffset + length;683 aBase->usedCapacity = aOffset + length; 703 684 a->data()[aSize] = b->data()[0]; 704 685 return UString::Rep::create(a, 0, length); 705 686 } 706 687 707 if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize && 708 (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) { 688 UString::BaseString* bBase = b->baseString(); 689 if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize 690 && (-bOffset != bBase->usedPreCapacity || aSize >= bSize)) { 709 691 // - a reaches the end of its buffer so it qualifies for shared append 710 692 // - also, it's at least a quarter the length of b - appending to a much shorter … … 725 707 } 726 708 727 if (-bOffset == b ->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {709 if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) { 728 710 // - b reaches the beginning of its buffer so it qualifies for shared prepend 729 711 // - also, it's at least a quarter the length of a - prepending to a much shorter … … 751 733 copyChars(d + aSize, b->data(), bSize); 752 734 PassRefPtr<UString::Rep> result = UString::Rep::create(d, length); 753 result-> capacity = newCapacity;735 result->baseString()->capacity = newCapacity; 754 736 755 737 a->checkConsistency(); … … 1052 1034 int tSize = t.size(); 1053 1035 int length = thisSize + tSize; 1036 BaseString* base = m_rep->baseString(); 1054 1037 1055 1038 // possible cases: … … 1059 1042 } else if (tSize == 0) { 1060 1043 // t is empty 1061 } else if (m_rep ->baseIsSelf()&& m_rep->rc == 1) {1044 } else if (m_rep == base && m_rep->rc == 1) { 1062 1045 // this is direct and has refcount of 1 (so we can just alter it directly) 1063 1046 expandCapacity(thisOffset + length); … … 1067 1050 m_rep->_hash = 0; 1068 1051 } 1069 } else if (thisOffset + thisSize == usedCapacity()&& thisSize >= minShareSize) {1052 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) { 1070 1053 // this reaches the end of the buffer - extend it if it's long enough to append to 1071 1054 expandCapacity(thisOffset + length); … … 1084 1067 copyChars(d + thisSize, t.data(), tSize); 1085 1068 m_rep = Rep::create(d, length); 1086 m_rep-> capacity = newCapacity;1069 m_rep->baseString()->capacity = newCapacity; 1087 1070 } 1088 1071 } … … 1112 1095 int thisOffset = m_rep->offset; 1113 1096 int length = size(); 1097 BaseString* base = m_rep->baseString(); 1114 1098 1115 1099 // possible cases: … … 1123 1107 d[0] = c; 1124 1108 m_rep = Rep::create(d, 1); 1125 m_rep-> capacity = newCapacity;1126 } 1127 } else if (m_rep ->baseIsSelf()&& m_rep->rc == 1) {1109 m_rep->baseString()->capacity = newCapacity; 1110 } 1111 } else if (m_rep == base && m_rep->rc == 1) { 1128 1112 // this is direct and has refcount of 1 (so we can just alter it directly) 1129 1113 expandCapacity(thisOffset + length + 1); … … 1134 1118 m_rep->_hash = 0; 1135 1119 } 1136 } else if (thisOffset + length == usedCapacity()&& length >= minShareSize) {1120 } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) { 1137 1121 // this reaches the end of the string - extend it and share 1138 1122 expandCapacity(thisOffset + length + 1); … … 1152 1136 d[length] = c; 1153 1137 m_rep = Rep::create(d, length + 1); 1154 m_rep-> capacity = newCapacity;1138 m_rep->baseString()->capacity = newCapacity; 1155 1139 } 1156 1140 } … … 1218 1202 int l = static_cast<int>(strlen(c)); 1219 1203 UChar* d; 1220 if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) { 1221 d = m_rep->buf; 1204 BaseString* base = m_rep->baseString(); 1205 if (m_rep->rc == 1 && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) { 1206 d = base->buf; 1222 1207 m_rep->_hash = 0; 1223 1208 m_rep->len = l;
Note:
See TracChangeset
for help on using the changeset viewer.