Changeset 44145 in webkit for trunk/JavaScriptCore
- Timestamp:
- May 25, 2009, 9:21:32 PM (16 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r44143 r44145 1 2009-05-25 David Levin <[email protected]> 2 3 Reviewed by Maciej Stachowiak and Oliver Hunt. 4 5 https://bugs.webkit.org/show_bug.cgi?id=25126 6 Allow the buffer underlying UString to be shared. 7 8 In order to not grow the underlying size of any structure, 9 there is a union in the Rep string which holds 10 + m_sharedBuffer -- a pointer to the shared ref counted buffer 11 if the class is BaseString and the buffer is being shared OR 12 + m_baseString -- the BaseString if the class is only UString::Rep 13 but not a UString::BaseString 14 15 Ideally, m_sharedBuffer would be a RefPtr, but it cannot be because 16 it is in a union. 17 18 No change in sunspider perf. 19 20 * JavaScriptCore.vcproj/WTF/WTF.vcproj: 21 * JavaScriptCore.xcodeproj/project.pbxproj: 22 * runtime/UString.cpp: 23 (JSC::UString::Rep::share): 24 (JSC::UString::Rep::destroy): 25 (JSC::UString::BaseString::sharedBuffer): 26 (JSC::UString::BaseString::setSharedBuffer): 27 (JSC::UString::BaseString::slowIsBufferReadOnly): 28 (JSC::expandCapacity): 29 (JSC::UString::Rep::reserveCapacity): 30 (JSC::UString::expandPreCapacity): 31 (JSC::concatenate): 32 (JSC::UString::append): 33 * runtime/UString.h: 34 (JSC::UString::Rep::Rep): 35 (JSC::UString::Rep::): 36 (JSC::UString::BaseString::isShared): 37 (JSC::UString::BaseString::isBufferReadOnly): 38 (JSC::UString::Rep::baseString): 39 * wtf/CrossThreadRefCounted.h: 40 (WTF::CrossThreadRefCounted::isShared): 41 * wtf/OwnFastMallocPtr.h: Added. 42 (WTF::OwnFastMallocPtr::OwnFastMallocPtr): 43 (WTF::OwnFastMallocPtr::~OwnFastMallocPtr): 44 (WTF::OwnFastMallocPtr::get): 45 (WTF::OwnFastMallocPtr::release): 46 1 47 2009-05-25 Oliver Hunt <[email protected]> 2 48 -
trunk/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj
r44095 r44145 222 222 </File> 223 223 <File 224 RelativePath="..\..\wtf\CrossThreadRefCounted.h" 225 > 226 </File> 227 <File 224 228 RelativePath="..\..\wtf\CurrentTime.cpp" 225 229 > … … 331 335 <File 332 336 RelativePath="..\..\wtf\OwnArrayPtr.h" 337 > 338 </File> 339 <File 340 RelativePath="..\..\wtf\OwnFastMallocPtr.h" 333 341 > 334 342 </File> -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r44095 r44145 43 43 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0B330C260F38C62300692DE3 /* TypeTraits.cpp */; }; 44 44 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; 45 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; 46 0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */; settings = {ATTRIBUTES = (Private, ); }; }; 45 47 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */; }; 46 48 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 456 458 0B330C260F38C62300692DE3 /* TypeTraits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeTraits.cpp; sourceTree = "<group>"; }; 457 459 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; }; 460 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnFastMallocPtr.h; sourceTree = "<group>"; }; 461 0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadRefCounted.h; sourceTree = "<group>"; }; 458 462 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; }; 459 463 141211020A48780900480255 /* minidom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = minidom.c; path = tests/minidom.c; sourceTree = "<group>"; }; … … 1162 1166 A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */, 1163 1167 A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */, 1168 0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */, 1164 1169 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */, 1165 1170 180B9AF00F16C569009BDBC5 /* CurrentTime.h */, … … 1193 1198 C0A2723F0E509F1E00E96E15 /* NotFound.h */, 1194 1199 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */, 1200 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */, 1195 1201 9303F567099118FA00AD71B8 /* OwnPtr.h */, 1196 1202 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */, … … 1830 1836 93052C350FB792190048FDC3 /* ParserArena.h in Headers */, 1831 1837 960626960FB8EC02009798AB /* JITStubCall.h in Headers */, 1838 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */, 1839 0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */, 1832 1840 ); 1833 1841 runOnlyForDeploymentPostprocessing = 0; -
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); -
trunk/JavaScriptCore/runtime/UString.h
r43856 r44145 2 2 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 3 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 4 * Copyright ( c) 2009,Google Inc. All rights reserved.4 * Copyright (C) 2009 Google Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 28 28 #include <string.h> 29 29 #include <wtf/Assertions.h> 30 #include <wtf/CrossThreadRefCounted.h> 31 #include <wtf/OwnFastMallocPtr.h> 30 32 #include <wtf/PassRefPtr.h> 31 33 #include <wtf/PtrAndFlags.h> … … 76 78 77 79 public: 80 typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; 78 81 struct BaseString; 79 82 struct Rep : Noncopyable { … … 102 105 static PassRefPtr<Rep> createFromUTF8(const char*); 103 106 107 // Uses SharedUChar to have joint ownership over the UChar*. 108 static PassRefPtr<Rep> share(UChar*, int, PassRefPtr<SharedUChar>); 109 104 110 void destroy(); 105 111 … … 146 152 147 153 protected: 148 // constructor for use by BaseString subclass; they are their own bases154 // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose. 149 155 Rep(int length) 150 156 : offset(0) … … 152 158 , rc(1) 153 159 , _hash(0) 154 , m_baseString( static_cast<BaseString*>(this))160 , m_baseString(0) 155 161 { 156 162 } … … 166 172 } 167 173 168 169 BaseString* m_baseString; 174 union { 175 // If !baseIsSelf() 176 BaseString* m_baseString; 177 // If baseIsSelf() 178 SharedUChar* m_sharedBuffer; 179 }; 170 180 171 181 private: … … 181 191 182 192 struct BaseString : public Rep { 183 bool isShared() { return rc != 1; } 193 bool isShared() { return rc != 1 || isBufferReadOnly(); } 194 void setSharedBuffer(PassRefPtr<SharedUChar>); 195 SharedUChar* sharedBuffer(); 196 197 bool isBufferReadOnly() 198 { 199 if (!m_sharedBuffer) 200 return false; 201 return slowIsBufferReadOnly(); 202 } 184 203 185 204 // potentially shared data. … … 205 224 checkConsistency(); 206 225 } 226 227 bool slowIsBufferReadOnly(); 207 228 208 229 friend struct Rep; … … 454 475 inline UString::BaseString* UString::Rep::baseString() 455 476 { 456 return m_baseString;477 return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ; 457 478 } 458 479 459 480 inline const UString::BaseString* UString::Rep::baseString() const 460 481 { 461 return m_baseString;482 return const_cast<Rep*>(this)->baseString(); 462 483 } 463 484 -
trunk/JavaScriptCore/wtf/CrossThreadRefCounted.h
r43663 r44145 36 36 #include <wtf/RefCounted.h> 37 37 #include <wtf/Threading.h> 38 #include <wtf/TypeTraits.h>39 38 40 39 namespace WTF { … … 66 65 void deref(); 67 66 T* release(); 67 68 bool isShared() const 69 { 70 return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef()); 71 } 68 72 69 73 #ifndef NDEBUG
Note:
See TracChangeset
for help on using the changeset viewer.