Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 0ef654a5d10e7706bca6f15208e02edee26f41c0..a14c92fdf79214769b42080c540f5d2c67bce682 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -5795,6 +5795,107 @@ static MaybeObject* Runtime_StringBuilderConcat(Arguments args) { |
} |
+template <typename sinkchar> |
+static inline void StringBuilderJoinHelper(String* separator, |
+ sinkchar* sink, |
+ FixedArray* fixed_array, |
+ int array_length) { |
+ ASSERT(array_length > 0); |
+ String* s = String::cast(fixed_array->get(0)); |
+ int position = s->length(); |
+ String::WriteToFlat(s, sink, 0, position); |
+ |
+ int separator_length = separator->length(); |
+ |
+ for (int i = 1; i < array_length; i++) { |
+ String::WriteToFlat(separator, sink + position, 0, separator_length); |
+ position += separator_length; |
+ |
+ String* element = String::cast(fixed_array->get(i)); |
+ int element_length = element->length(); |
+ String::WriteToFlat(element, sink + position, 0, element_length); |
+ position += element_length; |
+ } |
+} |
+ |
+ |
+static MaybeObject* Runtime_StringBuilderJoin(Arguments args) { |
+ NoHandleAllocation ha; |
+ ASSERT(args.length() == 3); |
+ CONVERT_CHECKED(JSArray, array, args[0]); |
+ if (!args[1]->IsSmi()) { |
+ Top::context()->mark_out_of_memory(); |
+ return Failure::OutOfMemoryException(); |
+ } |
+ int array_length = Smi::cast(args[1])->value(); |
+ CONVERT_CHECKED(String, separator, args[2]); |
+ |
+ if (!array->HasFastElements()) { |
+ return Top::Throw(Heap::illegal_argument_symbol()); |
+ } |
+ FixedArray* fixed_array = FixedArray::cast(array->elements()); |
+ if (fixed_array->length() < array_length) { |
+ array_length = fixed_array->length(); |
+ } |
+ |
+ if (array_length == 0) { |
+ return Heap::empty_string(); |
+ } else if (array_length == 1) { |
+ Object* first = fixed_array->get(0); |
+ if (first->IsString()) return first; |
+ } |
+ |
+ int separator_length = separator->length(); |
+ int max_nof_separators = |
+ (String::kMaxLength + separator_length - 1) / separator_length; |
+ if (max_nof_separators < (array_length - 1)) { |
+ Top::context()->mark_out_of_memory(); |
+ return Failure::OutOfMemoryException(); |
+ } |
+ int position = (array_length - 1) * separator_length; |
+ bool ascii = separator->HasOnlyAsciiChars(); |
sandholm
2011/02/14 15:23:04
You will always need a TwoByteString.
If everythin
|
+ for (int i = 0; i < array_length; i++) { |
+ int increment = 0; |
+ String* element = String::cast(fixed_array->get(i)); |
+ int element_length = element->length(); |
+ increment = element_length; |
+ if (ascii && !element->HasOnlyAsciiChars()) { |
+ ascii = false; |
+ } |
+ if (increment > String::kMaxLength - position) { |
+ Top::context()->mark_out_of_memory(); |
+ return Failure::OutOfMemoryException(); |
+ } |
+ position += increment; |
+ } |
+ |
+ int length = position; |
+ Object* object; |
+ |
+ if (ascii) { |
+ { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(length); |
+ if (!maybe_object->ToObject(&object)) return maybe_object; |
+ } |
+ SeqAsciiString* answer = SeqAsciiString::cast(object); |
+ StringBuilderJoinHelper(separator, |
+ answer->GetChars(), |
+ fixed_array, |
+ array_length); |
+ return answer; |
+ } else { |
+ { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length); |
+ if (!maybe_object->ToObject(&object)) return maybe_object; |
+ } |
+ SeqTwoByteString* answer = SeqTwoByteString::cast(object); |
+ StringBuilderJoinHelper(separator, |
+ answer->GetChars(), |
+ fixed_array, |
+ array_length); |
+ return answer; |
+ } |
+} |
+ |
+ |
static MaybeObject* Runtime_NumberOr(Arguments args) { |
NoHandleAllocation ha; |
ASSERT(args.length() == 2); |