LCOV - code coverage report
Current view: top level - src/objects - string-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 226 254 89.0 %
Date: 2019-03-21 Functions: 44 66 66.7 %

          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/hash-seed-inl.h"
      13             : #include "src/heap/factory.h"
      14             : #include "src/objects/name-inl.h"
      15             : #include "src/objects/smi-inl.h"
      16             : #include "src/objects/string-table-inl.h"
      17             : #include "src/string-hasher-inl.h"
      18             : 
      19             : // Has to be the last include (doesn't have include guards):
      20             : #include "src/objects/object-macros.h"
      21             : 
      22             : namespace v8 {
      23             : namespace internal {
      24             : 
      25  1291457124 : INT32_ACCESSORS(String, length, kLengthOffset)
      26             : 
      27             : int String::synchronized_length() const {
      28   437136171 :   return base::AsAtomic32::Acquire_Load(
      29   437136171 :       reinterpret_cast<const int32_t*>(FIELD_ADDR(*this, kLengthOffset)));
      30             : }
      31             : 
      32             : void String::synchronized_set_length(int value) {
      33    12650885 :   base::AsAtomic32::Release_Store(
      34    12650885 :       reinterpret_cast<int32_t*>(FIELD_ADDR(*this, kLengthOffset)), value);
      35             : }
      36             : 
      37    14756377 : OBJECT_CONSTRUCTORS_IMPL(String, Name)
      38             : OBJECT_CONSTRUCTORS_IMPL(SeqString, String)
      39           0 : OBJECT_CONSTRUCTORS_IMPL(SeqOneByteString, SeqString)
      40           0 : OBJECT_CONSTRUCTORS_IMPL(SeqTwoByteString, SeqString)
      41             : OBJECT_CONSTRUCTORS_IMPL(InternalizedString, String)
      42           0 : OBJECT_CONSTRUCTORS_IMPL(ConsString, String)
      43           0 : OBJECT_CONSTRUCTORS_IMPL(ThinString, String)
      44           0 : OBJECT_CONSTRUCTORS_IMPL(SlicedString, String)
      45             : OBJECT_CONSTRUCTORS_IMPL(ExternalString, String)
      46           0 : OBJECT_CONSTRUCTORS_IMPL(ExternalOneByteString, ExternalString)
      47           0 : OBJECT_CONSTRUCTORS_IMPL(ExternalTwoByteString, ExternalString)
      48             : 
      49           0 : CAST_ACCESSOR(ConsString)
      50           0 : CAST_ACCESSOR(ExternalOneByteString)
      51             : CAST_ACCESSOR(ExternalString)
      52           0 : CAST_ACCESSOR(ExternalTwoByteString)
      53             : CAST_ACCESSOR(InternalizedString)
      54           0 : CAST_ACCESSOR(SeqOneByteString)
      55             : CAST_ACCESSOR(SeqString)
      56           0 : CAST_ACCESSOR(SeqTwoByteString)
      57           0 : CAST_ACCESSOR(SlicedString)
      58    14756390 : CAST_ACCESSOR(String)
      59           0 : CAST_ACCESSOR(ThinString)
      60             : 
      61  6935378918 : StringShape::StringShape(const String str)
      62  6935378918 :     : type_(str->map()->instance_type()) {
      63             :   set_valid();
      64             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      65  6935378918 : }
      66             : 
      67             : StringShape::StringShape(Map map) : type_(map->instance_type()) {
      68             :   set_valid();
      69             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      70             : }
      71             : 
      72        1064 : StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) {
      73        1064 :   set_valid();
      74             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      75        1064 : }
      76             : 
      77             : bool StringShape::IsInternalized() {
      78             :   DCHECK(valid());
      79             :   STATIC_ASSERT(kNotInternalizedTag != 0);
      80           0 :   return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
      81             :          (kStringTag | kInternalizedTag);
      82             : }
      83             : 
      84        1064 : bool StringShape::IsCons() {
      85   137099766 :   return (type_ & kStringRepresentationMask) == kConsStringTag;
      86             : }
      87             : 
      88             : bool StringShape::IsThin() {
      89   172638188 :   return (type_ & kStringRepresentationMask) == kThinStringTag;
      90             : }
      91             : 
      92             : bool StringShape::IsSliced() {
      93     6069715 :   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
      94             : }
      95             : 
      96             : bool StringShape::IsIndirect() {
      97         611 :   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
      98             : }
      99             : 
     100             : bool StringShape::IsExternal() {
     101   112265552 :   return (type_ & kStringRepresentationMask) == kExternalStringTag;
     102             : }
     103             : 
     104             : bool StringShape::IsSequential() {
     105    71750103 :   return (type_ & kStringRepresentationMask) == kSeqStringTag;
     106             : }
     107             : 
     108             : StringRepresentationTag StringShape::representation_tag() {
     109   520174137 :   uint32_t tag = (type_ & kStringRepresentationMask);
     110             :   return static_cast<StringRepresentationTag>(tag);
     111             : }
     112             : 
     113   210420255 : uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; }
     114             : 
     115           0 : uint32_t StringShape::full_representation_tag() {
     116  6236722511 :   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
     117             : }
     118             : 
     119             : STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
     120             :               Internals::kFullStringRepresentationMask);
     121             : 
     122             : STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
     123             :               Internals::kStringEncodingMask);
     124             : 
     125             : bool StringShape::IsSequentialOneByte() {
     126             :   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
     127             : }
     128             : 
     129             : bool StringShape::IsSequentialTwoByte() {
     130             :   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
     131             : }
     132             : 
     133             : bool StringShape::IsExternalOneByte() {
     134          27 :   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
     135             : }
     136             : 
     137             : STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
     138             :               Internals::kExternalOneByteRepresentationTag);
     139             : 
     140             : STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
     141             : 
     142             : bool StringShape::IsExternalTwoByte() {
     143          67 :   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
     144             : }
     145             : 
     146             : STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
     147             :               Internals::kExternalTwoByteRepresentationTag);
     148             : 
     149             : STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
     150             : 
     151   137348485 : bool String::IsOneByteRepresentation() const {
     152             :   uint32_t type = map()->instance_type();
     153   137348485 :   return (type & kStringEncodingMask) == kOneByteStringTag;
     154             : }
     155             : 
     156      166515 : bool String::IsTwoByteRepresentation() const {
     157             :   uint32_t type = map()->instance_type();
     158      166515 :   return (type & kStringEncodingMask) == kTwoByteStringTag;
     159             : }
     160             : 
     161    17205486 : bool String::IsOneByteRepresentationUnderneath(String string) {
     162       16369 :   while (true) {
     163             :     uint32_t type = string.map()->instance_type();
     164             :     STATIC_ASSERT(kIsIndirectStringTag != 0);
     165             :     STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
     166             :     DCHECK(string.IsFlat());
     167    17221855 :     switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
     168             :       case kOneByteStringTag:
     169             :         return true;
     170             :       case kTwoByteStringTag:
     171     8824379 :         return false;
     172             :       default:  // Cons, sliced, thin, strings need to go deeper.
     173             :         string = string.GetUnderlying();
     174             :     }
     175             :   }
     176             : }
     177             : 
     178             : uc32 FlatStringReader::Get(int index) {
     179   388419562 :   if (is_one_byte_) {
     180   387570716 :     return Get<uint8_t>(index);
     181             :   } else {
     182      848846 :     return Get<uc16>(index);
     183             :   }
     184             : }
     185             : 
     186             : template <typename Char>
     187             : Char FlatStringReader::Get(int index) {
     188             :   DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
     189             :   DCHECK(0 <= index && index <= length_);
     190             :   if (sizeof(Char) == 1) {
     191   412993581 :     return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
     192             :   } else {
     193      853772 :     return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
     194             :   }
     195             : }
     196             : 
     197             : template <typename Char>
     198       86483 : class SequentialStringKey : public StringTableKey {
     199             :  public:
     200             :   explicit SequentialStringKey(Vector<const Char> string, uint64_t seed)
     201             :       : StringTableKey(StringHasher::HashSequentialString<Char>(
     202             :             string.start(), string.length(), seed)),
     203      172967 :         string_(string) {}
     204             : 
     205             :   Vector<const Char> string_;
     206             : };
     207             : 
     208       85448 : class OneByteStringKey : public SequentialStringKey<uint8_t> {
     209             :  public:
     210             :   OneByteStringKey(Vector<const uint8_t> str, uint64_t seed)
     211       85449 :       : SequentialStringKey<uint8_t>(str, seed) {}
     212             : 
     213      130442 :   bool IsMatch(Object string) override {
     214      130442 :     return String::cast(string)->IsOneByteEqualTo(string_);
     215             :   }
     216             : 
     217             :   Handle<String> AsHandle(Isolate* isolate) override;
     218             : };
     219             : 
     220      481445 : class SeqOneByteSubStringKey : public StringTableKey {
     221             :  public:
     222             : // VS 2017 on official builds gives this spurious warning:
     223             : // warning C4789: buffer 'key' of size 16 bytes will be overrun; 4 bytes will
     224             : // be written starting at offset 16
     225             : // https://bugs.chromium.org/p/v8/issues/detail?id=6068
     226             : #if defined(V8_CC_MSVC)
     227             : #pragma warning(push)
     228             : #pragma warning(disable : 4789)
     229             : #endif
     230      481445 :   SeqOneByteSubStringKey(Isolate* isolate, Handle<SeqOneByteString> string,
     231             :                          int from, int length)
     232      481445 :       : StringTableKey(0), string_(string), from_(from), length_(length) {
     233             :     // We have to set the hash later.
     234             :     DisallowHeapAllocation no_gc;
     235      481445 :     uint32_t hash = StringHasher::HashSequentialString(
     236      481445 :         string->GetChars(no_gc) + from, length, HashSeed(isolate));
     237             :     set_hash_field(hash);
     238             : 
     239             :     DCHECK_LE(0, length_);
     240             :     DCHECK_LE(from_ + length_, string_->length());
     241             :     DCHECK(string_->IsSeqOneByteString());
     242      481445 :   }
     243             : #if defined(V8_CC_MSVC)
     244             : #pragma warning(pop)
     245             : #endif
     246             : 
     247             :   bool IsMatch(Object string) override;
     248             :   Handle<String> AsHandle(Isolate* isolate) override;
     249             : 
     250             :  private:
     251             :   Handle<SeqOneByteString> string_;
     252             :   int from_;
     253             :   int length_;
     254             : };
     255             : 
     256        1035 : class TwoByteStringKey : public SequentialStringKey<uc16> {
     257             :  public:
     258             :   explicit TwoByteStringKey(Vector<const uc16> str, uint64_t seed)
     259        1035 :       : SequentialStringKey<uc16>(str, seed) {}
     260             : 
     261        1745 :   bool IsMatch(Object string) override {
     262        1745 :     return String::cast(string)->IsTwoByteEqualTo(string_);
     263             :   }
     264             : 
     265             :   Handle<String> AsHandle(Isolate* isolate) override;
     266             : };
     267             : 
     268             : // Utf8StringKey carries a vector of chars as key.
     269    13466799 : class Utf8StringKey : public StringTableKey {
     270             :  public:
     271             :   explicit Utf8StringKey(Vector<const char> string, uint64_t seed)
     272             :       : StringTableKey(StringHasher::ComputeUtf8Hash(string, seed, &chars_)),
     273    26933591 :         string_(string) {}
     274             : 
     275    18612674 :   bool IsMatch(Object string) override {
     276    18612674 :     return String::cast(string)->IsUtf8EqualTo(string_);
     277             :   }
     278             : 
     279      717008 :   Handle<String> AsHandle(Isolate* isolate) override {
     280             :     return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
     281      717008 :                                                              HashField());
     282             :   }
     283             : 
     284             :  private:
     285             :   Vector<const char> string_;
     286             :   int chars_;  // Caches the number of characters when computing the hash code.
     287             : };
     288             : 
     289    24987096 : bool String::Equals(String other) {
     290    24987096 :   if (other == *this) return true;
     291    62761122 :   if (this->IsInternalizedString() && other->IsInternalizedString()) {
     292             :     return false;
     293             :   }
     294     2939981 :   return SlowEquals(other);
     295             : }
     296             : 
     297     3260044 : bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) {
     298     3260044 :   if (one.is_identical_to(two)) return true;
     299    10756309 :   if (one->IsInternalizedString() && two->IsInternalizedString()) {
     300             :     return false;
     301             :   }
     302      742327 :   return SlowEquals(isolate, one, two);
     303             : }
     304             : 
     305    89566539 : Handle<String> String::Flatten(Isolate* isolate, Handle<String> string,
     306             :                                AllocationType allocation) {
     307    89566552 :   if (string->IsConsString()) {
     308             :     Handle<ConsString> cons = Handle<ConsString>::cast(string);
     309     9644547 :     if (cons->IsFlat()) {
     310             :       string = handle(cons->first(), isolate);
     311             :     } else {
     312     6013541 :       return SlowFlatten(isolate, cons, allocation);
     313             :     }
     314             :   }
     315    83553038 :   if (string->IsThinString()) {
     316             :     string = handle(Handle<ThinString>::cast(string)->actual(), isolate);
     317             :     DCHECK(!string->IsConsString());
     318             :   }
     319    83553038 :   return string;
     320             : }
     321             : 
     322             : uint16_t String::Get(int index) {
     323             :   DCHECK(index >= 0 && index < length());
     324 12133669403 :   switch (StringShape(*this).full_representation_tag()) {
     325             :     case kSeqStringTag | kOneByteStringTag:
     326      106744 :       return SeqOneByteString::cast(*this)->SeqOneByteStringGet(index);
     327             :     case kSeqStringTag | kTwoByteStringTag:
     328           0 :       return SeqTwoByteString::cast(*this)->SeqTwoByteStringGet(index);
     329             :     case kConsStringTag | kOneByteStringTag:
     330             :     case kConsStringTag | kTwoByteStringTag:
     331      273964 :       return ConsString::cast(*this)->ConsStringGet(index);
     332             :     case kExternalStringTag | kOneByteStringTag:
     333           0 :       return ExternalOneByteString::cast(*this)->ExternalOneByteStringGet(
     334           0 :           index);
     335             :     case kExternalStringTag | kTwoByteStringTag:
     336           0 :       return ExternalTwoByteString::cast(*this)->ExternalTwoByteStringGet(
     337           0 :           index);
     338             :     case kSlicedStringTag | kOneByteStringTag:
     339             :     case kSlicedStringTag | kTwoByteStringTag:
     340     1094429 :       return SlicedString::cast(*this)->SlicedStringGet(index);
     341             :     case kThinStringTag | kOneByteStringTag:
     342             :     case kThinStringTag | kTwoByteStringTag:
     343        2109 :       return ThinString::cast(*this)->ThinStringGet(index);
     344             :     default:
     345             :       break;
     346             :   }
     347             : 
     348           0 :   UNREACHABLE();
     349             : }
     350             : 
     351             : void String::Set(int index, uint16_t value) {
     352             :   DCHECK(index >= 0 && index < length());
     353             :   DCHECK(StringShape(*this).IsSequential());
     354             : 
     355             :   return this->IsOneByteRepresentation()
     356             :              ? SeqOneByteString::cast(*this)->SeqOneByteStringSet(index, value)
     357             :              : SeqTwoByteString::cast(*this)->SeqTwoByteStringSet(index, value);
     358             : }
     359             : 
     360    23731737 : bool String::IsFlat() {
     361    47463474 :   if (!StringShape(*this).IsCons()) return true;
     362    11561280 :   return ConsString::cast(*this)->second()->length() == 0;
     363             : }
     364             : 
     365             : String String::GetUnderlying() {
     366             :   // Giving direct access to underlying string only makes sense if the
     367             :   // wrapping string is already flattened.
     368             :   DCHECK(this->IsFlat());
     369             :   DCHECK(StringShape(*this).IsIndirect());
     370             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     371             :                 static_cast<int>(SlicedString::kParentOffset));
     372             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     373             :                 static_cast<int>(ThinString::kActualOffset));
     374             :   const int kUnderlyingOffset = SlicedString::kParentOffset;
     375       16369 :   return String::cast(READ_FIELD(*this, kUnderlyingOffset));
     376             : }
     377             : 
     378             : template <class Visitor>
     379   151621481 : ConsString String::VisitFlat(Visitor* visitor, String string,
     380             :                              const int offset) {
     381             :   DisallowHeapAllocation no_gc;
     382             :   int slice_offset = offset;
     383             :   const int length = string->length();
     384             :   DCHECK(offset <= length);
     385             :   while (true) {
     386             :     int32_t type = string->map()->instance_type();
     387   157703408 :     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
     388             :       case kSeqStringTag | kOneByteStringTag:
     389   284639692 :         visitor->VisitOneByteString(
     390             :             SeqOneByteString::cast(string)->GetChars(no_gc) + slice_offset,
     391             :             length - offset);
     392   142359389 :         return ConsString();
     393             : 
     394             :       case kSeqStringTag | kTwoByteStringTag:
     395     8793564 :         visitor->VisitTwoByteString(
     396             :             SeqTwoByteString::cast(string)->GetChars(no_gc) + slice_offset,
     397             :             length - offset);
     398     4396782 :         return ConsString();
     399             : 
     400             :       case kExternalStringTag | kOneByteStringTag:
     401     5254398 :         visitor->VisitOneByteString(
     402             :             ExternalOneByteString::cast(string)->GetChars() + slice_offset,
     403             :             length - offset);
     404     2627199 :         return ConsString();
     405             : 
     406             :       case kExternalStringTag | kTwoByteStringTag:
     407     4061436 :         visitor->VisitTwoByteString(
     408             :             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
     409             :             length - offset);
     410     2030718 :         return ConsString();
     411             : 
     412             :       case kSlicedStringTag | kOneByteStringTag:
     413             :       case kSlicedStringTag | kTwoByteStringTag: {
     414             :         SlicedString slicedString = SlicedString::cast(string);
     415     6056509 :         slice_offset += slicedString->offset();
     416             :         string = slicedString->parent();
     417             :         continue;
     418             :       }
     419             : 
     420             :       case kConsStringTag | kOneByteStringTag:
     421             :       case kConsStringTag | kTwoByteStringTag:
     422             :         return ConsString::cast(string);
     423             : 
     424             :       case kThinStringTag | kOneByteStringTag:
     425             :       case kThinStringTag | kTwoByteStringTag:
     426             :         string = ThinString::cast(string)->actual();
     427       25418 :         continue;
     428             : 
     429             :       default:
     430           0 :         UNREACHABLE();
     431             :     }
     432             :   }
     433             : }
     434             : 
     435             : template <>
     436             : inline Vector<const uint8_t> String::GetCharVector(
     437             :     const DisallowHeapAllocation& no_gc) {
     438     2560420 :   String::FlatContent flat = GetFlatContent(no_gc);
     439             :   DCHECK(flat.IsOneByte());
     440             :   return flat.ToOneByteVector();
     441             : }
     442             : 
     443             : template <>
     444             : inline Vector<const uc16> String::GetCharVector(
     445             :     const DisallowHeapAllocation& no_gc) {
     446     1183740 :   String::FlatContent flat = GetFlatContent(no_gc);
     447             :   DCHECK(flat.IsTwoByte());
     448             :   return flat.ToUC16Vector();
     449             : }
     450             : 
     451        1428 : uint32_t String::ToValidIndex(Object number) {
     452             :   uint32_t index = PositiveNumberToUint32(number);
     453        1428 :   uint32_t length_value = static_cast<uint32_t>(length());
     454        1428 :   if (index > length_value) return length_value;
     455        1284 :   return index;
     456             : }
     457             : 
     458      106744 : uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
     459             :   DCHECK(index >= 0 && index < length());
     460  7190086136 :   return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
     461             : }
     462             : 
     463     2378963 : void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
     464             :   DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
     465   986325377 :   WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize,
     466   986325377 :                    static_cast<byte>(value));
     467     2378963 : }
     468             : 
     469             : Address SeqOneByteString::GetCharsAddress() {
     470   581174640 :   return FIELD_ADDR(*this, kHeaderSize);
     471             : }
     472             : 
     473             : uint8_t* SeqOneByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     474             :   USE(no_gc);
     475   581174600 :   return reinterpret_cast<uint8_t*>(GetCharsAddress());
     476             : }
     477             : 
     478             : Address SeqTwoByteString::GetCharsAddress() {
     479          12 :   return FIELD_ADDR(*this, kHeaderSize);
     480             : }
     481             : 
     482             : uc16* SeqTwoByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     483             :   USE(no_gc);
     484    39581095 :   return reinterpret_cast<uc16*>(FIELD_ADDR(*this, kHeaderSize));
     485             : }
     486             : 
     487           0 : uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
     488             :   DCHECK(index >= 0 && index < length());
     489   225616369 :   return READ_UINT16_FIELD(*this, kHeaderSize + index * kShortSize);
     490             : }
     491             : 
     492          88 : void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
     493             :   DCHECK(index >= 0 && index < length());
     494    10700545 :   WRITE_UINT16_FIELD(*this, kHeaderSize + index * kShortSize, value);
     495          88 : }
     496             : 
     497             : int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
     498             :   return SizeFor(length());
     499             : }
     500             : 
     501             : int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
     502             :   return SizeFor(length());
     503             : }
     504             : 
     505             : String SlicedString::parent() {
     506     9894970 :   return String::cast(READ_FIELD(*this, kParentOffset));
     507             : }
     508             : 
     509     1915775 : void SlicedString::set_parent(Isolate* isolate, String parent,
     510             :                               WriteBarrierMode mode) {
     511             :   DCHECK(parent->IsSeqString() || parent->IsExternalString());
     512     1915775 :   WRITE_FIELD(*this, kParentOffset, parent);
     513     3831550 :   CONDITIONAL_WRITE_BARRIER(*this, kParentOffset, parent, mode);
     514     1915775 : }
     515             : 
     516    11810715 : SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
     517             : 
     518             : String ConsString::first() {
     519   177921603 :   return String::cast(READ_FIELD(*this, kFirstOffset));
     520             : }
     521             : 
     522      478451 : Object ConsString::unchecked_first() { return READ_FIELD(*this, kFirstOffset); }
     523             : 
     524    18500800 : void ConsString::set_first(Isolate* isolate, String value,
     525             :                            WriteBarrierMode mode) {
     526    18500800 :   WRITE_FIELD(*this, kFirstOffset, value);
     527    25604577 :   CONDITIONAL_WRITE_BARRIER(*this, kFirstOffset, value, mode);
     528    18500800 : }
     529             : 
     530             : String ConsString::second() {
     531   160648579 :   return String::cast(READ_FIELD(*this, kSecondOffset));
     532             : }
     533             : 
     534             : Object ConsString::unchecked_second() {
     535    82090082 :   return RELAXED_READ_FIELD(*this, kSecondOffset);
     536             : }
     537             : 
     538    18500801 : void ConsString::set_second(Isolate* isolate, String value,
     539             :                             WriteBarrierMode mode) {
     540    18500801 :   WRITE_FIELD(*this, kSecondOffset, value);
     541    25604578 :   CONDITIONAL_WRITE_BARRIER(*this, kSecondOffset, value, mode);
     542    18500801 : }
     543             : 
     544   115408482 : ACCESSORS(ThinString, actual, String, kActualOffset)
     545             : 
     546             : HeapObject ThinString::unchecked_actual() const {
     547     1377065 :   return HeapObject::unchecked_cast(READ_FIELD(*this, kActualOffset));
     548             : }
     549             : 
     550       87469 : bool ExternalString::is_uncached() const {
     551             :   InstanceType type = map()->instance_type();
     552       87469 :   return (type & kUncachedExternalStringMask) == kUncachedExternalStringTag;
     553             : }
     554             : 
     555             : Address ExternalString::resource_as_address() {
     556          30 :   return READ_UINTPTR_FIELD(*this, kResourceOffset);
     557             : }
     558             : 
     559          30 : void ExternalString::set_address_as_resource(Address address) {
     560          30 :   WRITE_UINTPTR_FIELD(*this, kResourceOffset, address);
     561          30 :   if (IsExternalOneByteString()) {
     562          15 :     ExternalOneByteString::cast(*this)->update_data_cache();
     563             :   } else {
     564          15 :     ExternalTwoByteString::cast(*this)->update_data_cache();
     565             :   }
     566          30 : }
     567             : 
     568             : uint32_t ExternalString::resource_as_uint32() {
     569          20 :   return static_cast<uint32_t>(READ_UINTPTR_FIELD(*this, kResourceOffset));
     570             : }
     571             : 
     572          10 : void ExternalString::set_uint32_as_resource(uint32_t value) {
     573          20 :   WRITE_UINTPTR_FIELD(*this, kResourceOffset, value);
     574          10 :   if (is_uncached()) return;
     575          10 :   WRITE_UINTPTR_FIELD(*this, kResourceDataOffset, kNullAddress);
     576             : }
     577             : 
     578       87009 : void ExternalString::DisposeResource() {
     579             :   v8::String::ExternalStringResourceBase* resource =
     580             :       reinterpret_cast<v8::String::ExternalStringResourceBase*>(
     581      174018 :           READ_UINTPTR_FIELD(*this, ExternalString::kResourceOffset));
     582             : 
     583             :   // Dispose of the C++ object if it has not already been disposed.
     584       87009 :   if (resource != nullptr) {
     585       86896 :     resource->Dispose();
     586       86896 :     WRITE_UINTPTR_FIELD(*this, ExternalString::kResourceOffset, kNullAddress);
     587             :   }
     588       87009 : }
     589             : 
     590             : const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
     591             :   return reinterpret_cast<Resource*>(
     592    24273790 :       READ_UINTPTR_FIELD(*this, kResourceOffset));
     593             : }
     594             : 
     595       68207 : void ExternalOneByteString::update_data_cache() {
     596       68207 :   if (is_uncached()) return;
     597       12326 :   WRITE_UINTPTR_FIELD(*this, kResourceDataOffset,
     598             :                       reinterpret_cast<Address>(resource()->data()));
     599             : }
     600             : 
     601       67843 : void ExternalOneByteString::SetResource(
     602             :     Isolate* isolate, const ExternalOneByteString::Resource* resource) {
     603       67843 :   set_resource(resource);
     604       67845 :   size_t new_payload = resource == nullptr ? 0 : resource->length();
     605       67845 :   if (new_payload > 0) {
     606       67780 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     607             :   }
     608       67847 : }
     609             : 
     610       68256 : void ExternalOneByteString::set_resource(
     611             :     const ExternalOneByteString::Resource* resource) {
     612      136512 :   WRITE_UINTPTR_FIELD(*this, kResourceOffset,
     613             :                       reinterpret_cast<Address>(resource));
     614       68256 :   if (resource != nullptr) update_data_cache();
     615       68257 : }
     616             : 
     617             : const uint8_t* ExternalOneByteString::GetChars() {
     618    12048694 :   return reinterpret_cast<const uint8_t*>(resource()->data());
     619             : }
     620             : 
     621           0 : uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
     622             :   DCHECK(index >= 0 && index < length());
     623     8864010 :   return GetChars()[index];
     624             : }
     625             : 
     626             : const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
     627             :   return reinterpret_cast<Resource*>(
     628     5026418 :       READ_UINTPTR_FIELD(*this, kResourceOffset));
     629             : }
     630             : 
     631       19252 : void ExternalTwoByteString::update_data_cache() {
     632       19252 :   if (is_uncached()) return;
     633       37904 :   WRITE_UINTPTR_FIELD(*this, kResourceDataOffset,
     634             :                       reinterpret_cast<Address>(resource()->data()));
     635             : }
     636             : 
     637       19295 : void ExternalTwoByteString::SetResource(
     638             :     Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
     639       19295 :   set_resource(resource);
     640       19295 :   size_t new_payload = resource == nullptr ? 0 : resource->length() * 2;
     641       19295 :   if (new_payload > 0) {
     642       19237 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     643             :   }
     644       19295 : }
     645             : 
     646       19295 : void ExternalTwoByteString::set_resource(
     647             :     const ExternalTwoByteString::Resource* resource) {
     648       38590 :   WRITE_UINTPTR_FIELD(*this, kResourceOffset,
     649             :                       reinterpret_cast<Address>(resource));
     650       19295 :   if (resource != nullptr) update_data_cache();
     651       19295 : }
     652             : 
     653     2494150 : const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
     654             : 
     655           0 : uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
     656             :   DCHECK(index >= 0 && index < length());
     657       58697 :   return GetChars()[index];
     658             : }
     659             : 
     660             : const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
     661             :     unsigned start) {
     662             :   return GetChars() + start;
     663             : }
     664             : 
     665    61174143 : int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
     666             : 
     667             : void ConsStringIterator::PushLeft(ConsString string) {
     668    63657596 :   frames_[depth_++ & kDepthMask] = string;
     669             : }
     670             : 
     671             : void ConsStringIterator::PushRight(ConsString string) {
     672             :   // Inplace update.
     673    31537107 :   frames_[(depth_ - 1) & kDepthMask] = string;
     674             : }
     675             : 
     676             : void ConsStringIterator::AdjustMaximumDepth() {
     677    30395037 :   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
     678             : }
     679             : 
     680             : void ConsStringIterator::Pop() {
     681             :   DCHECK_GT(depth_, 0);
     682             :   DCHECK(depth_ <= maximum_depth_);
     683    30957926 :   depth_--;
     684             : }
     685             : 
     686  1039907437 : uint16_t StringCharacterStream::GetNext() {
     687             :   DCHECK(buffer8_ != nullptr && end_ != nullptr);
     688             :   // Advance cursor if needed.
     689  1039907437 :   if (buffer8_ == end_) HasMore();
     690             :   DCHECK(buffer8_ < end_);
     691  1039907440 :   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
     692             : }
     693             : 
     694           0 : StringCharacterStream::StringCharacterStream(String string, int offset)
     695     6306735 :     : is_one_byte_(false) {
     696     6306735 :   Reset(string, offset);
     697           0 : }
     698             : 
     699    11558640 : void StringCharacterStream::Reset(String string, int offset) {
     700    11558640 :   buffer8_ = nullptr;
     701    11558640 :   end_ = nullptr;
     702    11558640 :   ConsString cons_string = String::VisitFlat(this, string, offset);
     703    11558640 :   iter_.Reset(cons_string, offset);
     704    11558645 :   if (!cons_string.is_null()) {
     705       16008 :     string = iter_.Next(&offset);
     706       57668 :     if (!string.is_null()) String::VisitFlat(this, string, offset);
     707             :   }
     708    11558645 : }
     709             : 
     710  1048898953 : bool StringCharacterStream::HasMore() {
     711  1048898953 :   if (buffer8_ != end_) return true;
     712             :   int offset;
     713    20015523 :   String string = iter_.Next(&offset);
     714             :   DCHECK_EQ(offset, 0);
     715    20015523 :   if (string.is_null()) return false;
     716     9521109 :   String::VisitFlat(this, string);
     717             :   DCHECK(buffer8_ != end_);
     718     9521109 :   return true;
     719             : }
     720             : 
     721             : void StringCharacterStream::VisitOneByteString(const uint8_t* chars,
     722             :                                                int length) {
     723    16842942 :   is_one_byte_ = true;
     724    16842942 :   buffer8_ = chars;
     725    16842942 :   end_ = chars + length;
     726             : }
     727             : 
     728             : void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
     729             :                                                int length) {
     730     4236660 :   is_one_byte_ = false;
     731     4236660 :   buffer16_ = chars;
     732     4236660 :   end_ = reinterpret_cast<const uint8_t*>(chars + length);
     733             : }
     734             : 
     735    38662262 : bool String::AsArrayIndex(uint32_t* index) {
     736             :   uint32_t field = hash_field();
     737    38662262 :   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
     738             :     return false;
     739             :   }
     740     7186423 :   return SlowAsArrayIndex(index);
     741             : }
     742             : 
     743             : SubStringRange::SubStringRange(String string,
     744             :                                const DisallowHeapAllocation& no_gc, int first,
     745             :                                int length)
     746             :     : string_(string),
     747             :       first_(first),
     748             :       length_(length == -1 ? string->length() : length),
     749           2 :       no_gc_(no_gc) {}
     750             : 
     751             : class SubStringRange::iterator final {
     752             :  public:
     753             :   typedef std::forward_iterator_tag iterator_category;
     754             :   typedef int difference_type;
     755             :   typedef uc16 value_type;
     756             :   typedef uc16* pointer;
     757             :   typedef uc16& reference;
     758             : 
     759             :   iterator(const iterator& other) = default;
     760             : 
     761             :   uc16 operator*() { return content_.Get(offset_); }
     762             :   bool operator==(const iterator& other) const {
     763             :     return content_.UsesSameString(other.content_) && offset_ == other.offset_;
     764             :   }
     765             :   bool operator!=(const iterator& other) const {
     766          62 :     return !content_.UsesSameString(other.content_) || offset_ != other.offset_;
     767             :   }
     768             :   iterator& operator++() {
     769          60 :     ++offset_;
     770             :     return *this;
     771             :   }
     772             :   iterator operator++(int);
     773             : 
     774             :  private:
     775             :   friend class String;
     776             :   friend class SubStringRange;
     777             :   iterator(String from, int offset, const DisallowHeapAllocation& no_gc)
     778           4 :       : content_(from->GetFlatContent(no_gc)), offset_(offset) {}
     779             :   String::FlatContent content_;
     780             :   int offset_;
     781             : };
     782             : 
     783             : SubStringRange::iterator SubStringRange::begin() {
     784             :   return SubStringRange::iterator(string_, first_, no_gc_);
     785             : }
     786             : 
     787             : SubStringRange::iterator SubStringRange::end() {
     788           2 :   return SubStringRange::iterator(string_, first_ + length_, no_gc_);
     789             : }
     790             : 
     791             : }  // namespace internal
     792             : }  // namespace v8
     793             : 
     794             : #include "src/objects/object-macros-undef.h"
     795             : 
     796             : #endif  // V8_OBJECTS_STRING_INL_H_

Generated by: LCOV version 1.10