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

Side by Side Diff: src/runtime.cc

Issue 6902144: Handle join of sparse arrays with non-empty separator more efficiently. (Closed)
Patch Set: Add test for empty separator. Fix brainfart. Created 9 years, 7 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
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/array-join.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 6141 matching lines...) Expand 10 before | Expand all | Expand 10 after
6152 ASSERT(sink + element_length <= end); 6152 ASSERT(sink + element_length <= end);
6153 String::WriteToFlat(element, sink, 0, element_length); 6153 String::WriteToFlat(element, sink, 0, element_length);
6154 sink += element_length; 6154 sink += element_length;
6155 } 6155 }
6156 ASSERT(sink == end); 6156 ASSERT(sink == end);
6157 6157
6158 ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead. 6158 ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead.
6159 return answer; 6159 return answer;
6160 } 6160 }
6161 6161
6162 template <typename Char>
6163 static void JoinSparseArrayWithSeparator(FixedArray* elements,
6164 int elements_length,
6165 uint32_t array_length,
6166 String* separator,
6167 Vector<Char> buffer) {
6168 int previous_separator_position = 0;
6169 int separator_length = separator->length();
6170 int cursor = 0;
6171 for (int i = 0; i < elements_length; i += 2) {
6172 int position = NumberToInt32(elements->get(i));
6173 String* string = String::cast(elements->get(i + 1));
6174 int string_length = string->length();
6175 if (string->length() > 0) {
6176 while (previous_separator_position < position) {
6177 String::WriteToFlat<Char>(separator, &buffer[cursor],
6178 0, separator_length);
6179 cursor += separator_length;
6180 previous_separator_position++;
6181 }
6182 String::WriteToFlat<Char>(string, &buffer[cursor],
6183 0, string_length);
6184 cursor += string->length();
6185 }
6186 }
6187 if (separator_length > 0) {
6188 // Array length must be representable as a signed 32-bit number,
6189 // otherwise the total string length would have been too large.
6190 ASSERT(array_length <= 0x7fffffff); // Is int32_t.
6191 int last_array_index = static_cast<int>(array_length - 1);
6192 while (previous_separator_position < last_array_index) {
6193 String::WriteToFlat<Char>(separator, &buffer[cursor],
6194 0, separator_length);
6195 cursor += separator_length;
6196 previous_separator_position++;
6197 }
6198 }
6199 ASSERT(cursor <= buffer.length());
6200 }
6201
6202
6203 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
6204 NoHandleAllocation ha;
6205 ASSERT(args.length() == 3);
6206 CONVERT_CHECKED(JSArray, elements_array, args[0]);
6207 RUNTIME_ASSERT(elements_array->HasFastElements());
6208 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
6209 CONVERT_CHECKED(String, separator, args[2]);
6210 // elements_array is fast-mode JSarray of alternating positions
6211 // (increasing order) and strings.
6212 // array_length is length of original array (used to add separators);
6213 // separator is string to put between elements. Assumed to be non-empty.
6214
6215 // Find total length of join result.
6216 int string_length = 0;
6217 bool is_ascii = true;
6218 int max_string_length = SeqAsciiString::kMaxLength;
6219 bool overflow = false;
6220 CONVERT_NUMBER_CHECKED(int, elements_length,
6221 Int32, elements_array->length());
6222 RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
6223 FixedArray* elements = FixedArray::cast(elements_array->elements());
6224 for (int i = 0; i < elements_length; i += 2) {
6225 RUNTIME_ASSERT(elements->get(i)->IsNumber());
6226 CONVERT_CHECKED(String, string, elements->get(i + 1));
6227 int length = string->length();
6228 if (is_ascii && !string->IsAsciiRepresentation()) {
6229 is_ascii = false;
6230 max_string_length = SeqTwoByteString::kMaxLength;
6231 }
6232 if (length > max_string_length ||
6233 max_string_length - length < string_length) {
6234 overflow = true;
6235 break;
6236 }
6237 string_length += length;
6238 }
6239 int separator_length = separator->length();
6240 if (!overflow && separator_length > 0) {
6241 if (array_length <= 0x7fffffffu) {
6242 int separator_count = static_cast<int>(array_length) - 1;
6243 int remaining_length = max_string_length - string_length;
6244 if ((remaining_length / separator_length) >= separator_count) {
6245 string_length += separator_length * (array_length - 1);
6246 } else {
6247 // Not room for the separators within the maximal string length.
6248 overflow = true;
6249 }
6250 } else {
6251 // Nonempty separator and at least 2^31-1 separators necessary
6252 // means that the string is too large to create.
6253 STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
6254 overflow = true;
6255 }
6256 }
6257 if (overflow) {
6258 // Throw OutOfMemory exception for creating too large a string.
6259 V8::FatalProcessOutOfMemory("Array join result too large.");
6260 }
6261
6262 if (is_ascii) {
6263 MaybeObject* result_allocation =
6264 isolate->heap()->AllocateRawAsciiString(string_length);
6265 if (result_allocation->IsFailure()) return result_allocation;
6266 SeqAsciiString* result_string =
6267 SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
6268 JoinSparseArrayWithSeparator<char>(elements,
6269 elements_length,
6270 array_length,
6271 separator,
6272 Vector<char>(result_string->GetChars(),
6273 string_length));
6274 return result_string;
6275 } else {
6276 MaybeObject* result_allocation =
6277 isolate->heap()->AllocateRawTwoByteString(string_length);
6278 if (result_allocation->IsFailure()) return result_allocation;
6279 SeqTwoByteString* result_string =
6280 SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
6281 JoinSparseArrayWithSeparator<uc16>(elements,
6282 elements_length,
6283 array_length,
6284 separator,
6285 Vector<uc16>(result_string->GetChars(),
6286 string_length));
6287 return result_string;
6288 }
6289 }
6290
6162 6291
6163 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) { 6292 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
6164 NoHandleAllocation ha; 6293 NoHandleAllocation ha;
6165 ASSERT(args.length() == 2); 6294 ASSERT(args.length() == 2);
6166 6295
6167 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); 6296 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6168 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); 6297 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6169 return isolate->heap()->NumberFromInt32(x | y); 6298 return isolate->heap()->NumberFromInt32(x | y);
6170 } 6299 }
6171 6300
(...skipping 5803 matching lines...) Expand 10 before | Expand all | Expand 10 after
11975 } else { 12104 } else {
11976 // Handle last resort GC and make sure to allow future allocations 12105 // Handle last resort GC and make sure to allow future allocations
11977 // to grow the heap without causing GCs (if possible). 12106 // to grow the heap without causing GCs (if possible).
11978 isolate->counters()->gc_last_resort_from_js()->Increment(); 12107 isolate->counters()->gc_last_resort_from_js()->Increment();
11979 isolate->heap()->CollectAllGarbage(false); 12108 isolate->heap()->CollectAllGarbage(false);
11980 } 12109 }
11981 } 12110 }
11982 12111
11983 12112
11984 } } // namespace v8::internal 12113 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/array-join.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698