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

Side by Side Diff: src/api.cc

Issue 9696032: Speed up WriteUtf8 in the case where the output buffer is large enough. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 9 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 3676 matching lines...) Expand 10 before | Expand all | Expand 10 after
3687 } 3687 }
3688 3688
3689 3689
3690 int String::Utf8Length() const { 3690 int String::Utf8Length() const {
3691 i::Handle<i::String> str = Utils::OpenHandle(this); 3691 i::Handle<i::String> str = Utils::OpenHandle(this);
3692 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0; 3692 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0;
3693 return i::Utf8Length(str); 3693 return i::Utf8Length(str);
3694 } 3694 }
3695 3695
3696 3696
3697 // Will fail with a negative answer if the recursion depth is too high.
3698 static int RecursivelySerializeToUtf8(i::String* string,
3699 char* buffer,
3700 int start,
3701 int end,
3702 int recursion_budget,
3703 int32_t previous_character,
3704 int32_t* last_character) {
3705 int utf8_bytes = 0;
3706 while (true) {
3707 if (string->IsAsciiRepresentation()) {
3708 i::String::WriteToFlat(string, buffer, start, end);
3709 *last_character = unibrow::Utf16::kNoPreviousCharacter;
3710 return utf8_bytes + end - start;
3711 }
3712 switch (i::StringShape(string).representation_tag()) {
3713 case i::kExternalStringTag: {
3714 const uint16_t* data = i::ExternalTwoByteString::cast(string)->
3715 ExternalTwoByteStringGetData(start);
3716 char* current = buffer;
3717 for (int i = start; i < end; i++) {
3718 uint16_t character = data[i];
3719 current +=
3720 unibrow::Utf8::Encode(current, character, previous_character);
3721 previous_character = character;
3722 }
3723 *last_character = previous_character;
3724 return utf8_bytes + current - buffer;
3725 }
3726 case i::kSeqStringTag: {
3727 const uint16_t* data =
3728 i::SeqTwoByteString::cast(string)->SeqTwoByteStringGetData(start);
3729 char* current = buffer;
3730 for (int i = start; i < end; i++) {
3731 uint16_t character = data[i];
3732 current +=
3733 unibrow::Utf8::Encode(current, character, previous_character);
3734 previous_character = character;
3735 }
3736 *last_character = previous_character;
3737 return utf8_bytes + current - buffer;
3738 }
3739 case i::kSlicedStringTag: {
3740 i::SlicedString* slice = i::SlicedString::cast(string);
3741 unsigned offset = slice->offset();
3742 string = slice->parent();
3743 start += offset;
3744 end += offset;
3745 }
fschneider 2012/03/20 09:45:49 Accidental fall-through here?
3746 case i::kConsStringTag: {
3747 i::ConsString* cons_string = i::ConsString::cast(string);
3748 i::String* first = cons_string->first();
3749 int boundary = first->length();
3750 if (start >= boundary) {
3751 // Only need RHS.
3752 string = cons_string->second();
3753 start -= boundary;
3754 end -= boundary;
3755 continue;
3756 } else if (end <= boundary) {
3757 // Only need LHS.
3758 string = first;
3759 } else {
3760 if (recursion_budget == 0) return -1;
3761 int extra_utf8_bytes =
3762 RecursivelySerializeToUtf8(first,
3763 buffer,
3764 start,
3765 boundary,
3766 recursion_budget - 1,
3767 previous_character,
3768 &previous_character);
3769 if (extra_utf8_bytes < 0) return extra_utf8_bytes;
3770 buffer += extra_utf8_bytes;
3771 utf8_bytes += extra_utf8_bytes;
3772 string = cons_string->second();
3773 start = 0;
3774 end -= boundary;
3775 }
3776 }
3777 }
3778 }
3779 UNREACHABLE();
3780 return 0;
3781 }
3782
3783
3697 int String::WriteUtf8(char* buffer, 3784 int String::WriteUtf8(char* buffer,
3698 int capacity, 3785 int capacity,
3699 int* nchars_ref, 3786 int* nchars_ref,
3700 int options) const { 3787 int options) const {
3701 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3788 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3702 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; 3789 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0;
3703 LOG_API(isolate, "String::WriteUtf8"); 3790 LOG_API(isolate, "String::WriteUtf8");
3704 ENTER_V8(isolate); 3791 ENTER_V8(isolate);
3705 i::Handle<i::String> str = Utils::OpenHandle(this); 3792 i::Handle<i::String> str = Utils::OpenHandle(this);
3793 int string_length = str->length();
3706 if (str->IsAsciiRepresentation()) { 3794 if (str->IsAsciiRepresentation()) {
3707 int len; 3795 int len;
3708 if (capacity == -1) { 3796 if (capacity == -1) {
3709 capacity = str->length() + 1; 3797 capacity = str->length() + 1;
3710 len = str->length(); 3798 len = string_length;
3711 } else { 3799 } else {
3712 len = i::Min(capacity, str->length()); 3800 len = i::Min(capacity, str->length());
3713 } 3801 }
3714 i::String::WriteToFlat(*str, buffer, 0, len); 3802 i::String::WriteToFlat(*str, buffer, 0, len);
3715 if (nchars_ref != NULL) *nchars_ref = len; 3803 if (nchars_ref != NULL) *nchars_ref = len;
3716 if (!(options & NO_NULL_TERMINATION) && capacity > len) { 3804 if (!(options & NO_NULL_TERMINATION) && capacity > len) {
3717 buffer[len] = '\0'; 3805 buffer[len] = '\0';
3718 return len + 1; 3806 return len + 1;
3719 } 3807 }
3720 return len; 3808 return len;
3721 } 3809 }
3722 3810
3811 if (capacity == -1 || capacity >= string_length * 3) {
3812 int32_t previous = unibrow::Utf16::kNoPreviousCharacter;
3813 const int kMaxRecursion = 100;
3814 int utf8_bytes =
3815 RecursivelySerializeToUtf8(*str,
3816 buffer,
3817 0,
3818 string_length,
3819 kMaxRecursion,
3820 previous,
3821 &previous);
3822 if (utf8_bytes >= 0) {
3823 // Success serializing with recursion.
3824 if ((options & NO_NULL_TERMINATION) == 0 &&
3825 (capacity > utf8_bytes || capacity == -1)) {
3826 buffer[utf8_bytes++] = '\0';
3827 }
3828 if (nchars_ref != NULL) *nchars_ref = string_length;
3829 return utf8_bytes;
3830 }
3831 FlattenString(str);
3832 // Recurse once. This time around the string is flat and the serializing
3833 // with recursion will certainly succeed.
3834 return WriteUtf8(buffer, capacity, nchars_ref, options);
3835 } else if (capacity >= string_length) {
3836 // First check that the buffer is large enough. If it is, then recurse
3837 // once without a capacity limit, which will get into the other branch of
3838 // this 'if'.
3839 int utf8_bytes = i::Utf8Length(str);
3840 if ((options & NO_NULL_TERMINATION) == 0) utf8_bytes++;
3841 if (utf8_bytes <= capacity) {
3842 return WriteUtf8(buffer, -1, nchars_ref, options);
3843 }
3844 }
3845
3846 // Slow case.
3723 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3847 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer();
3724 isolate->string_tracker()->RecordWrite(str); 3848 isolate->string_tracker()->RecordWrite(str);
3725 if (options & HINT_MANY_WRITES_EXPECTED) { 3849 if (options & HINT_MANY_WRITES_EXPECTED) {
3726 // Flatten the string for efficiency. This applies whether we are 3850 // Flatten the string for efficiency. This applies whether we are
3727 // using StringInputBuffer or Get(i) to access the characters. 3851 // using StringInputBuffer or Get(i) to access the characters.
3728 FlattenString(str); 3852 FlattenString(str);
3729 } 3853 }
3730 write_input_buffer.Reset(0, *str); 3854 write_input_buffer.Reset(0, *str);
3731 int len = str->length(); 3855 int len = str->length();
3732 // Encode the first K - 3 bytes directly into the buffer since we 3856 // Encode the first K - 3 bytes directly into the buffer since we
(...skipping 2489 matching lines...) Expand 10 before | Expand all | Expand 10 after
6222 6346
6223 6347
6224 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { 6348 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
6225 HandleScopeImplementer* scope_implementer = 6349 HandleScopeImplementer* scope_implementer =
6226 reinterpret_cast<HandleScopeImplementer*>(storage); 6350 reinterpret_cast<HandleScopeImplementer*>(storage);
6227 scope_implementer->IterateThis(v); 6351 scope_implementer->IterateThis(v);
6228 return storage + ArchiveSpacePerThread(); 6352 return storage + ArchiveSpacePerThread();
6229 } 6353 }
6230 6354
6231 } } // namespace v8::internal 6355 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698