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