Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: src/objects.cc

Issue 8011: Use direct copy and templates to speed up flattening of strings. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698