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