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