Changeset 44145 in webkit for trunk/JavaScriptCore/runtime/UString.cpp
- Timestamp:
- May 25, 2009, 9:21:32 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/UString.cpp
r43856 r44145 1 1 /* 2 2 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 4 4 * Copyright (C) 2007 Cameron Zwarich ([email protected]) 5 * Copyright ( c) 2009,Google Inc. All rights reserved.5 * Copyright (C) 2009 Google Inc. All rights reserved. 6 6 * 7 7 * This library is free software; you can redistribute it and/or … … 233 233 } 234 234 235 PassRefPtr<UString::Rep> UString::Rep::share(UChar* string, int length, PassRefPtr<UString::SharedUChar> sharedBuffer) 236 { 237 PassRefPtr<UString::Rep> rep = create(string, length); 238 rep->baseString()->setSharedBuffer(sharedBuffer); 239 rep->checkConsistency(); 240 return rep; 241 } 242 235 243 void UString::Rep::destroy() 236 244 { … … 242 250 if (identifierTable()) 243 251 Identifier::remove(this); 252 244 253 UString::BaseString* base = baseString(); 245 if (base == this) 246 fastFree(base->buf); 247 else 254 if (base == this) { 255 if (m_sharedBuffer) 256 m_sharedBuffer->deref(); 257 else 258 fastFree(base->buf); 259 } else 248 260 base->deref(); 249 261 … … 368 380 } 369 381 #endif 382 383 UString::SharedUChar* UString::BaseString::sharedBuffer() 384 { 385 // Don't share empty, null and 1 character strings from SmallStrings. 386 if (len <= 1) 387 return 0; 388 389 if (!m_sharedBuffer) 390 setSharedBuffer(SharedUChar::create(new OwnFastMallocPtr<UChar>(buf))); 391 return m_sharedBuffer; 392 } 393 394 void UString::BaseString::setSharedBuffer(PassRefPtr<UString::SharedUChar> sharedBuffer) 395 { 396 // The manual steps below are because m_sharedBuffer can't be a RefPtr. m_sharedBuffer 397 // is in a union with another variable to avoid making BaseString any larger. 398 if (m_sharedBuffer) 399 m_sharedBuffer->deref(); 400 m_sharedBuffer = sharedBuffer.releaseRef(); 401 } 402 403 bool UString::BaseString::slowIsBufferReadOnly() 404 { 405 // The buffer may not be modified as soon as the underlying data has been shared with another class. 406 if (m_sharedBuffer->isShared()) 407 return true; 408 409 // At this point, we know it that the underlying buffer isn't shared outside of this base class, 410 // so get rid of m_sharedBuffer. 411 OwnPtr<OwnFastMallocPtr<UChar> > mallocPtr(m_sharedBuffer->release()); 412 UChar* unsharedBuf = const_cast<UChar*>(mallocPtr->release()); 413 setSharedBuffer(0); 414 preCapacity += (buf - unsharedBuf); 415 buf = unsharedBuf; 416 return false; 417 } 370 418 371 419 // Put these early so they can be inlined. … … 418 466 { 419 467 rep->checkConsistency(); 468 ASSERT(!rep->baseString()->isBufferReadOnly()); 420 469 421 470 UString::BaseString* base = rep->baseString(); … … 443 492 // If the BaseString is shared with another string that is using more capacity than this 444 493 // string is, then growing the buffer won't help. 445 if (!m_baseString->buf || !m_baseString->capacity || (offset + len) != m_baseString->usedCapacity) 494 // If the BaseString's buffer is readonly, then it isn't allowed to grow. 495 UString::BaseString* base = baseString(); 496 if (!base->buf || !base->capacity || (offset + len) != base->usedCapacity || base->isBufferReadOnly()) 446 497 return false; 447 498 448 499 // If there is already sufficient capacity, no need to grow! 449 if (capacity <= m_baseString->capacity)500 if (capacity <= base->capacity) 450 501 return true; 451 502 452 503 checkConsistency(); 453 504 454 size_t newCapacity = expandedSize(capacity, m_baseString->preCapacity);455 UChar* oldBuf = m_baseString->buf;456 m_baseString->buf = reallocChars(m_baseString->buf, newCapacity);457 if (! m_baseString->buf) {458 m_baseString->buf = oldBuf;505 size_t newCapacity = expandedSize(capacity, base->preCapacity); 506 UChar* oldBuf = base->buf; 507 base->buf = reallocChars(base->buf, newCapacity); 508 if (!base->buf) { 509 base->buf = oldBuf; 459 510 return false; 460 511 } 461 m_baseString->capacity = newCapacity - m_baseString->preCapacity;512 base->capacity = newCapacity - base->preCapacity; 462 513 463 514 checkConsistency(); … … 474 525 { 475 526 m_rep->checkConsistency(); 527 ASSERT(!m_rep->baseString()->isBufferReadOnly()); 476 528 477 529 BaseString* base = m_rep->baseString(); … … 586 638 rep->_hash = 0; 587 639 } 588 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize ) {640 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { 589 641 // this reaches the end of the buffer - extend it if it's long enough to append to 590 642 if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length))) … … 595 647 } 596 648 } else { 597 // this is shared with someone using more capacity, gotta make a whole new string649 // This is shared in some way that prevents us from modifying base, so we must make a whole new string. 598 650 size_t newCapacity = expandedSize(length, 0); 599 651 UChar* d = allocChars(newCapacity); … … 641 693 rep->_hash = 0; 642 694 } 643 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize ) {695 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { 644 696 // this string reaches the end of the buffer - extend it 645 697 expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)); … … 651 703 } 652 704 } else { 653 // this is shared with someone using more capacity, gotta make a whole new string705 // This is shared in some way that prevents us from modifying base, so we must make a whole new string. 654 706 size_t newCapacity = expandedSize(length, 0); 655 707 UChar* d = allocChars(newCapacity); … … 682 734 683 735 UString::BaseString* aBase = a->baseString(); 684 if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity ) {736 if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity && !aBase->isBufferReadOnly()) { 685 737 // b is a single character (common fast case) 686 738 ++aBase->usedCapacity; … … 701 753 UString::BaseString* bBase = b->baseString(); 702 754 if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize 703 && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) ) {755 && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) && !aBase->isBufferReadOnly()) { 704 756 // - a reaches the end of its buffer so it qualifies for shared append 705 757 // - also, it's at least a quarter the length of b - appending to a much shorter … … 721 773 } 722 774 723 if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize ) {775 if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize && !bBase->isBufferReadOnly()) { 724 776 // - b reaches the beginning of its buffer so it qualifies for shared prepend 725 777 // - also, it's at least a quarter the length of a - prepending to a much shorter … … 1084 1136 m_rep->_hash = 0; 1085 1137 } 1086 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize ) {1138 } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { 1087 1139 // this reaches the end of the buffer - extend it if it's long enough to append to 1088 1140 expandCapacity(newCapacityWithOverflowCheck(thisOffset, length)); … … 1092 1144 } 1093 1145 } else { 1094 // this is shared with someone using more capacity, gotta make a whole new string1146 // This is shared in some way that prevents us from modifying base, so we must make a whole new string. 1095 1147 size_t newCapacity = expandedSize(length, 0); 1096 1148 UChar* d = allocChars(newCapacity); … … 1164 1216 m_rep->_hash = 0; 1165 1217 } 1166 } else if (thisOffset + length == base->usedCapacity && length >= minShareSize ) {1218 } else if (thisOffset + length == base->usedCapacity && length >= minShareSize && !base->isBufferReadOnly()) { 1167 1219 // this reaches the end of the string - extend it and share 1168 1220 expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true)); … … 1173 1225 } 1174 1226 } else { 1175 // this is shared with someone using more capacity, gotta make a whole new string1227 // This is shared in some way that prevents us from modifying base, so we must make a whole new string. 1176 1228 size_t newCapacity = expandedSize(length + 1, 0); 1177 1229 UChar* d = allocChars(newCapacity);
Note:
See TracChangeset
for help on using the changeset viewer.