Changeset 57912 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Apr 20, 2010, 1:33:56 PM (15 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 4 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSString.cpp
r57019 r57912 52 52 else { 53 53 for (unsigned i = 0; i < m_fiberCount; ++i) { 54 m_other.m_fibers[i]->deref();54 RopeImpl::deref(m_other.m_fibers[i]); 55 55 m_other.m_fibers[i] = 0; 56 56 } … … 63 63 UChar* position = buffer + m_length; 64 64 65 // Start with the current Rope .66 Vector<Rope ::Fiber, 32> workQueue;67 Rope ::Fiber currentFiber;65 // Start with the current RopeImpl. 66 Vector<RopeImpl::Fiber, 32> workQueue; 67 RopeImpl::Fiber currentFiber; 68 68 for (unsigned i = 0; i < (m_fiberCount - 1); ++i) 69 69 workQueue.append(m_other.m_fibers[i]); 70 70 currentFiber = m_other.m_fibers[m_fiberCount - 1]; 71 71 while (true) { 72 if ( currentFiber->isRope()) {73 Rope * rope = static_cast<URopeImpl*>(currentFiber);72 if (RopeImpl::isRope(currentFiber)) { 73 RopeImpl* rope = static_cast<RopeImpl*>(currentFiber); 74 74 // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' 75 75 // (we will be working backwards over the rope). … … 89 89 ASSERT(buffer == position); 90 90 for (unsigned i = 0; i < m_fiberCount; ++i) { 91 m_other.m_fibers[i]->deref();91 RopeImpl::deref(m_other.m_fibers[i]); 92 92 m_other.m_fibers[i] = 0; 93 93 } -
trunk/JavaScriptCore/runtime/JSString.h
r57055 r57912 30 30 #include "PropertyDescriptor.h" 31 31 #include "PropertySlot.h" 32 #include "RopeImpl.h" 32 33 33 34 namespace JSC { … … 67 68 friend class JSGlobalData; 68 69 69 typedef URopeImpl Rope;70 71 70 class RopeBuilder { 72 71 public: 73 72 RopeBuilder(unsigned fiberCount) 74 73 : m_index(0) 75 , m_rope(Rope ::tryCreateUninitialized(fiberCount))74 , m_rope(RopeImpl::tryCreateUninitialized(fiberCount)) 76 75 { 77 76 } … … 79 78 bool isOutOfMemory() { return !m_rope; } 80 79 81 void append(Rope ::Fiber& fiber)80 void append(RopeImpl::Fiber& fiber) 82 81 { 83 82 ASSERT(m_rope); … … 98 97 } 99 98 100 PassRefPtr<Rope > release()99 PassRefPtr<RopeImpl> release() 101 100 { 102 101 ASSERT(m_index == m_rope->fiberCount()); … … 108 107 private: 109 108 unsigned m_index; 110 RefPtr<Rope > m_rope;109 RefPtr<RopeImpl> m_rope; 111 110 }; 112 111 … … 138 137 ASSERT(!m_value.isNull()); 139 138 } 140 JSString(JSGlobalData* globalData, PassRefPtr<Rope > rope)139 JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope) 141 140 : JSCell(globalData->stringStructure.get()) 142 141 , m_length(rope->length()) … … 217 216 ASSERT(vptr() == JSGlobalData::jsStringVPtr); 218 217 for (unsigned i = 0; i < m_fiberCount; ++i) 219 m_other.m_fibers[i]->deref();218 RopeImpl::deref(m_other.m_fibers[i]); 220 219 221 220 if (!m_fiberCount && m_other.m_finalizerCallback) … … 269 268 if (jsString->isRope()) { 270 269 for (unsigned i = 0; i < jsString->m_fiberCount; ++i) { 271 Rope ::Fiber fiber = jsString->m_other.m_fibers[i];270 RopeImpl::Fiber fiber = jsString->m_other.m_fibers[i]; 272 271 fiber->ref(); 273 272 m_other.m_fibers[index++] = fiber; … … 310 309 static const unsigned s_maxInternalRopeLength = 3; 311 310 312 // A string is represented either by a UString or a Rope .311 // A string is represented either by a UString or a RopeImpl. 313 312 unsigned m_length; 314 313 mutable UString m_value; … … 318 317 JSStringFinalizerStruct() : m_finalizerCallback(0) {} 319 318 union { 320 mutable Rope ::Fiber m_fibers[s_maxInternalRopeLength];319 mutable RopeImpl::Fiber m_fibers[s_maxInternalRopeLength]; 321 320 struct { 322 321 JSStringFinalizerCallback m_finalizerCallback; -
trunk/JavaScriptCore/runtime/RopeImpl.cpp
r57903 r57912 25 25 26 26 #include "config.h" 27 #include "UStringImpl.h" 28 29 #include "Identifier.h" 30 #include "StdLibExtras.h" 31 #include "UString.h" 32 #include <wtf/unicode/UTF8.h> 33 34 using namespace WTF::Unicode; 35 using namespace std; 27 #include "RopeImpl.h" 36 28 37 29 namespace JSC { 38 30 39 static const unsigned minLengthToShare = 20; 40 41 UStringImpl::~UStringImpl() 42 { 43 ASSERT(!isStatic()); 44 45 if (isIdentifier()) 46 Identifier::remove(this); 47 48 BufferOwnership ownership = bufferOwnership(); 49 if (ownership != BufferInternal) { 50 if (ownership == BufferOwned) { 51 ASSERT(!m_sharedBuffer); 52 ASSERT(m_data); 53 fastFree(const_cast<UChar*>(m_data)); 54 } else if (ownership == BufferSubstring) { 55 ASSERT(m_substringBuffer); 56 m_substringBuffer->deref(); 57 } else { 58 ASSERT(ownership == BufferShared); 59 ASSERT(m_sharedBuffer); 60 m_sharedBuffer->deref(); 61 } 62 } 63 } 64 65 UStringImpl* UStringImpl::empty() 66 { 67 // FIXME: This works around a bug in our port of PCRE, that a regular expression 68 // run on the empty string may still perform a read from the first element, and 69 // as such we need this to be a valid pointer. No code should ever be reading 70 // from a zero length string, so this should be able to be a non-null pointer 71 // into the zero-page. 72 // Replace this with 'reinterpret_cast<UChar*>(static_cast<intptr_t>(1))' once 73 // PCRE goes away. 74 static UChar emptyUCharData = 0; 75 DEFINE_STATIC_LOCAL(UStringImpl, emptyString, (&emptyUCharData, 0, ConstructStaticString)); 76 return &emptyString; 77 } 78 79 PassRefPtr<UStringImpl> UStringImpl::createUninitialized(unsigned length, UChar*& data) 80 { 81 if (!length) { 82 data = 0; 83 return empty(); 84 } 85 86 // Allocate a single buffer large enough to contain the StringImpl 87 // struct as well as the data which it contains. This removes one 88 // heap allocation from this call. 89 if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar))) 90 CRASH(); 91 size_t size = sizeof(UStringImpl) + length * sizeof(UChar); 92 UStringImpl* string = static_cast<UStringImpl*>(fastMalloc(size)); 93 94 data = reinterpret_cast<UChar*>(string + 1); 95 return adoptRef(new (string) UStringImpl(length)); 96 } 97 98 PassRefPtr<UStringImpl> UStringImpl::create(const UChar* characters, unsigned length) 99 { 100 if (!characters || !length) 101 return empty(); 102 103 UChar* data; 104 PassRefPtr<UStringImpl> string = createUninitialized(length, data); 105 memcpy(data, characters, length * sizeof(UChar)); 106 return string; 107 } 108 109 PassRefPtr<UStringImpl> UStringImpl::create(const char* characters, unsigned length) 110 { 111 if (!characters || !length) 112 return empty(); 113 114 UChar* data; 115 PassRefPtr<UStringImpl> string = createUninitialized(length, data); 116 for (unsigned i = 0; i != length; ++i) { 117 unsigned char c = characters[i]; 118 data[i] = c; 119 } 120 return string; 121 } 122 123 PassRefPtr<UStringImpl> UStringImpl::create(const char* string) 124 { 125 if (!string) 126 return empty(); 127 return create(string, strlen(string)); 128 } 129 130 PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) 131 { 132 if (!length) 133 return empty(); 134 return adoptRef(new UStringImpl(buffer, length, sharedBuffer)); 135 } 136 137 SharedUChar* UStringImpl::sharedBuffer() 138 { 139 if (m_length < minLengthToShare) 140 return 0; 141 // All static strings are smaller that the minimim length to share. 142 ASSERT(!isStatic()); 143 144 BufferOwnership ownership = bufferOwnership(); 145 146 if (ownership == BufferInternal) 147 return 0; 148 if (ownership == BufferSubstring) 149 return m_substringBuffer->sharedBuffer(); 150 if (ownership == BufferOwned) { 151 ASSERT(!m_sharedBuffer); 152 m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef(); 153 m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; 154 } 155 156 ASSERT(bufferOwnership() == BufferShared); 157 ASSERT(m_sharedBuffer); 158 return m_sharedBuffer; 159 } 160 161 void URopeImpl::derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue) 31 void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue) 162 32 { 163 33 unsigned length = fiberCount(); 164 34 for (unsigned i = 0; i < length; ++i) { 165 35 Fiber& fiber = fibers(i); 166 if ( fiber->isRope()) {167 URopeImpl* nextRope = static_cast<URopeImpl*>(fiber);36 if (isRope(fiber)) { 37 RopeImpl* nextRope = static_cast<RopeImpl*>(fiber); 168 38 if (nextRope->hasOneRef()) 169 39 workQueue.append(nextRope); … … 175 45 } 176 46 177 void URopeImpl::destructNonRecursive()47 void RopeImpl::destructNonRecursive() 178 48 { 179 Vector< URopeImpl*, 32> workQueue;49 Vector<RopeImpl*, 32> workQueue; 180 50 181 51 derefFibersNonRecursive(workQueue); … … 183 53 184 54 while (!workQueue.isEmpty()) { 185 URopeImpl* rope = workQueue.last();55 RopeImpl* rope = workQueue.last(); 186 56 workQueue.removeLast(); 187 57 rope->derefFibersNonRecursive(workQueue); -
trunk/JavaScriptCore/runtime/RopeImpl.h
r57903 r57912 1 1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #ifndef UStringImpl_h27 #define UStringImpl_h26 #ifndef RopeImpl_h 27 #define RopeImpl_h 28 28 29 #include <limits> 30 #include <wtf/CrossThreadRefCounted.h> 31 #include <wtf/OwnFastMallocPtr.h> 32 #include <wtf/PossiblyNull.h> 33 #include <wtf/StringHashFunctions.h> 34 #include <wtf/Vector.h> 35 #include <wtf/unicode/Unicode.h> 29 #include "UStringImpl.h" 36 30 37 31 namespace JSC { 38 32 39 class IdentifierTable; 33 class RopeImpl : public UStringImplBase { 34 public: 35 // A RopeImpl is composed from a set of smaller strings called Fibers. 36 // Each Fiber in a rope is either UStringImpl or another RopeImpl. 37 typedef UStringImplBase* Fiber; 40 38 41 typedef OwnFastMallocPtr<const UChar> SharableUChar; 42 typedef CrossThreadRefCounted<SharableUChar> SharedUChar; 43 44 class UStringOrRopeImpl : public Noncopyable { 45 public: 46 bool isRope() { return (m_refCountAndFlags & s_refCountIsRope) == s_refCountIsRope; } 47 unsigned length() const { return m_length; } 48 49 void ref() { m_refCountAndFlags += s_refCountIncrement; } 50 inline void deref(); 51 52 protected: 53 enum BufferOwnership { 54 BufferInternal, 55 BufferOwned, 56 BufferSubstring, 57 BufferShared, 58 }; 59 60 using Noncopyable::operator new; 61 void* operator new(size_t, void* inPlace) { return inPlace; } 62 63 // For SmallStringStorage, which allocates an array and uses an in-place new. 64 UStringOrRopeImpl() { } 65 66 UStringOrRopeImpl(unsigned length, BufferOwnership ownership) 67 : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership) 68 , m_length(length) 69 { 70 ASSERT(!isRope()); 71 } 72 73 enum StaticStringConstructType { ConstructStaticString }; 74 UStringOrRopeImpl(unsigned length, StaticStringConstructType) 75 : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned) 76 , m_length(length) 77 { 78 ASSERT(!isRope()); 79 } 80 81 enum RopeConstructType { ConstructRope }; 82 UStringOrRopeImpl(RopeConstructType) 83 : m_refCountAndFlags(s_refCountIncrement | s_refCountIsRope) 84 , m_length(0) 85 { 86 ASSERT(isRope()); 87 } 88 89 // The bottom 5 bits hold flags, the top 27 bits hold the ref count. 90 // When dereferencing UStringImpls we check for the ref count AND the 91 // static bit both being zero - static strings are never deleted. 92 static const unsigned s_refCountMask = 0xFFFFFFE0; 93 static const unsigned s_refCountIncrement = 0x20; 94 static const unsigned s_refCountFlagStatic = 0x10; 95 static const unsigned s_refCountFlagShouldReportedCost = 0x8; 96 static const unsigned s_refCountFlagIsIdentifier = 0x4; 97 static const unsigned s_refCountMaskBufferOwnership = 0x3; 98 // Use an otherwise invalid permutation of flags (static & shouldReportedCost - 99 // static strings do not set shouldReportedCost in the constructor, and this bit 100 // is only ever cleared, not set) to identify objects that are ropes. 101 static const unsigned s_refCountIsRope = s_refCountFlagStatic | s_refCountFlagShouldReportedCost; 102 103 unsigned m_refCountAndFlags; 104 unsigned m_length; 105 }; 106 107 class UStringImpl : public UStringOrRopeImpl { 108 friend struct CStringTranslator; 109 friend struct UCharBufferTranslator; 110 friend class JIT; 111 friend class SmallStringsStorage; 112 friend class UStringOrRopeImpl; 113 friend void initializeUString(); 114 private: 115 // For SmallStringStorage, which allocates an array and uses an in-place new. 116 UStringImpl() { } 117 118 // Used to construct static strings, which have an special refCount that can never hit zero. 119 // This means that the static string will never be destroyed, which is important because 120 // static strings will be shared across threads & ref-counted in a non-threadsafe manner. 121 UStringImpl(const UChar* characters, unsigned length, StaticStringConstructType) 122 : UStringOrRopeImpl(length, ConstructStaticString) 123 , m_data(characters) 124 , m_buffer(0) 125 , m_hash(0) 126 { 127 hash(); 128 } 129 130 // Create a normal string with internal storage (BufferInternal) 131 UStringImpl(unsigned length) 132 : UStringOrRopeImpl(length, BufferInternal) 133 , m_data(reinterpret_cast<UChar*>(this + 1)) 134 , m_buffer(0) 135 , m_hash(0) 136 { 137 ASSERT(m_data); 138 ASSERT(m_length); 139 } 140 141 // Create a UStringImpl adopting ownership of the provided buffer (BufferOwned) 142 UStringImpl(const UChar* characters, unsigned length) 143 : UStringOrRopeImpl(length, BufferOwned) 144 , m_data(characters) 145 , m_buffer(0) 146 , m_hash(0) 147 { 148 ASSERT(m_data); 149 ASSERT(m_length); 150 } 151 152 // Used to create new strings that are a substring of an existing UStringImpl (BufferSubstring) 153 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<UStringImpl> base) 154 : UStringOrRopeImpl(length, BufferSubstring) 155 , m_data(characters) 156 , m_substringBuffer(base.releaseRef()) 157 , m_hash(0) 158 { 159 ASSERT(m_data); 160 ASSERT(m_length); 161 ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); 162 } 163 164 // Used to construct new strings sharing an existing SharedUChar (BufferShared) 165 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) 166 : UStringOrRopeImpl(length, BufferShared) 167 , m_data(characters) 168 , m_sharedBuffer(sharedBuffer.releaseRef()) 169 , m_hash(0) 170 { 171 ASSERT(m_data); 172 ASSERT(m_length); 173 } 174 175 // For use only by Identifier's XXXTranslator helpers. 176 void setHash(unsigned hash) 177 { 178 ASSERT(!isStatic()); 179 ASSERT(!m_hash); 180 ASSERT(hash == computeHash(m_data, m_length)); 181 m_hash = hash; 182 } 183 184 public: 185 ~UStringImpl(); 186 187 static PassRefPtr<UStringImpl> create(const UChar*, unsigned length); 188 static PassRefPtr<UStringImpl> create(const char*, unsigned length); 189 static PassRefPtr<UStringImpl> create(const char*); 190 static PassRefPtr<UStringImpl> create(const UChar*, unsigned length, PassRefPtr<SharedUChar>); 191 static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned length) 192 { 193 ASSERT(rep); 194 ASSERT(length <= rep->length()); 195 196 if (!length) 197 return empty(); 198 199 UStringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); 200 return adoptRef(new UStringImpl(rep->m_data + offset, length, ownerRep)); 201 } 202 203 static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output); 204 static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output) 205 { 206 if (!length) { 207 output = 0; 208 return empty(); 209 } 210 211 if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar))) 212 return 0; 213 UStringImpl* resultImpl; 214 if (!tryFastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)).getValue(resultImpl)) 215 return 0; 216 output = reinterpret_cast<UChar*>(resultImpl + 1); 217 return adoptRef(new(resultImpl) UStringImpl(length)); 218 } 219 220 template<size_t inlineCapacity> 221 static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) 222 { 223 if (size_t size = vector.size()) { 224 ASSERT(vector.data()); 225 return adoptRef(new UStringImpl(vector.releaseBuffer(), size)); 226 } 227 return empty(); 228 } 229 230 SharedUChar* sharedBuffer(); 231 const UChar* characters() const { return m_data; } 232 233 size_t cost() 234 { 235 // For substrings, return the cost of the base string. 236 if (bufferOwnership() == BufferSubstring) 237 return m_substringBuffer->cost(); 238 239 if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) { 240 m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost; 241 return m_length; 242 } 243 return 0; 244 } 245 246 bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } 247 void setIsIdentifier(bool isIdentifier) 248 { 249 ASSERT(!isStatic()); 250 if (isIdentifier) 251 m_refCountAndFlags |= s_refCountFlagIsIdentifier; 252 else 253 m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; 254 } 255 256 unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } 257 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } 258 static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); } 259 static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); } 260 static unsigned computeHash(const char* data) { return WTF::stringHash(data); } 261 262 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } 263 264 static UStringImpl* empty(); 265 266 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) 267 { 268 if (numCharacters <= s_copyCharsInlineCutOff) { 269 for (unsigned i = 0; i < numCharacters; ++i) 270 destination[i] = source[i]; 271 } else 272 memcpy(destination, source, numCharacters * sizeof(UChar)); 273 } 274 275 private: 276 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 277 static const unsigned s_copyCharsInlineCutOff = 20; 278 279 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 280 bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } 281 282 const UChar* m_data; 283 union { 284 void* m_buffer; 285 UStringImpl* m_substringBuffer; 286 SharedUChar* m_sharedBuffer; 287 }; 288 mutable unsigned m_hash; 289 }; 290 291 class URopeImpl : public UStringOrRopeImpl { 292 friend class UStringOrRopeImpl; 293 public: 294 // A URopeImpl is composed from a set of smaller strings called Fibers. 295 // Each Fiber in a rope is either UStringImpl or another URopeImpl. 296 typedef UStringOrRopeImpl* Fiber; 297 298 // Creates a URopeImpl comprising of 'fiberCount' Fibers. 299 // The URopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the URopeImpl. 300 static PassRefPtr<URopeImpl> tryCreateUninitialized(unsigned fiberCount) 39 // Creates a RopeImpl comprising of 'fiberCount' Fibers. 40 // The RopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the RopeImpl. 41 static PassRefPtr<RopeImpl> tryCreateUninitialized(unsigned fiberCount) 301 42 { 302 43 void* allocation; 303 if (tryFastMalloc(sizeof( URopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation))304 return adoptRef(new (allocation) URopeImpl(fiberCount));44 if (tryFastMalloc(sizeof(RopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) 45 return adoptRef(new (allocation) RopeImpl(fiberCount)); 305 46 return 0; 306 47 } … … 318 59 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); } 319 60 61 static bool isRope(Fiber fiber) 62 { 63 return !fiber->isStringImpl(); 64 } 65 66 static void deref(Fiber fiber) 67 { 68 if (isRope(fiber)) 69 static_cast<RopeImpl*>(fiber)->deref(); 70 else 71 static_cast<UStringImpl*>(fiber)->deref(); 72 } 73 320 74 private: 321 URopeImpl(unsigned fiberCount) : UStringOrRopeImpl(ConstructRope), m_fiberCount(fiberCount) {}75 RopeImpl(unsigned fiberCount) : UStringImplBase(ConstructNonStringImpl), m_fiberCount(fiberCount) {} 322 76 323 77 void destructNonRecursive(); 324 void derefFibersNonRecursive(Vector< URopeImpl*, 32>& workQueue);78 void derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue); 325 79 326 80 bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } … … 330 84 }; 331 85 332 inline void UStringOrRopeImpl::deref()333 {334 if (isRope())335 static_cast<URopeImpl*>(this)->deref();336 else337 static_cast<UStringImpl*>(this)->deref();338 }339 340 bool equal(const UStringImpl*, const UStringImpl*);341 342 86 } 343 87 -
trunk/JavaScriptCore/runtime/UStringImpl.cpp
r57748 r57912 159 159 } 160 160 161 void URopeImpl::derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue)162 {163 unsigned length = fiberCount();164 for (unsigned i = 0; i < length; ++i) {165 Fiber& fiber = fibers(i);166 if (fiber->isRope()) {167 URopeImpl* nextRope = static_cast<URopeImpl*>(fiber);168 if (nextRope->hasOneRef())169 workQueue.append(nextRope);170 else171 nextRope->deref();172 } else173 static_cast<UStringImpl*>(fiber)->deref();174 }175 }176 177 void URopeImpl::destructNonRecursive()178 {179 Vector<URopeImpl*, 32> workQueue;180 181 derefFibersNonRecursive(workQueue);182 delete this;183 184 while (!workQueue.isEmpty()) {185 URopeImpl* rope = workQueue.last();186 workQueue.removeLast();187 rope->derefFibersNonRecursive(workQueue);188 delete rope;189 }190 }191 192 161 } // namespace JSC -
trunk/JavaScriptCore/runtime/UStringImpl.h
r57851 r57912 42 42 typedef CrossThreadRefCounted<SharableUChar> SharedUChar; 43 43 44 class UString OrRopeImpl: public Noncopyable {44 class UStringImplBase : public Noncopyable { 45 45 public: 46 bool is Rope() { return (m_refCountAndFlags & s_refCountIsRope) == s_refCountIsRope; }46 bool isStringImpl() { return (m_refCountAndFlags & s_refCountInvalidForStringImpl) != s_refCountInvalidForStringImpl; } 47 47 unsigned length() const { return m_length; } 48 48 49 49 void ref() { m_refCountAndFlags += s_refCountIncrement; } 50 inline void deref();51 50 52 51 protected: … … 62 61 63 62 // For SmallStringStorage, which allocates an array and uses an in-place new. 64 UString OrRopeImpl() { }65 66 UString OrRopeImpl(unsigned length, BufferOwnership ownership)63 UStringImplBase() { } 64 65 UStringImplBase(unsigned length, BufferOwnership ownership) 67 66 : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership) 68 67 , m_length(length) 69 68 { 70 ASSERT( !isRope());69 ASSERT(isStringImpl()); 71 70 } 72 71 73 72 enum StaticStringConstructType { ConstructStaticString }; 74 UString OrRopeImpl(unsigned length, StaticStringConstructType)73 UStringImplBase(unsigned length, StaticStringConstructType) 75 74 : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned) 76 75 , m_length(length) 77 76 { 78 ASSERT(!isRope()); 79 } 80 81 enum RopeConstructType { ConstructRope }; 82 UStringOrRopeImpl(RopeConstructType) 83 : m_refCountAndFlags(s_refCountIncrement | s_refCountIsRope) 77 ASSERT(isStringImpl()); 78 } 79 80 // This constructor is not used when creating UStringImpl objects, 81 // and sets the flags into a state marking the object as such. 82 enum NonStringImplConstructType { ConstructNonStringImpl }; 83 UStringImplBase(NonStringImplConstructType) 84 : m_refCountAndFlags(s_refCountIncrement | s_refCountInvalidForStringImpl) 84 85 , m_length(0) 85 86 { 86 ASSERT( isRope());87 ASSERT(!isStringImpl()); 87 88 } 88 89 … … 96 97 static const unsigned s_refCountFlagIsIdentifier = 0x4; 97 98 static const unsigned s_refCountMaskBufferOwnership = 0x3; 98 // Use an otherwise invalid permutation of flags (static & shouldReportedCost -99 // s tatic strings do not set shouldReportedCost in the constructor, and this bit100 // is only ever cleared, not set) to identify objects that are ropes.101 static const unsigned s_refCountI sRope= s_refCountFlagStatic | s_refCountFlagShouldReportedCost;99 // An invalid permutation of flags (static & shouldReportedCost - static strings do not 100 // set shouldReportedCost in the constructor, and this bit is only ever cleared, not set). 101 // Used by "ConstructNonStringImpl" constructor, above. 102 static const unsigned s_refCountInvalidForStringImpl = s_refCountFlagStatic | s_refCountFlagShouldReportedCost; 102 103 103 104 unsigned m_refCountAndFlags; … … 105 106 }; 106 107 107 class UStringImpl : public UString OrRopeImpl{108 class UStringImpl : public UStringImplBase { 108 109 friend struct CStringTranslator; 109 110 friend struct UCharBufferTranslator; 110 111 friend class JIT; 111 112 friend class SmallStringsStorage; 112 friend class UStringOrRopeImpl;113 113 friend void initializeUString(); 114 114 private: … … 120 120 // static strings will be shared across threads & ref-counted in a non-threadsafe manner. 121 121 UStringImpl(const UChar* characters, unsigned length, StaticStringConstructType) 122 : UString OrRopeImpl(length, ConstructStaticString)122 : UStringImplBase(length, ConstructStaticString) 123 123 , m_data(characters) 124 124 , m_buffer(0) … … 130 130 // Create a normal string with internal storage (BufferInternal) 131 131 UStringImpl(unsigned length) 132 : UString OrRopeImpl(length, BufferInternal)132 : UStringImplBase(length, BufferInternal) 133 133 , m_data(reinterpret_cast<UChar*>(this + 1)) 134 134 , m_buffer(0) … … 141 141 // Create a UStringImpl adopting ownership of the provided buffer (BufferOwned) 142 142 UStringImpl(const UChar* characters, unsigned length) 143 : UString OrRopeImpl(length, BufferOwned)143 : UStringImplBase(length, BufferOwned) 144 144 , m_data(characters) 145 145 , m_buffer(0) … … 152 152 // Used to create new strings that are a substring of an existing UStringImpl (BufferSubstring) 153 153 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<UStringImpl> base) 154 : UString OrRopeImpl(length, BufferSubstring)154 : UStringImplBase(length, BufferSubstring) 155 155 , m_data(characters) 156 156 , m_substringBuffer(base.releaseRef()) … … 164 164 // Used to construct new strings sharing an existing SharedUChar (BufferShared) 165 165 UStringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) 166 : UString OrRopeImpl(length, BufferShared)166 : UStringImplBase(length, BufferShared) 167 167 , m_data(characters) 168 168 , m_sharedBuffer(sharedBuffer.releaseRef()) … … 289 289 }; 290 290 291 class URopeImpl : public UStringOrRopeImpl { 292 friend class UStringOrRopeImpl; 293 public: 294 // A URopeImpl is composed from a set of smaller strings called Fibers. 295 // Each Fiber in a rope is either UStringImpl or another URopeImpl. 296 typedef UStringOrRopeImpl* Fiber; 297 298 // Creates a URopeImpl comprising of 'fiberCount' Fibers. 299 // The URopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the URopeImpl. 300 static PassRefPtr<URopeImpl> tryCreateUninitialized(unsigned fiberCount) 301 { 302 void* allocation; 303 if (tryFastMalloc(sizeof(URopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) 304 return adoptRef(new (allocation) URopeImpl(fiberCount)); 305 return 0; 306 } 307 308 void initializeFiber(unsigned &index, Fiber fiber) 309 { 310 m_fibers[index++] = fiber; 311 fiber->ref(); 312 m_length += fiber->length(); 313 } 314 315 unsigned fiberCount() { return m_fiberCount; } 316 Fiber& fibers(unsigned index) { return m_fibers[index]; } 317 318 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); } 319 320 private: 321 URopeImpl(unsigned fiberCount) : UStringOrRopeImpl(ConstructRope), m_fiberCount(fiberCount) {} 322 323 void destructNonRecursive(); 324 void derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue); 325 326 bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } 327 328 unsigned m_fiberCount; 329 Fiber m_fibers[1]; 330 }; 331 332 inline void UStringOrRopeImpl::deref() 333 { 334 if (isRope()) 335 static_cast<URopeImpl*>(this)->deref(); 336 else 337 static_cast<UStringImpl*>(this)->deref(); 291 bool equal(const UStringImpl*, const UStringImpl*); 292 338 293 } 339 294 340 bool equal(const UStringImpl*, const UStringImpl*);341 342 }343 344 295 #endif
Note:
See TracChangeset
for help on using the changeset viewer.