LCOV - code coverage report
Current view: top level - src/objects - string-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 271 279 97.1 %
Date: 2019-02-19 Functions: 79 93 84.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/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  1145599161 : INT32_ACCESSORS(String, length, kLengthOffset)
      26             : 
      27             : int String::synchronized_length() const {
      28             :   return base::AsAtomic32::Acquire_Load(
      29   493383968 :       reinterpret_cast<const int32_t*>(FIELD_ADDR(*this, kLengthOffset)));
      30             : }
      31             : 
      32             : void String::synchronized_set_length(int value) {
      33             :   base::AsAtomic32::Release_Store(
      34    11800141 :       reinterpret_cast<int32_t*>(FIELD_ADDR(*this, kLengthOffset)), value);
      35             : }
      36             : 
      37  4228840018 : OBJECT_CONSTRUCTORS_IMPL(String, Name)
      38    23574764 : OBJECT_CONSTRUCTORS_IMPL(SeqString, String)
      39 17907512828 : OBJECT_CONSTRUCTORS_IMPL(SeqOneByteString, SeqString)
      40   604752926 : OBJECT_CONSTRUCTORS_IMPL(SeqTwoByteString, SeqString)
      41    14989630 : OBJECT_CONSTRUCTORS_IMPL(InternalizedString, String)
      42   463737726 : OBJECT_CONSTRUCTORS_IMPL(ConsString, String)
      43    29967600 : OBJECT_CONSTRUCTORS_IMPL(ThinString, String)
      44    23912640 : OBJECT_CONSTRUCTORS_IMPL(SlicedString, String)
      45      343416 : OBJECT_CONSTRUCTORS_IMPL(ExternalString, String)
      46    23971426 : OBJECT_CONSTRUCTORS_IMPL(ExternalOneByteString, ExternalString)
      47     4773938 : OBJECT_CONSTRUCTORS_IMPL(ExternalTwoByteString, ExternalString)
      48             : 
      49   231868697 : CAST_ACCESSOR(ConsString)
      50    11985712 : CAST_ACCESSOR(ExternalOneByteString)
      51      171710 : CAST_ACCESSOR(ExternalString)
      52     2386969 : CAST_ACCESSOR(ExternalTwoByteString)
      53     7494815 : CAST_ACCESSOR(InternalizedString)
      54  8953756910 : CAST_ACCESSOR(SeqOneByteString)
      55    11787383 : CAST_ACCESSOR(SeqString)
      56   302376463 : CAST_ACCESSOR(SeqTwoByteString)
      57    11956328 : CAST_ACCESSOR(SlicedString)
      58  2106141486 : CAST_ACCESSOR(String)
      59    14983835 : CAST_ACCESSOR(ThinString)
      60             : 
      61  6481623593 : StringShape::StringShape(const String str)
      62  6858264472 :     : type_(str->map()->instance_type()) {
      63             :   set_valid();
      64             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      65  6481623593 : }
      66             : 
      67             : StringShape::StringShape(Map map) : type_(map->instance_type()) {
      68             :   set_valid();
      69             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      70             : }
      71             : 
      72        1232 : StringShape::StringShape(InstanceType t) : type_(static_cast<uint32_t>(t)) {
      73        1232 :   set_valid();
      74             :   DCHECK_EQ(type_ & kIsNotStringMask, kStringTag);
      75        1232 : }
      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             : bool StringShape::HasOnlyOneByteChars() {
      85     1958489 :   return (type_ & kStringEncodingMask) == kOneByteStringTag ||
      86     1958489 :          (type_ & kOneByteDataHintMask) == kOneByteDataHintTag;
      87             : }
      88             : 
      89    97897817 : bool StringShape::IsCons() {
      90   113733602 :   return (type_ & kStringRepresentationMask) == kConsStringTag;
      91             : }
      92             : 
      93   162555145 : bool StringShape::IsThin() {
      94   162666297 :   return (type_ & kStringRepresentationMask) == kThinStringTag;
      95             : }
      96             : 
      97     5934241 : bool StringShape::IsSliced() {
      98     6045393 :   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
      99             : }
     100             : 
     101             : bool StringShape::IsIndirect() {
     102         621 :   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
     103             : }
     104             : 
     105    96437674 : bool StringShape::IsExternal() {
     106    98498515 :   return (type_ & kStringRepresentationMask) == kExternalStringTag;
     107             : }
     108             : 
     109    77038621 : bool StringShape::IsSequential() {
     110    77038621 :   return (type_ & kStringRepresentationMask) == kSeqStringTag;
     111             : }
     112             : 
     113             : StringRepresentationTag StringShape::representation_tag() {
     114   460700886 :   uint32_t tag = (type_ & kStringRepresentationMask);
     115             :   return static_cast<StringRepresentationTag>(tag);
     116             : }
     117             : 
     118   156434438 : uint32_t StringShape::encoding_tag() { return type_ & kStringEncodingMask; }
     119             : 
     120  6041761334 : uint32_t StringShape::full_representation_tag() {
     121  6242743834 :   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
     122             : }
     123             : 
     124             : STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) ==
     125             :               Internals::kFullStringRepresentationMask);
     126             : 
     127             : STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) ==
     128             :               Internals::kStringEncodingMask);
     129             : 
     130             : bool StringShape::IsSequentialOneByte() {
     131             :   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
     132             : }
     133             : 
     134             : bool StringShape::IsSequentialTwoByte() {
     135             :   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
     136             : }
     137             : 
     138             : bool StringShape::IsExternalOneByte() {
     139          27 :   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
     140             : }
     141             : 
     142             : STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) ==
     143             :               Internals::kExternalOneByteRepresentationTag);
     144             : 
     145             : STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag);
     146             : 
     147             : bool StringShape::IsExternalTwoByte() {
     148          67 :   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
     149             : }
     150             : 
     151             : STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) ==
     152             :               Internals::kExternalTwoByteRepresentationTag);
     153             : 
     154             : STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
     155             : 
     156   130924405 : bool String::IsOneByteRepresentation() const {
     157             :   uint32_t type = map()->instance_type();
     158   130924405 :   return (type & kStringEncodingMask) == kOneByteStringTag;
     159             : }
     160             : 
     161      165719 : bool String::IsTwoByteRepresentation() const {
     162             :   uint32_t type = map()->instance_type();
     163      165719 :   return (type & kStringEncodingMask) == kTwoByteStringTag;
     164             : }
     165             : 
     166    14304896 : bool String::IsOneByteRepresentationUnderneath(String string) {
     167             :   while (true) {
     168             :     uint32_t type = string.map()->instance_type();
     169             :     STATIC_ASSERT(kIsIndirectStringTag != 0);
     170             :     STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
     171             :     DCHECK(string.IsFlat());
     172    14318044 :     switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
     173             :       case kOneByteStringTag:
     174             :         return true;
     175             :       case kTwoByteStringTag:
     176     8173968 :         return false;
     177             :       default:  // Cons, sliced, thin, strings need to go deeper.
     178       13148 :         string = string.GetUnderlying();
     179             :     }
     180       13148 :   }
     181             : }
     182             : 
     183     9621066 : bool String::HasOnlyOneByteChars() {
     184             :   uint32_t type = map()->instance_type();
     185    19242118 :   return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
     186    19242118 :          IsOneByteRepresentation();
     187             : }
     188             : 
     189   388515581 : uc32 FlatStringReader::Get(int index) {
     190   388433999 :   if (is_one_byte_) {
     191   387585145 :     return Get<uint8_t>(index);
     192             :   } else {
     193      848854 :     return Get<uc16>(index);
     194             :   }
     195             : }
     196             : 
     197             : template <typename Char>
     198  2441860297 : Char FlatStringReader::Get(int index) {
     199             :   DCHECK_EQ(is_one_byte_, sizeof(Char) == 1);
     200             :   DCHECK(0 <= index && index <= length_);
     201             :   if (sizeof(Char) == 1) {
     202  2829441346 :     return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]);
     203             :   } else {
     204      852950 :     return static_cast<Char>(static_cast<const uc16*>(start_)[index]);
     205             :   }
     206             : }
     207             : 
     208             : template <typename Char>
     209           0 : class SequentialStringKey : public StringTableKey {
     210             :  public:
     211       85895 :   explicit SequentialStringKey(Vector<const Char> string, uint64_t seed)
     212             :       : StringTableKey(StringHasher::HashSequentialString<Char>(
     213             :             string.start(), string.length(), seed)),
     214      257685 :         string_(string) {}
     215             : 
     216             :   Vector<const Char> string_;
     217             : };
     218             : 
     219           0 : class OneByteStringKey : public SequentialStringKey<uint8_t> {
     220             :  public:
     221             :   OneByteStringKey(Vector<const uint8_t> str, uint64_t seed)
     222       84860 :       : SequentialStringKey<uint8_t>(str, seed) {}
     223             : 
     224      129053 :   bool IsMatch(Object string) override {
     225      129053 :     return String::cast(string)->IsOneByteEqualTo(string_);
     226             :   }
     227             : 
     228             :   Handle<String> AsHandle(Isolate* isolate) override;
     229             : };
     230             : 
     231           0 : class SeqOneByteSubStringKey : public StringTableKey {
     232             :  public:
     233             : // VS 2017 on official builds gives this spurious warning:
     234             : // warning C4789: buffer 'key' of size 16 bytes will be overrun; 4 bytes will
     235             : // be written starting at offset 16
     236             : // https://bugs.chromium.org/p/v8/issues/detail?id=6068
     237             : #if defined(V8_CC_MSVC)
     238             : #pragma warning(push)
     239             : #pragma warning(disable : 4789)
     240             : #endif
     241      470711 :   SeqOneByteSubStringKey(Isolate* isolate, Handle<SeqOneByteString> string,
     242             :                          int from, int length)
     243      470711 :       : StringTableKey(0), string_(string), from_(from), length_(length) {
     244             :     // We have to set the hash later.
     245             :     DisallowHeapAllocation no_gc;
     246             :     uint32_t hash = StringHasher::HashSequentialString(
     247      941422 :         string->GetChars(no_gc) + from, length, HashSeed(isolate));
     248             :     set_hash_field(hash);
     249             : 
     250             :     DCHECK_LE(0, length_);
     251             :     DCHECK_LE(from_ + length_, string_->length());
     252             :     DCHECK(string_->IsSeqOneByteString());
     253      470711 :   }
     254             : #if defined(V8_CC_MSVC)
     255             : #pragma warning(pop)
     256             : #endif
     257             : 
     258             :   bool IsMatch(Object string) override;
     259             :   Handle<String> AsHandle(Isolate* isolate) override;
     260             : 
     261             :  private:
     262             :   Handle<SeqOneByteString> string_;
     263             :   int from_;
     264             :   int length_;
     265             : };
     266             : 
     267           0 : class TwoByteStringKey : public SequentialStringKey<uc16> {
     268             :  public:
     269             :   explicit TwoByteStringKey(Vector<const uc16> str, uint64_t seed)
     270        1035 :       : SequentialStringKey<uc16>(str, seed) {}
     271             : 
     272        2255 :   bool IsMatch(Object string) override {
     273        2255 :     return String::cast(string)->IsTwoByteEqualTo(string_);
     274             :   }
     275             : 
     276             :   Handle<String> AsHandle(Isolate* isolate) override;
     277             : };
     278             : 
     279             : // Utf8StringKey carries a vector of chars as key.
     280           0 : class Utf8StringKey : public StringTableKey {
     281             :  public:
     282    12949744 :   explicit Utf8StringKey(Vector<const char> string, uint64_t seed)
     283             :       : StringTableKey(StringHasher::ComputeUtf8Hash(string, seed, &chars_)),
     284    25899488 :         string_(string) {}
     285             : 
     286    18001618 :   bool IsMatch(Object string) override {
     287    18001618 :     return String::cast(string)->IsUtf8EqualTo(string_);
     288             :   }
     289             : 
     290      488255 :   Handle<String> AsHandle(Isolate* isolate) override {
     291             :     return isolate->factory()->NewInternalizedStringFromUtf8(string_, chars_,
     292      488255 :                                                              HashField());
     293             :   }
     294             : 
     295             :  private:
     296             :   Vector<const char> string_;
     297             :   int chars_;  // Caches the number of characters when computing the hash code.
     298             : };
     299             : 
     300    23617808 : bool String::Equals(String other) {
     301    23617808 :   if (other == *this) return true;
     302    58900279 :   if (this->IsInternalizedString() && other->IsInternalizedString()) {
     303             :     return false;
     304             :   }
     305     2861008 :   return SlowEquals(other);
     306             : }
     307             : 
     308     3221990 : bool String::Equals(Isolate* isolate, Handle<String> one, Handle<String> two) {
     309     3221990 :   if (one.is_identical_to(two)) return true;
     310    10711870 :   if (one->IsInternalizedString() && two->IsInternalizedString()) {
     311             :     return false;
     312             :   }
     313      733889 :   return SlowEquals(isolate, one, two);
     314             : }
     315             : 
     316    88031168 : Handle<String> String::Flatten(Isolate* isolate, Handle<String> string,
     317             :                                PretenureFlag pretenure) {
     318   176062330 :   if (string->IsConsString()) {
     319     9293162 :     Handle<ConsString> cons = Handle<ConsString>::cast(string);
     320     9293162 :     if (cons->IsFlat()) {
     321     7230702 :       string = handle(cons->first(), isolate);
     322             :     } else {
     323     5677811 :       return SlowFlatten(isolate, cons, pretenure);
     324             :     }
     325             :   }
     326   164706638 :   if (string->IsThinString()) {
     327     2658570 :     string = handle(Handle<ThinString>::cast(string)->actual(), isolate);
     328             :     DCHECK(!string->IsConsString());
     329             :   }
     330    82353296 :   return string;
     331             : }
     332             : 
     333             : uint16_t String::Get(int index) {
     334             :   DCHECK(index >= 0 && index < length());
     335  6041761334 :   switch (StringShape(*this).full_representation_tag()) {
     336             :     case kSeqStringTag | kOneByteStringTag:
     337  5805882553 :       return SeqOneByteString::cast(*this)->SeqOneByteStringGet(index);
     338             :     case kSeqStringTag | kTwoByteStringTag:
     339   225616973 :       return SeqTwoByteString::cast(*this)->SeqTwoByteStringGet(index);
     340             :     case kConsStringTag | kOneByteStringTag:
     341             :     case kConsStringTag | kTwoByteStringTag:
     342      273197 :       return ConsString::cast(*this)->ConsStringGet(index);
     343             :     case kExternalStringTag | kOneByteStringTag:
     344             :       return ExternalOneByteString::cast(*this)->ExternalOneByteStringGet(
     345     8838050 :           index);
     346             :     case kExternalStringTag | kTwoByteStringTag:
     347             :       return ExternalTwoByteString::cast(*this)->ExternalTwoByteStringGet(
     348       54884 :           index);
     349             :     case kSlicedStringTag | kOneByteStringTag:
     350             :     case kSlicedStringTag | kTwoByteStringTag:
     351     1093567 :       return SlicedString::cast(*this)->SlicedStringGet(index);
     352             :     case kThinStringTag | kOneByteStringTag:
     353             :     case kThinStringTag | kTwoByteStringTag:
     354        2118 :       return ThinString::cast(*this)->ThinStringGet(index);
     355             :     default:
     356             :       break;
     357             :   }
     358             : 
     359           0 :   UNREACHABLE();
     360             : }
     361             : 
     362             : void String::Set(int index, uint16_t value) {
     363             :   DCHECK(index >= 0 && index < length());
     364             :   DCHECK(StringShape(*this).IsSequential());
     365             : 
     366             :   return this->IsOneByteRepresentation()
     367             :              ? SeqOneByteString::cast(*this)->SeqOneByteStringSet(index, value)
     368             :              : SeqTwoByteString::cast(*this)->SeqTwoByteStringSet(index, value);
     369             : }
     370             : 
     371    12645516 : bool String::IsFlat() {
     372    12645516 :   if (!StringShape(*this).IsCons()) return true;
     373    22419794 :   return ConsString::cast(*this)->second()->length() == 0;
     374             : }
     375             : 
     376       13148 : String String::GetUnderlying() {
     377             :   // Giving direct access to underlying string only makes sense if the
     378             :   // wrapping string is already flattened.
     379             :   DCHECK(this->IsFlat());
     380             :   DCHECK(StringShape(*this).IsIndirect());
     381             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     382             :                 static_cast<int>(SlicedString::kParentOffset));
     383             :   STATIC_ASSERT(static_cast<int>(ConsString::kFirstOffset) ==
     384             :                 static_cast<int>(ThinString::kActualOffset));
     385             :   const int kUnderlyingOffset = SlicedString::kParentOffset;
     386       26296 :   return String::cast(READ_FIELD(*this, kUnderlyingOffset));
     387             : }
     388             : 
     389             : template <class Visitor>
     390    91094137 : ConsString String::VisitFlat(Visitor* visitor, String string,
     391             :                              const int offset) {
     392             :   DisallowHeapAllocation no_gc;
     393             :   int slice_offset = offset;
     394             :   const int length = string->length();
     395             :   DCHECK(offset <= length);
     396             :   while (true) {
     397             :     int32_t type = string->map()->instance_type();
     398    97174933 :     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
     399             :       case kSeqStringTag | kOneByteStringTag:
     400   163558532 :         visitor->VisitOneByteString(
     401             :             SeqOneByteString::cast(string)->GetChars(no_gc) + slice_offset,
     402             :             length - offset);
     403    81818967 :         return ConsString();
     404             : 
     405             :       case kSeqStringTag | kTwoByteStringTag:
     406     8793332 :         visitor->VisitTwoByteString(
     407             :             SeqTwoByteString::cast(string)->GetChars(no_gc) + slice_offset,
     408             :             length - offset);
     409     4396666 :         return ConsString();
     410             : 
     411             :       case kExternalStringTag | kOneByteStringTag:
     412     5254398 :         visitor->VisitOneByteString(
     413             :             ExternalOneByteString::cast(string)->GetChars() + slice_offset,
     414             :             length - offset);
     415     2627199 :         return ConsString();
     416             : 
     417             :       case kExternalStringTag | kTwoByteStringTag:
     418     4061436 :         visitor->VisitTwoByteString(
     419             :             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
     420             :             length - offset);
     421     2030718 :         return ConsString();
     422             : 
     423             :       case kSlicedStringTag | kOneByteStringTag:
     424             :       case kSlicedStringTag | kTwoByteStringTag: {
     425     6056738 :         SlicedString slicedString = SlicedString::cast(string);
     426     6056738 :         slice_offset += slicedString->offset();
     427     6056738 :         string = slicedString->parent();
     428             :         continue;
     429             :       }
     430             : 
     431             :       case kConsStringTag | kOneByteStringTag:
     432             :       case kConsStringTag | kTwoByteStringTag:
     433             :         return ConsString::cast(string);
     434             : 
     435             :       case kThinStringTag | kOneByteStringTag:
     436             :       case kThinStringTag | kTwoByteStringTag:
     437       24058 :         string = ThinString::cast(string)->actual();
     438       24058 :         continue;
     439             : 
     440             :       default:
     441           0 :         UNREACHABLE();
     442             :     }
     443             :   }
     444             : }
     445             : 
     446             : template <>
     447             : inline Vector<const uint8_t> String::GetCharVector(
     448             :     const DisallowHeapAllocation& no_gc) {
     449     1420387 :   String::FlatContent flat = GetFlatContent(no_gc);
     450             :   DCHECK(flat.IsOneByte());
     451     1420388 :   return flat.ToOneByteVector();
     452             : }
     453             : 
     454             : template <>
     455             : inline Vector<const uc16> String::GetCharVector(
     456             :     const DisallowHeapAllocation& no_gc) {
     457      860964 :   String::FlatContent flat = GetFlatContent(no_gc);
     458             :   DCHECK(flat.IsTwoByte());
     459      860964 :   return flat.ToUC16Vector();
     460             : }
     461             : 
     462         333 : uint32_t String::ToValidIndex(Object number) {
     463        1410 :   uint32_t index = PositiveNumberToUint32(number);
     464        1410 :   uint32_t length_value = static_cast<uint32_t>(length());
     465        1410 :   if (index > length_value) return length_value;
     466         324 :   return index;
     467             : }
     468             : 
     469  6877007941 : uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
     470             :   DCHECK(index >= 0 && index < length());
     471  7150876828 :   return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
     472             : }
     473             : 
     474  2611396954 : void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
     475             :   DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
     476  3401473921 :   WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize,
     477  3401473921 :                    static_cast<byte>(value));
     478  2611396954 : }
     479             : 
     480             : Address SeqOneByteString::GetCharsAddress() {
     481   510416547 :   return FIELD_ADDR(*this, kHeaderSize);
     482             : }
     483             : 
     484         645 : uint8_t* SeqOneByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     485             :   USE(no_gc);
     486   510416507 :   return reinterpret_cast<uint8_t*>(GetCharsAddress());
     487             : }
     488             : 
     489             : Address SeqTwoByteString::GetCharsAddress() {
     490          12 :   return FIELD_ADDR(*this, kHeaderSize);
     491             : }
     492             : 
     493           5 : uc16* SeqTwoByteString::GetChars(const DisallowHeapAllocation& no_gc) {
     494             :   USE(no_gc);
     495    31895658 :   return reinterpret_cast<uc16*>(FIELD_ADDR(*this, kHeaderSize));
     496             : }
     497             : 
     498   225616973 : uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
     499             :   DCHECK(index >= 0 && index < length());
     500   225616973 :   return READ_UINT16_FIELD(*this, kHeaderSize + index * kShortSize);
     501             : }
     502             : 
     503     1442793 : void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
     504             :   DCHECK(index >= 0 && index < length());
     505     8449087 :   WRITE_UINT16_FIELD(*this, kHeaderSize + index * kShortSize, value);
     506     1442793 : }
     507             : 
     508             : int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
     509             :   return SizeFor(length());
     510             : }
     511             : 
     512             : int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
     513             :   return SizeFor(length());
     514             : }
     515             : 
     516     9891788 : String SlicedString::parent() {
     517    19783576 :   return String::cast(READ_FIELD(*this, kParentOffset));
     518             : }
     519             : 
     520     1916092 : void SlicedString::set_parent(Isolate* isolate, String parent,
     521             :                               WriteBarrierMode mode) {
     522             :   DCHECK(parent->IsSeqString() || parent->IsExternalString());
     523     1916092 :   WRITE_FIELD(*this, kParentOffset, parent);
     524     5748276 :   CONDITIONAL_WRITE_BARRIER(*this, kParentOffset, parent, mode);
     525     1916092 : }
     526             : 
     527    21699588 : SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
     528             : 
     529   170065712 : String ConsString::first() {
     530   340131424 :   return String::cast(READ_FIELD(*this, kFirstOffset));
     531             : }
     532             : 
     533     1527996 : Object ConsString::unchecked_first() { return READ_FIELD(*this, kFirstOffset); }
     534             : 
     535    17982290 : void ConsString::set_first(Isolate* isolate, String value,
     536             :                            WriteBarrierMode mode) {
     537    17982290 :   WRITE_FIELD(*this, kFirstOffset, value);
     538    31587182 :   CONDITIONAL_WRITE_BARRIER(*this, kFirstOffset, value, mode);
     539    17982290 : }
     540             : 
     541   146394101 : String ConsString::second() {
     542   292788202 :   return String::cast(READ_FIELD(*this, kSecondOffset));
     543             : }
     544             : 
     545    50772457 : Object ConsString::unchecked_second() {
     546   101544914 :   return RELAXED_READ_FIELD(*this, kSecondOffset);
     547             : }
     548             : 
     549    17982290 : void ConsString::set_second(Isolate* isolate, String value,
     550             :                             WriteBarrierMode mode) {
     551    17982290 :   WRITE_FIELD(*this, kSecondOffset, value);
     552    31587182 :   CONDITIONAL_WRITE_BARRIER(*this, kSecondOffset, value, mode);
     553    17982290 : }
     554             : 
     555    64333131 : ACCESSORS(ThinString, actual, String, kActualOffset)
     556             : 
     557             : HeapObject ThinString::unchecked_actual() const {
     558     1374381 :   return HeapObject::unchecked_cast(READ_FIELD(*this, kActualOffset));
     559             : }
     560             : 
     561       86864 : bool ExternalString::is_uncached() const {
     562             :   InstanceType type = map()->instance_type();
     563       86864 :   return (type & kUncachedExternalStringMask) == kUncachedExternalStringTag;
     564             : }
     565             : 
     566             : Address ExternalString::resource_as_address() {
     567          30 :   return *reinterpret_cast<Address*>(FIELD_ADDR(*this, kResourceOffset));
     568             : }
     569             : 
     570          30 : void ExternalString::set_address_as_resource(Address address) {
     571          30 :   *reinterpret_cast<Address*>(FIELD_ADDR(*this, kResourceOffset)) = address;
     572          60 :   if (IsExternalOneByteString()) {
     573          15 :     ExternalOneByteString::cast(*this)->update_data_cache();
     574             :   } else {
     575          15 :     ExternalTwoByteString::cast(*this)->update_data_cache();
     576             :   }
     577          30 : }
     578             : 
     579             : uint32_t ExternalString::resource_as_uint32() {
     580             :   return static_cast<uint32_t>(
     581          20 :       *reinterpret_cast<uintptr_t*>(FIELD_ADDR(*this, kResourceOffset)));
     582             : }
     583             : 
     584          10 : void ExternalString::set_uint32_as_resource(uint32_t value) {
     585          10 :   *reinterpret_cast<uintptr_t*>(FIELD_ADDR(*this, kResourceOffset)) = value;
     586          20 :   if (is_uncached()) return;
     587             :   const char** data_field =
     588          10 :       reinterpret_cast<const char**>(FIELD_ADDR(*this, kResourceDataOffset));
     589          10 :   *data_field = nullptr;
     590             : }
     591             : 
     592             : const ExternalOneByteString::Resource* ExternalOneByteString::resource() {
     593    11985483 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(*this, kResourceOffset));
     594             : }
     595             : 
     596       67597 : void ExternalOneByteString::update_data_cache() {
     597      135193 :   if (is_uncached()) return;
     598             :   const char** data_field =
     599        6078 :       reinterpret_cast<const char**>(FIELD_ADDR(*this, kResourceDataOffset));
     600        6078 :   *data_field = resource()->data();
     601             : }
     602             : 
     603       67246 : void ExternalOneByteString::SetResource(
     604             :     Isolate* isolate, const ExternalOneByteString::Resource* resource) {
     605             :   set_resource(resource);
     606       67245 :   size_t new_payload = resource == nullptr ? 0 : resource->length();
     607       67245 :   if (new_payload > 0) {
     608       67180 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     609             :   }
     610       67244 : }
     611             : 
     612             : void ExternalOneByteString::set_resource(
     613             :     const ExternalOneByteString::Resource* resource) {
     614       67447 :   *reinterpret_cast<const Resource**>(FIELD_ADDR(*this, kResourceOffset)) =
     615       67648 :       resource;
     616       67648 :   if (resource != nullptr) update_data_cache();
     617             : }
     618             : 
     619             : const uint8_t* ExternalOneByteString::GetChars() {
     620    11898728 :   return reinterpret_cast<const uint8_t*>(resource()->data());
     621             : }
     622             : 
     623     8838050 : uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) {
     624             :   DCHECK(index >= 0 && index < length());
     625     8838050 :   return GetChars()[index];
     626             : }
     627             : 
     628             : const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
     629     2386771 :   return *reinterpret_cast<Resource**>(FIELD_ADDR(*this, kResourceOffset));
     630             : }
     631             : 
     632       19257 : void ExternalTwoByteString::update_data_cache() {
     633       38514 :   if (is_uncached()) return;
     634             :   const uint16_t** data_field = reinterpret_cast<const uint16_t**>(
     635       19117 :       FIELD_ADDR(*this, kResourceDataOffset));
     636       19117 :   *data_field = resource()->data();
     637             : }
     638             : 
     639       19300 : void ExternalTwoByteString::SetResource(
     640             :     Isolate* isolate, const ExternalTwoByteString::Resource* resource) {
     641             :   set_resource(resource);
     642       19300 :   size_t new_payload = resource == nullptr ? 0 : resource->length() * 2;
     643       19300 :   if (new_payload > 0) {
     644       19242 :     isolate->heap()->UpdateExternalString(*this, 0, new_payload);
     645             :   }
     646       19300 : }
     647             : 
     648             : void ExternalTwoByteString::set_resource(
     649             :     const ExternalTwoByteString::Resource* resource) {
     650       19300 :   *reinterpret_cast<const Resource**>(FIELD_ADDR(*this, kResourceOffset)) =
     651       19300 :       resource;
     652       19300 :   if (resource != nullptr) update_data_cache();
     653             : }
     654             : 
     655     2367547 : const uint16_t* ExternalTwoByteString::GetChars() { return resource()->data(); }
     656             : 
     657       54884 : uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
     658             :   DCHECK(index >= 0 && index < length());
     659       54884 :   return GetChars()[index];
     660             : }
     661             : 
     662             : const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
     663             :     unsigned start) {
     664             :   return GetChars() + start;
     665             : }
     666             : 
     667    10856267 : int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; }
     668             : 
     669             : void ConsStringIterator::PushLeft(ConsString string) {
     670    38491326 :   frames_[depth_++ & kDepthMask] = string;
     671             : }
     672             : 
     673             : void ConsStringIterator::PushRight(ConsString string) {
     674             :   // Inplace update.
     675     6371933 :   frames_[(depth_ - 1) & kDepthMask] = string;
     676             : }
     677             : 
     678             : void ConsStringIterator::AdjustMaximumDepth() {
     679     5243201 :   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
     680             : }
     681             : 
     682             : void ConsStringIterator::Pop() {
     683             :   DCHECK_GT(depth_, 0);
     684             :   DCHECK(depth_ <= maximum_depth_);
     685     5805214 :   depth_--;
     686             : }
     687             : 
     688  1039030401 : uint16_t StringCharacterStream::GetNext() {
     689             :   DCHECK(buffer8_ != nullptr && end_ != nullptr);
     690             :   // Advance cursor if needed.
     691  1039030401 :   if (buffer8_ == end_) HasMore();
     692             :   DCHECK(buffer8_ < end_);
     693  1039030402 :   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
     694             : }
     695             : 
     696     6248143 : StringCharacterStream::StringCharacterStream(String string, int offset)
     697     6248143 :     : is_one_byte_(false) {
     698     6248143 :   Reset(string, offset);
     699     6248143 : }
     700             : 
     701    11449075 : void StringCharacterStream::Reset(String string, int offset) {
     702    11449075 :   buffer8_ = nullptr;
     703    11449075 :   end_ = nullptr;
     704    11449075 :   ConsString cons_string = String::VisitFlat(this, string, offset);
     705    11449074 :   iter_.Reset(cons_string, offset);
     706    11449074 :   if (!cons_string.is_null()) {
     707       16166 :     string = iter_.Next(&offset);
     708       57342 :     if (!string.is_null()) String::VisitFlat(this, string, offset);
     709             :   }
     710    11449074 : }
     711             : 
     712  1047995499 : bool StringCharacterStream::HasMore() {
     713  1047995499 :   if (buffer8_ != end_) return true;
     714             :   int offset;
     715    19920367 :   String string = iter_.Next(&offset);
     716             :   DCHECK_EQ(offset, 0);
     717    19920367 :   if (string.is_null()) return false;
     718     9521315 :   String::VisitFlat(this, string);
     719             :   DCHECK(buffer8_ != end_);
     720     9521315 :   return true;
     721             : }
     722             : 
     723             : void StringCharacterStream::VisitOneByteString(const uint8_t* chars,
     724             :                                                int length) {
     725    16733586 :   is_one_byte_ = true;
     726    16733586 :   buffer8_ = chars;
     727    16733586 :   end_ = chars + length;
     728             : }
     729             : 
     730             : void StringCharacterStream::VisitTwoByteString(const uint16_t* chars,
     731             :                                                int length) {
     732     4236658 :   is_one_byte_ = false;
     733     4236658 :   buffer16_ = chars;
     734     4236658 :   end_ = reinterpret_cast<const uint8_t*>(chars + length);
     735             : }
     736             : 
     737    38593108 : bool String::AsArrayIndex(uint32_t* index) {
     738             :   uint32_t field = hash_field();
     739    38593108 :   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
     740             :     return false;
     741             :   }
     742     8277489 :   return SlowAsArrayIndex(index);
     743             : }
     744             : 
     745             : SubStringRange::SubStringRange(String string,
     746             :                                const DisallowHeapAllocation& no_gc, int first,
     747             :                                int length)
     748             :     : string_(string),
     749             :       first_(first),
     750             :       length_(length == -1 ? string->length() : length),
     751           2 :       no_gc_(no_gc) {}
     752             : 
     753             : class SubStringRange::iterator final {
     754             :  public:
     755             :   typedef std::forward_iterator_tag iterator_category;
     756             :   typedef int difference_type;
     757             :   typedef uc16 value_type;
     758             :   typedef uc16* pointer;
     759             :   typedef uc16& reference;
     760             : 
     761             :   iterator(const iterator& other) = default;
     762             : 
     763          60 :   uc16 operator*() { return content_.Get(offset_); }
     764             :   bool operator==(const iterator& other) const {
     765             :     return content_.UsesSameString(other.content_) && offset_ == other.offset_;
     766             :   }
     767             :   bool operator!=(const iterator& other) const {
     768          62 :     return !content_.UsesSameString(other.content_) || offset_ != other.offset_;
     769             :   }
     770             :   iterator& operator++() {
     771          60 :     ++offset_;
     772             :     return *this;
     773             :   }
     774             :   iterator operator++(int);
     775             : 
     776             :  private:
     777             :   friend class String;
     778             :   friend class SubStringRange;
     779             :   iterator(String from, int offset, const DisallowHeapAllocation& no_gc)
     780           4 :       : content_(from->GetFlatContent(no_gc)), offset_(offset) {}
     781             :   String::FlatContent content_;
     782             :   int offset_;
     783             : };
     784             : 
     785             : SubStringRange::iterator SubStringRange::begin() {
     786             :   return SubStringRange::iterator(string_, first_, no_gc_);
     787             : }
     788             : 
     789             : SubStringRange::iterator SubStringRange::end() {
     790           2 :   return SubStringRange::iterator(string_, first_ + length_, no_gc_);
     791             : }
     792             : 
     793             : }  // namespace internal
     794             : }  // namespace v8
     795             : 
     796             : #include "src/objects/object-macros-undef.h"
     797             : 
     798             : #endif  // V8_OBJECTS_STRING_INL_H_

Generated by: LCOV version 1.10