OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 } | 721 } |
722 | 722 |
723 // Set the length. | 723 // Set the length. |
724 array->set_length(Smi::FromInt(new_length)); | 724 array->set_length(Smi::FromInt(new_length)); |
725 | 725 |
726 return result_array; | 726 return result_array; |
727 } | 727 } |
728 | 728 |
729 | 729 |
730 BUILTIN(ArrayConcat) { | 730 BUILTIN(ArrayConcat) { |
731 Counters::array_concat_builtin_total.Increment(); | 731 if (!ArrayPrototypeHasNoElements()) { |
732 if (args.length() != 2) { | |
733 // Fast case only for concating two arrays. | |
734 return CallJsBuiltin("ArrayConcat", args); | |
735 } | |
736 Counters::array_concat_builtin_two_args.Increment(); | |
737 | |
738 Object* receiver_obj = *args.receiver(); | |
739 FixedArray* receiver_elms = NULL; | |
740 Object* arg_obj = args[1]; | |
741 FixedArray* arg_elms = NULL; | |
742 if (!IsJSArrayWithFastElements(receiver_obj, &receiver_elms) | |
743 || !IsJSArrayWithFastElements(arg_obj, &arg_elms) | |
744 || !ArrayPrototypeHasNoElements()) { | |
745 return CallJsBuiltin("ArrayConcat", args); | 732 return CallJsBuiltin("ArrayConcat", args); |
746 } | 733 } |
747 | 734 |
748 JSArray* receiver_array = JSArray::cast(receiver_obj); | 735 // Iterate through all the arguments performing checks |
749 ASSERT(receiver_array->HasFastElements()); | 736 // and calculating total length. |
750 JSArray* arg_array = JSArray::cast(arg_obj); | 737 int n_arguments = args.length(); |
751 ASSERT(arg_array->HasFastElements()); | 738 int result_len = 0; |
| 739 for (int i = 0; i < n_arguments; i++) { |
| 740 Object* arg = args[i]; |
| 741 if (!arg->IsJSArray() || JSArray::cast(arg)->HasFastElements()) { |
| 742 return CallJsBuiltin("ArrayConcat", args); |
| 743 } |
752 | 744 |
753 int receiver_len = Smi::cast(receiver_array->length())->value(); | 745 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
754 int arg_len = Smi::cast(arg_array->length())->value(); | |
755 ASSERT(receiver_len <= (Smi::kMaxValue - arg_len)); | |
756 | 746 |
757 int result_len = receiver_len + arg_len; | 747 // We shouldn't overflow when adding another len. |
758 if (result_len > FixedArray::kMaxSize) { | 748 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
759 return CallJsBuiltin("ArrayConcat", args); | 749 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 750 USE(kHalfOfMaxInt); |
| 751 result_len += len; |
| 752 ASSERT(result_len >= 0); |
| 753 |
| 754 if (result_len > FixedArray::kMaxLength) { |
| 755 return CallJsBuiltin("ArrayConcat", args); |
| 756 } |
760 } | 757 } |
| 758 |
761 if (result_len == 0) { | 759 if (result_len == 0) { |
762 return AllocateEmptyJSArray(); | 760 return AllocateEmptyJSArray(); |
763 } | 761 } |
764 | 762 |
765 // Allocate result. | 763 // Allocate result. |
766 Object* result = AllocateJSArray(); | 764 Object* result = AllocateJSArray(); |
767 if (result->IsFailure()) return result; | 765 if (result->IsFailure()) return result; |
768 JSArray* result_array = JSArray::cast(result); | 766 JSArray* result_array = JSArray::cast(result); |
769 | 767 |
770 result = Heap::AllocateUninitializedFixedArray(result_len); | 768 result = Heap::AllocateUninitializedFixedArray(result_len); |
771 if (result->IsFailure()) return result; | 769 if (result->IsFailure()) return result; |
772 FixedArray* result_elms = FixedArray::cast(result); | 770 FixedArray* result_elms = FixedArray::cast(result); |
773 | 771 |
774 // Copy data. | 772 // Copy data. |
775 AssertNoAllocation no_gc; | 773 AssertNoAllocation no_gc; |
776 CopyElements(&no_gc, result_elms, 0, receiver_elms, 0, receiver_len); | 774 int start_pos = 0; |
777 CopyElements(&no_gc, result_elms, receiver_len, arg_elms, 0, arg_len); | 775 for (int i = 0; i < n_arguments; i++) { |
| 776 JSArray* array = JSArray::cast(args[i]); |
| 777 FixedArray* elms = FixedArray::cast(array->elements()); |
| 778 int len = Smi::cast(array->length())->value(); |
| 779 CopyElements(&no_gc, result_elms, start_pos, elms, 0, len); |
| 780 start_pos += len; |
| 781 } |
| 782 ASSERT(start_pos == result_len); |
778 | 783 |
779 // Set the length and elements. | 784 // Set the length and elements. |
780 result_array->set_length(Smi::FromInt(result_len)); | 785 result_array->set_length(Smi::FromInt(result_len)); |
781 result_array->set_elements(result_elms); | 786 result_array->set_elements(result_elms); |
782 | 787 |
783 return result_array; | 788 return result_array; |
784 } | 789 } |
785 | 790 |
786 | 791 |
787 // ----------------------------------------------------------------------------- | 792 // ----------------------------------------------------------------------------- |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 if (entry->contains(pc)) { | 1432 if (entry->contains(pc)) { |
1428 return names_[i]; | 1433 return names_[i]; |
1429 } | 1434 } |
1430 } | 1435 } |
1431 } | 1436 } |
1432 return NULL; | 1437 return NULL; |
1433 } | 1438 } |
1434 | 1439 |
1435 | 1440 |
1436 } } // namespace v8::internal | 1441 } } // namespace v8::internal |
OLD | NEW |