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_
|