LCOV - code coverage report
Current view: top level - src/objects - string-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 266 277 96.0 %
Date: 2019-01-20 Functions: 85 100 85.0 %

          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/handles-inl.h"
      12             : #include "src/heap/factory.h"
      13             : #include "src/objects/name-inl.h"
      14             : #include "src/objects/smi-inl.h"
      15             : #include "src/objects/string-table-inl.h"
      16             : #include "src/string-hasher-inl.h"
      17             : 
      18             : // Has to be the last include (doesn't have include guards):
      19             : #include "src/objects/object-macros.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : 
      24  1130243702 : INT32_ACCESSORS(String, length, kLengthOffset)
      25             : 
      26             : int String::synchronized_length() const {
      27             :   return base::AsAtomic32::Acquire_Load(
      28   535229656 :       reinterpret_cast<const int32_t*>(FIELD_ADDR(this, kLengthOffset)));
      29             : }
      30             : 
      31             : void String::synchronized_set_length(int value) {
      32             :   base::AsAtomic32::Release_Store(
      33    11899933 :       reinterpret_cast<int32_t*>(FIELD_ADDR(this, kLengthOffset)), value);
      34             : }
      35             : 
      36  4402191648 : OBJECT_CONSTRUCTORS_IMPL(String, Name)
      37    24477318 : OBJECT_CONSTRUCTORS_IMPL(SeqString, String)
      38 17947805562 : OBJECT_CONSTRUCTORS_IMPL(SeqOneByteString, SeqString)
      39   605484712 : OBJECT_CONSTRUCTORS_IMPL(SeqTwoByteString, SeqString)
      40    14985986 : OBJECT_CONSTRUCTORS_IMPL(InternalizedString, String)
      41   445231028 : OBJECT_CONSTRUCTORS_IMPL(ConsString, String)
      42    30491674 : OBJECT_CONSTRUCTORS_IMPL(ThinString, String)
      43    23852336 : OBJECT_CONSTRUCTORS_IMPL(SlicedString, String)
      44      350986 : OBJECT_CONSTRUCTORS_IMPL(ExternalString, String)
      45    24064572 : OBJECT_CONSTRUCTORS_IMPL(ExternalOneByteString, ExternalString)
      46     4773186 : OBJECT_CONSTRUCTORS_IMPL(ExternalTwoByteString, ExternalString)
      47             : 
      48   222616298 : CAST_ACCESSOR(ConsString)
      49    12032286 : CAST_ACCESSOR(ExternalOneByteString)
      50      175496 : CAST_ACCESSOR(ExternalString)
      51     2386593 : CAST_ACCESSOR(ExternalTwoByteString)
      52     7492993 : CAST_ACCESSOR(InternalizedString)
      53  8973907886 : CAST_ACCESSOR(SeqOneByteString)
      54    12238659 : CAST_ACCESSOR(SeqString)
      55   302742357 : CAST_ACCESSOR(SeqTwoByteString)
      56    11926177 : CAST_ACCESSOR(SlicedString)
      57  2192388772 : CAST_ACCESSOR(String)
      58    15245866 : CAST_ACCESSOR(ThinString)
      59             : 
      60  6486710372 : StringShape::StringShape(const String str)
      61  6849957382 :     : type_(str->map()->instance_type()) {
      62             :   set_valid();
      63             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      64  6486710372 : }
      65             : 
      66             : StringShape::StringShape(Map map) : type_(map->instance_type()) {
      67             :   set_valid();
      68             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      69             : }
      70             : 
      71        1232 : StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) {
      72             :   set_valid();
      73             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      74             : }
      75             : 
      76             : bool StringShape::IsInternalized() {
      77             :   DCHECK(valid());
      78             :   STATIC_ASSERT(kNotInternalizedTag != 0);
      79           0 :   return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
      80             :          (kStringTag | kInternalizedTag);
      81             : }
      82             : 
      83             : bool StringShape::HasOnlyOneByteChars() {
      84     1955588 :   return (type_ & kStringEncodingMask) == kOneByteStringTag ||
      85     1955588 :          (type_ & kOneByteDataHintMask) == kOneByteDataHintTag;
      86             : }
      87             : 
      88    95378659 : bool StringShape::IsCons() {
      89   111249634 :   return (type_ & kStringRepresentationMask) == kConsStringTag;
      90             : }
      91             : 
      92   161290055 : bool StringShape::IsThin() {
      93   161408154 :   return (type_ & kStringRepresentationMask) == kThinStringTag;
      94             : }
      95             : 
      96     5923282 : bool StringShape::IsSliced() {
      97     6041381 :   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
      98             : }
      99             : 
     100             : bool StringShape::IsIndirect() {
     101         621 :   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
     102             : }
     103             : 
     104    98664796 : bool StringShape::IsExternal() {
     105   100726105 :   return (type_ & kStringRepresentationMask) == kExternalStringTag;
     106             : }
     107             : 
     108    77460868 : bool StringShape::IsSequential() {
     109    77460868 :   return (type_ & kStringRepresentationMask) == kSeqStringTag;
     110             : }
     111             : 
     112             : StringRepresentationTag StringShape::representation_tag() {
     113   444722685 :   uint32_t tag = (type_ & kStringRepresentationMask);
     114             :   return static_cast<StringRepresentationTag>(tag);
     115             : }
     116             : 
     117   151099371 : uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; }
     118             : 
     119  6047992882 : uint32_t StringShape::full_representation_tag() {
     120  6240874895 :   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
     121             : }
     122             : 
     123             : STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
     124             :               Internals::kFullStringRepresentationMask);
     125             : 
     126             : STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
     127             :               Internals::kStringEncodingMask);
     128             : 
     129             : bool StringShape::IsSequentialOneByte() {
     130             :   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
     131             : }
     132             : 
     133             : bool StringShape::IsSequentialTwoByte() {
     134             :   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
     135             : }
     136             : 
     137             : bool StringShape::IsExternalOneByte() {
     138          27 :   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
     139             : }
     140             : 
     141             : STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
     142             :               Internals::kExternalOneByteRepresentationTag);
     143             : 
     144             : STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
     145             : 
     146             : bool StringShape::IsExternalTwoByte() {
     147          67 :   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
     148             : }
     149             : 
     150             : STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
     151             :               Internals::kExternalTwoByteRepresentationTag);
     152             : 
     153             : STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
     154             : 
     155   132106984 : bool String::IsOneByteRepresentation() const {
     156             :   uint32_t type = map()->instance_type();
     157   132106984 :   return (type & kStringEncodingMask) == kOneByteStringTag;
     158             : }
     159             : 
     160      168446 : bool String::IsTwoByteRepresentation() const {
     161             :   uint32_t type = map()->instance_type();
     162      168446 :   return (type & kStringEncodingMask) == kTwoByteStringTag;
     163             : }
     164             : 
     165     5803454 : bool String::IsOneByteRepresentationUnderneath(String string) {
     166             :   while (true) {
     167             :     uint32_t type = string.map()->instance_type();
     168             :     STATIC_ASSERT(kIsIndirectStringTag != 0);
     169             :     STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
     170             :     DCHECK(string.IsFlat());
     171     5805080 :     switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
     172             :       case kOneByteStringTag:
     173             :         return true;
     174             :       case kTwoByteStringTag:
     175     2865992 :         return false;
     176             :       default:  // Cons, sliced, thin, strings need to go deeper.
     177        1626 :         string = string.GetUnderlying();
     178             :     }
     179        1626 :   }
     180             : }
     181             : 
     182     9557572 : bool String::HasOnlyOneByteChars() {
     183             :   uint32_t type = map()->instance_type();
     184    19115130 :   return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
     185    19115130 :          IsOneByteRepresentation();
     186             : }
     187             : 
     188   389038789 : uc32 FlatStringReader::Get(int index) {
     189   389038789 :   if (is_one_byte_) {
     190   388188663 :     return Get<uint8_t>(index);
     191             :   } else {
     192      850126 :     return Get<uc16>(index);
     193             :   }
     194             : }
     195             : 
     196             : template <typename Char>
     197  2441918991 : Char FlatStringReader::Get(int index) {
     198             :   DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
     199             :   DCHECK(0 <= index && index <= length_);
     200             :   if (sizeof(Char) == 1) {
     201  2830103216 :     return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
     202             :   } else {
     203      854564 :     return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
     204             :   }
     205             : }
     206             : 
     207             : template <typename Char>
     208           0 : class SequentialStringKey : public StringTableKey {
     209             :  public:
     210       88702 :   explicit SequentialStringKey(Vector<const Char> string, uint64_t seed)
     211             :       : StringTableKey(StringHasher::HashSequentialString<Char>(
     212             :             string.start(), string.length(), seed)),
     213      266105 :         string_(string) {}
     214             : 
     215             :   Vector<const Char> string_;
     216             : };
     217             : 
     218           0 : class OneByteStringKey : public SequentialStringKey<uint8_t> {
     219             :  public:
     220             :   OneByteStringKey(Vector<const uint8_t> str, uint64_t seed)
     221       88702 :       : SequentialStringKey<uint8_t>(str, seed) {}
     222             : 
     223      176462 :   bool IsMatch(Object string) override {
     224      176462 :     return String::cast(string)->IsOneByteEqualTo(string_);
     225             :   }
     226             : 
     227             :   Handle<String> AsHandle(Isolate* isolate) override;
     228             : };
     229             : 
     230           0 : class SeqOneByteSubStringKey : public StringTableKey {
     231             :  public:
     232             : // VS 2017 on official builds gives this spurious warning:
     233             : // warning C4789: buffer 'key' of size 16 bytes will be overrun; 4 bytes will
     234             : // be written starting at offset 16
     235             : // https://bugs.chromium.org/p/v8/issues/detail?id=6068
     236             : #if defined(V8_CC_MSVC)
     237             : #pragma warning(push)
     238             : #pragma warning(disable : 4789)
     239             : #endif
     240      473684 :   SeqOneByteSubStringKey(Isolate* isolate, Handle<SeqOneByteString> string,
     241             :                          int from, int length)
     242      473684 :       : StringTableKey(0), string_(string), from_(from), length_(length) {
     243             :     // We have to set the hash later.
     244             :     DisallowHeapAllocation no_gc;
     245             :     uint32_t hash = StringHasher::HashSequentialString(
     246      947368 :         string->GetChars(no_gc) + from, length, isolate->heap()->HashSeed());
     247             :     set_hash_field(hash);
     248             : 
     249             :     DCHECK_LE(0, length_);
     250             :     DCHECK_LE(from_ + length_, string_->length());
     251             :     DCHECK(string_->IsSeqOneByteString());
     252      473684 :   }
     253             : #if defined(V8_CC_MSVC)
     254             : #pragma warning(pop)
     255             : #endif
     256             : 
     257             :   bool IsMatch(Object string) override;
     258             :   Handle<String> AsHandle(Isolate* isolate) override;
     259             : 
     260             :  private:
     261             :   Handle<SeqOneByteString> string_;
     262             :   int from_;
     263             :   int length_;
     264             : };
     265             : 
     266           0 : class TwoByteStringKey : public SequentialStringKey<uc16> {
     267             :  public:
     268             :   explicit TwoByteStringKey(Vector<const uc16> str, uint64_t seed)
     269           0 :       : SequentialStringKey<uc16>(str, seed) {}
     270             : 
     271           0 :   bool IsMatch(Object string) override {
     272           0 :     return String::cast(string)->IsTwoByteEqualTo(string_);
     273             :   }
     274             : 
     275             :   Handle<String> AsHandle(Isolate* isolate) override;
     276             : };
     277             : 
     278             : // Utf8StringKey carries a vector of chars as key.
     279           0 : class Utf8StringKey : public StringTableKey {
     280             :  public:
     281    14534352 :   explicit Utf8StringKey(Vector<const char> string, uint64_t seed)
     282             :       : StringTableKey(StringHasher::ComputeUtf8Hash(string, seed, &chars_)),
     283    29068715 :         string_(string) {}
     284             : 
     285    19961600 :   bool IsMatch(Object string) override {
     286    19961601 :     return String::cast(string)->IsUtf8EqualTo(string_);
     287             :   }
     288             : 
     289      799304 :   Handle<String> AsHandle(Isolate* isolate) override {
     290             :     return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
     291      799304 :                                                              HashField());
     292             :   }
     293             : 
     294             :  private:
     295             :   Vector<const char> string_;
     296             :   int chars_;  // Caches the number of characters when computing the hash code.
     297             : };
     298             : 
     299    24097924 : bool String::Equals(String other) {
     300    24097924 :   if (other == *this) return true;
     301    60332770 :   if (this->IsInternalizedString() && other->IsInternalizedString()) {
     302             :     return false;
     303             :   }
     304     2860681 :   return SlowEquals(other);
     305             : }
     306             : 
     307     3251939 : bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) {
     308     3251939 :   if (one.is_identical_to(two)) return true;
     309    10770082 :   if (one->IsInternalizedString() && two->IsInternalizedString()) {
     310             :     return false;
     311             :   }
     312      742173 :   return SlowEquals(isolate, one, two);
     313             : }
     314             : 
     315    85500232 : Handle<String> String::Flatten(Isolate* isolate, Handle<String> string,
     316             :                                PretenureFlag pretenure) {
     317   171000509 :   if (string->IsConsString()) {
     318     9325743 :     Handle<ConsString> cons = Handle<ConsString>::cast(string);
     319     9325743 :     if (cons->IsFlat()) {
     320     7088164 :       string = handle(cons->first(), isolate);
     321             :     } else {
     322     5781661 :       return SlowFlatten(isolate, cons, pretenure);
     323             :     }
     324             :   }
     325   159437180 :   if (string->IsThinString()) {
     326     2618958 :     string = handle(Handle<ThinString>::cast(string)->actual(), isolate);
     327             :     DCHECK(!string->IsConsString());
     328             :   }
     329    79718585 :   return string;
     330             : }
     331             : 
     332             : uint16_t String::Get(int index) {
     333             :   DCHECK(index >= 0 && index < length());
     334  6047992887 :   switch (StringShape(*this).full_representation_tag()) {
     335             :     case kSeqStringTag | kOneByteStringTag:
     336  5812064549 :       return SeqOneByteString::cast(*this)->SeqOneByteStringGet(index);
     337             :     case kSeqStringTag | kTwoByteStringTag:
     338   225619778 :       return SeqTwoByteString::cast(*this)->SeqTwoByteStringGet(index);
     339             :     case kConsStringTag | kOneByteStringTag:
     340             :     case kConsStringTag | kTwoByteStringTag:
     341      273526 :       return ConsString::cast(*this)->ConsStringGet(index);
     342             :     case kExternalStringTag | kOneByteStringTag:
     343             :       return ExternalOneByteString::cast(*this)->ExternalOneByteStringGet(
     344     8882173 :           index);
     345             :     case kExternalStringTag | kTwoByteStringTag:
     346             :       return ExternalTwoByteString::cast(*this)->ExternalTwoByteStringGet(
     347       54823 :           index);
     348             :     case kSlicedStringTag | kOneByteStringTag:
     349             :     case kSlicedStringTag | kTwoByteStringTag:
     350     1095402 :       return SlicedString::cast(*this)->SlicedStringGet(index);
     351             :     case kThinStringTag | kOneByteStringTag:
     352             :     case kThinStringTag | kTwoByteStringTag:
     353        2624 :       return ThinString::cast(*this)->ThinStringGet(index);
     354             :     default:
     355             :       break;
     356             :   }
     357             : 
     358           0 :   UNREACHABLE();
     359             : }
     360             : 
     361             : void String::Set(int index, uint16_t value) {
     362             :   DCHECK(index >= 0 && index < length());
     363             :   DCHECK(StringShape(*this).IsSequential());
     364             : 
     365             :   return this->IsOneByteRepresentation()
     366             :              ? SeqOneByteString::cast(*this)->SeqOneByteStringSet(index, value)
     367             :              : SeqTwoByteString::cast(*this)->SeqTwoByteStringSet(index, value);
     368             : }
     369             : 
     370    12673611 : bool String::IsFlat() {
     371    12673611 :   if (!StringShape(*this).IsCons()) return true;
     372    22484956 :   return ConsString::cast(*this)->second()->length() == 0;
     373             : }
     374             : 
     375        1626 : String String::GetUnderlying() {
     376             :   // Giving direct access to underlying string only makes sense if the
     377             :   // wrapping string is already flattened.
     378             :   DCHECK(this->IsFlat());
     379             :   DCHECK(StringShape(*this).IsIndirect());
     380             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     381             :                 static_cast<int>(SlicedString::kParentOffset));
     382             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     383             :                 static_cast<int>(ThinString::kActualOffset));
     384             :   const int kUnderlyingOffset = SlicedString::kParentOffset;
     385        3252 :   return String::cast(READ_FIELD(this, kUnderlyingOffset));
     386             : }
     387             : 
     388             : template <class Visitor>
     389    92634895 : ConsString String::VisitFlat(Visitor* visitor, String string,
     390             :                              const int offset) {
     391             :   DisallowHeapAllocation no_gc;
     392             :   int slice_offset = offset;
     393             :   const int length = string->length();
     394             :   DCHECK(offset <= length);
     395             :   while (true) {
     396             :     int32_t type = string->map()->instance_type();
     397    98724204 :     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
     398             :       case kSeqStringTag | kOneByteStringTag:
     399   166635030 :         visitor->VisitOneByteString(
     400             :             SeqOneByteString::cast(string)->GetChars(no_gc) + slice_offset,
     401             :             length - offset);
     402    83357610 :         return ConsString();
     403             : 
     404             :       case kSeqStringTag | kTwoByteStringTag:
     405     8796412 :         visitor->VisitTwoByteString(
     406             :             SeqTwoByteString::cast(string)->GetChars(no_gc) + slice_offset,
     407             :             length - offset);
     408     4398206 :         return ConsString();
     409             : 
     410             :       case kExternalStringTag | kOneByteStringTag:
     411     5254402 :         visitor->VisitOneByteString(
     412             :             ExternalOneByteString::cast(string)->GetChars() + slice_offset,
     413             :             length - offset);
     414     2627201 :         return ConsString();
     415             : 
     416             :       case kExternalStringTag | kTwoByteStringTag:
     417     4061436 :         visitor->VisitTwoByteString(
     418             :             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
     419             :             length - offset);
     420     2030718 :         return ConsString();
     421             : 
     422             :       case kSlicedStringTag | kOneByteStringTag:
     423             :       case kSlicedStringTag | kTwoByteStringTag: {
     424     6056822 :         SlicedString slicedString = SlicedString::cast(string);
     425     6056822 :         slice_offset += slicedString->offset();
     426     6056822 :         string = slicedString->parent();
     427             :         continue;
     428             :       }
     429             : 
     430             :       case kConsStringTag | kOneByteStringTag:
     431             :       case kConsStringTag | kTwoByteStringTag:
     432             :         return ConsString::cast(string);
     433             : 
     434             :       case kThinStringTag | kOneByteStringTag:
     435             :       case kThinStringTag | kTwoByteStringTag:
     436       32487 :         string = ThinString::cast(string)->actual();
     437       32487 :         continue;
     438             : 
     439             :       default:
     440           0 :         UNREACHABLE();
     441             :     }
     442             :   }
     443             : }
     444             : 
     445             : template <>
     446             : inline Vector<const uint8_t> String::GetCharVector(
     447             :     const DisallowHeapAllocation& no_gc) {
     448     1440259 :   String::FlatContent flat = GetFlatContent(no_gc);
     449             :   DCHECK(flat.IsOneByte());
     450     1440262 :   return flat.ToOneByteVector();
     451             : }
     452             : 
     453             : template <>
     454             : inline Vector<const uc16> String::GetCharVector(
     455             :     const DisallowHeapAllocation& no_gc) {
     456      860966 :   String::FlatContent flat = GetFlatContent(no_gc);
     457             :   DCHECK(flat.IsTwoByte());
     458      860966 :   return flat.ToUC16Vector();
     459             : }
     460             : 
     461         333 : uint32_t String::ToValidIndex(Object number) {
     462        4102 :   uint32_t index = PositiveNumberToUint32(number);
     463        4102 :   uint32_t length_value = static_cast<uint32_t>(length());
     464        4102 :   if (index > length_value) return length_value;
     465         324 :   return index;
     466             : }
     467             : 
     468  6869806222 : uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
     469             :   DCHECK(index >= 0 && index < length());
     470  7141852229 :   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
     471             : }
     472             : 
     473  2611160994 : void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
     474             :   DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
     475  3388950892 :   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
     476  3388950892 :                    static_cast<byte>(value));
     477  2611160994 : }
     478             : 
     479             : Address SeqOneByteString::GetCharsAddress() {
     480   511290115 :   return FIELD_ADDR(this, kHeaderSize);
     481             : }
     482             : 
     483         645 : uint8_t* SeqOneByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     484             :   USE(no_gc);
     485   511290065 :   return reinterpret_cast<uint8_t*>(GetCharsAddress());
     486             : }
     487             : 
     488             : Address SeqTwoByteString::GetCharsAddress() {
     489          15 :   return FIELD_ADDR(this, kHeaderSize);
     490             : }
     491             : 
     492           5 : uc16* SeqTwoByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     493             :   USE(no_gc);
     494    29120358 :   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
     495             : }
     496             : 
     497   225619778 : uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
     498             :   DCHECK(index >= 0 && index < length());
     499   225619778 :   return READ_UINT16_FIELD(this, kHeaderSize + index * kShortSize);
     500             : }
     501             : 
     502     1443150 : void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
     503             :   DCHECK(index >= 0 && index < length());
     504     8449504 :   WRITE_UINT16_FIELD(this, kHeaderSize + index * kShortSize, value);
     505     1443150 : }
     506             : 
     507             : int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
     508             :   return SizeFor(length());
     509             : }
     510             : 
     511             : int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
     512             :   return SizeFor(length());
     513             : }
     514             : 
     515     9874217 : String SlicedString::parent() {
     516    19748434 :   return String::cast(READ_FIELD(*this, kParentOffset));
     517             : }
     518             : 
     519     1899436 : void SlicedString::set_parent(Isolate* isolate, String parent,
     520             :                               WriteBarrierMode mode) {
     521             :   DCHECK(parent->IsSeqString() || parent->IsExternalString());
     522     1899436 :   WRITE_FIELD(*this, kParentOffset, parent);
     523     5698308 :   CONDITIONAL_WRITE_BARRIER(*this, kParentOffset, parent, mode);
     524     1899436 : }
     525             : 
     526    21647790 : SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
     527             : 
     528   160977918 : String ConsString::first() {
     529   321955837 :   return String::cast(READ_FIELD(this, kFirstOffset));
     530             : }
     531             : 
     532     1565622 : Object ConsString::unchecked_first() { return READ_FIELD(*this, kFirstOffset); }
     533             : 
     534    18153001 : void ConsString::set_first(Isolate* isolate, String value,
     535             :                            WriteBarrierMode mode) {
     536    18153001 :   WRITE_FIELD(*this, kFirstOffset, value);
     537    31805853 :   CONDITIONAL_WRITE_BARRIER(*this, kFirstOffset, value, mode);
     538    18153001 : }
     539             : 
     540   137410387 : String ConsString::second() {
     541   274820775 :   return String::cast(READ_FIELD(*this, kSecondOffset));
     542             : }
     543             : 
     544    52265464 : Object ConsString::unchecked_second() {
     545   104530928 :   return RELAXED_READ_FIELD(*this, kSecondOffset);
     546             : }
     547             : 
     548    18153001 : void ConsString::set_second(Isolate* isolate, String value,
     549             :                             WriteBarrierMode mode) {
     550    18153001 :   WRITE_FIELD(*this, kSecondOffset, value);
     551    31805853 :   CONDITIONAL_WRITE_BARRIER(*this, kSecondOffset, value, mode);
     552    18153001 : }
     553             : 
     554    65426938 : ACCESSORS(ThinString, actual, String, kActualOffset);
     555             : 
     556             : HeapObject ThinString::unchecked_actual() const {
     557     1416931 :   return HeapObject::unchecked_cast(READ_FIELD(*this, kActualOffset));
     558             : }
     559             : 
     560       88778 : bool ExternalString::is_uncached() const {
     561             :   InstanceType type = map()->instance_type();
     562       88778 :   return (type & kUncachedExternalStringMask) == kUncachedExternalStringTag;
     563             : }
     564             : 
     565             : Address ExternalString::resource_as_address() {
     566          30 :   return *reinterpret_cast<Address*>(FIELD_ADDR(*this, kResourceOffset));
     567             : }
     568             : 
     569          30 : void ExternalString::set_address_as_resource(Address address) {
     570          30 :   *reinterpret_cast<Address*>(FIELD_ADDR(*this, kResourceOffset)) = address;
     571          60 :   if (IsExternalOneByteString()) {
     572          15 :     ExternalOneByteString::cast(*this)->update_data_cache();
     573             :   } else {
     574          15 :     ExternalTwoByteString::cast(*this)->update_data_cache();
     575             :   }
     576          30 : }
     577             : 
     578             : uint32_t ExternalString::resource_as_uint32() {
     579             :   return static_cast<uint32_t>(
     580          20 :       *reinterpret_cast<uintptr_t*>(FIELD_ADDR(*this, kResourceOffset)));
     581             : }
     582             : 
     583          10 : void ExternalString::set_uint32_as_resource(uint32_t value) {
     584          10 :   *reinterpret_cast<uintptr_t*>(FIELD_ADDR(*this, kResourceOffset)) = value;
     585          20 :   if (is_uncached()) return;
     586             :   const char** data_field =
     587          10 :       reinterpret_cast<const char**>(FIELD_ADDR(*this, kResourceDataOffset));
     588          10 :   *data_field = nullptr;
     589             : }
     590             : 
     591             : const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
     592    12032053 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(*this, kResourceOffset));
     593             : }
     594             : 
     595       69511 : void ExternalOneByteString::update_data_cache() {
     596      139022 :   if (is_uncached()) return;
     597             :   const char** data_field =
     598        6167 :       reinterpret_cast<const char**>(FIELD_ADDR(*this, kResourceDataOffset));
     599        6167 :   *data_field = resource()->data();
     600             : }
     601             : 
     602       69169 : void ExternalOneByteString::SetResource(
     603             :     Isolate* isolate, const ExternalOneByteString::Resource* resource) {
     604             :   set_resource(resource);
     605       69169 :   size_t new_payload = resource == nullptr ? 0 : resource->length();
     606       69169 :   if (new_payload > 0)
     607       69104 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     608       69170 : }
     609             : 
     610             : void ExternalOneByteString::set_resource(
     611             :     const ExternalOneByteString::Resource* resource) {
     612       69365 :   *reinterpret_cast<const Resource**>(FIELD_ADDR(*this, kResourceOffset)) =
     613       69561 :       resource;
     614       69561 :   if (resource != nullptr) update_data_cache();
     615             : }
     616             : 
     617             : const uint8_t* ExternalOneByteString::GetChars() {
     618    11942813 :   return reinterpret_cast<const uint8_t*>(resource()->data());
     619             : }
     620             : 
     621     8882173 : uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
     622             :   DCHECK(index >= 0 && index < length());
     623     8882173 :   return GetChars()[index];
     624             : }
     625             : 
     626             : const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
     627     2386395 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(*this, kResourceOffset));
     628             : }
     629             : 
     630       19257 : void ExternalTwoByteString::update_data_cache() {
     631       38514 :   if (is_uncached()) return;
     632             :   const uint16_t** data_field = reinterpret_cast<const uint16_t**>(
     633       19117 :       FIELD_ADDR(*this, kResourceDataOffset));
     634       19117 :   *data_field = resource()->data();
     635             : }
     636             : 
     637       19300 : void ExternalTwoByteString::SetResource(
     638             :     Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
     639             :   set_resource(resource);
     640       19300 :   size_t new_payload = resource == nullptr ? 0 : resource->length() * 2;
     641       19300 :   if (new_payload > 0)
     642       19242 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     643       19300 : }
     644             : 
     645             : void ExternalTwoByteString::set_resource(
     646             :     const ExternalTwoByteString::Resource* resource) {
     647       19300 :   *reinterpret_cast<const Resource**>(FIELD_ADDR(*this, kResourceOffset)) =
     648       19300 :       resource;
     649       19300 :   if (resource != nullptr) update_data_cache();
     650             : }
     651             : 
     652     2367171 : const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
     653             : 
     654       54823 : uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
     655             :   DCHECK(index >= 0 && index < length());
     656       54823 :   return GetChars()[index];
     657             : }
     658             : 
     659             : const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
     660             :     unsigned start) {
     661             :   return GetChars() + start;
     662             : }
     663             : 
     664    10857365 : int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
     665             : 
     666             : void ConsStringIterator::PushLeft(ConsString string) {
     667    38491459 :   frames_[depth_++ & kDepthMask] = string;
     668             : }
     669             : 
     670             : void ConsStringIterator::PushRight(ConsString string) {
     671             :   // Inplace update.
     672     6371921 :   frames_[(depth_ - 1) & kDepthMask] = string;
     673             : }
     674             : 
     675             : void ConsStringIterator::AdjustMaximumDepth() {
     676     5244166 :   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
     677             : }
     678             : 
     679             : void ConsStringIterator::Pop() {
     680             :   DCHECK_GT(depth_, 0);
     681             :   DCHECK(depth_ <= maximum_depth_);
     682     5806324 :   depth_--;
     683             : }
     684             : 
     685  1038761144 : uint16_t StringCharacterStream::GetNext() {
     686             :   DCHECK(buffer8_ != nullptr && end_ != nullptr);
     687             :   // Advance cursor if needed.
     688  1038761144 :   if (buffer8_ == end_) HasMore();
     689             :   DCHECK(buffer8_ < end_);
     690  1038761147 :   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
     691             : }
     692             : 
     693     6230123 : StringCharacterStream::StringCharacterStream(String string, int offset)
     694     6230123 :     : is_one_byte_(false) {
     695     6230123 :   Reset(string, offset);
     696     6230121 : }
     697             : 
     698    11402652 : void StringCharacterStream::Reset(String string, int offset) {
     699    11402652 :   buffer8_ = nullptr;
     700    11402652 :   end_ = nullptr;
     701    11402652 :   ConsString cons_string = String::VisitFlat(this, string, offset);
     702    11402642 :   iter_.Reset(cons_string, offset);
     703    11402642 :   if (!cons_string.is_null()) {
     704       16228 :     string = iter_.Next(&offset);
     705       57404 :     if (!string.is_null()) String::VisitFlat(this, string, offset);
     706             :   }
     707    11402642 : }
     708             : 
     709  1047604418 : bool StringCharacterStream::HasMore() {
     710  1047604418 :   if (buffer8_ != end_) return true;
     711             :   int offset;
     712    19856093 :   String string = iter_.Next(&offset);
     713             :   DCHECK_EQ(offset, 0);
     714    19856093 :   if (string.is_null()) return false;
     715     9521453 :   String::VisitFlat(this, string);
     716             :   DCHECK(buffer8_ != end_);
     717     9521453 :   return true;
     718             : }
     719             : 
     720             : void StringCharacterStream::VisitOneByteString(const uint8_t* chars,
     721             :                                                int length) {
     722    16687273 :   is_one_byte_ = true;
     723    16687273 :   buffer8_ = chars;
     724    16687273 :   end_ = chars + length;
     725             : }
     726             : 
     727             : void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
     728             :                                                int length) {
     729     4236677 :   is_one_byte_ = false;
     730     4236677 :   buffer16_ = chars;
     731     4236677 :   end_ = reinterpret_cast<const uint8_t*>(chars + length);
     732             : }
     733             : 
     734    38728848 : bool String::AsArrayIndex(uint32_t* index) {
     735             :   uint32_t field = hash_field();
     736    38728848 :   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
     737             :     return false;
     738             :   }
     739     8332260 :   return SlowAsArrayIndex(index);
     740             : }
     741             : 
     742             : SubStringRange::SubStringRange(String string,
     743             :                                const DisallowHeapAllocation& no_gc, int first,
     744             :                                int length)
     745             :     : string_(string),
     746             :       first_(first),
     747             :       length_(length == -1 ? string->length() : length),
     748           2 :       no_gc_(no_gc) {}
     749             : 
     750             : class SubStringRange::iterator final {
     751             :  public:
     752             :   typedef std::forward_iterator_tag iterator_category;
     753             :   typedef int difference_type;
     754             :   typedef uc16 value_type;
     755             :   typedef uc16* pointer;
     756             :   typedef uc16& reference;
     757             : 
     758             :   iterator(const iterator& other) = default;
     759             : 
     760          60 :   uc16 operator*() { return content_.Get(offset_); }
     761             :   bool operator==(const iterator& other) const {
     762             :     return content_.UsesSameString(other.content_) && offset_ == other.offset_;
     763             :   }
     764             :   bool operator!=(const iterator& other) const {
     765          62 :     return !content_.UsesSameString(other.content_) || offset_ != other.offset_;
     766             :   }
     767             :   iterator& operator++() {
     768          60 :     ++offset_;
     769             :     return *this;
     770             :   }
     771             :   iterator operator++(int);
     772             : 
     773             :  private:
     774             :   friend class String;
     775             :   friend class SubStringRange;
     776             :   iterator(String from, int offset, const DisallowHeapAllocation& no_gc)
     777           4 :       : content_(from->GetFlatContent(no_gc)), offset_(offset) {}
     778             :   String::FlatContent content_;
     779             :   int offset_;
     780             : };
     781             : 
     782             : SubStringRange::iterator SubStringRange::begin() {
     783             :   return SubStringRange::iterator(string_, first_, no_gc_);
     784             : }
     785             : 
     786             : SubStringRange::iterator SubStringRange::end() {
     787           2 :   return SubStringRange::iterator(string_, first_ + length_, no_gc_);
     788             : }
     789             : 
     790             : }  // namespace internal
     791             : }  // namespace v8
     792             : 
     793             : #include "src/objects/object-macros-undef.h"
     794             : 
     795             : #endif  // V8_OBJECTS_STRING_INL_H_

Generated by: LCOV version 1.10