| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/conversions-inl.h" | 8 #include "src/conversions-inl.h" |
| 9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
| 10 #include "src/regexp/jsregexp-inl.h" | 10 #include "src/regexp/jsregexp-inl.h" |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 490 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 491 isolate, answer, isolate->factory()->NewRawTwoByteString(length)); | 491 isolate, answer, isolate->factory()->NewRawTwoByteString(length)); |
| 492 StringBuilderConcatHelper(*special, answer->GetChars(), | 492 StringBuilderConcatHelper(*special, answer->GetChars(), |
| 493 FixedArray::cast(array->elements()), | 493 FixedArray::cast(array->elements()), |
| 494 array_length); | 494 array_length); |
| 495 return *answer; | 495 return *answer; |
| 496 } | 496 } |
| 497 } | 497 } |
| 498 | 498 |
| 499 | 499 |
| 500 RUNTIME_FUNCTION(Runtime_StringBuilderJoin) { | |
| 501 HandleScope scope(isolate); | |
| 502 DCHECK(args.length() == 3); | |
| 503 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); | |
| 504 int32_t array_length; | |
| 505 if (!args[1]->ToInt32(&array_length)) { | |
| 506 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); | |
| 507 } | |
| 508 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); | |
| 509 RUNTIME_ASSERT(array->HasFastObjectElements()); | |
| 510 RUNTIME_ASSERT(array_length >= 0); | |
| 511 | |
| 512 Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); | |
| 513 if (fixed_array->length() < array_length) { | |
| 514 array_length = fixed_array->length(); | |
| 515 } | |
| 516 | |
| 517 if (array_length == 0) { | |
| 518 return isolate->heap()->empty_string(); | |
| 519 } else if (array_length == 1) { | |
| 520 Object* first = fixed_array->get(0); | |
| 521 RUNTIME_ASSERT(first->IsString()); | |
| 522 return first; | |
| 523 } | |
| 524 | |
| 525 int separator_length = separator->length(); | |
| 526 RUNTIME_ASSERT(separator_length > 0); | |
| 527 int max_nof_separators = | |
| 528 (String::kMaxLength + separator_length - 1) / separator_length; | |
| 529 if (max_nof_separators < (array_length - 1)) { | |
| 530 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); | |
| 531 } | |
| 532 int length = (array_length - 1) * separator_length; | |
| 533 for (int i = 0; i < array_length; i++) { | |
| 534 Object* element_obj = fixed_array->get(i); | |
| 535 RUNTIME_ASSERT(element_obj->IsString()); | |
| 536 String* element = String::cast(element_obj); | |
| 537 int increment = element->length(); | |
| 538 if (increment > String::kMaxLength - length) { | |
| 539 STATIC_ASSERT(String::kMaxLength < kMaxInt); | |
| 540 length = kMaxInt; // Provoke exception; | |
| 541 break; | |
| 542 } | |
| 543 length += increment; | |
| 544 } | |
| 545 | |
| 546 Handle<SeqTwoByteString> answer; | |
| 547 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 548 isolate, answer, isolate->factory()->NewRawTwoByteString(length)); | |
| 549 | |
| 550 DisallowHeapAllocation no_gc; | |
| 551 | |
| 552 uc16* sink = answer->GetChars(); | |
| 553 #ifdef DEBUG | |
| 554 uc16* end = sink + length; | |
| 555 #endif | |
| 556 | |
| 557 RUNTIME_ASSERT(fixed_array->get(0)->IsString()); | |
| 558 String* first = String::cast(fixed_array->get(0)); | |
| 559 String* separator_raw = *separator; | |
| 560 int first_length = first->length(); | |
| 561 String::WriteToFlat(first, sink, 0, first_length); | |
| 562 sink += first_length; | |
| 563 | |
| 564 for (int i = 1; i < array_length; i++) { | |
| 565 DCHECK(sink + separator_length <= end); | |
| 566 String::WriteToFlat(separator_raw, sink, 0, separator_length); | |
| 567 sink += separator_length; | |
| 568 | |
| 569 RUNTIME_ASSERT(fixed_array->get(i)->IsString()); | |
| 570 String* element = String::cast(fixed_array->get(i)); | |
| 571 int element_length = element->length(); | |
| 572 DCHECK(sink + element_length <= end); | |
| 573 String::WriteToFlat(element, sink, 0, element_length); | |
| 574 sink += element_length; | |
| 575 } | |
| 576 DCHECK(sink == end); | |
| 577 | |
| 578 // Use %_FastOneByteArrayJoin instead. | |
| 579 DCHECK(!answer->IsOneByteRepresentation()); | |
| 580 return *answer; | |
| 581 } | |
| 582 | |
| 583 template <typename Char> | 500 template <typename Char> |
| 584 static void JoinSparseArrayWithSeparator(FixedArray* elements, | 501 static void JoinSparseArrayWithSeparator(FixedArray* elements, |
| 585 int elements_length, | 502 int elements_length, |
| 586 uint32_t array_length, | 503 uint32_t array_length, |
| 587 String* separator, | 504 String* separator, |
| 588 Vector<Char> buffer) { | 505 Vector<Char> buffer) { |
| 589 DisallowHeapAllocation no_gc; | 506 DisallowHeapAllocation no_gc; |
| 590 int previous_separator_position = 0; | 507 int previous_separator_position = 0; |
| 591 int separator_length = separator->length(); | 508 int separator_length = separator->length(); |
| 592 int cursor = 0; | 509 int cursor = 0; |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 SealHandleScope shs(isolate); | 1226 SealHandleScope shs(isolate); |
| 1310 DCHECK(args.length() == 2); | 1227 DCHECK(args.length() == 2); |
| 1311 if (!args[0]->IsString()) return isolate->heap()->undefined_value(); | 1228 if (!args[0]->IsString()) return isolate->heap()->undefined_value(); |
| 1312 if (!args[1]->IsNumber()) return isolate->heap()->undefined_value(); | 1229 if (!args[1]->IsNumber()) return isolate->heap()->undefined_value(); |
| 1313 if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value(); | 1230 if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value(); |
| 1314 return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate); | 1231 return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate); |
| 1315 } | 1232 } |
| 1316 | 1233 |
| 1317 } // namespace internal | 1234 } // namespace internal |
| 1318 } // namespace v8 | 1235 } // namespace v8 |
| OLD | NEW |