OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 return true; // An MP3File, an M. | 726 return true; // An MP3File, an M. |
727 } | 727 } |
728 return false; | 728 return false; |
729 } | 729 } |
730 | 730 |
731 | 731 |
732 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { | 732 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { |
733 #ifdef DEBUG | 733 #ifdef DEBUG |
734 // Do not attempt to flatten in debug mode when allocation is not | 734 // Do not attempt to flatten in debug mode when allocation is not |
735 // allowed. This is to avoid an assertion failure when allocating. | 735 // allowed. This is to avoid an assertion failure when allocating. |
736 // Flattening strings is the only case where we always allow | 736 // Flattening and truncating strings are the only cases where we always |
737 // allocation because no GC is performed if the allocation fails. | 737 // allow allocation because no GC is performed if the allocation fails. |
738 if (!HEAP->IsAllocationAllowed()) return this; | 738 if (!HEAP->IsAllocationAllowed()) return this; |
739 #endif | 739 #endif |
740 | 740 |
| 741 ASSERT(StringShape(this).representation_tag() == kConsStringTag); |
| 742 |
741 Heap* heap = GetHeap(); | 743 Heap* heap = GetHeap(); |
742 switch (StringShape(this).representation_tag()) { | 744 ConsString* cs = ConsString::cast(this); |
743 case kConsStringTag: { | 745 // There's little point in putting the flat string in new space if the |
744 ConsString* cs = ConsString::cast(this); | 746 // cons string is in old space. It can never get GCed until there is |
745 if (cs->second()->length() == 0) { | 747 // an old space GC. |
746 return cs->first(); | 748 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; |
747 } | 749 int len = length(); |
748 // There's little point in putting the flat string in new space if the | 750 Object* object; |
749 // cons string is in old space. It can never get GCed until there is | 751 String* result; |
750 // an old space GC. | 752 if (IsAsciiRepresentation()) { |
751 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; | 753 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure); |
752 int len = length(); | 754 if (!maybe_object->ToObject(&object)) return maybe_object; |
753 Object* object; | |
754 String* result; | |
755 if (IsAsciiRepresentation()) { | |
756 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure); | |
757 if (!maybe_object->ToObject(&object)) return maybe_object; | |
758 } | |
759 result = String::cast(object); | |
760 String* first = cs->first(); | |
761 int first_length = first->length(); | |
762 char* dest = SeqAsciiString::cast(result)->GetChars(); | |
763 WriteToFlat(first, dest, 0, first_length); | |
764 String* second = cs->second(); | |
765 WriteToFlat(second, | |
766 dest + first_length, | |
767 0, | |
768 len - first_length); | |
769 } else { | |
770 { MaybeObject* maybe_object = | |
771 heap->AllocateRawTwoByteString(len, tenure); | |
772 if (!maybe_object->ToObject(&object)) return maybe_object; | |
773 } | |
774 result = String::cast(object); | |
775 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | |
776 String* first = cs->first(); | |
777 int first_length = first->length(); | |
778 WriteToFlat(first, dest, 0, first_length); | |
779 String* second = cs->second(); | |
780 WriteToFlat(second, | |
781 dest + first_length, | |
782 0, | |
783 len - first_length); | |
784 } | |
785 cs->set_first(result); | |
786 cs->set_second(heap->empty_string()); | |
787 return result; | |
788 } | 755 } |
789 default: | 756 result = String::cast(object); |
790 return this; | 757 String* first = cs->first(); |
| 758 int first_length = first->length(); |
| 759 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 760 WriteToFlat(first, dest, 0, first_length); |
| 761 String* second = cs->second(); |
| 762 WriteToFlat(second, |
| 763 dest + first_length, |
| 764 0, |
| 765 len - first_length); |
| 766 } else { |
| 767 { MaybeObject* maybe_object = |
| 768 heap->AllocateRawTwoByteString(len, tenure); |
| 769 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 770 } |
| 771 result = String::cast(object); |
| 772 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
| 773 String* first = cs->first(); |
| 774 int first_length = first->length(); |
| 775 WriteToFlat(first, dest, 0, first_length); |
| 776 String* second = cs->second(); |
| 777 WriteToFlat(second, |
| 778 dest + first_length, |
| 779 0, |
| 780 len - first_length); |
791 } | 781 } |
| 782 cs->set_first(result); |
| 783 cs->set_second(heap->empty_string()); |
| 784 ASSERT(this->IsFlat()); |
| 785 return result; |
792 } | 786 } |
793 | 787 |
794 | 788 |
| 789 MaybeObject* String::SlowTryTruncate(PretenureFlag pretenure) { |
| 790 #ifdef DEBUG |
| 791 // Do not attempt to truncate in debug mode when allocation is not |
| 792 // allowed. This is to avoid an assertion failure when allocating. |
| 793 // Flattening and truncating strings are the only cases where we always |
| 794 // allow allocation because no GC is performed if the allocation fails. |
| 795 if (!HEAP->IsAllocationAllowed()) return this; |
| 796 #endif |
| 797 ASSERT(StringShape(this).representation_tag() == kSlicedStringTag); |
| 798 |
| 799 Heap* heap = GetHeap(); |
| 800 SlicedString* slice = SlicedString::cast(this); |
| 801 // There's little point in putting the truncated string in new space if the |
| 802 // sliced string is in old space. It can never get GCed until there is |
| 803 // an old space GC. |
| 804 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; |
| 805 int len = length(); |
| 806 int offset = slice->offset(); |
| 807 Object* object; |
| 808 String* result; |
| 809 if (IsAsciiRepresentation()) { |
| 810 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure); |
| 811 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 812 } |
| 813 result = String::cast(object); |
| 814 String* parent = slice->parent(); |
| 815 ASSERT(StringShape(parent).IsSequentialAscii()); |
| 816 WriteToFlat(parent, SeqAsciiString::cast(result)->GetChars(), |
| 817 offset, offset + len); |
| 818 } else { |
| 819 { MaybeObject* maybe_object = |
| 820 heap->AllocateRawTwoByteString(len, tenure); |
| 821 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 822 } |
| 823 result = String::cast(object); |
| 824 String* parent = slice->parent(); |
| 825 ASSERT(StringShape(parent).IsSequentialTwoByte()); |
| 826 WriteToFlat(parent, SeqTwoByteString::cast(result)->GetChars(), |
| 827 offset, offset + len); |
| 828 } |
| 829 slice->set_parent(result); |
| 830 slice->set_offset(0); |
| 831 return result; |
| 832 } |
| 833 |
| 834 |
795 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 835 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
796 // Externalizing twice leaks the external resource, so it's | 836 // Externalizing twice leaks the external resource, so it's |
797 // prohibited by the API. | 837 // prohibited by the API. |
798 ASSERT(!this->IsExternalString()); | 838 ASSERT(!this->IsExternalString()); |
799 #ifdef DEBUG | 839 #ifdef DEBUG |
800 if (FLAG_enable_slow_asserts) { | 840 if (FLAG_enable_slow_asserts) { |
801 // Assert that the resource and the string are equivalent. | 841 // Assert that the resource and the string are equivalent. |
802 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 842 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
803 ScopedVector<uc16> smart_chars(this->length()); | 843 ScopedVector<uc16> smart_chars(this->length()); |
804 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 844 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 ObjectVisitor* v) { | 1202 ObjectVisitor* v) { |
1163 // Avoiding <Type>::cast(this) because it accesses the map pointer field. | 1203 // Avoiding <Type>::cast(this) because it accesses the map pointer field. |
1164 // During GC, the map pointer field is encoded. | 1204 // During GC, the map pointer field is encoded. |
1165 if (type < FIRST_NONSTRING_TYPE) { | 1205 if (type < FIRST_NONSTRING_TYPE) { |
1166 switch (type & kStringRepresentationMask) { | 1206 switch (type & kStringRepresentationMask) { |
1167 case kSeqStringTag: | 1207 case kSeqStringTag: |
1168 break; | 1208 break; |
1169 case kConsStringTag: | 1209 case kConsStringTag: |
1170 ConsString::BodyDescriptor::IterateBody(this, v); | 1210 ConsString::BodyDescriptor::IterateBody(this, v); |
1171 break; | 1211 break; |
| 1212 case kSlicedStringTag: |
| 1213 SlicedString::BodyDescriptor::IterateBody(this, v); |
| 1214 break; |
1172 case kExternalStringTag: | 1215 case kExternalStringTag: |
1173 if ((type & kStringEncodingMask) == kAsciiStringTag) { | 1216 if ((type & kStringEncodingMask) == kAsciiStringTag) { |
1174 reinterpret_cast<ExternalAsciiString*>(this)-> | 1217 reinterpret_cast<ExternalAsciiString*>(this)-> |
1175 ExternalAsciiStringIterateBody(v); | 1218 ExternalAsciiStringIterateBody(v); |
1176 } else { | 1219 } else { |
1177 reinterpret_cast<ExternalTwoByteString*>(this)-> | 1220 reinterpret_cast<ExternalTwoByteString*>(this)-> |
1178 ExternalTwoByteStringIterateBody(v); | 1221 ExternalTwoByteStringIterateBody(v); |
1179 } | 1222 } |
1180 break; | 1223 break; |
1181 } | 1224 } |
(...skipping 4056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5238 | 5281 |
5239 int offset = 0; | 5282 int offset = 0; |
5240 int length = this->length(); | 5283 int length = this->length(); |
5241 StringRepresentationTag string_tag = StringShape(this).representation_tag(); | 5284 StringRepresentationTag string_tag = StringShape(this).representation_tag(); |
5242 String* string = this; | 5285 String* string = this; |
5243 if (string_tag == kConsStringTag) { | 5286 if (string_tag == kConsStringTag) { |
5244 ConsString* cons = ConsString::cast(string); | 5287 ConsString* cons = ConsString::cast(string); |
5245 ASSERT(cons->second()->length() == 0); | 5288 ASSERT(cons->second()->length() == 0); |
5246 string = cons->first(); | 5289 string = cons->first(); |
5247 string_tag = StringShape(string).representation_tag(); | 5290 string_tag = StringShape(string).representation_tag(); |
| 5291 ASSERT(string_tag != kConsStringTag); |
5248 } | 5292 } |
5249 if (string_tag == kSeqStringTag) { | 5293 if (string_tag == kSlicedStringTag) { |
5250 SeqAsciiString* seq = SeqAsciiString::cast(string); | 5294 // Note that the parent of a slice cannot be a cons. |
5251 char* start = seq->GetChars(); | 5295 SlicedString* slice = SlicedString::cast(string); |
| 5296 offset = slice->offset(); |
| 5297 string = slice->parent(); |
| 5298 } |
| 5299 if (string_tag == kExternalStringTag) { |
| 5300 ExternalAsciiString* ext = ExternalAsciiString::cast(string); |
| 5301 const char* start = ext->resource()->data(); |
5252 return Vector<const char>(start + offset, length); | 5302 return Vector<const char>(start + offset, length); |
5253 } | 5303 } |
5254 ASSERT(string_tag == kExternalStringTag); | 5304 ASSERT(StringShape(string).representation_tag() == kSeqStringTag); |
5255 ExternalAsciiString* ext = ExternalAsciiString::cast(string); | 5305 SeqAsciiString* seq = SeqAsciiString::cast(string); |
5256 const char* start = ext->resource()->data(); | 5306 char* start = seq->GetChars(); |
5257 return Vector<const char>(start + offset, length); | 5307 return Vector<const char>(start + offset, length); |
5258 } | 5308 } |
5259 | 5309 |
5260 | 5310 |
5261 Vector<const uc16> String::ToUC16Vector() { | 5311 Vector<const uc16> String::ToUC16Vector() { |
5262 ASSERT(IsTwoByteRepresentation()); | 5312 ASSERT(IsTwoByteRepresentation()); |
5263 ASSERT(IsFlat()); | 5313 ASSERT(IsFlat()); |
5264 | 5314 |
5265 int offset = 0; | 5315 int offset = 0; |
5266 int length = this->length(); | 5316 int length = this->length(); |
5267 StringRepresentationTag string_tag = StringShape(this).representation_tag(); | 5317 StringRepresentationTag string_tag = StringShape(this).representation_tag(); |
5268 String* string = this; | 5318 String* string = this; |
5269 if (string_tag == kConsStringTag) { | 5319 if (string_tag == kConsStringTag) { |
5270 ConsString* cons = ConsString::cast(string); | 5320 ConsString* cons = ConsString::cast(string); |
5271 ASSERT(cons->second()->length() == 0); | 5321 ASSERT(cons->second()->length() == 0); |
5272 string = cons->first(); | 5322 string = cons->first(); |
5273 string_tag = StringShape(string).representation_tag(); | 5323 string_tag = StringShape(string).representation_tag(); |
| 5324 ASSERT(string_tag != kConsStringTag); |
5274 } | 5325 } |
5275 if (string_tag == kSeqStringTag) { | 5326 if (string_tag == kSlicedStringTag) { |
5276 SeqTwoByteString* seq = SeqTwoByteString::cast(string); | 5327 // Note that the parent of a slice cannot be a cons. |
5277 return Vector<const uc16>(seq->GetChars() + offset, length); | 5328 SlicedString* slice = SlicedString::cast(string); |
| 5329 offset = slice->offset(); |
| 5330 string = slice->parent(); |
5278 } | 5331 } |
5279 ASSERT(string_tag == kExternalStringTag); | 5332 if (string_tag == kExternalStringTag) { |
5280 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); | 5333 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); |
5281 const uc16* start = | 5334 const uc16* start = |
5282 reinterpret_cast<const uc16*>(ext->resource()->data()); | 5335 reinterpret_cast<const uc16*>(ext->resource()->data()); |
5283 return Vector<const uc16>(start + offset, length); | 5336 return Vector<const uc16>(start + offset, length); |
| 5337 } |
| 5338 ASSERT(StringShape(string).representation_tag() == kSeqStringTag); |
| 5339 SeqTwoByteString* seq = SeqTwoByteString::cast(string); |
| 5340 return Vector<const uc16>(seq->GetChars() + offset, length); |
5284 } | 5341 } |
5285 | 5342 |
5286 | 5343 |
5287 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 5344 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
5288 RobustnessFlag robust_flag, | 5345 RobustnessFlag robust_flag, |
5289 int offset, | 5346 int offset, |
5290 int length, | 5347 int length, |
5291 int* length_return) { | 5348 int* length_return) { |
5292 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 5349 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
5293 return SmartPointer<char>(NULL); | 5350 return SmartPointer<char>(NULL); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5351 | 5408 |
5352 | 5409 |
5353 const uc16* String::GetTwoByteData(unsigned start) { | 5410 const uc16* String::GetTwoByteData(unsigned start) { |
5354 ASSERT(!IsAsciiRepresentation()); | 5411 ASSERT(!IsAsciiRepresentation()); |
5355 switch (StringShape(this).representation_tag()) { | 5412 switch (StringShape(this).representation_tag()) { |
5356 case kSeqStringTag: | 5413 case kSeqStringTag: |
5357 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); | 5414 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); |
5358 case kExternalStringTag: | 5415 case kExternalStringTag: |
5359 return ExternalTwoByteString::cast(this)-> | 5416 return ExternalTwoByteString::cast(this)-> |
5360 ExternalTwoByteStringGetData(start); | 5417 ExternalTwoByteStringGetData(start); |
| 5418 case kSlicedStringTag: { |
| 5419 SlicedString* slice = SlicedString::cast(this); |
| 5420 return slice->parent()->GetTwoByteData(start + slice->offset()); |
| 5421 } |
5361 case kConsStringTag: | 5422 case kConsStringTag: |
5362 UNREACHABLE(); | 5423 UNREACHABLE(); |
5363 return NULL; | 5424 return NULL; |
5364 } | 5425 } |
5365 UNREACHABLE(); | 5426 UNREACHABLE(); |
5366 return NULL; | 5427 return NULL; |
5367 } | 5428 } |
5368 | 5429 |
5369 | 5430 |
5370 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 5431 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5641 &rbb->remaining, | 5702 &rbb->remaining, |
5642 offset_ptr, | 5703 offset_ptr, |
5643 max_chars); | 5704 max_chars); |
5644 } else { | 5705 } else { |
5645 ExternalTwoByteString::cast(input)-> | 5706 ExternalTwoByteString::cast(input)-> |
5646 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 5707 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
5647 offset_ptr, | 5708 offset_ptr, |
5648 max_chars); | 5709 max_chars); |
5649 return rbb->util_buffer; | 5710 return rbb->util_buffer; |
5650 } | 5711 } |
| 5712 case kSlicedStringTag: |
| 5713 return SlicedString::cast(input)->SlicedStringReadBlock(rbb, |
| 5714 offset_ptr, |
| 5715 max_chars); |
5651 default: | 5716 default: |
5652 break; | 5717 break; |
5653 } | 5718 } |
5654 | 5719 |
5655 UNREACHABLE(); | 5720 UNREACHABLE(); |
5656 return 0; | 5721 return 0; |
5657 } | 5722 } |
5658 | 5723 |
5659 | 5724 |
5660 void Relocatable::PostGarbageCollectionProcessing() { | 5725 void Relocatable::PostGarbageCollectionProcessing() { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5782 if (input->IsAsciiRepresentation()) { | 5847 if (input->IsAsciiRepresentation()) { |
5783 ExternalAsciiString::cast(input)-> | 5848 ExternalAsciiString::cast(input)-> |
5784 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); | 5849 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); |
5785 } else { | 5850 } else { |
5786 ExternalTwoByteString::cast(input)-> | 5851 ExternalTwoByteString::cast(input)-> |
5787 ExternalTwoByteStringReadBlockIntoBuffer(rbb, | 5852 ExternalTwoByteStringReadBlockIntoBuffer(rbb, |
5788 offset_ptr, | 5853 offset_ptr, |
5789 max_chars); | 5854 max_chars); |
5790 } | 5855 } |
5791 return; | 5856 return; |
| 5857 case kSlicedStringTag: |
| 5858 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb, |
| 5859 offset_ptr, |
| 5860 max_chars); |
| 5861 return; |
5792 default: | 5862 default: |
5793 break; | 5863 break; |
5794 } | 5864 } |
5795 | 5865 |
5796 UNREACHABLE(); | 5866 UNREACHABLE(); |
5797 return; | 5867 return; |
5798 } | 5868 } |
5799 | 5869 |
5800 | 5870 |
5801 const unibrow::byte* String::ReadBlock(String* input, | 5871 const unibrow::byte* String::ReadBlock(String* input, |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5916 } else { | 5986 } else { |
5917 return string->Get(index); | 5987 return string->Get(index); |
5918 } | 5988 } |
5919 } | 5989 } |
5920 | 5990 |
5921 UNREACHABLE(); | 5991 UNREACHABLE(); |
5922 return 0; | 5992 return 0; |
5923 } | 5993 } |
5924 | 5994 |
5925 | 5995 |
| 5996 uint16_t SlicedString::SlicedStringGet(int index) { |
| 5997 return parent()->Get(offset() + index); |
| 5998 } |
| 5999 |
| 6000 |
| 6001 const unibrow::byte* SlicedString::SlicedStringReadBlock( |
| 6002 ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) { |
| 6003 unsigned offset = this->offset(); |
| 6004 *offset_ptr += offset; |
| 6005 const unibrow::byte* answer = String::ReadBlock(String::cast(parent()), |
| 6006 buffer, offset_ptr, chars); |
| 6007 *offset_ptr -= offset; |
| 6008 return answer; |
| 6009 } |
| 6010 |
| 6011 |
| 6012 void SlicedString::SlicedStringReadBlockIntoBuffer( |
| 6013 ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) { |
| 6014 unsigned offset = this->offset(); |
| 6015 *offset_ptr += offset; |
| 6016 String::ReadBlockIntoBuffer(String::cast(parent()), |
| 6017 buffer, offset_ptr, chars); |
| 6018 *offset_ptr -= offset; |
| 6019 } |
| 6020 |
5926 template <typename sinkchar> | 6021 template <typename sinkchar> |
5927 void String::WriteToFlat(String* src, | 6022 void String::WriteToFlat(String* src, |
5928 sinkchar* sink, | 6023 sinkchar* sink, |
5929 int f, | 6024 int f, |
5930 int t) { | 6025 int t) { |
5931 String* source = src; | 6026 String* source = src; |
5932 int from = f; | 6027 int from = f; |
5933 int to = t; | 6028 int to = t; |
5934 while (true) { | 6029 while (true) { |
5935 ASSERT(0 <= from && from <= to && to <= source->length()); | 6030 ASSERT(0 <= from && from <= to && to <= source->length()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5983 WriteToFlat(second, | 6078 WriteToFlat(second, |
5984 sink + boundary - from, | 6079 sink + boundary - from, |
5985 0, | 6080 0, |
5986 to - boundary); | 6081 to - boundary); |
5987 to = boundary; | 6082 to = boundary; |
5988 } | 6083 } |
5989 source = first; | 6084 source = first; |
5990 } | 6085 } |
5991 break; | 6086 break; |
5992 } | 6087 } |
| 6088 case kAsciiStringTag | kSlicedStringTag: |
| 6089 case kTwoByteStringTag | kSlicedStringTag: { |
| 6090 SlicedString* slice = SlicedString::cast(source); |
| 6091 unsigned offset = slice->offset(); |
| 6092 WriteToFlat(slice->parent(), sink, from + offset, to + offset); |
| 6093 return; |
| 6094 } |
5993 } | 6095 } |
5994 } | 6096 } |
5995 } | 6097 } |
5996 | 6098 |
5997 | 6099 |
5998 template <typename IteratorA, typename IteratorB> | 6100 template <typename IteratorA, typename IteratorB> |
5999 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { | 6101 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { |
6000 // General slow case check. We know that the ia and ib iterators | 6102 // General slow case check. We know that the ia and ib iterators |
6001 // have the same length. | 6103 // have the same length. |
6002 while (ia->has_more()) { | 6104 while (ia->has_more()) { |
(...skipping 5935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11938 if (break_point_objects()->IsUndefined()) return 0; | 12040 if (break_point_objects()->IsUndefined()) return 0; |
11939 // Single beak point. | 12041 // Single beak point. |
11940 if (!break_point_objects()->IsFixedArray()) return 1; | 12042 if (!break_point_objects()->IsFixedArray()) return 1; |
11941 // Multiple break points. | 12043 // Multiple break points. |
11942 return FixedArray::cast(break_point_objects())->length(); | 12044 return FixedArray::cast(break_point_objects())->length(); |
11943 } | 12045 } |
11944 #endif | 12046 #endif |
11945 | 12047 |
11946 | 12048 |
11947 } } // namespace v8::internal | 12049 } } // namespace v8::internal |
OLD | NEW |