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