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