OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 | 186 |
187 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, | 187 static MaybeObject* ArrayCodeGenericCommon(Arguments* args, |
188 Isolate* isolate, | 188 Isolate* isolate, |
189 JSFunction* constructor) { | 189 JSFunction* constructor) { |
190 Heap* heap = isolate->heap(); | 190 Heap* heap = isolate->heap(); |
191 isolate->counters()->array_function_runtime()->Increment(); | 191 isolate->counters()->array_function_runtime()->Increment(); |
192 | 192 |
193 JSArray* array; | 193 JSArray* array; |
194 if (CalledAsConstructor(isolate)) { | 194 if (CalledAsConstructor(isolate)) { |
195 array = JSArray::cast((*args)[0]); | 195 array = JSArray::cast((*args)[0]); |
196 array->set_length(Smi::FromInt(0)); | |
197 array->set_elements(heap->empty_fixed_array()); | |
198 if (!FLAG_smi_only_arrays) { | |
199 if (array->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { | |
200 // Initialize elements and length in case the transition fails. | |
Jakob Kummerow
2012/01/23 17:16:55
This comment seems misplaced.
danno
2012/01/26 21:32:34
Done.
| |
201 Context* global_context = isolate->context()->global_context(); | |
202 array->set_map(Map::cast(global_context->object_js_array_map())); | |
203 } | |
204 } | |
196 } else { | 205 } else { |
197 // Allocate the JS Array | 206 // Allocate the JS Array |
198 Object* obj; | 207 MaybeObject* maybe_obj = |
199 { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); | 208 heap->AllocateEmptyJSArray(FAST_SMI_ONLY_ELEMENTS); |
200 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 209 if (!maybe_obj->To(&array)) return maybe_obj; |
201 } | |
202 array = JSArray::cast(obj); | |
203 } | 210 } |
204 | 211 |
205 // Optimize the case where there is one argument and the argument is a | 212 // Optimize the case where there is one argument and the argument is a |
206 // small smi. | 213 // small smi. |
207 if (args->length() == 2) { | 214 if (args->length() == 2) { |
208 Object* obj = (*args)[1]; | 215 Object* obj = (*args)[1]; |
209 if (obj->IsSmi()) { | 216 if (obj->IsSmi()) { |
210 int len = Smi::cast(obj)->value(); | 217 int len = Smi::cast(obj)->value(); |
211 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { | 218 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { |
212 Object* obj; | 219 Object* obj; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 | 301 |
295 | 302 |
296 BUILTIN(ArrayCodeGeneric) { | 303 BUILTIN(ArrayCodeGeneric) { |
297 return ArrayCodeGenericCommon( | 304 return ArrayCodeGenericCommon( |
298 &args, | 305 &args, |
299 isolate, | 306 isolate, |
300 isolate->context()->global_context()->array_function()); | 307 isolate->context()->global_context()->array_function()); |
301 } | 308 } |
302 | 309 |
303 | 310 |
304 MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) { | |
305 JSFunction* array_function = | |
306 heap->isolate()->context()->global_context()->array_function(); | |
307 Object* result; | |
308 { MaybeObject* maybe_result = heap->AllocateJSObject(array_function); | |
309 if (!maybe_result->ToObject(&result)) return maybe_result; | |
310 } | |
311 return result; | |
312 } | |
313 | |
314 | |
315 MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) { | |
316 Object* result; | |
317 { MaybeObject* maybe_result = AllocateJSArray(heap); | |
318 if (!maybe_result->ToObject(&result)) return maybe_result; | |
319 } | |
320 JSArray* result_array = JSArray::cast(result); | |
321 result_array->set_length(Smi::FromInt(0)); | |
322 result_array->set_elements(heap->empty_fixed_array()); | |
323 return result_array; | |
324 } | |
325 | |
326 | |
327 static void CopyElements(Heap* heap, | 311 static void CopyElements(Heap* heap, |
328 AssertNoAllocation* no_gc, | 312 AssertNoAllocation* no_gc, |
329 FixedArray* dst, | 313 FixedArray* dst, |
330 int dst_index, | 314 int dst_index, |
331 FixedArray* src, | 315 FixedArray* src, |
332 int src_index, | 316 int src_index, |
333 int len) { | 317 int len) { |
318 if (len == 0) return; | |
334 ASSERT(dst != src); // Use MoveElements instead. | 319 ASSERT(dst != src); // Use MoveElements instead. |
335 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); | 320 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
336 ASSERT(len > 0); | 321 ASSERT(len > 0); |
337 CopyWords(dst->data_start() + dst_index, | 322 CopyWords(dst->data_start() + dst_index, |
338 src->data_start() + src_index, | 323 src->data_start() + src_index, |
339 len); | 324 len); |
340 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); | 325 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); |
341 if (mode == UPDATE_WRITE_BARRIER) { | 326 if (mode == UPDATE_WRITE_BARRIER) { |
342 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); | 327 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
343 } | 328 } |
344 heap->incremental_marking()->RecordWrites(dst); | 329 heap->incremental_marking()->RecordWrites(dst); |
345 } | 330 } |
346 | 331 |
347 | 332 |
348 static void MoveElements(Heap* heap, | 333 static void MoveElements(Heap* heap, |
349 AssertNoAllocation* no_gc, | 334 AssertNoAllocation* no_gc, |
350 FixedArray* dst, | 335 FixedArray* dst, |
351 int dst_index, | 336 int dst_index, |
352 FixedArray* src, | 337 FixedArray* src, |
353 int src_index, | 338 int src_index, |
354 int len) { | 339 int len) { |
340 if (len == 0) return; | |
355 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); | 341 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
356 memmove(dst->data_start() + dst_index, | 342 memmove(dst->data_start() + dst_index, |
357 src->data_start() + src_index, | 343 src->data_start() + src_index, |
358 len * kPointerSize); | 344 len * kPointerSize); |
359 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); | 345 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); |
360 if (mode == UPDATE_WRITE_BARRIER) { | 346 if (mode == UPDATE_WRITE_BARRIER) { |
361 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); | 347 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
362 } | 348 } |
363 heap->incremental_marking()->RecordWrites(dst); | 349 heap->incremental_marking()->RecordWrites(dst); |
364 } | 350 } |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
536 if (new_length > elms->length()) { | 522 if (new_length > elms->length()) { |
537 // New backing storage is needed. | 523 // New backing storage is needed. |
538 int capacity = new_length + (new_length >> 1) + 16; | 524 int capacity = new_length + (new_length >> 1) + 16; |
539 Object* obj; | 525 Object* obj; |
540 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); | 526 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); |
541 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 527 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
542 } | 528 } |
543 FixedArray* new_elms = FixedArray::cast(obj); | 529 FixedArray* new_elms = FixedArray::cast(obj); |
544 | 530 |
545 AssertNoAllocation no_gc; | 531 AssertNoAllocation no_gc; |
546 if (len > 0) { | 532 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); |
547 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); | |
548 } | |
549 FillWithHoles(heap, new_elms, new_length, capacity); | 533 FillWithHoles(heap, new_elms, new_length, capacity); |
550 | 534 |
551 elms = new_elms; | 535 elms = new_elms; |
552 } | 536 } |
553 | 537 |
554 // Add the provided values. | 538 // Add the provided values. |
555 AssertNoAllocation no_gc; | 539 AssertNoAllocation no_gc; |
556 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 540 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
557 for (int index = 0; index < to_add; index++) { | 541 for (int index = 0; index < to_add; index++) { |
558 elms->set(index + len, args[index + 1], mode); | 542 elms->set(index + len, args[index + 1], mode); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 | 658 |
675 if (new_length > elms->length()) { | 659 if (new_length > elms->length()) { |
676 // New backing storage is needed. | 660 // New backing storage is needed. |
677 int capacity = new_length + (new_length >> 1) + 16; | 661 int capacity = new_length + (new_length >> 1) + 16; |
678 Object* obj; | 662 Object* obj; |
679 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); | 663 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); |
680 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 664 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
681 } | 665 } |
682 FixedArray* new_elms = FixedArray::cast(obj); | 666 FixedArray* new_elms = FixedArray::cast(obj); |
683 AssertNoAllocation no_gc; | 667 AssertNoAllocation no_gc; |
684 if (len > 0) { | 668 CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); |
685 CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); | |
686 } | |
687 FillWithHoles(heap, new_elms, new_length, capacity); | 669 FillWithHoles(heap, new_elms, new_length, capacity); |
688 elms = new_elms; | 670 elms = new_elms; |
689 array->set_elements(elms); | 671 array->set_elements(elms); |
690 } else { | 672 } else { |
691 AssertNoAllocation no_gc; | 673 AssertNoAllocation no_gc; |
692 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); | 674 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); |
693 } | 675 } |
694 | 676 |
695 // Add the provided values. | 677 // Add the provided values. |
696 AssertNoAllocation no_gc; | 678 AssertNoAllocation no_gc; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
774 } | 756 } |
775 | 757 |
776 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. | 758 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
777 int k = (relative_start < 0) ? Max(len + relative_start, 0) | 759 int k = (relative_start < 0) ? Max(len + relative_start, 0) |
778 : Min(relative_start, len); | 760 : Min(relative_start, len); |
779 | 761 |
780 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. | 762 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
781 int final = (relative_end < 0) ? Max(len + relative_end, 0) | 763 int final = (relative_end < 0) ? Max(len + relative_end, 0) |
782 : Min(relative_end, len); | 764 : Min(relative_end, len); |
783 | 765 |
766 ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind(); | |
767 | |
784 // Calculate the length of result array. | 768 // Calculate the length of result array. |
785 int result_len = final - k; | 769 int result_len = final - k; |
Jakob Kummerow
2012/01/23 17:16:55
"= Max(final - k, 0)" please, as there's no guaran
danno
2012/01/26 21:32:34
Done.
| |
786 if (result_len <= 0) { | |
787 return AllocateEmptyJSArray(heap); | |
788 } | |
789 | 770 |
790 Object* result; | 771 MaybeObject* maybe_array = |
791 { MaybeObject* maybe_result = AllocateJSArray(heap); | 772 heap->AllocateJSArrayAndStorage(elements_kind, |
792 if (!maybe_result->ToObject(&result)) return maybe_result; | 773 result_len, |
793 } | 774 result_len); |
794 JSArray* result_array = JSArray::cast(result); | 775 JSArray* result_array; |
795 | 776 if (!maybe_array->To(&result_array)) return maybe_array; |
796 { MaybeObject* maybe_result = | |
797 heap->AllocateUninitializedFixedArray(result_len); | |
798 if (!maybe_result->ToObject(&result)) return maybe_result; | |
799 } | |
800 FixedArray* result_elms = FixedArray::cast(result); | |
801 | |
802 MaybeObject* maybe_object = | |
803 result_array->EnsureCanContainElements(result_elms, | |
804 DONT_ALLOW_DOUBLE_ELEMENTS); | |
805 if (maybe_object->IsFailure()) return maybe_object; | |
806 | 777 |
807 AssertNoAllocation no_gc; | 778 AssertNoAllocation no_gc; |
808 CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len); | 779 CopyElements(heap, &no_gc, FixedArray::cast(result_array->elements()), 0, |
780 elms, k, result_len); | |
809 | 781 |
810 // Set elements. | |
811 result_array->set_elements(result_elms); | |
812 | |
813 // Set the length. | |
814 result_array->set_length(Smi::FromInt(result_len)); | |
815 | |
816 // Set the ElementsKind. | |
817 ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind(); | |
818 if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), | |
819 elements_kind)) { | |
820 MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); | |
821 if (maybe->IsFailure()) return maybe; | |
822 } | |
823 return result_array; | 782 return result_array; |
824 } | 783 } |
825 | 784 |
826 | 785 |
827 BUILTIN(ArraySplice) { | 786 BUILTIN(ArraySplice) { |
828 Heap* heap = isolate->heap(); | 787 Heap* heap = isolate->heap(); |
829 Object* receiver = *args.receiver(); | 788 Object* receiver = *args.receiver(); |
830 Object* elms_obj; | 789 Object* elms_obj; |
831 { MaybeObject* maybe_elms_obj = | 790 { MaybeObject* maybe_elms_obj = |
832 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3); | 791 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
873 if (arg2->IsSmi()) { | 832 if (arg2->IsSmi()) { |
874 value = Smi::cast(arg2)->value(); | 833 value = Smi::cast(arg2)->value(); |
875 } else { | 834 } else { |
876 return CallJsBuiltin(isolate, "ArraySplice", args); | 835 return CallJsBuiltin(isolate, "ArraySplice", args); |
877 } | 836 } |
878 } | 837 } |
879 actual_delete_count = Min(Max(value, 0), len - actual_start); | 838 actual_delete_count = Min(Max(value, 0), len - actual_start); |
880 } | 839 } |
881 | 840 |
882 JSArray* result_array = NULL; | 841 JSArray* result_array = NULL; |
883 if (actual_delete_count == 0) { | 842 ElementsKind elements_kind = |
884 Object* result; | 843 JSObject::cast(receiver)->GetElementsKind(); |
885 { MaybeObject* maybe_result = AllocateEmptyJSArray(heap); | 844 MaybeObject* maybe_array = |
886 if (!maybe_result->ToObject(&result)) return maybe_result; | 845 heap->AllocateJSArrayAndStorage(elements_kind, |
887 } | 846 actual_delete_count, |
888 result_array = JSArray::cast(result); | 847 actual_delete_count); |
889 } else { | 848 if (!maybe_array->To(&result_array)) return maybe_array; |
890 // Allocate result array. | |
891 Object* result; | |
892 { MaybeObject* maybe_result = AllocateJSArray(heap); | |
893 if (!maybe_result->ToObject(&result)) return maybe_result; | |
894 } | |
895 result_array = JSArray::cast(result); | |
896 | 849 |
897 { MaybeObject* maybe_result = | 850 { |
898 heap->AllocateUninitializedFixedArray(actual_delete_count); | |
899 if (!maybe_result->ToObject(&result)) return maybe_result; | |
900 } | |
901 FixedArray* result_elms = FixedArray::cast(result); | |
902 | |
903 AssertNoAllocation no_gc; | 851 AssertNoAllocation no_gc; |
904 // Fill newly created array. | 852 // Fill newly created array. |
905 CopyElements(heap, | 853 CopyElements(heap, |
906 &no_gc, | 854 &no_gc, |
907 result_elms, 0, | 855 FixedArray::cast(result_array->elements()), 0, |
908 elms, actual_start, | 856 elms, actual_start, |
909 actual_delete_count); | 857 actual_delete_count); |
910 | |
911 // Set elements. | |
912 result_array->set_elements(result_elms); | |
913 | |
914 // Set the length. | |
915 result_array->set_length(Smi::FromInt(actual_delete_count)); | |
916 | |
917 // Set the ElementsKind. | |
918 ElementsKind elements_kind = array->GetElementsKind(); | |
919 if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), | |
920 elements_kind)) { | |
921 MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); | |
922 if (maybe->IsFailure()) return maybe; | |
923 } | |
924 } | 858 } |
925 | 859 |
926 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; | 860 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
927 int new_length = len - actual_delete_count + item_count; | 861 int new_length = len - actual_delete_count + item_count; |
928 | 862 |
929 bool elms_changed = false; | 863 bool elms_changed = false; |
930 if (item_count < actual_delete_count) { | 864 if (item_count < actual_delete_count) { |
931 // Shrink the array. | 865 // Shrink the array. |
932 const bool trim_array = !heap->lo_space()->Contains(elms) && | 866 const bool trim_array = !heap->lo_space()->Contains(elms) && |
933 ((actual_start + item_count) < | 867 ((actual_start + item_count) < |
934 (len - actual_delete_count - actual_start)); | 868 (len - actual_delete_count - actual_start)); |
935 if (trim_array) { | 869 if (trim_array) { |
936 const int delta = actual_delete_count - item_count; | 870 const int delta = actual_delete_count - item_count; |
937 | 871 |
938 if (actual_start > 0) { | 872 { |
939 AssertNoAllocation no_gc; | 873 AssertNoAllocation no_gc; |
940 MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start); | 874 MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start); |
941 } | 875 } |
942 | 876 |
943 elms = LeftTrimFixedArray(heap, elms, delta); | 877 elms = LeftTrimFixedArray(heap, elms, delta); |
944 | 878 |
945 elms_changed = true; | 879 elms_changed = true; |
946 } else { | 880 } else { |
947 AssertNoAllocation no_gc; | 881 AssertNoAllocation no_gc; |
948 MoveElements(heap, &no_gc, | 882 MoveElements(heap, &no_gc, |
(...skipping 11 matching lines...) Expand all Loading... | |
960 if (new_length > elms->length()) { | 894 if (new_length > elms->length()) { |
961 // New backing storage is needed. | 895 // New backing storage is needed. |
962 int capacity = new_length + (new_length >> 1) + 16; | 896 int capacity = new_length + (new_length >> 1) + 16; |
963 Object* obj; | 897 Object* obj; |
964 { MaybeObject* maybe_obj = | 898 { MaybeObject* maybe_obj = |
965 heap->AllocateUninitializedFixedArray(capacity); | 899 heap->AllocateUninitializedFixedArray(capacity); |
966 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 900 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
967 } | 901 } |
968 FixedArray* new_elms = FixedArray::cast(obj); | 902 FixedArray* new_elms = FixedArray::cast(obj); |
969 | 903 |
970 AssertNoAllocation no_gc; | 904 { |
971 // Copy the part before actual_start as is. | 905 AssertNoAllocation no_gc; |
972 if (actual_start > 0) { | 906 // Copy the part before actual_start as is. |
973 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start); | 907 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start); |
974 } | 908 const int to_copy = len - actual_delete_count - actual_start; |
975 const int to_copy = len - actual_delete_count - actual_start; | |
976 if (to_copy > 0) { | |
977 CopyElements(heap, &no_gc, | 909 CopyElements(heap, &no_gc, |
978 new_elms, actual_start + item_count, | 910 new_elms, actual_start + item_count, |
979 elms, actual_start + actual_delete_count, | 911 elms, actual_start + actual_delete_count, |
980 to_copy); | 912 to_copy); |
981 } | 913 } |
914 | |
982 FillWithHoles(heap, new_elms, new_length, capacity); | 915 FillWithHoles(heap, new_elms, new_length, capacity); |
983 | 916 |
984 elms = new_elms; | 917 elms = new_elms; |
985 elms_changed = true; | 918 elms_changed = true; |
986 } else { | 919 } else { |
987 AssertNoAllocation no_gc; | 920 AssertNoAllocation no_gc; |
988 MoveElements(heap, &no_gc, | 921 MoveElements(heap, &no_gc, |
989 elms, actual_start + item_count, | 922 elms, actual_start + item_count, |
990 elms, actual_start + actual_delete_count, | 923 elms, actual_start + actual_delete_count, |
991 (len - actual_delete_count - actual_start)); | 924 (len - actual_delete_count - actual_start)); |
(...skipping 23 matching lines...) Expand all Loading... | |
1015 JSObject* array_proto = | 948 JSObject* array_proto = |
1016 JSObject::cast(global_context->array_function()->prototype()); | 949 JSObject::cast(global_context->array_function()->prototype()); |
1017 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { | 950 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { |
1018 return CallJsBuiltin(isolate, "ArrayConcat", args); | 951 return CallJsBuiltin(isolate, "ArrayConcat", args); |
1019 } | 952 } |
1020 | 953 |
1021 // Iterate through all the arguments performing checks | 954 // Iterate through all the arguments performing checks |
1022 // and calculating total length. | 955 // and calculating total length. |
1023 int n_arguments = args.length(); | 956 int n_arguments = args.length(); |
1024 int result_len = 0; | 957 int result_len = 0; |
958 ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS; | |
1025 for (int i = 0; i < n_arguments; i++) { | 959 for (int i = 0; i < n_arguments; i++) { |
1026 Object* arg = args[i]; | 960 Object* arg = args[i]; |
1027 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements() | 961 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements() |
1028 || JSArray::cast(arg)->GetPrototype() != array_proto) { | 962 || JSArray::cast(arg)->GetPrototype() != array_proto) { |
1029 return CallJsBuiltin(isolate, "ArrayConcat", args); | 963 return CallJsBuiltin(isolate, "ArrayConcat", args); |
1030 } | 964 } |
1031 | 965 |
1032 int len = Smi::cast(JSArray::cast(arg)->length())->value(); | 966 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
1033 | 967 |
1034 // We shouldn't overflow when adding another len. | 968 // We shouldn't overflow when adding another len. |
1035 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 969 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
1036 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 970 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
1037 USE(kHalfOfMaxInt); | 971 USE(kHalfOfMaxInt); |
1038 result_len += len; | 972 result_len += len; |
1039 ASSERT(result_len >= 0); | 973 ASSERT(result_len >= 0); |
1040 | 974 |
1041 if (result_len > FixedArray::kMaxLength) { | 975 if (result_len > FixedArray::kMaxLength) { |
1042 return CallJsBuiltin(isolate, "ArrayConcat", args); | 976 return CallJsBuiltin(isolate, "ArrayConcat", args); |
1043 } | 977 } |
1044 } | |
1045 | 978 |
1046 if (result_len == 0) { | 979 if (!JSArray::cast(arg)->HasFastTypeElements()) { |
Jakob Kummerow
2012/01/23 17:16:55
This condition will never be true, as it's already
danno
2012/01/26 21:32:34
Done.
| |
1047 return AllocateEmptyJSArray(heap); | 980 elements_kind = FAST_ELEMENTS; |
981 } | |
1048 } | 982 } |
1049 | 983 |
1050 // Allocate result. | 984 // Allocate result. |
1051 Object* result; | 985 JSArray* result_array; |
1052 { MaybeObject* maybe_result = AllocateJSArray(heap); | 986 MaybeObject* maybe_array = |
1053 if (!maybe_result->ToObject(&result)) return maybe_result; | 987 heap->AllocateJSArrayAndStorage(elements_kind, |
1054 } | 988 result_len, |
1055 JSArray* result_array = JSArray::cast(result); | 989 result_len); |
1056 | 990 if (!maybe_array->To(&result_array)) return maybe_array; |
1057 { MaybeObject* maybe_result = | 991 if (result_len == 0) return result_array; |
1058 heap->AllocateUninitializedFixedArray(result_len); | |
1059 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1060 } | |
1061 FixedArray* result_elms = FixedArray::cast(result); | |
1062 | |
1063 // Ensure element type transitions happen before copying elements in. | |
1064 if (result_array->HasFastSmiOnlyElements()) { | |
1065 for (int i = 0; i < n_arguments; i++) { | |
1066 JSArray* array = JSArray::cast(args[i]); | |
1067 if (!array->HasFastSmiOnlyElements()) { | |
1068 result_array->EnsureCanContainHeapObjectElements(); | |
1069 break; | |
1070 } | |
1071 } | |
1072 } | |
1073 | 992 |
1074 // Copy data. | 993 // Copy data. |
1075 AssertNoAllocation no_gc; | 994 AssertNoAllocation no_gc; |
1076 int start_pos = 0; | 995 int start_pos = 0; |
996 FixedArray* result_elms(FixedArray::cast(result_array->elements())); | |
1077 for (int i = 0; i < n_arguments; i++) { | 997 for (int i = 0; i < n_arguments; i++) { |
1078 JSArray* array = JSArray::cast(args[i]); | 998 JSArray* array = JSArray::cast(args[i]); |
1079 int len = Smi::cast(array->length())->value(); | 999 int len = Smi::cast(array->length())->value(); |
1080 if (len > 0) { | 1000 FixedArray* elms = FixedArray::cast(array->elements()); |
1081 FixedArray* elms = FixedArray::cast(array->elements()); | 1001 CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); |
1082 CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); | 1002 start_pos += len; |
1083 start_pos += len; | |
1084 } | |
1085 } | 1003 } |
1086 ASSERT(start_pos == result_len); | 1004 ASSERT(start_pos == result_len); |
1087 | 1005 |
1088 // Set the length and elements. | |
1089 result_array->set_length(Smi::FromInt(result_len)); | |
1090 result_array->set_elements(result_elms); | |
1091 | |
1092 return result_array; | 1006 return result_array; |
1093 } | 1007 } |
1094 | 1008 |
1095 | 1009 |
1096 // ----------------------------------------------------------------------------- | 1010 // ----------------------------------------------------------------------------- |
1097 // Strict mode poison pills | 1011 // Strict mode poison pills |
1098 | 1012 |
1099 | 1013 |
1100 BUILTIN(StrictModePoisonPill) { | 1014 BUILTIN(StrictModePoisonPill) { |
1101 HandleScope scope; | 1015 HandleScope scope; |
(...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1828 return Handle<Code>(code_address); \ | 1742 return Handle<Code>(code_address); \ |
1829 } | 1743 } |
1830 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1744 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1831 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1745 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1832 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1746 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1833 #undef DEFINE_BUILTIN_ACCESSOR_C | 1747 #undef DEFINE_BUILTIN_ACCESSOR_C |
1834 #undef DEFINE_BUILTIN_ACCESSOR_A | 1748 #undef DEFINE_BUILTIN_ACCESSOR_A |
1835 | 1749 |
1836 | 1750 |
1837 } } // namespace v8::internal | 1751 } } // namespace v8::internal |
OLD | NEW |