Chromium Code Reviews| 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 |