OLD | NEW |
---|---|
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
521 case kConsStringTag: { | 521 case kConsStringTag: { |
522 ConsString* cs = ConsString::cast(this); | 522 ConsString* cs = ConsString::cast(this); |
523 if (String::cast(cs->second())->length() == 0) { | 523 if (String::cast(cs->second())->length() == 0) { |
524 return this; | 524 return this; |
525 } | 525 } |
526 // There's little point in putting the flat string in new space if the | 526 // There's little point in putting the flat string in new space if the |
527 // cons string is in old space. It can never get GCed until there is | 527 // cons string is in old space. It can never get GCed until there is |
528 // an old space GC. | 528 // an old space GC. |
529 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; | 529 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; |
530 int len = length(); | 530 int len = length(); |
531 Object* object = IsAsciiRepresentation() ? | 531 Object* object; |
532 Heap::AllocateRawAsciiString(len, tenure) : | 532 String* result; |
533 Heap::AllocateRawTwoByteString(len, tenure); | 533 if (IsAsciiRepresentation()) { |
534 if (object->IsFailure()) return object; | 534 object = Heap::AllocateRawAsciiString(len, tenure); |
535 String* result = String::cast(object); | 535 if (object->IsFailure()) return object; |
536 Flatten(this, result, 0, len, 0); | 536 result = String::cast(object); |
537 String* first = String::cast(cs->first()); | |
538 int first_length = first->length(); | |
539 byte* dest = SeqAsciiString::cast(result)->GetCharsAddress(); | |
540 WriteToFlat(first, dest, 0, first_length); | |
541 WriteToFlat(String::cast(cs->second()), dest + first_length, 0, len - fi rst_length); | |
542 } else { | |
543 object = Heap::AllocateRawTwoByteString(len, tenure); | |
544 if (object->IsFailure()) return object; | |
545 result = String::cast(object); | |
546 uc16* dest = reinterpret_cast<uc16*>( | |
547 SeqTwoByteString::cast(result)->GetCharsAddress()); | |
Christian Plesner Hansen
2008/10/21 14:16:22
Maybe add an accessor on seq two byte string that
Erik Corry
2008/10/22 11:59:48
Good idea.
| |
548 String* first = String::cast(cs->first()); | |
549 int first_length = first->length(); | |
550 WriteToFlat(first, dest, 0, first_length); | |
551 WriteToFlat(String::cast(cs->second()), dest + first_length, 0, len - fi rst_length); | |
552 } | |
537 cs->set_first(result); | 553 cs->set_first(result); |
538 cs->set_second(Heap::empty_string()); | 554 cs->set_second(Heap::empty_string()); |
539 return this; | 555 return this; |
540 } | 556 } |
541 default: | 557 default: |
542 return this; | 558 return this; |
543 } | 559 } |
544 } | 560 } |
545 | 561 |
546 | 562 |
(...skipping 2315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2862 TryFlatten(); | 2878 TryFlatten(); |
2863 Access<StringInputBuffer> buffer(&string_input_buffer); | 2879 Access<StringInputBuffer> buffer(&string_input_buffer); |
2864 buffer->Reset(0, this); | 2880 buffer->Reset(0, this); |
2865 int result = 0; | 2881 int result = 0; |
2866 while (buffer->has_more()) | 2882 while (buffer->has_more()) |
2867 result += unibrow::Utf8::Length(buffer->GetNext()); | 2883 result += unibrow::Utf8::Length(buffer->GetNext()); |
2868 return result; | 2884 return result; |
2869 } | 2885 } |
2870 | 2886 |
2871 | 2887 |
2872 Vector<const char> String::ToAsciiVector() { | 2888 Vector<const byte> String::ToAsciiVector() { |
2873 ASSERT(IsAsciiRepresentation()); | 2889 ASSERT(IsAsciiRepresentation()); |
2874 ASSERT(IsFlat()); | 2890 ASSERT(IsFlat()); |
2875 | 2891 |
2876 int offset = 0; | 2892 int offset = 0; |
2877 int length = this->length(); | 2893 int length = this->length(); |
2878 StringRepresentationTag string_tag = representation_tag(); | 2894 StringRepresentationTag string_tag = representation_tag(); |
2879 String* string = this; | 2895 String* string = this; |
2880 if (string_tag == kSlicedStringTag) { | 2896 if (string_tag == kSlicedStringTag) { |
2881 SlicedString* sliced = SlicedString::cast(string); | 2897 SlicedString* sliced = SlicedString::cast(string); |
2882 offset += sliced->start(); | 2898 offset += sliced->start(); |
2883 string = String::cast(sliced->buffer()); | 2899 string = String::cast(sliced->buffer()); |
2884 string_tag = string->representation_tag(); | 2900 string_tag = string->representation_tag(); |
2885 } else if (string_tag == kConsStringTag) { | 2901 } else if (string_tag == kConsStringTag) { |
2886 ConsString* cons = ConsString::cast(string); | 2902 ConsString* cons = ConsString::cast(string); |
2887 ASSERT(String::cast(cons->second())->length() == 0); | 2903 ASSERT(String::cast(cons->second())->length() == 0); |
2888 string = String::cast(cons->first()); | 2904 string = String::cast(cons->first()); |
2889 string_tag = string->representation_tag(); | 2905 string_tag = string->representation_tag(); |
2890 } | 2906 } |
2891 if (string_tag == kSeqStringTag) { | 2907 if (string_tag == kSeqStringTag) { |
2892 SeqAsciiString* seq = SeqAsciiString::cast(string); | 2908 SeqAsciiString* seq = SeqAsciiString::cast(string); |
2893 char* start = reinterpret_cast<char*>(seq->GetCharsAddress()); | 2909 byte* start = seq->GetCharsAddress(); |
2894 return Vector<const char>(start + offset, length); | 2910 return Vector<const byte>(start + offset, length); |
2895 } | 2911 } |
2896 ASSERT(string_tag == kExternalStringTag); | 2912 ASSERT(string_tag == kExternalStringTag); |
2897 ExternalAsciiString* ext = ExternalAsciiString::cast(string); | 2913 ExternalAsciiString* ext = ExternalAsciiString::cast(string); |
2898 const char* start = ext->resource()->data(); | 2914 const byte* start = reinterpret_cast<const byte*>(ext->resource()->data()); |
Christian Plesner Hansen
2008/10/21 14:16:22
Bleh. Why not stick with char?
Erik Corry
2008/10/22 11:59:48
Done
| |
2899 return Vector<const char>(start + offset, length); | 2915 return Vector<const byte>(start + offset, length); |
2900 } | 2916 } |
2901 | 2917 |
2902 | 2918 |
2903 Vector<const uc16> String::ToUC16Vector() { | 2919 Vector<const uc16> String::ToUC16Vector() { |
2904 ASSERT(IsTwoByteStringRepresentation()); | 2920 ASSERT(IsTwoByteStringRepresentation()); |
2905 ASSERT(IsFlat()); | 2921 ASSERT(IsFlat()); |
2906 | 2922 |
2907 int offset = 0; | 2923 int offset = 0; |
2908 int length = this->length(); | 2924 int length = this->length(); |
2909 StringRepresentationTag string_tag = representation_tag(); | 2925 StringRepresentationTag string_tag = representation_tag(); |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3550 String* buf = String::cast(buffer()); | 3566 String* buf = String::cast(buffer()); |
3551 ASSERT(!buf->StringIsSlicedString()); | 3567 ASSERT(!buf->StringIsSlicedString()); |
3552 if (buf->StringIsConsString()) { | 3568 if (buf->StringIsConsString()) { |
3553 Object* ok = buf->Flatten(); | 3569 Object* ok = buf->Flatten(); |
3554 if (ok->IsFailure()) return ok; | 3570 if (ok->IsFailure()) return ok; |
3555 } | 3571 } |
3556 return this; | 3572 return this; |
3557 } | 3573 } |
3558 | 3574 |
3559 | 3575 |
3560 void String::Flatten(String* src, | 3576 // Assumes that if the sink is ASCII then the src will also be ASCII |
3561 String* sink, | 3577 // representation (not just ASCII in a 16 bit string). |
3562 int f, | 3578 template <typename sinkchar> |
3563 int t, | 3579 void String::WriteToFlat(String* src, |
3564 int so) { | 3580 sinkchar* sink, |
3581 int f, | |
3582 int t) { | |
3565 String* source = src; | 3583 String* source = src; |
3566 int from = f; | 3584 int from = f; |
3567 int to = t; | 3585 int to = t; |
3568 int sink_offset = so; | |
3569 while (true) { | 3586 while (true) { |
3570 ASSERT(0 <= from && from <= to && to <= source->length()); | 3587 ASSERT(0 <= from && from <= to && to <= source->length()); |
3571 ASSERT(0 <= sink_offset && sink_offset < sink->length()); | 3588 switch (source->full_representation_tag()) { |
3572 switch (source->representation_tag()) { | 3589 case kAsciiStringTag + kExternalStringTag: { |
3573 case kSeqStringTag: | 3590 if (sizeof(sinkchar) == 1) { |
3574 case kExternalStringTag: { | 3591 memcpy( |
Christian Plesner Hansen
2008/10/21 14:16:22
Could this be simplified by using a template-ified
Erik Corry
2008/10/22 11:59:48
Done.
| |
3575 Access<StringInputBuffer> buffer(&string_input_buffer); | 3592 sink, |
3576 buffer->Reset(from, source); | 3593 ExternalAsciiString::cast(source)->resource()->data() + from, |
3577 int j = sink_offset; | 3594 to - from); |
3578 for (int i = from; i < to; i++) { | 3595 } else { |
3579 uc32 c = buffer->GetNext(); | 3596 Cpy168( |
3580 sink->Set(j++, c); | 3597 sink, |
3598 // Sign cast. | |
3599 reinterpret_cast<const byte*>( | |
3600 ExternalAsciiString::cast(source)->resource()->data()) + | |
3601 from, | |
3602 to - from); | |
3581 } | 3603 } |
3582 return; | 3604 return; |
3583 } | 3605 } |
3584 case kSlicedStringTag: { | 3606 case kTwoByteStringTag + kExternalStringTag: { |
Christian Plesner Hansen
2008/10/21 14:16:22
If | gives the same result as + we should use that
Erik Corry
2008/10/22 11:59:48
Done
| |
3607 ASSERT(sizeof(sinkchar) == 2); | |
3608 memcpy( | |
3609 sink, | |
3610 ExternalTwoByteString::cast(source)->resource()->data() + (from << 1 ), | |
3611 (to - from) << 1); | |
3612 return; | |
3613 } | |
3614 case kAsciiStringTag + kSeqStringTag: { | |
3615 if (sizeof(sinkchar) == 1) { | |
3616 const byte* src = | |
Christian Plesner Hansen
2008/10/21 14:16:22
Isn't this the branch where we can memcpy? Source
Erik Corry
2008/10/22 11:59:48
The non-memcpy may be marginally faster, but this
| |
3617 SeqAsciiString::cast(source)->GetCharsAddress() + from; | |
3618 const byte* end = src - from + to; | |
3619 while (src < end) { | |
3620 *sink++ = *src++; | |
3621 } | |
3622 } else { | |
3623 Cpy168( | |
Christian Plesner Hansen
2008/10/21 14:16:22
Conversely, this looks to me like we're memcpying
Erik Corry
2008/10/22 11:59:48
Gone in new version.
| |
3624 sink, | |
3625 SeqAsciiString::cast(source)->GetCharsAddress() + from, | |
3626 to - from); | |
3627 } | |
3628 return; | |
3629 } | |
3630 case kTwoByteStringTag + kSeqStringTag: { | |
3631 ASSERT(sizeof(sinkchar) == 2); | |
3632 memcpy( | |
3633 sink, | |
3634 SeqTwoByteString::cast(source)->GetCharsAddress() + (from << 1), | |
3635 (to - from) << 1); | |
3636 return; | |
3637 } | |
3638 case kAsciiStringTag + kSlicedStringTag: | |
3639 case kTwoByteStringTag + kSlicedStringTag: { | |
3585 SlicedString* sliced_string = SlicedString::cast(source); | 3640 SlicedString* sliced_string = SlicedString::cast(source); |
3586 int start = sliced_string->start(); | 3641 int start = sliced_string->start(); |
3587 from += start; | 3642 from += start; |
3588 to += start; | 3643 to += start; |
3589 source = String::cast(sliced_string->buffer()); | 3644 source = String::cast(sliced_string->buffer()); |
3645 break; | |
3590 } | 3646 } |
3591 break; | 3647 case kAsciiStringTag + kConsStringTag: |
3592 case kConsStringTag: { | 3648 case kTwoByteStringTag + kConsStringTag: { |
3593 ConsString* cons_string = ConsString::cast(source); | 3649 ConsString* cons_string = ConsString::cast(source); |
3594 String* first = String::cast(cons_string->first()); | 3650 String* first = String::cast(cons_string->first()); |
3595 int boundary = first->length(); | 3651 int boundary = first->length(); |
3596 if (to - boundary >= boundary - from) { | 3652 if (boundary < 64 || to - boundary >= boundary - from) { |
Christian Plesner Hansen
2008/10/21 14:16:22
Magic number. Please define a constant.
Erik Corry
2008/10/22 11:59:48
I got rid of this optimization because I found a t
| |
3597 // Right hand side is longer. Recurse over left. | 3653 // Right hand side is longer. Recurse over left. |
3598 if (from < boundary) { | 3654 if (from < boundary) { |
3599 Flatten(first, sink, from, boundary, sink_offset); | 3655 WriteToFlat(first, sink, from, boundary); |
3600 sink_offset += boundary - from; | 3656 sink += boundary - from; |
3601 from = 0; | 3657 from = 0; |
3602 } else { | 3658 } else { |
3603 from -= boundary; | 3659 from -= boundary; |
3604 } | 3660 } |
3605 to -= boundary; | 3661 to -= boundary; |
3606 source = String::cast(cons_string->second()); | 3662 source = String::cast(cons_string->second()); |
3607 } else { | 3663 } else { |
3608 // Left hand side is longer. Recurse over right. The hasher | 3664 // Left hand side is longer. Recurse over right. The hasher |
3609 // needs us to visit the string from left to right so doing | 3665 // needs us to visit the string from left to right so doing |
3610 // this invalidates that hash. | 3666 // this invalidates that hash. |
3611 if (to > boundary) { | 3667 if (to > boundary) { |
3612 String* second = String::cast(cons_string->second()); | 3668 String* second = String::cast(cons_string->second()); |
3613 Flatten(second, | 3669 WriteToFlat(second, |
3614 sink, | 3670 sink + boundary - from, |
3615 0, | 3671 0, |
3616 to - boundary, | 3672 to - boundary); |
3617 sink_offset + boundary - from); | |
3618 to = boundary; | 3673 to = boundary; |
3619 } | 3674 } |
3620 source = first; | 3675 source = first; |
3621 } | 3676 } |
3677 break; | |
3622 } | 3678 } |
3623 break; | |
3624 } | 3679 } |
3625 } | 3680 } |
3626 } | 3681 } |
3627 | 3682 |
3628 | 3683 |
3629 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { | 3684 void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { |
3630 IteratePointer(v, kBufferOffset); | 3685 IteratePointer(v, kBufferOffset); |
3631 } | 3686 } |
3632 | 3687 |
3633 | 3688 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3683 } | 3738 } |
3684 | 3739 |
3685 | 3740 |
3686 static StringInputBuffer string_compare_buffer_b; | 3741 static StringInputBuffer string_compare_buffer_b; |
3687 | 3742 |
3688 | 3743 |
3689 template <typename IteratorA> | 3744 template <typename IteratorA> |
3690 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { | 3745 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { |
3691 if (b->IsFlat()) { | 3746 if (b->IsFlat()) { |
3692 if (b->IsAsciiRepresentation()) { | 3747 if (b->IsAsciiRepresentation()) { |
3693 VectorIterator<char> ib(b->ToAsciiVector()); | 3748 VectorIterator<const byte> ib(b->ToAsciiVector()); |
Christian Plesner Hansen
2008/10/21 14:16:22
There's no need to explicitly add 'const' to a Vec
Erik Corry
2008/10/22 11:59:48
OK
| |
3694 return CompareStringContents(ia, &ib); | 3749 return CompareStringContents(ia, &ib); |
3695 } else { | 3750 } else { |
3696 VectorIterator<uc16> ib(b->ToUC16Vector()); | 3751 VectorIterator<const uc16> ib(b->ToUC16Vector()); |
3697 return CompareStringContents(ia, &ib); | 3752 return CompareStringContents(ia, &ib); |
3698 } | 3753 } |
3699 } else { | 3754 } else { |
3700 string_compare_buffer_b.Reset(0, b); | 3755 string_compare_buffer_b.Reset(0, b); |
3701 return CompareStringContents(ia, &string_compare_buffer_b); | 3756 return CompareStringContents(ia, &string_compare_buffer_b); |
3702 } | 3757 } |
3703 } | 3758 } |
3704 | 3759 |
3705 | 3760 |
3706 static StringInputBuffer string_compare_buffer_a; | 3761 static StringInputBuffer string_compare_buffer_a; |
(...skipping 13 matching lines...) Expand all Loading... | |
3720 | 3775 |
3721 if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) { | 3776 if (this->IsSeqAsciiString() && other->IsSeqAsciiString()) { |
3722 const char* str1 = SeqAsciiString::cast(this)->GetChars(); | 3777 const char* str1 = SeqAsciiString::cast(this)->GetChars(); |
3723 const char* str2 = SeqAsciiString::cast(other)->GetChars(); | 3778 const char* str2 = SeqAsciiString::cast(other)->GetChars(); |
3724 return CompareRawStringContents(Vector<const char>(str1, len), | 3779 return CompareRawStringContents(Vector<const char>(str1, len), |
3725 Vector<const char>(str2, len)); | 3780 Vector<const char>(str2, len)); |
3726 } | 3781 } |
3727 | 3782 |
3728 if (this->IsFlat()) { | 3783 if (this->IsFlat()) { |
3729 if (this->IsAsciiRepresentation()) { | 3784 if (this->IsAsciiRepresentation()) { |
3730 Vector<const char> vec1 = this->ToAsciiVector(); | 3785 Vector<const byte> vec1 = this->ToAsciiVector(); |
3731 if (other->IsFlat()) { | 3786 if (other->IsFlat()) { |
3732 if (other->IsAsciiRepresentation()) { | 3787 if (other->IsAsciiRepresentation()) { |
3733 Vector<const char> vec2 = other->ToAsciiVector(); | 3788 Vector<const byte> vec2 = other->ToAsciiVector(); |
3734 return CompareRawStringContents(vec1, vec2); | 3789 return CompareRawStringContents(vec1, vec2); |
3735 } else { | 3790 } else { |
3736 VectorIterator<char> buf1(vec1); | 3791 VectorIterator<const byte> buf1(vec1); |
3737 VectorIterator<uc16> ib(other->ToUC16Vector()); | 3792 VectorIterator<const uc16> ib(other->ToUC16Vector()); |
3738 return CompareStringContents(&buf1, &ib); | 3793 return CompareStringContents(&buf1, &ib); |
3739 } | 3794 } |
3740 } else { | 3795 } else { |
3741 VectorIterator<char> buf1(vec1); | 3796 VectorIterator<const byte> buf1(vec1); |
3742 string_compare_buffer_b.Reset(0, other); | 3797 string_compare_buffer_b.Reset(0, other); |
3743 return CompareStringContents(&buf1, &string_compare_buffer_b); | 3798 return CompareStringContents(&buf1, &string_compare_buffer_b); |
3744 } | 3799 } |
3745 } else { | 3800 } else { |
3746 Vector<const uc16> vec1 = this->ToUC16Vector(); | 3801 Vector<const uc16> vec1 = this->ToUC16Vector(); |
3747 if (other->IsFlat()) { | 3802 if (other->IsFlat()) { |
3748 if (other->IsAsciiRepresentation()) { | 3803 if (other->IsAsciiRepresentation()) { |
3749 VectorIterator<uc16> buf1(vec1); | 3804 VectorIterator<const uc16> buf1(vec1); |
3750 VectorIterator<char> ib(other->ToAsciiVector()); | 3805 VectorIterator<const byte> ib(other->ToAsciiVector()); |
3751 return CompareStringContents(&buf1, &ib); | 3806 return CompareStringContents(&buf1, &ib); |
3752 } else { | 3807 } else { |
3753 Vector<const uc16> vec2(other->ToUC16Vector()); | 3808 Vector<const uc16> vec2(other->ToUC16Vector()); |
3754 return CompareRawStringContents(vec1, vec2); | 3809 return CompareRawStringContents(vec1, vec2); |
3755 } | 3810 } |
3756 } else { | 3811 } else { |
3757 VectorIterator<uc16> buf1(vec1); | 3812 VectorIterator<const uc16> buf1(vec1); |
3758 string_compare_buffer_b.Reset(0, other); | 3813 string_compare_buffer_b.Reset(0, other); |
3759 return CompareStringContents(&buf1, &string_compare_buffer_b); | 3814 return CompareStringContents(&buf1, &string_compare_buffer_b); |
3760 } | 3815 } |
3761 } | 3816 } |
3762 } else { | 3817 } else { |
3763 string_compare_buffer_a.Reset(0, this); | 3818 string_compare_buffer_a.Reset(0, this); |
3764 return CompareStringContentsPartial(&string_compare_buffer_a, other); | 3819 return CompareStringContentsPartial(&string_compare_buffer_a, other); |
3765 } | 3820 } |
3766 } | 3821 } |
3767 | 3822 |
(...skipping 2710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6478 // No break point. | 6533 // No break point. |
6479 if (break_point_objects()->IsUndefined()) return 0; | 6534 if (break_point_objects()->IsUndefined()) return 0; |
6480 // Single beak point. | 6535 // Single beak point. |
6481 if (!break_point_objects()->IsFixedArray()) return 1; | 6536 if (!break_point_objects()->IsFixedArray()) return 1; |
6482 // Multiple break points. | 6537 // Multiple break points. |
6483 return FixedArray::cast(break_point_objects())->length(); | 6538 return FixedArray::cast(break_point_objects())->length(); |
6484 } | 6539 } |
6485 | 6540 |
6486 | 6541 |
6487 } } // namespace v8::internal | 6542 } } // namespace v8::internal |
OLD | NEW |