| 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/regexp/jsregexp-inl.h" | 8 #include "src/regexp/jsregexp-inl.h" |
| 9 #include "src/string-builder.h" | 9 #include "src/string-builder.h" |
| 10 #include "src/string-search.h" | 10 #include "src/string-search.h" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 HandleScope scope(isolate); | 133 HandleScope scope(isolate); |
| 134 DCHECK(args.length() == 3); | 134 DCHECK(args.length() == 3); |
| 135 | 135 |
| 136 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); | 136 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); |
| 137 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); | 137 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); |
| 138 CONVERT_ARG_HANDLE_CHECKED(Object, index, 2); | 138 CONVERT_ARG_HANDLE_CHECKED(Object, index, 2); |
| 139 | 139 |
| 140 uint32_t start_index = 0; | 140 uint32_t start_index = 0; |
| 141 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); | 141 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); |
| 142 | 142 |
| 143 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); | 143 CHECK(start_index <= static_cast<uint32_t>(sub->length())); |
| 144 int position = StringMatch(isolate, sub, pat, start_index); | 144 int position = StringMatch(isolate, sub, pat, start_index); |
| 145 return Smi::FromInt(position); | 145 return Smi::FromInt(position); |
| 146 } | 146 } |
| 147 | 147 |
| 148 | 148 |
| 149 template <typename schar, typename pchar> | 149 template <typename schar, typename pchar> |
| 150 static int StringMatchBackwards(Vector<const schar> subject, | 150 static int StringMatchBackwards(Vector<const schar> subject, |
| 151 Vector<const pchar> pattern, int idx) { | 151 Vector<const pchar> pattern, int idx) { |
| 152 int pattern_length = pattern.length(); | 152 int pattern_length = pattern.length(); |
| 153 DCHECK(pattern_length >= 1); | 153 DCHECK(pattern_length >= 1); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); | 313 CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); |
| 314 CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); | 314 CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); |
| 315 isolate->counters()->string_add_runtime()->Increment(); | 315 isolate->counters()->string_add_runtime()->Increment(); |
| 316 RETURN_RESULT_OR_FAILURE(isolate, | 316 RETURN_RESULT_OR_FAILURE(isolate, |
| 317 isolate->factory()->NewConsString(str1, str2)); | 317 isolate->factory()->NewConsString(str1, str2)); |
| 318 } | 318 } |
| 319 | 319 |
| 320 | 320 |
| 321 RUNTIME_FUNCTION(Runtime_InternalizeString) { | 321 RUNTIME_FUNCTION(Runtime_InternalizeString) { |
| 322 HandleScope handles(isolate); | 322 HandleScope handles(isolate); |
| 323 RUNTIME_ASSERT(args.length() == 1); | 323 DCHECK(args.length() == 1); |
| 324 CONVERT_ARG_HANDLE_CHECKED(String, string, 0); | 324 CONVERT_ARG_HANDLE_CHECKED(String, string, 0); |
| 325 return *isolate->factory()->InternalizeString(string); | 325 return *isolate->factory()->InternalizeString(string); |
| 326 } | 326 } |
| 327 | 327 |
| 328 | 328 |
| 329 RUNTIME_FUNCTION(Runtime_StringMatch) { | 329 RUNTIME_FUNCTION(Runtime_StringMatch) { |
| 330 HandleScope handles(isolate); | 330 HandleScope handles(isolate); |
| 331 DCHECK(args.length() == 3); | 331 DCHECK(args.length() == 3); |
| 332 | 332 |
| 333 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 333 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 334 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); | 334 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); |
| 335 CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2); | 335 CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2); |
| 336 | 336 |
| 337 RUNTIME_ASSERT(regexp_info->HasFastObjectElements()); | 337 CHECK(regexp_info->HasFastObjectElements()); |
| 338 | 338 |
| 339 RegExpImpl::GlobalCache global_cache(regexp, subject, isolate); | 339 RegExpImpl::GlobalCache global_cache(regexp, subject, isolate); |
| 340 if (global_cache.HasException()) return isolate->heap()->exception(); | 340 if (global_cache.HasException()) return isolate->heap()->exception(); |
| 341 | 341 |
| 342 int capture_count = regexp->CaptureCount(); | 342 int capture_count = regexp->CaptureCount(); |
| 343 | 343 |
| 344 ZoneScope zone_scope(isolate->runtime_zone()); | 344 ZoneScope zone_scope(isolate->runtime_zone()); |
| 345 ZoneList<int> offsets(8, zone_scope.zone()); | 345 ZoneList<int> offsets(8, zone_scope.zone()); |
| 346 | 346 |
| 347 while (true) { | 347 while (true) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 HandleScope scope(isolate); | 424 HandleScope scope(isolate); |
| 425 DCHECK(args.length() == 3); | 425 DCHECK(args.length() == 3); |
| 426 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); | 426 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
| 427 int32_t array_length; | 427 int32_t array_length; |
| 428 if (!args[1]->ToInt32(&array_length)) { | 428 if (!args[1]->ToInt32(&array_length)) { |
| 429 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); | 429 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); |
| 430 } | 430 } |
| 431 CONVERT_ARG_HANDLE_CHECKED(String, special, 2); | 431 CONVERT_ARG_HANDLE_CHECKED(String, special, 2); |
| 432 | 432 |
| 433 size_t actual_array_length = 0; | 433 size_t actual_array_length = 0; |
| 434 RUNTIME_ASSERT( | 434 CHECK(TryNumberToSize(isolate, array->length(), &actual_array_length)); |
| 435 TryNumberToSize(isolate, array->length(), &actual_array_length)); | 435 CHECK(array_length >= 0); |
| 436 RUNTIME_ASSERT(array_length >= 0); | 436 CHECK(static_cast<size_t>(array_length) <= actual_array_length); |
| 437 RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length); | |
| 438 | 437 |
| 439 // This assumption is used by the slice encoding in one or two smis. | 438 // This assumption is used by the slice encoding in one or two smis. |
| 440 DCHECK(Smi::kMaxValue >= String::kMaxLength); | 439 DCHECK(Smi::kMaxValue >= String::kMaxLength); |
| 441 | 440 |
| 442 RUNTIME_ASSERT(array->HasFastElements()); | 441 CHECK(array->HasFastElements()); |
| 443 JSObject::EnsureCanContainHeapObjectElements(array); | 442 JSObject::EnsureCanContainHeapObjectElements(array); |
| 444 | 443 |
| 445 int special_length = special->length(); | 444 int special_length = special->length(); |
| 446 if (!array->HasFastObjectElements()) { | 445 if (!array->HasFastObjectElements()) { |
| 447 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 446 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
| 448 } | 447 } |
| 449 | 448 |
| 450 int length; | 449 int length; |
| 451 bool one_byte = special->HasOnlyOneByteChars(); | 450 bool one_byte = special->HasOnlyOneByteChars(); |
| 452 | 451 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 | 492 |
| 494 RUNTIME_FUNCTION(Runtime_StringBuilderJoin) { | 493 RUNTIME_FUNCTION(Runtime_StringBuilderJoin) { |
| 495 HandleScope scope(isolate); | 494 HandleScope scope(isolate); |
| 496 DCHECK(args.length() == 3); | 495 DCHECK(args.length() == 3); |
| 497 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); | 496 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
| 498 int32_t array_length; | 497 int32_t array_length; |
| 499 if (!args[1]->ToInt32(&array_length)) { | 498 if (!args[1]->ToInt32(&array_length)) { |
| 500 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); | 499 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); |
| 501 } | 500 } |
| 502 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); | 501 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); |
| 503 RUNTIME_ASSERT(array->HasFastObjectElements()); | 502 CHECK(array->HasFastObjectElements()); |
| 504 RUNTIME_ASSERT(array_length >= 0); | 503 CHECK(array_length >= 0); |
| 505 | 504 |
| 506 Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); | 505 Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); |
| 507 if (fixed_array->length() < array_length) { | 506 if (fixed_array->length() < array_length) { |
| 508 array_length = fixed_array->length(); | 507 array_length = fixed_array->length(); |
| 509 } | 508 } |
| 510 | 509 |
| 511 if (array_length == 0) { | 510 if (array_length == 0) { |
| 512 return isolate->heap()->empty_string(); | 511 return isolate->heap()->empty_string(); |
| 513 } else if (array_length == 1) { | 512 } else if (array_length == 1) { |
| 514 Object* first = fixed_array->get(0); | 513 Object* first = fixed_array->get(0); |
| 515 RUNTIME_ASSERT(first->IsString()); | 514 CHECK(first->IsString()); |
| 516 return first; | 515 return first; |
| 517 } | 516 } |
| 518 | 517 |
| 519 int separator_length = separator->length(); | 518 int separator_length = separator->length(); |
| 520 RUNTIME_ASSERT(separator_length > 0); | 519 CHECK(separator_length > 0); |
| 521 int max_nof_separators = | 520 int max_nof_separators = |
| 522 (String::kMaxLength + separator_length - 1) / separator_length; | 521 (String::kMaxLength + separator_length - 1) / separator_length; |
| 523 if (max_nof_separators < (array_length - 1)) { | 522 if (max_nof_separators < (array_length - 1)) { |
| 524 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); | 523 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewInvalidStringLengthError()); |
| 525 } | 524 } |
| 526 int length = (array_length - 1) * separator_length; | 525 int length = (array_length - 1) * separator_length; |
| 527 for (int i = 0; i < array_length; i++) { | 526 for (int i = 0; i < array_length; i++) { |
| 528 Object* element_obj = fixed_array->get(i); | 527 Object* element_obj = fixed_array->get(i); |
| 529 RUNTIME_ASSERT(element_obj->IsString()); | 528 CHECK(element_obj->IsString()); |
| 530 String* element = String::cast(element_obj); | 529 String* element = String::cast(element_obj); |
| 531 int increment = element->length(); | 530 int increment = element->length(); |
| 532 if (increment > String::kMaxLength - length) { | 531 if (increment > String::kMaxLength - length) { |
| 533 STATIC_ASSERT(String::kMaxLength < kMaxInt); | 532 STATIC_ASSERT(String::kMaxLength < kMaxInt); |
| 534 length = kMaxInt; // Provoke exception; | 533 length = kMaxInt; // Provoke exception; |
| 535 break; | 534 break; |
| 536 } | 535 } |
| 537 length += increment; | 536 length += increment; |
| 538 } | 537 } |
| 539 | 538 |
| 540 Handle<SeqTwoByteString> answer; | 539 Handle<SeqTwoByteString> answer; |
| 541 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 540 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 542 isolate, answer, isolate->factory()->NewRawTwoByteString(length)); | 541 isolate, answer, isolate->factory()->NewRawTwoByteString(length)); |
| 543 | 542 |
| 544 DisallowHeapAllocation no_gc; | 543 DisallowHeapAllocation no_gc; |
| 545 | 544 |
| 546 uc16* sink = answer->GetChars(); | 545 uc16* sink = answer->GetChars(); |
| 547 #ifdef DEBUG | 546 #ifdef DEBUG |
| 548 uc16* end = sink + length; | 547 uc16* end = sink + length; |
| 549 #endif | 548 #endif |
| 550 | 549 |
| 551 RUNTIME_ASSERT(fixed_array->get(0)->IsString()); | 550 CHECK(fixed_array->get(0)->IsString()); |
| 552 String* first = String::cast(fixed_array->get(0)); | 551 String* first = String::cast(fixed_array->get(0)); |
| 553 String* separator_raw = *separator; | 552 String* separator_raw = *separator; |
| 554 | 553 |
| 555 int first_length = first->length(); | 554 int first_length = first->length(); |
| 556 String::WriteToFlat(first, sink, 0, first_length); | 555 String::WriteToFlat(first, sink, 0, first_length); |
| 557 sink += first_length; | 556 sink += first_length; |
| 558 | 557 |
| 559 for (int i = 1; i < array_length; i++) { | 558 for (int i = 1; i < array_length; i++) { |
| 560 DCHECK(sink + separator_length <= end); | 559 DCHECK(sink + separator_length <= end); |
| 561 String::WriteToFlat(separator_raw, sink, 0, separator_length); | 560 String::WriteToFlat(separator_raw, sink, 0, separator_length); |
| 562 sink += separator_length; | 561 sink += separator_length; |
| 563 | 562 |
| 564 RUNTIME_ASSERT(fixed_array->get(i)->IsString()); | 563 CHECK(fixed_array->get(i)->IsString()); |
| 565 String* element = String::cast(fixed_array->get(i)); | 564 String* element = String::cast(fixed_array->get(i)); |
| 566 int element_length = element->length(); | 565 int element_length = element->length(); |
| 567 DCHECK(sink + element_length <= end); | 566 DCHECK(sink + element_length <= end); |
| 568 String::WriteToFlat(element, sink, 0, element_length); | 567 String::WriteToFlat(element, sink, 0, element_length); |
| 569 sink += element_length; | 568 sink += element_length; |
| 570 } | 569 } |
| 571 DCHECK(sink == end); | 570 DCHECK(sink == end); |
| 572 | 571 |
| 573 // Use %_FastOneByteArrayJoin instead. | 572 // Use %_FastOneByteArrayJoin instead. |
| 574 DCHECK(!answer->IsOneByteRepresentation()); | 573 DCHECK(!answer->IsOneByteRepresentation()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 | 632 |
| 634 | 633 |
| 635 RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) { | 634 RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) { |
| 636 HandleScope scope(isolate); | 635 HandleScope scope(isolate); |
| 637 DCHECK(args.length() == 3); | 636 DCHECK(args.length() == 3); |
| 638 CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0); | 637 CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0); |
| 639 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); | 638 CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]); |
| 640 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); | 639 CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); |
| 641 // elements_array is fast-mode JSarray of alternating positions | 640 // elements_array is fast-mode JSarray of alternating positions |
| 642 // (increasing order) and strings. | 641 // (increasing order) and strings. |
| 643 RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements()); | 642 CHECK(elements_array->HasFastSmiOrObjectElements()); |
| 644 // array_length is length of original array (used to add separators); | 643 // array_length is length of original array (used to add separators); |
| 645 // separator is string to put between elements. Assumed to be non-empty. | 644 // separator is string to put between elements. Assumed to be non-empty. |
| 646 RUNTIME_ASSERT(array_length > 0); | 645 CHECK(array_length > 0); |
| 647 | 646 |
| 648 // Find total length of join result. | 647 // Find total length of join result. |
| 649 int string_length = 0; | 648 int string_length = 0; |
| 650 bool is_one_byte = separator->IsOneByteRepresentation(); | 649 bool is_one_byte = separator->IsOneByteRepresentation(); |
| 651 bool overflow = false; | 650 bool overflow = false; |
| 652 CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length()); | 651 CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length()); |
| 653 RUNTIME_ASSERT(elements_length <= elements_array->elements()->length()); | 652 CHECK(elements_length <= elements_array->elements()->length()); |
| 654 RUNTIME_ASSERT((elements_length & 1) == 0); // Even length. | 653 CHECK((elements_length & 1) == 0); // Even length. |
| 655 FixedArray* elements = FixedArray::cast(elements_array->elements()); | 654 FixedArray* elements = FixedArray::cast(elements_array->elements()); |
| 656 { | 655 { |
| 657 DisallowHeapAllocation no_gc; | 656 DisallowHeapAllocation no_gc; |
| 658 for (int i = 0; i < elements_length; i += 2) { | 657 for (int i = 0; i < elements_length; i += 2) { |
| 659 String* string = String::cast(elements->get(i + 1)); | 658 String* string = String::cast(elements->get(i + 1)); |
| 660 int length = string->length(); | 659 int length = string->length(); |
| 661 if (is_one_byte && !string->IsOneByteRepresentation()) { | 660 if (is_one_byte && !string->IsOneByteRepresentation()) { |
| 662 is_one_byte = false; | 661 is_one_byte = false; |
| 663 } | 662 } |
| 664 if (length > String::kMaxLength || | 663 if (length > String::kMaxLength || |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 SealHandleScope shs(isolate); | 1206 SealHandleScope shs(isolate); |
| 1208 DCHECK(args.length() == 2); | 1207 DCHECK(args.length() == 2); |
| 1209 if (!args[0]->IsString()) return isolate->heap()->undefined_value(); | 1208 if (!args[0]->IsString()) return isolate->heap()->undefined_value(); |
| 1210 if (!args[1]->IsNumber()) return isolate->heap()->undefined_value(); | 1209 if (!args[1]->IsNumber()) return isolate->heap()->undefined_value(); |
| 1211 if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value(); | 1210 if (std::isinf(args.number_at(1))) return isolate->heap()->nan_value(); |
| 1212 return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate); | 1211 return __RT_impl_Runtime_StringCharCodeAtRT(args, isolate); |
| 1213 } | 1212 } |
| 1214 | 1213 |
| 1215 } // namespace internal | 1214 } // namespace internal |
| 1216 } // namespace v8 | 1215 } // namespace v8 |
| OLD | NEW |