Changeset 97827 in webkit for trunk/Source/JavaScriptCore/runtime/JSString.h
- Timestamp:
- Oct 18, 2011, 7:54:29 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/JSString.h
r97537 r97827 60 60 JSString* jsOwnedString(ExecState*, const UString&); 61 61 62 JSString* jsStringBuilder(JSGlobalData*); 63 62 64 class JS_EXPORTCLASS JSString : public JSCell { 63 65 public: … … 66 68 friend class SpecializedThunkJIT; 67 69 friend struct ThunkHelpers; 70 friend JSString* jsStringBuilder(JSGlobalData*); 68 71 69 72 typedef JSCell Base; … … 71 74 class RopeBuilder { 72 75 public: 73 RopeBuilder( unsigned fiberCount)74 : m_ index(0)75 , m_ rope(RopeImpl::tryCreateUninitialized(fiberCount))76 RopeBuilder(JSGlobalData& globalData) 77 : m_globalData(globalData) 78 , m_jsString(jsStringBuilder(&globalData)) 76 79 { 77 80 } 78 81 79 bool isOutOfMemory() { return !m_rope; }80 81 void append(RopeImpl::Fiber& fiber)82 {83 ASSERT(m_rope);84 m_rope->initializeFiber(m_index, fiber);85 }86 void append(const UString& string)87 {88 ASSERT(m_rope);89 m_rope->initializeFiber(m_index, string.impl());90 }91 82 void append(JSString* jsString) 92 83 { 93 if ( jsString->isRope()) {94 for (unsigned i = 0; i < jsString->m_fiberCount; ++i)95 append(jsString->m_fibers[i]);96 } else97 append(jsString->string());84 if (m_jsString->m_fiberCount == JSString::s_maxInternalRopeLength) 85 expand(); 86 m_jsString->m_fibers[m_jsString->m_fiberCount].set(m_globalData, m_jsString, jsString); 87 m_jsString->m_fiberCount += 1; 88 m_jsString->m_length += jsString->m_length; 98 89 } 99 90 100 PassRefPtr<RopeImpl>release()91 JSString* release() 101 92 { 102 ASSERT(m_index == m_rope->fiberCount()); 103 return m_rope.release(); 93 JSString* tmp = m_jsString; 94 m_jsString = 0; 95 return tmp; 104 96 } 105 97 106 unsigned length() { return m_ rope->length(); }98 unsigned length() { return m_jsString->m_length; } 107 99 108 100 private: 109 unsigned m_index; 110 RefPtr<RopeImpl> m_rope; 101 void expand(); 102 103 JSGlobalData& m_globalData; 104 JSString* m_jsString; 111 105 }; 112 106 113 class RopeIterator {114 public:115 RopeIterator() { }116 117 RopeIterator(RopeImpl::Fiber* fibers, size_t fiberCount)118 {119 ASSERT(fiberCount);120 m_workQueue.append(WorkItem(fibers, fiberCount));121 skipRopes();122 }123 124 RopeIterator& operator++()125 {126 WorkItem& item = m_workQueue.last();127 ASSERT(!RopeImpl::isRope(item.fibers[item.i]));128 if (++item.i == item.fiberCount)129 m_workQueue.removeLast();130 skipRopes();131 return *this;132 }133 134 StringImpl* operator*()135 {136 WorkItem& item = m_workQueue.last();137 RopeImpl::Fiber fiber = item.fibers[item.i];138 ASSERT(!RopeImpl::isRope(fiber));139 return static_cast<StringImpl*>(fiber);140 }141 142 bool operator!=(const RopeIterator& other) const143 {144 return m_workQueue != other.m_workQueue;145 }146 147 private:148 struct WorkItem {149 WorkItem(RopeImpl::Fiber* fibers, size_t fiberCount)150 : fibers(fibers)151 , fiberCount(fiberCount)152 , i(0)153 {154 }155 156 bool operator!=(const WorkItem& other) const157 {158 return fibers != other.fibers || fiberCount != other.fiberCount || i != other.i;159 }160 161 RopeImpl::Fiber* fibers;162 size_t fiberCount;163 size_t i;164 };165 166 void skipRopes()167 {168 if (m_workQueue.isEmpty())169 return;170 171 while (1) {172 WorkItem& item = m_workQueue.last();173 RopeImpl::Fiber fiber = item.fibers[item.i];174 if (!RopeImpl::isRope(fiber))175 break;176 RopeImpl* rope = static_cast<RopeImpl*>(fiber);177 if (++item.i == item.fiberCount)178 m_workQueue.removeLast();179 m_workQueue.append(WorkItem(rope->fibers(), rope->fiberCount()));180 }181 }182 183 Vector<WorkItem, 16> m_workQueue;184 };185 186 107 private: 187 ALWAYS_INLINE JSString(JSGlobalData& globalData, const UString&value)108 JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value) 188 109 : JSCell(globalData, globalData.stringStructure.get()) 189 , m_length(value.length())190 110 , m_value(value) 191 111 , m_fiberCount(0) … … 193 113 } 194 114 195 enum HasOtherOwnerType { HasOtherOwner }; 196 JSString(JSGlobalData& globalData, const UString& value, HasOtherOwnerType) 115 JSString(JSGlobalData& globalData) 197 116 : JSCell(globalData, globalData.stringStructure.get()) 198 , m_length(value.length())199 , m_value(value)200 117 , m_fiberCount(0) 201 118 { 202 119 } 203 JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType) 204 : JSCell(globalData, globalData.stringStructure.get()) 205 , m_length(value->length()) 206 , m_value(value) 207 , m_fiberCount(0) 208 { 209 } 210 JSString(JSGlobalData& globalData, PassRefPtr<RopeImpl> rope) 211 : JSCell(globalData, globalData.stringStructure.get()) 212 , m_length(rope->length()) 213 , m_fiberCount(1) 214 { 215 } 216 // This constructor constructs a new string by concatenating s1 & s2. 217 // This should only be called with fiberCount <= 3. 218 JSString(JSGlobalData& globalData, unsigned fiberCount, JSString* s1, JSString* s2) 219 : JSCell(globalData, globalData.stringStructure.get()) 220 , m_length(s1->length() + s2->length()) 221 , m_fiberCount(fiberCount) 222 { 223 } 224 // This constructor constructs a new string by concatenating s1 & s2. 225 // This should only be called with fiberCount <= 3. 226 JSString(JSGlobalData& globalData, unsigned fiberCount, JSString* s1, const UString& u2) 227 : JSCell(globalData, globalData.stringStructure.get()) 228 , m_length(s1->length() + u2.length()) 229 , m_fiberCount(fiberCount) 230 { 231 } 232 // This constructor constructs a new string by concatenating s1 & s2. 233 // This should only be called with fiberCount <= 3. 234 JSString(JSGlobalData& globalData, unsigned fiberCount, const UString& u1, JSString* s2) 235 : JSCell(globalData, globalData.stringStructure.get()) 236 , m_length(u1.length() + s2->length()) 237 , m_fiberCount(fiberCount) 238 { 239 } 240 JSString(ExecState* exec) 241 : JSCell(exec->globalData(), exec->globalData().stringStructure.get()) 242 , m_length(0) 243 , m_fiberCount(s_maxInternalRopeLength) 244 { 245 } 246 247 // This constructor constructs a new string by concatenating u1 & u2. 248 JSString(JSGlobalData& globalData, const UString& u1, const UString& u2) 249 : JSCell(globalData, globalData.stringStructure.get()) 250 , m_length(u1.length() + u2.length()) 251 , m_fiberCount(2) 252 { 253 } 254 255 // This constructor constructs a new string by concatenating u1, u2 & u3. 256 JSString(JSGlobalData& globalData, const UString& u1, const UString& u2, const UString& u3) 257 : JSCell(globalData, globalData.stringStructure.get()) 258 , m_length(u1.length() + u2.length() + u3.length()) 259 , m_fiberCount(s_maxInternalRopeLength) 260 { 261 } 262 263 void finishCreation(JSGlobalData& globalData, const UString& value) 120 121 void finishCreation(JSGlobalData& globalData) 264 122 { 265 123 Base::finishCreation(globalData); 124 m_length = 0; 125 } 126 127 void finishCreation(JSGlobalData& globalData, size_t length) 128 { 266 129 ASSERT(!m_value.isNull()); 267 Heap::heap(this)->reportExtraMemoryCost(value.impl()->cost());268 }269 270 void finishCreation(JSGlobalData& globalData)271 {272 130 Base::finishCreation(globalData); 131 m_length = length; 132 } 133 134 void finishCreation(JSGlobalData& globalData, size_t length, size_t cost) 135 { 273 136 ASSERT(!m_value.isNull()); 274 }275 276 void finishCreation(JSGlobalData& globalData, PassRefPtr<RopeImpl> rope)277 {278 137 Base::finishCreation(globalData); 279 m_fibers[0] = rope.leakRef(); 280 } 281 282 void finishCreation(JSGlobalData& globalData, unsigned fiberCount, JSString* s1, JSString* s2) 138 m_length = length; 139 Heap::heap(this)->reportExtraMemoryCost(cost); 140 } 141 142 void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) 283 143 { 284 144 Base::finishCreation(globalData); 285 ASSERT_UNUSED(fiberCount, fiberCount <= s_maxInternalRopeLength); 286 unsigned index = 0; 287 appendStringInCreate(index, s1); 288 appendStringInCreate(index, s2); 289 ASSERT(fiberCount == index); 290 } 291 292 void finishCreation(JSGlobalData& globalData, unsigned fiberCount, JSString* s1, const UString& u2) 145 m_length = s1->length() + s2->length(); 146 m_fiberCount = 2; 147 m_fibers[0].set(globalData, this, s1); 148 m_fibers[1].set(globalData, this, s2); 149 } 150 151 void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) 293 152 { 294 153 Base::finishCreation(globalData); 295 ASSERT_UNUSED(fiberCount, fiberCount <= s_maxInternalRopeLength); 296 unsigned index = 0; 297 appendStringInCreate(index, s1); 298 appendStringInCreate(index, u2); 299 ASSERT(fiberCount == index); 300 } 301 302 void finishCreation(JSGlobalData& globalData, unsigned fiberCount, const UString& u1, JSString* s2) 303 { 304 Base::finishCreation(globalData); 305 ASSERT_UNUSED(fiberCount, fiberCount <= s_maxInternalRopeLength); 306 unsigned index = 0; 307 appendStringInCreate(index, u1); 308 appendStringInCreate(index, s2); 309 ASSERT(fiberCount == index); 310 } 311 312 // Fills in the new string by concatenating v1, v2 & v3. 313 // This should only be called with fiberCount <= 3 ... which since every 314 // value must require a fiberCount of at least one implies that the length 315 // for each value must be exactly 1! 316 void finishCreation(ExecState* exec, JSValue v1, JSValue v2, JSValue v3) 317 { 318 Base::finishCreation(exec->globalData()); 319 unsigned index = 0; 320 appendValueInCreateAndIncrementLength(exec, index, v1); 321 appendValueInCreateAndIncrementLength(exec, index, v2); 322 appendValueInCreateAndIncrementLength(exec, index, v3); 323 ASSERT(index == s_maxInternalRopeLength); 324 } 325 326 void finishCreation(JSGlobalData& globalData, const UString& u1, const UString& u2) 327 { 328 Base::finishCreation(globalData); 329 unsigned index = 0; 330 appendStringInCreate(index, u1); 331 appendStringInCreate(index, u2); 332 ASSERT(index <= s_maxInternalRopeLength); 333 } 334 335 void finishCreation(JSGlobalData& globalData, const UString& u1, const UString& u2, const UString& u3) 336 { 337 Base::finishCreation(globalData); 338 unsigned index = 0; 339 appendStringInCreate(index, u1); 340 appendStringInCreate(index, u2); 341 appendStringInCreate(index, u3); 342 ASSERT(index <= s_maxInternalRopeLength); 343 } 344 345 public: 346 static JSString* create(JSGlobalData& globalData, const UString& value) 347 { 348 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, value); 349 newString->finishCreation(globalData, value); 350 return newString; 351 } 352 static JSString* createHasOtherOwner(JSGlobalData& globalData, const UString& value) 353 { 354 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, value, HasOtherOwner); 355 newString->finishCreation(globalData, value); 356 return newString; 357 } 358 static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value) 359 { 360 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, value, HasOtherOwner); 154 m_length = s1->length() + s2->length() + s3->length(); 155 m_fiberCount = 3; 156 m_fibers[0].set(globalData, this, s1); 157 m_fibers[1].set(globalData, this, s2); 158 m_fibers[2].set(globalData, this, s3); 159 } 160 161 static JSString* createNull(JSGlobalData& globalData) 162 { 163 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData); 361 164 newString->finishCreation(globalData); 362 165 return newString; 363 166 } 364 static JSString* create(JSGlobalData& globalData, PassRefPtr<RopeImpl> rope) 365 { 366 RefPtr<RopeImpl> tempRope = rope; 367 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, tempRope); 368 newString->finishCreation(globalData, tempRope); 167 168 public: 169 static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value) 170 { 171 ASSERT(value); 172 size_t length = value->length(); 173 size_t cost = value->cost(); 174 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, value); 175 newString->finishCreation(globalData, length, cost); 369 176 return newString; 370 177 } 371 static JSString* create(JSGlobalData& globalData, unsigned fiberCount,JSString* s1, JSString* s2)372 { 373 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData , fiberCount, s1, s2);374 newString->finishCreation(globalData, fiberCount,s1, s2);178 static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) 179 { 180 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData); 181 newString->finishCreation(globalData, s1, s2); 375 182 return newString; 376 183 } 377 static JSString* create(JSGlobalData& globalData, unsigned fiberCount, JSString* s1, const UString& u2)378 { 379 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData , fiberCount, s1, u2);380 newString->finishCreation(globalData, fiberCount, s1, u2);184 static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) 185 { 186 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData); 187 newString->finishCreation(globalData, s1, s2, s3); 381 188 return newString; 382 189 } 383 static JSString* create(JSGlobalData& globalData, unsigned fiberCount, const UString& u1, JSString* s2) 384 { 385 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, fiberCount, u1, s2); 386 newString->finishCreation(globalData, fiberCount, u1, s2); 190 static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value) 191 { 192 ASSERT(value); 193 size_t length = value->length(); 194 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, value); 195 newString->finishCreation(globalData, length); 387 196 return newString; 388 197 } 389 static JSString* create(ExecState* exec, JSValue v1, JSValue v2, JSValue v3) 390 { 391 JSString* newString = new (allocateCell<JSString>(*exec->heap())) JSString(exec); 392 newString->finishCreation(exec, v1, v2, v3); 393 return newString; 394 } 395 static JSString* create(JSGlobalData& globalData, const UString& u1, const UString& u2) 396 { 397 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, u1, u2); 398 newString->finishCreation(globalData, u1, u2); 399 return newString; 400 } 401 static JSString* create(JSGlobalData& globalData, const UString& u1, const UString& u2, const UString& u3) 402 { 403 JSString* newString = new (allocateCell<JSString>(globalData.heap)) JSString(globalData, u1, u2, u3); 404 newString->finishCreation(globalData, u1, u2, u3); 405 return newString; 406 } 407 408 ~JSString() 409 { 410 ASSERT(vptr() == JSGlobalData::jsStringVPtr); 411 for (unsigned i = 0; i < m_fiberCount; ++i) 412 RopeImpl::deref(m_fibers[i]); 413 } 198 199 virtual ~JSString(); 414 200 415 201 const UString& value(ExecState* exec) const … … 455 241 static const ClassInfo s_info; 456 242 243 static void visitChildren(JSCell*, SlotVisitor&); 244 457 245 private: 458 246 JSString(VPtrStealingHackType) … … 465 253 void resolveRopeSlowCase(ExecState*, UChar*) const; 466 254 void outOfMemory(ExecState*) const; 467 JSString* substringFromRope(ExecState*, unsigned offset, unsigned length);468 469 void appendStringInCreate(unsigned& index, const UString& string)470 {471 StringImpl* impl = string.impl();472 impl->ref();473 m_fibers[index++] = impl;474 Heap::heap(this)->reportExtraMemoryCost(string.impl()->cost());475 }476 477 void appendStringInCreate(unsigned& index, JSString* jsString)478 {479 if (jsString->isRope()) {480 for (unsigned i = 0; i < jsString->m_fiberCount; ++i) {481 RopeImpl::Fiber fiber = jsString->m_fibers[i];482 fiber->ref();483 m_fibers[index++] = fiber;484 }485 } else486 appendStringInCreate(index, jsString->string());487 }488 489 void appendValueInCreateAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)490 {491 if (v.isString()) {492 ASSERT(v.asCell()->isString());493 JSString* s = static_cast<JSString*>(v.asCell());494 ASSERT(s->fiberCount() == 1);495 appendStringInCreate(index, s);496 m_length += s->length();497 } else {498 UString u(v.toString(exec));499 StringImpl* impl = u.impl();500 impl->ref();501 m_fibers[index++] = impl;502 m_length += u.length();503 }504 }505 255 506 256 virtual JSObject* toThisObject(ExecState*) const; … … 519 269 mutable UString m_value; 520 270 mutable unsigned m_fiberCount; 521 mutable FixedArray< RopeImpl::Fiber, s_maxInternalRopeLength> m_fibers;271 mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers; 522 272 523 273 bool isRope() const { return m_fiberCount; } … … 526 276 527 277 friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2); 528 friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2);529 friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2);530 278 friend JSValue jsString(ExecState* exec, Register* strings, unsigned count); 531 279 friend JSValue jsString(ExecState* exec, JSValue thisValue); … … 560 308 if (c <= maxSingleCharacterString) 561 309 return globalData->smallStrings.singleCharacterString(globalData, c); 562 return fixupVPtr(globalData, JSString::create(*globalData, UString(&c, 1) ));310 return fixupVPtr(globalData, JSString::create(*globalData, UString(&c, 1).impl())); 563 311 } 564 312 … … 570 318 if (c <= maxSingleCharacterString) 571 319 return globalData->smallStrings.singleCharacterString(globalData, c); 572 return fixupVPtr(globalData, JSString::create(*globalData, UString(StringImpl::create(s.impl(), offset, 1))));320 return fixupVPtr(globalData, JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1))); 573 321 } 574 322 … … 578 326 ASSERT(s[0]); 579 327 ASSERT(s[1]); 580 return fixupVPtr(globalData, JSString::create(*globalData, s));328 return fixupVPtr(globalData, JSString::create(*globalData, UString(s).impl())); 581 329 } 582 330 … … 584 332 { 585 333 ASSERT(s.length() > 1); 586 return fixupVPtr(globalData, JSString::create(*globalData, s ));334 return fixupVPtr(globalData, JSString::create(*globalData, s.impl())); 587 335 } 588 336 … … 606 354 return globalData->smallStrings.singleCharacterString(globalData, c); 607 355 } 608 return fixupVPtr(globalData, JSString::create(*globalData, s ));356 return fixupVPtr(globalData, JSString::create(*globalData, s.impl())); 609 357 } 610 358 … … 617 365 if (!length) 618 366 return globalData->smallStrings.emptyString(globalData); 619 if (s->isRope()) 620 return s->substringFromRope(exec, offset, length); 621 return jsSubstring(globalData, s->m_value, offset, length); 367 return jsSubstring(globalData, s->value(exec), offset, length); 622 368 } 623 369 … … 634 380 return globalData->smallStrings.singleCharacterString(globalData, c); 635 381 } 636 return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, UString(StringImpl::create(s.impl(), offset, length))));382 return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length))); 637 383 } 638 384 … … 647 393 return globalData->smallStrings.singleCharacterString(globalData, c); 648 394 } 649 return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, s)); 395 return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, s.impl())); 396 } 397 398 inline JSString* jsStringBuilder(JSGlobalData* globalData) 399 { 400 return fixupVPtr(globalData, JSString::createNull(*globalData)); 650 401 } 651 402 … … 727 478 } 728 479 729 inline UString JSValue::toPrimitiveString(ExecState* exec) const730 {731 ASSERT(!isString());732 if (isInt32())733 return exec->globalData().numericStrings.add(asInt32());734 if (isDouble())735 return exec->globalData().numericStrings.add(asDouble());736 if (isTrue())737 return "true";738 if (isFalse())739 return "false";740 if (isNull())741 return "null";742 if (isUndefined())743 return "undefined";744 ASSERT(isCell());745 return asCell()->toPrimitive(exec, NoPreference).toString(exec);746 }747 748 480 } // namespace JSC 749 481
Note:
See TracChangeset
for help on using the changeset viewer.