LCOV - code coverage report
Current view: top level - src/objects - string-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 201 220 91.4 %
Date: 2017-10-20 Functions: 50 65 76.9 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_OBJECTS_STRING_INL_H_
       6             : #define V8_OBJECTS_STRING_INL_H_
       7             : 
       8             : #include "src/objects/string.h"
       9             : 
      10             : #include "src/conversions-inl.h"
      11             : #include "src/factory.h"
      12             : #include "src/objects/name-inl.h"
      13             : #include "src/string-hasher-inl.h"
      14             : 
      15             : // Has to be the last include (doesn't have include guards):
      16             : #include "src/objects/object-macros.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21 11339522005 : SMI_ACCESSORS(String, length, kLengthOffset)
      22   504481637 : SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset)
      23             : 
      24             : CAST_ACCESSOR(ConsString)
      25             : CAST_ACCESSOR(ExternalOneByteString)
      26             : CAST_ACCESSOR(ExternalString)
      27             : CAST_ACCESSOR(ExternalTwoByteString)
      28             : CAST_ACCESSOR(SeqOneByteString)
      29             : CAST_ACCESSOR(SeqString)
      30             : CAST_ACCESSOR(SeqTwoByteString)
      31             : CAST_ACCESSOR(SlicedString)
      32             : CAST_ACCESSOR(String)
      33             : CAST_ACCESSOR(ThinString)
      34             : 
      35  1082400573 : StringShape::StringShape(const String* str)
      36  1524864212 :     : type_(str->map()->instance_type()) {
      37             :   set_valid();
      38             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      39  1082400573 : }
      40             : 
      41             : StringShape::StringShape(Map* map) : type_(map->instance_type()) {
      42             :   set_valid();
      43             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      44             : }
      45             : 
      46         682 : StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) {
      47             :   set_valid();
      48             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      49             : }
      50             : 
      51             : bool StringShape::IsInternalized() {
      52             :   DCHECK(valid());
      53             :   STATIC_ASSERT(kNotInternalizedTag != 0);
      54           0 :   return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
      55             :          (kStringTag | kInternalizedTag);
      56             : }
      57             : 
      58             : bool StringShape::HasOnlyOneByteChars() {
      59       47085 :   return (type_ & kStringEncodingMask) == kOneByteStringTag ||
      60       47085 :          (type_ & kOneByteDataHintMask) == kOneByteDataHintTag;
      61             : }
      62             : 
      63    62333041 : bool StringShape::IsCons() {
      64    91351601 :   return (type_ & kStringRepresentationMask) == kConsStringTag;
      65             : }
      66             : 
      67   185698158 : bool StringShape::IsThin() {
      68   186297056 :   return (type_ & kStringRepresentationMask) == kThinStringTag;
      69             : }
      70             : 
      71     3714281 : bool StringShape::IsSliced() {
      72     4313179 :   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
      73             : }
      74             : 
      75             : bool StringShape::IsIndirect() {
      76         664 :   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
      77             : }
      78             : 
      79    97597086 : bool StringShape::IsExternal() {
      80    97754788 :   return (type_ & kStringRepresentationMask) == kExternalStringTag;
      81             : }
      82             : 
      83    84409179 : bool StringShape::IsSequential() {
      84    84413129 :   return (type_ & kStringRepresentationMask) == kSeqStringTag;
      85             : }
      86             : 
      87             : StringRepresentationTag StringShape::representation_tag() {
      88   342621347 :   uint32_t tag = (type_ & kStringRepresentationMask);
      89             :   return static_cast<StringRepresentationTag>(tag);
      90             : }
      91             : 
      92   114300301 : uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; }
      93             : 
      94   648648885 : uint32_t StringShape::full_representation_tag() {
      95   945254810 :   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
      96             : }
      97             : 
      98             : STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
      99             :               Internals::kFullStringRepresentationMask);
     100             : 
     101             : STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
     102             :               Internals::kStringEncodingMask);
     103             : 
     104             : bool StringShape::IsSequentialOneByte() {
     105             :   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
     106             : }
     107             : 
     108             : bool StringShape::IsSequentialTwoByte() {
     109             :   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
     110             : }
     111             : 
     112             : bool StringShape::IsExternalOneByte() {
     113          67 :   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
     114             : }
     115             : 
     116             : STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
     117             :               Internals::kExternalOneByteRepresentationTag);
     118             : 
     119             : STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
     120             : 
     121             : bool StringShape::IsExternalTwoByte() {
     122         107 :   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
     123             : }
     124             : 
     125             : STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
     126             :               Internals::kExternalTwoByteRepresentationTag);
     127             : 
     128             : STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
     129             : 
     130    72036850 : bool String::IsOneByteRepresentation() const {
     131             :   uint32_t type = map()->instance_type();
     132   174168169 :   return (type & kStringEncodingMask) == kOneByteStringTag;
     133             : }
     134             : 
     135       94667 : bool String::IsTwoByteRepresentation() const {
     136             :   uint32_t type = map()->instance_type();
     137       94719 :   return (type & kStringEncodingMask) == kTwoByteStringTag;
     138             : }
     139             : 
     140     6504088 : bool String::IsOneByteRepresentationUnderneath() {
     141             :   uint32_t type = map()->instance_type();
     142             :   STATIC_ASSERT(kIsIndirectStringTag != 0);
     143             :   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
     144             :   DCHECK(IsFlat());
     145     6504088 :   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
     146             :     case kOneByteStringTag:
     147             :       return true;
     148             :     case kTwoByteStringTag:
     149     2962646 :       return false;
     150             :     default:  // Cons or sliced string.  Need to go deeper.
     151        8194 :       return GetUnderlying()->IsOneByteRepresentation();
     152             :   }
     153             : }
     154             : 
     155             : bool String::IsTwoByteRepresentationUnderneath() {
     156             :   uint32_t type = map()->instance_type();
     157             :   STATIC_ASSERT(kIsIndirectStringTag != 0);
     158             :   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
     159             :   DCHECK(IsFlat());
     160             :   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
     161             :     case kOneByteStringTag:
     162             :       return false;
     163             :     case kTwoByteStringTag:
     164             :       return true;
     165             :     default:  // Cons or sliced string.  Need to go deeper.
     166             :       return GetUnderlying()->IsTwoByteRepresentation();
     167             :   }
     168             : }
     169             : 
     170    13038698 : bool String::HasOnlyOneByteChars() {
     171             :   uint32_t type = map()->instance_type();
     172    26077272 :   return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
     173    13038698 :          IsOneByteRepresentation();
     174             : }
     175             : 
     176   431727355 : uc32 FlatStringReader::Get(int index) {
     177   431727355 :   if (is_one_byte_) {
     178   430823196 :     return Get<uint8_t>(index);
     179             :   } else {
     180      904159 :     return Get<uc16>(index);
     181             :   }
     182             : }
     183             : 
     184             : template <typename Char>
     185  2710312250 : Char FlatStringReader::Get(int index) {
     186             :   DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
     187             :   DCHECK(0 <= index && index <= length_);
     188             :   if (sizeof(Char) == 1) {
     189  3141117459 :     return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
     190             :   } else {
     191      922146 :     return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
     192             :   }
     193             : }
     194             : 
     195             : template <typename Char>
     196           0 : class SequentialStringKey : public StringTableKey {
     197             :  public:
     198      168429 :   explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
     199             :       : StringTableKey(StringHasher::HashSequentialString<Char>(
     200             :             string.start(), string.length(), seed)),
     201      505287 :         string_(string) {}
     202             : 
     203             :   Vector<const Char> string_;
     204             : };
     205             : 
     206           0 : class OneByteStringKey : public SequentialStringKey<uint8_t> {
     207             :  public:
     208             :   OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
     209      168429 :       : SequentialStringKey<uint8_t>(str, seed) {}
     210             : 
     211      183775 :   bool IsMatch(Object* string) override {
     212      183775 :     return String::cast(string)->IsOneByteEqualTo(string_);
     213             :   }
     214             : 
     215             :   Handle<String> AsHandle(Isolate* isolate) override;
     216             : };
     217             : 
     218           0 : class SeqOneByteSubStringKey : public StringTableKey {
     219             :  public:
     220             : // VS 2017 on official builds gives this spurious warning:
     221             : // warning C4789: buffer 'key' of size 16 bytes will be overrun; 4 bytes will
     222             : // be written starting at offset 16
     223             : // https://bugs.chromium.org/p/v8/issues/detail?id=6068
     224             : #if defined(V8_CC_MSVC)
     225             : #pragma warning(push)
     226             : #pragma warning(disable : 4789)
     227             : #endif
     228      112004 :   SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length)
     229             :       : StringTableKey(StringHasher::HashSequentialString(
     230      112004 :             string->GetChars() + from, length, string->GetHeap()->HashSeed())),
     231             :         string_(string),
     232             :         from_(from),
     233      224008 :         length_(length) {
     234             :     DCHECK_LE(0, length_);
     235             :     DCHECK_LE(from_ + length_, string_->length());
     236             :     DCHECK(string_->IsSeqOneByteString());
     237      112004 :   }
     238             : #if defined(V8_CC_MSVC)
     239             : #pragma warning(pop)
     240             : #endif
     241             : 
     242             :   bool IsMatch(Object* string) override;
     243             :   Handle<String> AsHandle(Isolate* isolate) override;
     244             : 
     245             :  private:
     246             :   Handle<SeqOneByteString> string_;
     247             :   int from_;
     248             :   int length_;
     249             : };
     250             : 
     251           0 : class TwoByteStringKey : public SequentialStringKey<uc16> {
     252             :  public:
     253             :   explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
     254           0 :       : SequentialStringKey<uc16>(str, seed) {}
     255             : 
     256           0 :   bool IsMatch(Object* string) override {
     257           0 :     return String::cast(string)->IsTwoByteEqualTo(string_);
     258             :   }
     259             : 
     260             :   Handle<String> AsHandle(Isolate* isolate) override;
     261             : };
     262             : 
     263             : // Utf8StringKey carries a vector of chars as key.
     264           0 : class Utf8StringKey : public StringTableKey {
     265             :  public:
     266    16790285 :   explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
     267             :       : StringTableKey(StringHasher::ComputeUtf8Hash(string, seed, &chars_)),
     268    33580570 :         string_(string) {}
     269             : 
     270    25797661 :   bool IsMatch(Object* string) override {
     271    25797661 :     return String::cast(string)->IsUtf8EqualTo(string_);
     272             :   }
     273             : 
     274      192006 :   Handle<String> AsHandle(Isolate* isolate) override {
     275             :     return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
     276      192006 :                                                              HashField());
     277             :   }
     278             : 
     279             :  private:
     280             :   Vector<const char> string_;
     281             :   int chars_;  // Caches the number of characters when computing the hash code.
     282             : };
     283             : 
     284    36754801 : bool String::Equals(String* other) {
     285    36754801 :   if (other == this) return true;
     286    61392743 :   if (this->IsInternalizedString() && other->IsInternalizedString()) {
     287             :     return false;
     288             :   }
     289     2928632 :   return SlowEquals(other);
     290             : }
     291             : 
     292     4712123 : bool String::Equals(Handle<String> one, Handle<String> two) {
     293     4712123 :   if (one.is_identical_to(two)) return true;
     294     4931368 :   if (one->IsInternalizedString() && two->IsInternalizedString()) {
     295             :     return false;
     296             :   }
     297     4313882 :   return SlowEquals(one, two);
     298             : }
     299             : 
     300    51938116 : Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
     301    51938117 :   if (string->IsConsString()) {
     302             :     Handle<ConsString> cons = Handle<ConsString>::cast(string);
     303     4179541 :     if (cons->IsFlat()) {
     304             :       string = handle(cons->first());
     305             :     } else {
     306     4013358 :       return SlowFlatten(cons, pretenure);
     307             :     }
     308             :   }
     309    47924756 :   if (string->IsThinString()) {
     310             :     string = handle(Handle<ThinString>::cast(string)->actual());
     311             :     DCHECK(!string->IsConsString());
     312             :   }
     313    47924756 :   return string;
     314             : }
     315             : 
     316             : uint16_t String::Get(int index) {
     317             :   DCHECK(index >= 0 && index < length());
     318   648648895 :   switch (StringShape(this).full_representation_tag()) {
     319             :     case kSeqStringTag | kOneByteStringTag:
     320   410160658 :       return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
     321             :     case kSeqStringTag | kTwoByteStringTag:
     322   231332106 :       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
     323             :     case kConsStringTag | kOneByteStringTag:
     324             :     case kConsStringTag | kTwoByteStringTag:
     325     2576397 :       return ConsString::cast(this)->ConsStringGet(index);
     326             :     case kExternalStringTag | kOneByteStringTag:
     327     3283400 :       return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index);
     328             :     case kExternalStringTag | kTwoByteStringTag:
     329       56184 :       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
     330             :     case kSlicedStringTag | kOneByteStringTag:
     331             :     case kSlicedStringTag | kTwoByteStringTag:
     332     1237991 :       return SlicedString::cast(this)->SlicedStringGet(index);
     333             :     case kThinStringTag | kOneByteStringTag:
     334             :     case kThinStringTag | kTwoByteStringTag:
     335        2158 :       return ThinString::cast(this)->ThinStringGet(index);
     336             :     default:
     337             :       break;
     338             :   }
     339             : 
     340           0 :   UNREACHABLE();
     341             : }
     342             : 
     343             : void String::Set(int index, uint16_t value) {
     344             :   DCHECK(index >= 0 && index < length());
     345             :   DCHECK(StringShape(this).IsSequential());
     346             : 
     347             :   return this->IsOneByteRepresentation()
     348             :              ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
     349             :              : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
     350             : }
     351             : 
     352     6148391 : bool String::IsFlat() {
     353     6148391 :   if (!StringShape(this).IsCons()) return true;
     354     6096284 :   return ConsString::cast(this)->second()->length() == 0;
     355             : }
     356             : 
     357             : String* String::GetUnderlying() {
     358             :   // Giving direct access to underlying string only makes sense if the
     359             :   // wrapping string is already flattened.
     360             :   DCHECK(this->IsFlat());
     361             :   DCHECK(StringShape(this).IsIndirect());
     362             :   STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
     363             :   STATIC_ASSERT(ConsString::kFirstOffset == ThinString::kActualOffset);
     364             :   const int kUnderlyingOffset = SlicedString::kParentOffset;
     365        8194 :   return String::cast(READ_FIELD(this, kUnderlyingOffset));
     366             : }
     367             : 
     368             : template <class Visitor>
     369   139634545 : ConsString* String::VisitFlat(Visitor* visitor, String* string,
     370             :                               const int offset) {
     371             :   int slice_offset = offset;
     372             :   const int length = string->length();
     373             :   DCHECK(offset <= length);
     374             :   while (true) {
     375             :     int32_t type = string->map()->instance_type();
     376   145862814 :     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
     377             :       case kSeqStringTag | kOneByteStringTag:
     378   245645136 :         visitor->VisitOneByteString(
     379   122822568 :             SeqOneByteString::cast(string)->GetChars() + slice_offset,
     380             :             length - offset);
     381   122822695 :         return nullptr;
     382             : 
     383             :       case kSeqStringTag | kTwoByteStringTag:
     384    13843832 :         visitor->VisitTwoByteString(
     385     6921916 :             SeqTwoByteString::cast(string)->GetChars() + slice_offset,
     386             :             length - offset);
     387     6921916 :         return nullptr;
     388             : 
     389             :       case kExternalStringTag | kOneByteStringTag:
     390     5266956 :         visitor->VisitOneByteString(
     391             :             ExternalOneByteString::cast(string)->GetChars() + slice_offset,
     392             :             length - offset);
     393     2633478 :         return nullptr;
     394             : 
     395             :       case kExternalStringTag | kTwoByteStringTag:
     396     4061508 :         visitor->VisitTwoByteString(
     397             :             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
     398             :             length - offset);
     399     2030754 :         return nullptr;
     400             : 
     401             :       case kSlicedStringTag | kOneByteStringTag:
     402             :       case kSlicedStringTag | kTwoByteStringTag: {
     403             :         SlicedString* slicedString = SlicedString::cast(string);
     404     6166086 :         slice_offset += slicedString->offset();
     405             :         string = slicedString->parent();
     406     6166086 :         continue;
     407             :       }
     408             : 
     409             :       case kConsStringTag | kOneByteStringTag:
     410             :       case kConsStringTag | kTwoByteStringTag:
     411       39610 :         return ConsString::cast(string);
     412             : 
     413             :       case kThinStringTag | kOneByteStringTag:
     414             :       case kThinStringTag | kTwoByteStringTag:
     415             :         string = ThinString::cast(string)->actual();
     416       62183 :         continue;
     417             : 
     418             :       default:
     419           0 :         UNREACHABLE();
     420             :     }
     421             :   }
     422             : }
     423             : 
     424             : template <>
     425             : inline Vector<const uint8_t> String::GetCharVector() {
     426     1380819 :   String::FlatContent flat = GetFlatContent();
     427             :   DCHECK(flat.IsOneByte());
     428     1380819 :   return flat.ToOneByteVector();
     429             : }
     430             : 
     431             : template <>
     432             : inline Vector<const uc16> String::GetCharVector() {
     433      903271 :   String::FlatContent flat = GetFlatContent();
     434             :   DCHECK(flat.IsTwoByte());
     435      903271 :   return flat.ToUC16Vector();
     436             : }
     437             : 
     438         333 : uint32_t String::ToValidIndex(Object* number) {
     439        5774 :   uint32_t index = PositiveNumberToUint32(number);
     440        5774 :   uint32_t length_value = static_cast<uint32_t>(length());
     441        5774 :   if (index > length_value) return length_value;
     442         324 :   return index;
     443             : }
     444             : 
     445  1620151626 : uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
     446             :   DCHECK(index >= 0 && index < length());
     447  1682649569 :   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
     448             : }
     449             : 
     450  2892461271 : void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
     451             :   DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
     452  3671834585 :   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
     453  3671834585 :                    static_cast<byte>(value));
     454  2892461271 : }
     455             : 
     456             : Address SeqOneByteString::GetCharsAddress() {
     457             :   return FIELD_ADDR(this, kHeaderSize);
     458             : }
     459             : 
     460       33311 : uint8_t* SeqOneByteString::GetChars() {
     461       33311 :   return reinterpret_cast<uint8_t*>(GetCharsAddress());
     462             : }
     463             : 
     464             : Address SeqTwoByteString::GetCharsAddress() {
     465             :   return FIELD_ADDR(this, kHeaderSize);
     466             : }
     467             : 
     468       62573 : uc16* SeqTwoByteString::GetChars() {
     469       62573 :   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
     470             : }
     471             : 
     472   231332106 : uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
     473             :   DCHECK(index >= 0 && index < length());
     474   231332106 :   return READ_UINT16_FIELD(this, kHeaderSize + index * kShortSize);
     475             : }
     476             : 
     477     1526731 : void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
     478             :   DCHECK(index >= 0 && index < length());
     479    12783636 :   WRITE_UINT16_FIELD(this, kHeaderSize + index * kShortSize, value);
     480     1526731 : }
     481             : 
     482             : int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
     483             :   return SizeFor(length());
     484             : }
     485             : 
     486             : int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
     487             :   return SizeFor(length());
     488             : }
     489             : 
     490             : String* SlicedString::parent() {
     491    10158492 :   return String::cast(READ_FIELD(this, kParentOffset));
     492             : }
     493             : 
     494     2144506 : void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
     495             :   DCHECK(parent->IsSeqString() || parent->IsExternalString());
     496     2144506 :   WRITE_FIELD(this, kParentOffset, parent);
     497     8578024 :   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
     498     2144506 : }
     499             : 
     500    12302973 : SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
     501             : 
     502             : String* ConsString::first() {
     503  9998165938 :   return String::cast(READ_FIELD(this, kFirstOffset));
     504             : }
     505             : 
     506      639025 : Object* ConsString::unchecked_first() { return READ_FIELD(this, kFirstOffset); }
     507             : 
     508    20284898 : void ConsString::set_first(String* value, WriteBarrierMode mode) {
     509    20284898 :   WRITE_FIELD(this, kFirstOffset, value);
     510    36656570 :   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
     511    20284899 : }
     512             : 
     513             : String* ConsString::second() {
     514   181544223 :   return String::cast(READ_FIELD(this, kSecondOffset));
     515             : }
     516             : 
     517             : Object* ConsString::unchecked_second() {
     518    96273428 :   return RELAXED_READ_FIELD(this, kSecondOffset);
     519             : }
     520             : 
     521    20284899 : void ConsString::set_second(String* value, WriteBarrierMode mode) {
     522    20284899 :   WRITE_FIELD(this, kSecondOffset, value);
     523    36656574 :   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
     524    20284899 : }
     525             : 
     526    61508089 : ACCESSORS(ThinString, actual, String, kActualOffset);
     527             : 
     528             : bool ExternalString::is_short() {
     529             :   InstanceType type = map()->instance_type();
     530      590473 :   return (type & kShortExternalStringMask) == kShortExternalStringTag;
     531             : }
     532             : 
     533             : const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
     534     7130433 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
     535             : }
     536             : 
     537      571206 : void ExternalOneByteString::update_data_cache() {
     538     1142412 :   if (is_short()) return;
     539             :   const char** data_field =
     540             :       reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
     541        5848 :   *data_field = resource()->data();
     542             : }
     543             : 
     544             : void ExternalOneByteString::set_resource(
     545             :     const ExternalOneByteString::Resource* resource) {
     546             :   DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize));
     547             :   *reinterpret_cast<const Resource**>(FIELD_ADDR(this, kResourceOffset)) =
     548      571226 :       resource;
     549      571206 :   if (resource != nullptr) update_data_cache();
     550             : }
     551             : 
     552             : const uint8_t* ExternalOneByteString::GetChars() {
     553     6430338 :   return reinterpret_cast<const uint8_t*>(resource()->data());
     554             : }
     555             : 
     556     3283400 : uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
     557             :   DCHECK(index >= 0 && index < length());
     558     3283400 :   return GetChars()[index];
     559             : }
     560             : 
     561             : const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
     562     2391059 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
     563             : }
     564             : 
     565       19267 : void ExternalTwoByteString::update_data_cache() {
     566       38534 :   if (is_short()) return;
     567             :   const uint16_t** data_field =
     568             :       reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
     569       19144 :   *data_field = resource()->data();
     570             : }
     571             : 
     572             : void ExternalTwoByteString::set_resource(
     573             :     const ExternalTwoByteString::Resource* resource) {
     574             :   *reinterpret_cast<const Resource**>(FIELD_ADDR(this, kResourceOffset)) =
     575       19272 :       resource;
     576       19267 :   if (resource != nullptr) update_data_cache();
     577             : }
     578             : 
     579     2371848 : const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
     580             : 
     581       56184 : uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
     582             :   DCHECK(index >= 0 && index < length());
     583       56184 :   return GetChars()[index];
     584             : }
     585             : 
     586             : const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
     587             :     unsigned start) {
     588          62 :   return GetChars() + start;
     589             : }
     590             : 
     591    39915014 : int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
     592             : 
     593             : void ConsStringIterator::PushLeft(ConsString* string) {
     594  9839744380 :   frames_[depth_++ & kDepthMask] = string;
     595             : }
     596             : 
     597             : void ConsStringIterator::PushRight(ConsString* string) {
     598             :   // Inplace update.
     599    10482543 :   frames_[(depth_ - 1) & kDepthMask] = string;
     600             : }
     601             : 
     602             : void ConsStringIterator::AdjustMaximumDepth() {
     603    13237701 :   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
     604             : }
     605             : 
     606             : void ConsStringIterator::Pop() {
     607             :   DCHECK_GT(depth_, 0);
     608             :   DCHECK(depth_ <= maximum_depth_);
     609    31128641 :   depth_--;
     610             : }
     611             : 
     612  1036723502 : uint16_t StringCharacterStream::GetNext() {
     613             :   DCHECK(buffer8_ != nullptr && end_ != nullptr);
     614             :   // Advance cursor if needed.
     615  1036723502 :   if (buffer8_ == end_) HasMore();
     616             :   DCHECK(buffer8_ < end_);
     617  1036723502 :   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
     618             : }
     619             : 
     620           0 : StringCharacterStream::StringCharacterStream(String* string, int offset)
     621     5033190 :     : is_one_byte_(false) {
     622     5033190 :   Reset(string, offset);
     623           0 : }
     624             : 
     625     8227837 : void StringCharacterStream::Reset(String* string, int offset) {
     626     8227837 :   buffer8_ = nullptr;
     627     8227837 :   end_ = nullptr;
     628     8227837 :   ConsString* cons_string = String::VisitFlat(this, string, offset);
     629     8227838 :   iter_.Reset(cons_string, offset);
     630     8227838 :   if (cons_string != nullptr) {
     631       21374 :     string = iter_.Next(&offset);
     632       66838 :     if (string != nullptr) String::VisitFlat(this, string, offset);
     633             :   }
     634     8227838 : }
     635             : 
     636  1041535663 : bool StringCharacterStream::HasMore() {
     637  1041535663 :   if (buffer8_ != end_) return true;
     638             :   int offset;
     639    16012445 :   String* string = iter_.Next(&offset);
     640             :   DCHECK_EQ(offset, 0);
     641    16012445 :   if (string == nullptr) return false;
     642     9553127 :   String::VisitFlat(this, string);
     643             :   DCHECK(buffer8_ != end_);
     644     9553127 :   return true;
     645             : }
     646             : 
     647             : void StringCharacterStream::VisitOneByteString(const uint8_t* chars,
     648             :                                                int length) {
     649    13544118 :   is_one_byte_ = true;
     650    13544118 :   buffer8_ = chars;
     651    13544118 :   end_ = chars + length;
     652             : }
     653             : 
     654             : void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
     655             :                                                int length) {
     656     4236702 :   is_one_byte_ = false;
     657     4236702 :   buffer16_ = chars;
     658     4236702 :   end_ = reinterpret_cast<const uint8_t*>(chars + length);
     659             : }
     660             : 
     661   100641429 : bool String::AsArrayIndex(uint32_t* index) {
     662             :   uint32_t field = hash_field();
     663   100641429 :   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
     664             :     return false;
     665             :   }
     666    12573935 :   return SlowAsArrayIndex(index);
     667             : }
     668             : 
     669             : void String::SetForwardedInternalizedString(String* canonical) {
     670             :   DCHECK(IsInternalizedString());
     671             :   DCHECK(HasHashCode());
     672        2420 :   if (canonical == this) return;  // No need to forward.
     673             :   DCHECK(SlowEquals(canonical));
     674             :   DCHECK(canonical->IsInternalizedString());
     675             :   DCHECK(canonical->HasHashCode());
     676        2420 :   WRITE_FIELD(this, kHashFieldSlot, canonical);
     677             :   // Setting the hash field to a tagged value sets the LSB, causing the hash
     678             :   // code to be interpreted as uninitialized.  We use this fact to recognize
     679             :   // that we have a forwarded string.
     680             :   DCHECK(!HasHashCode());
     681             : }
     682             : 
     683             : String* String::GetForwardedInternalizedString() {
     684             :   DCHECK(IsInternalizedString());
     685        9077 :   if (HasHashCode()) return this;
     686        1715 :   String* canonical = String::cast(READ_FIELD(this, kHashFieldSlot));
     687             :   DCHECK(canonical->IsInternalizedString());
     688             :   DCHECK(SlowEquals(canonical));
     689             :   DCHECK(canonical->HasHashCode());
     690             :   return canonical;
     691             : }
     692             : 
     693             : String::SubStringRange::SubStringRange(String* string, int first, int length)
     694             :     : string_(string),
     695             :       first_(first),
     696           0 :       length_(length == -1 ? string->length() : length) {}
     697             : 
     698             : class String::SubStringRange::iterator final {
     699             :  public:
     700             :   typedef std::forward_iterator_tag iterator_category;
     701             :   typedef int difference_type;
     702             :   typedef uc16 value_type;
     703             :   typedef uc16* pointer;
     704             :   typedef uc16& reference;
     705             : 
     706             :   iterator(const iterator& other)
     707             :       : content_(other.content_), offset_(other.offset_) {}
     708             : 
     709           0 :   uc16 operator*() { return content_.Get(offset_); }
     710             :   bool operator==(const iterator& other) const {
     711             :     return content_.UsesSameString(other.content_) && offset_ == other.offset_;
     712             :   }
     713             :   bool operator!=(const iterator& other) const {
     714           0 :     return !content_.UsesSameString(other.content_) || offset_ != other.offset_;
     715             :   }
     716             :   iterator& operator++() {
     717           0 :     ++offset_;
     718             :     return *this;
     719             :   }
     720             :   iterator operator++(int);
     721             : 
     722             :  private:
     723             :   friend class String;
     724             :   iterator(String* from, int offset)
     725           0 :       : content_(from->GetFlatContent()), offset_(offset) {}
     726             :   String::FlatContent content_;
     727             :   int offset_;
     728             : };
     729             : 
     730             : String::SubStringRange::iterator String::SubStringRange::begin() {
     731             :   return String::SubStringRange::iterator(string_, first_);
     732             : }
     733             : 
     734             : String::SubStringRange::iterator String::SubStringRange::end() {
     735           0 :   return String::SubStringRange::iterator(string_, first_ + length_);
     736             : }
     737             : 
     738             : }  // namespace internal
     739             : }  // namespace v8
     740             : 
     741             : #include "src/objects/object-macros-undef.h"
     742             : 
     743             : #endif  // V8_OBJECTS_STRING_INL_H_

Generated by: LCOV version 1.10