Changeset 54804 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Feb 15, 2010, 5:32:06 PM (15 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSString.cpp
r53371 r54804 32 32 namespace JSC { 33 33 34 void JSString::Rope::destructNonRecursive()34 void Rope::destructNonRecursive() 35 35 { 36 36 Vector<Rope*, 32> workQueue; … … 38 38 39 39 while (true) { 40 unsigned length = rope-> ropeLength();40 unsigned length = rope->fiberCount(); 41 41 for (unsigned i = 0; i < length; ++i) { 42 42 Fiber& fiber = rope->fibers(i); … … 62 62 } 63 63 64 JSString::Rope::~Rope()64 Rope::~Rope() 65 65 { 66 66 destructNonRecursive(); … … 83 83 // Allocate the buffer to hold the final string, position initially points to the end. 84 84 UChar* buffer; 85 if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_ stringLength, buffer))85 if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_length, buffer)) 86 86 m_value = newImpl; 87 87 else { 88 for (unsigned i = 0; i < m_ ropeLength; ++i) {88 for (unsigned i = 0; i < m_fiberCount; ++i) { 89 89 m_fibers[i].deref(); 90 90 m_fibers[i] = static_cast<void*>(0); 91 91 } 92 m_ ropeLength= 0;92 m_fiberCount = 0; 93 93 ASSERT(!isRope()); 94 94 ASSERT(m_value == UString()); … … 96 96 return; 97 97 } 98 UChar* position = buffer + m_ stringLength;98 UChar* position = buffer + m_length; 99 99 100 100 // Start with the current Rope. 101 101 Vector<Rope::Fiber, 32> workQueue; 102 102 Rope::Fiber currentFiber; 103 for (unsigned i = 0; i < (m_ ropeLength- 1); ++i)103 for (unsigned i = 0; i < (m_fiberCount - 1); ++i) 104 104 workQueue.append(m_fibers[i]); 105 currentFiber = m_fibers[m_ ropeLength- 1];105 currentFiber = m_fibers[m_fiberCount - 1]; 106 106 while (true) { 107 107 if (currentFiber.isRope()) { … … 109 109 // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' 110 110 // (we will be working backwards over the rope). 111 unsigned ropeLengthMinusOne = rope->ropeLength() - 1;112 for (unsigned i = 0; i < ropeLengthMinusOne; ++i)111 unsigned fiberCountMinusOne = rope->fiberCount() - 1; 112 for (unsigned i = 0; i < fiberCountMinusOne; ++i) 113 113 workQueue.append(rope->fibers(i)); 114 currentFiber = rope->fibers( ropeLengthMinusOne);114 currentFiber = rope->fibers(fiberCountMinusOne); 115 115 } else { 116 116 UString::Rep* string = currentFiber.string(); … … 123 123 // Create a string from the UChar buffer, clear the rope RefPtr. 124 124 ASSERT(buffer == position); 125 for (unsigned i = 0; i < m_ ropeLength; ++i) {125 for (unsigned i = 0; i < m_fiberCount; ++i) { 126 126 m_fibers[i].deref(); 127 127 m_fibers[i] = static_cast<void*>(0); 128 128 } 129 m_ ropeLength= 0;129 m_fiberCount = 0; 130 130 131 131 ASSERT(!isRope()); … … 154 154 bool JSString::toBoolean(ExecState*) const 155 155 { 156 return m_ stringLength;156 return m_length; 157 157 } 158 158 … … 216 216 { 217 217 if (propertyName == exec->propertyNames().length) { 218 descriptor.setDescriptor(jsNumber(exec, m_ stringLength), DontEnum | DontDelete | ReadOnly);218 descriptor.setDescriptor(jsNumber(exec, m_length), DontEnum | DontDelete | ReadOnly); 219 219 return true; 220 220 } … … 222 222 bool isStrictUInt32; 223 223 unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); 224 if (isStrictUInt32 && i < m_ stringLength) {224 if (isStrictUInt32 && i < m_length) { 225 225 descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly); 226 226 return true; -
trunk/JavaScriptCore/runtime/JSString.h
r54545 r54804 33 33 namespace JSC { 34 34 35 // FIXME: this class is on its way out into a different header. 36 class Rope : public RefCounted<Rope> { 37 public: 38 // A Rope is composed from a set of smaller strings called Fibers. 39 // Each Fiber in a rope is either UString::Rep or another Rope. 40 class Fiber { 41 public: 42 Fiber() : m_value(0) {} 43 Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {} 44 Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {} 45 46 Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {} 47 48 void deref() 49 { 50 if (isRope()) 51 rope()->deref(); 52 else 53 string()->deref(); 54 } 55 56 Fiber& ref() 57 { 58 if (isString()) 59 string()->ref(); 60 else 61 rope()->ref(); 62 return *this; 63 } 64 65 unsigned refAndGetLength() 66 { 67 if (isString()) { 68 UString::Rep* rep = string(); 69 return rep->ref()->size(); 70 } else { 71 Rope* r = rope(); 72 r->ref(); 73 return r->length(); 74 } 75 } 76 77 bool isRope() { return m_value & 1; } 78 Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); } 79 bool isString() { return !isRope(); } 80 UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); } 81 82 void* nonFiber() { return reinterpret_cast<void*>(m_value); } 83 private: 84 intptr_t m_value; 85 }; 86 87 // Creates a Rope comprising of 'fiberCount' Fibers. 88 // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope. 89 static PassRefPtr<Rope> tryCreateUninitialized(unsigned fiberCount) 90 { 91 void* allocation; 92 if (tryFastMalloc(sizeof(Rope) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) 93 return adoptRef(new (allocation) Rope(fiberCount)); 94 return 0; 95 } 96 97 ~Rope(); 98 void destructNonRecursive(); 99 100 void initializeFiber(unsigned &index, Fiber& fiber) 101 { 102 m_fibers[index++] = fiber; 103 m_length += fiber.refAndGetLength(); 104 } 105 void initializeFiber(unsigned &index, UStringImpl* impl) 106 { 107 m_fibers[index++] = Fiber(impl); 108 m_length += impl->ref()->size(); 109 } 110 111 unsigned fiberCount() { return m_fiberCount; } 112 unsigned length() { return m_length; } 113 Fiber& fibers(unsigned index) { return m_fibers[index]; } 114 115 private: 116 Rope(unsigned fiberCount) : m_fiberCount(fiberCount), m_length(0) {} 117 void* operator new(size_t, void* inPlace) { return inPlace; } 118 119 unsigned m_fiberCount; 120 unsigned m_length; 121 Fiber m_fibers[1]; 122 }; 123 35 124 class JSString; 36 125 … … 68 157 friend class JSGlobalData; 69 158 70 // A Rope is a string composed of a set of substrings. 71 class Rope : public RefCounted<Rope> { 159 class RopeBuilder { 72 160 public: 73 // A Rope is composed from a set of smaller strings called Fibers. 74 // Each Fiber in a rope is either UString::Rep or another Rope. 75 class Fiber { 76 public: 77 Fiber() : m_value(0) {} 78 Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {} 79 Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {} 80 81 Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {} 82 83 void deref() 84 { 85 if (isRope()) 86 rope()->deref(); 87 else 88 string()->deref(); 89 } 90 91 Fiber& ref() 92 { 93 if (isString()) 94 string()->ref(); 95 else 96 rope()->ref(); 97 return *this; 98 } 99 100 unsigned refAndGetLength() 101 { 102 if (isString()) { 103 UString::Rep* rep = string(); 104 return rep->ref()->size(); 105 } else { 106 Rope* r = rope(); 107 r->ref(); 108 return r->stringLength(); 109 } 110 } 111 112 bool isRope() { return m_value & 1; } 113 Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); } 114 bool isString() { return !isRope(); } 115 UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); } 116 117 void* nonFiber() { return reinterpret_cast<void*>(m_value); } 118 private: 119 intptr_t m_value; 120 }; 121 122 // Creates a Rope comprising of 'ropeLength' Fibers. 123 // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope. 124 static PassRefPtr<Rope> createOrNull(unsigned ropeLength) 125 { 126 void* allocation; 127 if (tryFastMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation)) 128 return adoptRef(new (allocation) Rope(ropeLength)); 129 return 0; 130 } 131 132 ~Rope(); 133 void destructNonRecursive(); 134 135 void append(unsigned &index, Fiber& fiber) 136 { 137 m_fibers[index++] = fiber; 138 m_stringLength += fiber.refAndGetLength(); 139 } 140 void append(unsigned &index, const UString& string) 141 { 142 UString::Rep* rep = string.rep(); 143 m_fibers[index++] = Fiber(rep); 144 m_stringLength += rep->ref()->size(); 145 } 146 void append(unsigned& index, JSString* jsString) 161 RopeBuilder(unsigned fiberCount) 162 : m_index(0) 163 , m_rope(Rope::tryCreateUninitialized(fiberCount)) 164 { 165 } 166 167 bool isOutOfMemory() { return !m_rope; } 168 169 void append(Rope::Fiber& fiber) 170 { 171 ASSERT(m_rope); 172 m_rope->initializeFiber(m_index, fiber); 173 } 174 void append(const UString& string) 175 { 176 ASSERT(m_rope); 177 m_rope->initializeFiber(m_index, string.rep()); 178 } 179 void append(JSString* jsString) 147 180 { 148 181 if (jsString->isRope()) { 149 for (unsigned i = 0; i < jsString->m_ ropeLength; ++i)150 append( index,jsString->m_fibers[i]);182 for (unsigned i = 0; i < jsString->m_fiberCount; ++i) 183 append(jsString->m_fibers[i]); 151 184 } else 152 append(index, jsString->string()); 153 } 154 155 unsigned ropeLength() { return m_ropeLength; } 156 unsigned stringLength() { return m_stringLength; } 157 Fiber& fibers(unsigned index) { return m_fibers[index]; } 185 append(jsString->string()); 186 } 187 188 PassRefPtr<Rope> release() 189 { 190 ASSERT(m_index == m_rope->fiberCount()); 191 return m_rope.release(); 192 } 158 193 159 194 private: 160 Rope(unsigned ropeLength) : m_ropeLength(ropeLength), m_stringLength(0) {} 161 void* operator new(size_t, void* inPlace) { return inPlace; } 162 163 unsigned m_ropeLength; 164 unsigned m_stringLength; 165 Fiber m_fibers[1]; 195 unsigned m_index; 196 RefPtr<Rope> m_rope; 166 197 }; 167 198 168 199 ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value) 169 200 : JSCell(globalData->stringStructure.get()) 170 , m_ stringLength(value.size())201 , m_length(value.size()) 171 202 , m_value(value) 172 , m_ ropeLength(0)203 , m_fiberCount(0) 173 204 { 174 205 Heap::heap(this)->reportExtraMemoryCost(value.cost()); … … 178 209 JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType) 179 210 : JSCell(globalData->stringStructure.get()) 180 , m_ stringLength(value.size())211 , m_length(value.size()) 181 212 , m_value(value) 182 , m_ ropeLength(0)213 , m_fiberCount(0) 183 214 { 184 215 } 185 216 JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType) 186 217 : JSCell(globalData->stringStructure.get()) 187 , m_ stringLength(value->size())218 , m_length(value->size()) 188 219 , m_value(value) 189 , m_ ropeLength(0)190 { 191 } 192 JSString(JSGlobalData* globalData, PassRefPtr< JSString::Rope> rope)193 : JSCell(globalData->stringStructure.get()) 194 , m_ stringLength(rope->stringLength())195 , m_ ropeLength(1)220 , m_fiberCount(0) 221 { 222 } 223 JSString(JSGlobalData* globalData, PassRefPtr<Rope> rope) 224 : JSCell(globalData->stringStructure.get()) 225 , m_length(rope->length()) 226 , m_fiberCount(1) 196 227 { 197 228 m_fibers[0] = rope.releaseRef(); 198 229 } 199 230 // This constructor constructs a new string by concatenating s1 & s2. 200 // This should only be called with ropeLength<= 3.201 JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2)202 : JSCell(globalData->stringStructure.get()) 203 , m_ stringLength(s1->length() + s2->length())204 , m_ ropeLength(ropeLength)205 { 206 ASSERT( ropeLength<= s_maxInternalRopeLength);231 // This should only be called with fiberCount <= 3. 232 JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2) 233 : JSCell(globalData->stringStructure.get()) 234 , m_length(s1->length() + s2->length()) 235 , m_fiberCount(fiberCount) 236 { 237 ASSERT(fiberCount <= s_maxInternalRopeLength); 207 238 unsigned index = 0; 208 239 appendStringInConstruct(index, s1); 209 240 appendStringInConstruct(index, s2); 210 ASSERT( ropeLength== index);241 ASSERT(fiberCount == index); 211 242 } 212 243 // This constructor constructs a new string by concatenating s1 & s2. 213 // This should only be called with ropeLength<= 3.214 JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, const UString& u2)215 : JSCell(globalData->stringStructure.get()) 216 , m_ stringLength(s1->length() + u2.size())217 , m_ ropeLength(ropeLength)218 { 219 ASSERT( ropeLength<= s_maxInternalRopeLength);244 // This should only be called with fiberCount <= 3. 245 JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2) 246 : JSCell(globalData->stringStructure.get()) 247 , m_length(s1->length() + u2.size()) 248 , m_fiberCount(fiberCount) 249 { 250 ASSERT(fiberCount <= s_maxInternalRopeLength); 220 251 unsigned index = 0; 221 252 appendStringInConstruct(index, s1); 222 253 appendStringInConstruct(index, u2); 223 ASSERT( ropeLength== index);254 ASSERT(fiberCount == index); 224 255 } 225 256 // This constructor constructs a new string by concatenating s1 & s2. 226 // This should only be called with ropeLength<= 3.227 JSString(JSGlobalData* globalData, unsigned ropeLength, const UString& u1, JSString* s2)228 : JSCell(globalData->stringStructure.get()) 229 , m_ stringLength(u1.size() + s2->length())230 , m_ ropeLength(ropeLength)231 { 232 ASSERT( ropeLength<= s_maxInternalRopeLength);257 // This should only be called with fiberCount <= 3. 258 JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2) 259 : JSCell(globalData->stringStructure.get()) 260 , m_length(u1.size() + s2->length()) 261 , m_fiberCount(fiberCount) 262 { 263 ASSERT(fiberCount <= s_maxInternalRopeLength); 233 264 unsigned index = 0; 234 265 appendStringInConstruct(index, u1); 235 266 appendStringInConstruct(index, s2); 236 ASSERT( ropeLength== index);267 ASSERT(fiberCount == index); 237 268 } 238 269 // This constructor constructs a new string by concatenating v1, v2 & v3. 239 // This should only be called with ropeLength<= 3 ... which since every240 // value must require a ropeLengthof at least one implies that the length270 // This should only be called with fiberCount <= 3 ... which since every 271 // value must require a fiberCount of at least one implies that the length 241 272 // for each value must be exactly 1! 242 273 JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3) 243 274 : JSCell(exec->globalData().stringStructure.get()) 244 , m_ stringLength(0)245 , m_ ropeLength(s_maxInternalRopeLength)275 , m_length(0) 276 , m_fiberCount(s_maxInternalRopeLength) 246 277 { 247 278 unsigned index = 0; … … 254 285 JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context) 255 286 : JSCell(globalData->stringStructure.get()) 256 , m_ stringLength(value.size())287 , m_length(value.size()) 257 288 , m_value(value) 258 , m_ ropeLength(0)289 , m_fiberCount(0) 259 290 { 260 291 // nasty hack because we can't union non-POD types … … 267 298 { 268 299 ASSERT(vptr() == JSGlobalData::jsStringVPtr); 269 for (unsigned i = 0; i < m_ ropeLength; ++i)300 for (unsigned i = 0; i < m_fiberCount; ++i) 270 301 m_fibers[i].deref(); 271 302 272 if (!m_ ropeLength&& m_fibers[0].nonFiber()) {303 if (!m_fiberCount && m_fibers[0].nonFiber()) { 273 304 JSStringFinalizerCallback finalizer = reinterpret_cast<JSStringFinalizerCallback>(m_fibers[0].nonFiber()); 274 305 finalizer(this, m_fibers[1].nonFiber()); … … 289 320 return m_value; 290 321 } 291 unsigned length() { return m_ stringLength; }322 unsigned length() { return m_length; } 292 323 293 324 bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); … … 295 326 bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); 296 327 297 bool canGetIndex(unsigned i) { return i < m_ stringLength; }328 bool canGetIndex(unsigned i) { return i < m_length; } 298 329 JSString* getIndex(ExecState*, unsigned); 299 330 … … 304 335 JSString(VPtrStealingHackType) 305 336 : JSCell(0) 306 , m_ ropeLength(0)337 , m_fiberCount(0) 307 338 { 308 339 } … … 318 349 { 319 350 if (jsString->isRope()) { 320 for (unsigned i = 0; i < jsString->m_ ropeLength; ++i)351 for (unsigned i = 0; i < jsString->m_fiberCount; ++i) 321 352 m_fibers[index++] = jsString->m_fibers[i].ref(); 322 353 } else … … 329 360 ASSERT(asCell(v)->isString()); 330 361 JSString* s = static_cast<JSString*>(asCell(v)); 331 ASSERT(s-> ropeLength() == 1);362 ASSERT(s->fiberCount() == 1); 332 363 appendStringInConstruct(index, s); 333 m_ stringLength += s->length();364 m_length += s->length(); 334 365 } else { 335 366 UString u(v.toString(exec)); 336 367 m_fibers[index++] = Rope::Fiber(u.rep()->ref()); 337 m_ stringLength += u.size();368 m_length += u.size(); 338 369 } 339 370 } … … 358 389 359 390 // A string is represented either by a UString or a Rope. 360 unsigned m_ stringLength;391 unsigned m_length; 361 392 mutable UString m_value; 362 mutable unsigned m_ ropeLength;393 mutable unsigned m_fiberCount; 363 394 mutable Rope::Fiber m_fibers[s_maxInternalRopeLength]; 364 395 365 bool isRope() const { return m_ ropeLength; }396 bool isRope() const { return m_fiberCount; } 366 397 UString& string() { ASSERT(!isRope()); return m_value; } 367 unsigned ropeLength() { return m_ropeLength ? m_ropeLength: 1; }398 unsigned fiberCount() { return m_fiberCount ? m_fiberCount : 1; } 368 399 369 400 friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2); … … 494 525 { 495 526 if (propertyName == exec->propertyNames().length) { 496 slot.setValue(jsNumber(exec, m_ stringLength));527 slot.setValue(jsNumber(exec, m_length)); 497 528 return true; 498 529 } … … 500 531 bool isStrictUInt32; 501 532 unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); 502 if (isStrictUInt32 && i < m_ stringLength) {533 if (isStrictUInt32 && i < m_length) { 503 534 slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i)); 504 535 return true; … … 510 541 ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) 511 542 { 512 if (propertyName < m_ stringLength) {543 if (propertyName < m_length) { 513 544 slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName)); 514 545 return true; -
trunk/JavaScriptCore/runtime/Operations.h
r54394 r54804 43 43 return s1; 44 44 45 unsigned ropeLength = s1->ropeLength() + s2->ropeLength();45 unsigned fiberCount = s1->fiberCount() + s2->fiberCount(); 46 46 JSGlobalData* globalData = &exec->globalData(); 47 47 48 if (ropeLength <= JSString::s_maxInternalRopeLength) 49 return new (globalData) JSString(globalData, ropeLength, s1, s2); 50 51 unsigned index = 0; 52 RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); 53 if (UNLIKELY(!rope)) 48 if (fiberCount <= JSString::s_maxInternalRopeLength) 49 return new (globalData) JSString(globalData, fiberCount, s1, s2); 50 51 JSString::RopeBuilder ropeBuilder(fiberCount); 52 if (UNLIKELY(ropeBuilder.isOutOfMemory())) 54 53 return throwOutOfMemoryError(exec); 55 rope->append(index, s1); 56 rope->append(index, s2); 57 ASSERT(index == ropeLength); 58 return new (globalData) JSString(globalData, rope.release()); 54 ropeBuilder.append(s1); 55 ropeBuilder.append(s2); 56 return new (globalData) JSString(globalData, ropeBuilder.release()); 59 57 } 60 58 61 59 ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2) 62 60 { 63 unsigned ropeLength = 1 + s2->ropeLength();61 unsigned fiberCount = 1 + s2->fiberCount(); 64 62 JSGlobalData* globalData = &exec->globalData(); 65 63 66 if (ropeLength <= JSString::s_maxInternalRopeLength) 67 return new (globalData) JSString(globalData, ropeLength, u1, s2); 68 69 unsigned index = 0; 70 RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); 71 if (UNLIKELY(!rope)) 64 if (fiberCount <= JSString::s_maxInternalRopeLength) 65 return new (globalData) JSString(globalData, fiberCount, u1, s2); 66 67 JSString::RopeBuilder ropeBuilder(fiberCount); 68 if (UNLIKELY(ropeBuilder.isOutOfMemory())) 72 69 return throwOutOfMemoryError(exec); 73 rope->append(index, u1); 74 rope->append(index, s2); 75 ASSERT(index == ropeLength); 76 return new (globalData) JSString(globalData, rope.release()); 70 ropeBuilder.append(u1); 71 ropeBuilder.append(s2); 72 return new (globalData) JSString(globalData, ropeBuilder.release()); 77 73 } 78 74 79 75 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2) 80 76 { 81 unsigned ropeLength = s1->ropeLength() + 1;77 unsigned fiberCount = s1->fiberCount() + 1; 82 78 JSGlobalData* globalData = &exec->globalData(); 83 79 84 if (ropeLength <= JSString::s_maxInternalRopeLength) 85 return new (globalData) JSString(globalData, ropeLength, s1, u2); 86 87 unsigned index = 0; 88 RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); 89 if (UNLIKELY(!rope)) 80 if (fiberCount <= JSString::s_maxInternalRopeLength) 81 return new (globalData) JSString(globalData, fiberCount, s1, u2); 82 83 JSString::RopeBuilder ropeBuilder(fiberCount); 84 if (UNLIKELY(ropeBuilder.isOutOfMemory())) 90 85 return throwOutOfMemoryError(exec); 91 rope->append(index, s1); 92 rope->append(index, u2); 93 ASSERT(index == ropeLength); 94 return new (globalData) JSString(globalData, rope.release()); 86 ropeBuilder.append(s1); 87 ropeBuilder.append(u2); 88 return new (globalData) JSString(globalData, ropeBuilder.release()); 95 89 } 96 90 … … 99 93 ASSERT(count >= 3); 100 94 101 unsigned ropeLength= 0;95 unsigned fiberCount = 0; 102 96 for (unsigned i = 0; i < count; ++i) { 103 97 JSValue v = strings[i].jsValue(); 104 98 if (LIKELY(v.isString())) 105 ropeLength += asString(v)->ropeLength();99 fiberCount += asString(v)->fiberCount(); 106 100 else 107 ++ ropeLength;101 ++fiberCount; 108 102 } 109 103 110 104 JSGlobalData* globalData = &exec->globalData(); 111 if ( ropeLength== 3)105 if (fiberCount == 3) 112 106 return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue()); 113 107 114 RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);115 if (UNLIKELY( !rope))108 JSString::RopeBuilder ropeBuilder(fiberCount); 109 if (UNLIKELY(ropeBuilder.isOutOfMemory())) 116 110 return throwOutOfMemoryError(exec); 117 111 118 unsigned index = 0;119 112 for (unsigned i = 0; i < count; ++i) { 120 113 JSValue v = strings[i].jsValue(); 121 114 if (LIKELY(v.isString())) 122 rope ->append(index,asString(v));115 ropeBuilder.append(asString(v)); 123 116 else 124 rope->append(index, v.toString(exec)); 125 } 126 127 ASSERT(index == ropeLength); 128 return new (globalData) JSString(globalData, rope.release()); 117 ropeBuilder.append(v.toString(exec)); 118 } 119 120 return new (globalData) JSString(globalData, ropeBuilder.release()); 129 121 } 130 122 131 123 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args) 132 124 { 133 unsigned ropeLength= 0;125 unsigned fiberCount = 0; 134 126 if (LIKELY(thisValue.isString())) 135 ropeLength += asString(thisValue)->ropeLength();127 fiberCount += asString(thisValue)->fiberCount(); 136 128 else 137 ++ ropeLength;129 ++fiberCount; 138 130 for (unsigned i = 0; i < args.size(); ++i) { 139 131 JSValue v = args.at(i); 140 132 if (LIKELY(v.isString())) 141 ropeLength += asString(v)->ropeLength();133 fiberCount += asString(v)->fiberCount(); 142 134 else 143 ++ ropeLength;144 } 145 146 RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);147 if (UNLIKELY( !rope))135 ++fiberCount; 136 } 137 138 JSString::RopeBuilder ropeBuilder(fiberCount); 139 if (UNLIKELY(ropeBuilder.isOutOfMemory())) 148 140 return throwOutOfMemoryError(exec); 149 141 150 unsigned index = 0;151 142 if (LIKELY(thisValue.isString())) 152 rope ->append(index,asString(thisValue));143 ropeBuilder.append(asString(thisValue)); 153 144 else 154 rope ->append(index,thisValue.toString(exec));145 ropeBuilder.append(thisValue.toString(exec)); 155 146 for (unsigned i = 0; i < args.size(); ++i) { 156 147 JSValue v = args.at(i); 157 148 if (LIKELY(v.isString())) 158 rope ->append(index,asString(v));149 ropeBuilder.append(asString(v)); 159 150 else 160 rope->append(index, v.toString(exec)); 161 } 162 ASSERT(index == ropeLength); 151 ropeBuilder.append(v.toString(exec)); 152 } 163 153 164 154 JSGlobalData* globalData = &exec->globalData(); 165 return new (globalData) JSString(globalData, rope .release());155 return new (globalData) JSString(globalData, ropeBuilder.release()); 166 156 } 167 157
Note:
See TracChangeset
for help on using the changeset viewer.