Chromium Code Reviews| Index: src/runtime/runtime-strings.cc |
| diff --git a/src/runtime/runtime-strings.cc b/src/runtime/runtime-strings.cc |
| index 3654968a3b199c765bc6dfd52ac5664aa55e85ee..77e07440edb7c4debff1a9dc1bd672fad3001bab 100644 |
| --- a/src/runtime/runtime-strings.cc |
| +++ b/src/runtime/runtime-strings.cc |
| @@ -557,6 +557,7 @@ RUNTIME_FUNCTION(Runtime_StringBuilderJoin) { |
| RUNTIME_ASSERT(fixed_array->get(0)->IsString()); |
| String* first = String::cast(fixed_array->get(0)); |
| String* separator_raw = *separator; |
| + |
| int first_length = first->length(); |
| String::WriteToFlat(first, sink, 0, first_length); |
| sink += first_length; |
| @@ -580,6 +581,26 @@ RUNTIME_FUNCTION(Runtime_StringBuilderJoin) { |
| return *answer; |
| } |
| +template <typename sinkchar> |
| +static void WriteRepeatToFlat(String* src, sinkchar* buffer, int repeat, |
| + int length) { |
| + if (repeat == 0) return; |
| + |
| + String::WriteToFlat<sinkchar>(src, buffer, 0, length); |
| + |
| + sinkchar* start = buffer; |
| + int done = 1; |
| + buffer += length; |
| + |
| + while (done < repeat) { |
| + int block = Min(done, repeat - done); |
| + int block_chars = block * length; |
| + CopyChars(buffer, start, block_chars); |
|
Yang
2016/03/15 09:23:10
I wonder whether it makes sense to, in case of one
|
| + buffer += block_chars; |
| + done += block; |
| + } |
| +} |
| + |
| template <typename Char> |
| static void JoinSparseArrayWithSeparator(FixedArray* elements, |
| int elements_length, |
| @@ -589,34 +610,30 @@ static void JoinSparseArrayWithSeparator(FixedArray* elements, |
| DisallowHeapAllocation no_gc; |
| int previous_separator_position = 0; |
| int separator_length = separator->length(); |
| + DCHECK_LT(0, separator_length); |
| int cursor = 0; |
| for (int i = 0; i < elements_length; i += 2) { |
| int position = NumberToInt32(elements->get(i)); |
| String* string = String::cast(elements->get(i + 1)); |
| int string_length = string->length(); |
| if (string->length() > 0) { |
| - while (previous_separator_position < position) { |
| - String::WriteToFlat<Char>(separator, &buffer[cursor], 0, |
| - separator_length); |
| - cursor += separator_length; |
| - previous_separator_position++; |
| - } |
| + int repeat = position - previous_separator_position; |
| + WriteRepeatToFlat<Char>(separator, &buffer[cursor], repeat, |
| + separator_length); |
| + cursor += repeat * separator_length; |
| + previous_separator_position = position; |
| String::WriteToFlat<Char>(string, &buffer[cursor], 0, string_length); |
| cursor += string->length(); |
| } |
| } |
| - if (separator_length > 0) { |
| - // Array length must be representable as a signed 32-bit number, |
| - // otherwise the total string length would have been too large. |
| - DCHECK(array_length <= 0x7fffffff); // Is int32_t. |
| - int last_array_index = static_cast<int>(array_length - 1); |
| - while (previous_separator_position < last_array_index) { |
| - String::WriteToFlat<Char>(separator, &buffer[cursor], 0, |
| - separator_length); |
| - cursor += separator_length; |
| - previous_separator_position++; |
| - } |
| - } |
| + |
| + int last_array_index = static_cast<int>(array_length - 1); |
| + // Array length must be representable as a signed 32-bit number, |
| + // otherwise the total string length would have been too large. |
| + DCHECK(array_length <= 0x7fffffff); // Is int32_t. |
| + int repeat = last_array_index - previous_separator_position; |
| + WriteRepeatToFlat<Char>(separator, &buffer[cursor], repeat, separator_length); |
| + cursor += repeat * separator_length; |
| DCHECK(cursor <= buffer.length()); |
| } |