OLD | NEW |
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 Loading... |
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 (is_int32(array_length)) { |
| 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 Loading... |
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 |
OLD | NEW |