OLD | NEW |
---|---|
1 // Copyright 2012 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 |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
818 MaybeObject* maybe_failure = accessor->CopyElements( | 818 MaybeObject* maybe_failure = accessor->CopyElements( |
819 NULL, k, kind, result_array->elements(), 0, result_len, elms); | 819 NULL, k, kind, result_array->elements(), 0, result_len, elms); |
820 ASSERT(!maybe_failure->IsFailure()); | 820 ASSERT(!maybe_failure->IsFailure()); |
821 USE(maybe_failure); | 821 USE(maybe_failure); |
822 | 822 |
823 return result_array; | 823 return result_array; |
824 } | 824 } |
825 | 825 |
826 | 826 |
827 BUILTIN(ArraySplice) { | 827 BUILTIN(ArraySplice) { |
828 HandleScope scope(isolate); | |
828 Heap* heap = isolate->heap(); | 829 Heap* heap = isolate->heap(); |
829 Object* receiver = *args.receiver(); | 830 Handle<Object> receiver = args.receiver(); |
830 FixedArrayBase* elms_obj; | 831 Handle<Object> elms_or_null = |
831 MaybeObject* maybe_elms = | 832 EnsureJSArrayWithWritableFastElementsWrapper(isolate, receiver, &args, 3); |
832 EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 3); | 833 RETURN_IF_EMPTY_HANDLE(isolate, elms_or_null); |
833 if (maybe_elms == NULL) { | 834 |
835 if ((*elms_or_null == NULL) || | |
836 !IsJSArrayFastElementMovingAllowed(heap, | |
837 *Handle<JSArray>::cast(receiver))) { | |
834 return CallJsBuiltin(isolate, "ArraySplice", args); | 838 return CallJsBuiltin(isolate, "ArraySplice", args); |
835 } | 839 } |
836 if (!maybe_elms->To(&elms_obj)) return maybe_elms; | 840 Handle<FixedArrayBase> elms_obj = Handle<FixedArrayBase>::cast(elms_or_null); |
837 | 841 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
838 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { | |
839 return CallJsBuiltin(isolate, "ArraySplice", args); | |
840 } | |
841 JSArray* array = JSArray::cast(receiver); | |
842 ASSERT(!array->map()->is_observed()); | 842 ASSERT(!array->map()->is_observed()); |
843 | 843 |
844 int len = Smi::cast(array->length())->value(); | 844 int len = Smi::cast(array->length())->value(); |
845 | 845 |
846 int n_arguments = args.length() - 1; | 846 int n_arguments = args.length() - 1; |
847 | 847 |
848 int relative_start = 0; | 848 int relative_start = 0; |
849 if (n_arguments > 0) { | 849 if (n_arguments > 0) { |
850 Object* arg1 = args[1]; | 850 Handle<Object> arg1 = args.at<Object>(1); |
851 if (arg1->IsSmi()) { | 851 if (arg1->IsSmi()) { |
852 relative_start = Smi::cast(arg1)->value(); | 852 relative_start = Handle<Smi>::cast(arg1)->value(); |
853 } else if (arg1->IsHeapNumber()) { | 853 } else if (arg1->IsHeapNumber()) { |
854 double start = HeapNumber::cast(arg1)->value(); | 854 double start = Handle<HeapNumber>::cast(arg1)->value(); |
855 if (start < kMinInt || start > kMaxInt) { | 855 if (start < kMinInt || start > kMaxInt) { |
856 return CallJsBuiltin(isolate, "ArraySplice", args); | 856 return CallJsBuiltin(isolate, "ArraySplice", args); |
857 } | 857 } |
858 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); | 858 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); |
859 } else if (!arg1->IsUndefined()) { | 859 } else if (!arg1->IsUndefined()) { |
860 return CallJsBuiltin(isolate, "ArraySplice", args); | 860 return CallJsBuiltin(isolate, "ArraySplice", args); |
861 } | 861 } |
862 } | 862 } |
863 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) | 863 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) |
864 : Min(relative_start, len); | 864 : Min(relative_start, len); |
(...skipping 24 matching lines...) Expand all Loading... | |
889 | 889 |
890 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; | 890 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; |
891 int new_length = len - actual_delete_count + item_count; | 891 int new_length = len - actual_delete_count + item_count; |
892 | 892 |
893 // For double mode we do not support changing the length. | 893 // For double mode we do not support changing the length. |
894 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) { | 894 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) { |
895 return CallJsBuiltin(isolate, "ArraySplice", args); | 895 return CallJsBuiltin(isolate, "ArraySplice", args); |
896 } | 896 } |
897 | 897 |
898 if (new_length == 0) { | 898 if (new_length == 0) { |
899 MaybeObject* maybe_array = heap->AllocateJSArrayWithElements( | 899 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( |
900 elms_obj, elements_kind, actual_delete_count); | 900 elms_obj, elements_kind, actual_delete_count); |
901 if (maybe_array->IsFailure()) return maybe_array; | |
902 array->set_elements(heap->empty_fixed_array()); | 901 array->set_elements(heap->empty_fixed_array()); |
903 array->set_length(Smi::FromInt(0)); | 902 array->set_length(Smi::FromInt(0)); |
904 return maybe_array; | 903 return *result; |
905 } | 904 } |
906 | 905 |
907 JSArray* result_array = NULL; | 906 Handle<JSArray> result_array = |
908 MaybeObject* maybe_array = | 907 isolate->factory()->NewJSArray(elements_kind, |
909 heap->AllocateJSArrayAndStorage(elements_kind, | 908 actual_delete_count, |
910 actual_delete_count, | 909 actual_delete_count); |
911 actual_delete_count); | |
912 if (!maybe_array->To(&result_array)) return maybe_array; | |
913 | 910 |
914 if (actual_delete_count > 0) { | 911 if (actual_delete_count > 0) { |
915 DisallowHeapAllocation no_gc; | 912 DisallowHeapAllocation no_gc; |
916 ElementsAccessor* accessor = array->GetElementsAccessor(); | 913 ElementsAccessor* accessor = array->GetElementsAccessor(); |
917 MaybeObject* maybe_failure = accessor->CopyElements( | 914 accessor->CopyElements( |
918 NULL, actual_start, elements_kind, result_array->elements(), | 915 Handle<JSObject>::null(), actual_start, elements_kind, |
919 0, actual_delete_count, elms_obj); | 916 handle(result_array->elements()), 0, actual_delete_count, elms_obj); |
920 // Cannot fail since the origin and target array are of the same elements | |
921 // kind. | |
922 ASSERT(!maybe_failure->IsFailure()); | |
923 USE(maybe_failure); | |
924 } | 917 } |
925 | 918 |
926 bool elms_changed = false; | 919 bool elms_changed = false; |
927 if (item_count < actual_delete_count) { | 920 if (item_count < actual_delete_count) { |
928 // Shrink the array. | 921 // Shrink the array. |
929 const bool trim_array = !heap->lo_space()->Contains(elms_obj) && | 922 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) && |
930 ((actual_start + item_count) < | 923 ((actual_start + item_count) < |
931 (len - actual_delete_count - actual_start)); | 924 (len - actual_delete_count - actual_start)); |
932 if (trim_array) { | 925 if (trim_array) { |
933 const int delta = actual_delete_count - item_count; | 926 const int delta = actual_delete_count - item_count; |
934 | 927 |
935 if (elms_obj->IsFixedDoubleArray()) { | 928 if (elms_obj->IsFixedDoubleArray()) { |
936 FixedDoubleArray* elms = FixedDoubleArray::cast(elms_obj); | 929 Handle<FixedDoubleArray> elms = |
937 MoveDoubleElements(elms, delta, elms, 0, actual_start); | 930 Handle<FixedDoubleArray>::cast(elms_obj); |
931 MoveDoubleElements(*elms, delta, *elms, 0, actual_start); | |
938 } else { | 932 } else { |
939 FixedArray* elms = FixedArray::cast(elms_obj); | 933 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
940 DisallowHeapAllocation no_gc; | 934 DisallowHeapAllocation no_gc; |
941 heap->MoveElements(elms, delta, 0, actual_start); | 935 heap->MoveElements(*elms, delta, 0, actual_start); |
942 } | 936 } |
943 | 937 |
944 elms_obj = LeftTrimFixedArray(heap, elms_obj, delta); | 938 elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta)); |
945 | 939 |
946 elms_changed = true; | 940 elms_changed = true; |
947 } else { | 941 } else { |
948 if (elms_obj->IsFixedDoubleArray()) { | 942 if (elms_obj->IsFixedDoubleArray()) { |
949 FixedDoubleArray* elms = FixedDoubleArray::cast(elms_obj); | 943 Handle<FixedDoubleArray> elms = |
950 MoveDoubleElements(elms, actual_start + item_count, | 944 Handle<FixedDoubleArray>::cast(elms_obj); |
951 elms, actual_start + actual_delete_count, | 945 MoveDoubleElements(*elms, actual_start + item_count, |
946 *elms, actual_start + actual_delete_count, | |
952 (len - actual_delete_count - actual_start)); | 947 (len - actual_delete_count - actual_start)); |
953 FillWithHoles(elms, new_length, len); | 948 FillWithHoles(*elms, new_length, len); |
954 } else { | 949 } else { |
955 FixedArray* elms = FixedArray::cast(elms_obj); | 950 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
956 DisallowHeapAllocation no_gc; | 951 DisallowHeapAllocation no_gc; |
957 heap->MoveElements(elms, actual_start + item_count, | 952 heap->MoveElements(*elms, actual_start + item_count, |
958 actual_start + actual_delete_count, | 953 actual_start + actual_delete_count, |
959 (len - actual_delete_count - actual_start)); | 954 (len - actual_delete_count - actual_start)); |
960 FillWithHoles(heap, elms, new_length, len); | 955 FillWithHoles(heap, *elms, new_length, len); |
961 } | 956 } |
962 } | 957 } |
963 } else if (item_count > actual_delete_count) { | 958 } else if (item_count > actual_delete_count) { |
964 FixedArray* elms = FixedArray::cast(elms_obj); | 959 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
965 // Currently fixed arrays cannot grow too big, so | 960 // Currently fixed arrays cannot grow too big, so |
966 // we should never hit this case. | 961 // we should never hit this case. |
967 ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); | 962 ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); |
968 | 963 |
969 // Check if array need to grow. | 964 // Check if array need to grow. |
970 if (new_length > elms->length()) { | 965 if (new_length > elms->length()) { |
971 // New backing storage is needed. | 966 // New backing storage is needed. |
972 int capacity = new_length + (new_length >> 1) + 16; | 967 int capacity = new_length + (new_length >> 1) + 16; |
973 FixedArray* new_elms; | 968 Handle<FixedArray> new_elms = |
974 MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); | 969 isolate->factory()->NewUninitializedFixedArray(capacity); |
975 if (!maybe_obj->To(&new_elms)) return maybe_obj; | |
976 | 970 |
977 DisallowHeapAllocation no_gc; | 971 DisallowHeapAllocation no_gc; |
978 | 972 |
979 ElementsKind kind = array->GetElementsKind(); | 973 ElementsKind kind = array->GetElementsKind(); |
980 ElementsAccessor* accessor = array->GetElementsAccessor(); | 974 ElementsAccessor* accessor = array->GetElementsAccessor(); |
981 if (actual_start > 0) { | 975 if (actual_start > 0) { |
982 // Copy the part before actual_start as is. | 976 // Copy the part before actual_start as is. |
983 MaybeObject* maybe_failure = accessor->CopyElements( | 977 accessor->CopyElements( |
984 NULL, 0, kind, new_elms, 0, actual_start, elms); | 978 Handle<JSObject>::null(), 0, kind, new_elms, 0, actual_start, elms); |
985 ASSERT(!maybe_failure->IsFailure()); | |
986 USE(maybe_failure); | |
987 } | 979 } |
988 MaybeObject* maybe_failure = accessor->CopyElements( | 980 accessor->CopyElements( |
Yang
2014/03/20 15:21:41
I should have noticed this in an earlier CL. Why d
Igor Sheludko
2014/03/21 09:49:39
Done.
| |
989 NULL, actual_start + actual_delete_count, kind, new_elms, | 981 Handle<JSObject>::null(), actual_start + actual_delete_count, kind, |
990 actual_start + item_count, | 982 new_elms, actual_start + item_count, |
991 ElementsAccessor::kCopyToEndAndInitializeToHole, elms); | 983 ElementsAccessor::kCopyToEndAndInitializeToHole, elms); |
992 ASSERT(!maybe_failure->IsFailure()); | |
993 USE(maybe_failure); | |
994 | 984 |
995 elms_obj = new_elms; | 985 elms_obj = new_elms; |
996 elms_changed = true; | 986 elms_changed = true; |
997 } else { | 987 } else { |
998 DisallowHeapAllocation no_gc; | 988 DisallowHeapAllocation no_gc; |
999 heap->MoveElements(elms, actual_start + item_count, | 989 heap->MoveElements(*elms, actual_start + item_count, |
1000 actual_start + actual_delete_count, | 990 actual_start + actual_delete_count, |
1001 (len - actual_delete_count - actual_start)); | 991 (len - actual_delete_count - actual_start)); |
1002 } | 992 } |
1003 } | 993 } |
1004 | 994 |
1005 if (IsFastDoubleElementsKind(elements_kind)) { | 995 if (IsFastDoubleElementsKind(elements_kind)) { |
1006 FixedDoubleArray* elms = FixedDoubleArray::cast(elms_obj); | 996 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj); |
1007 for (int k = actual_start; k < actual_start + item_count; k++) { | 997 for (int k = actual_start; k < actual_start + item_count; k++) { |
1008 Object* arg = args[3 + k - actual_start]; | 998 Object* arg = args[3 + k - actual_start]; |
1009 if (arg->IsSmi()) { | 999 if (arg->IsSmi()) { |
1010 elms->set(k, Smi::cast(arg)->value()); | 1000 elms->set(k, Smi::cast(arg)->value()); |
1011 } else { | 1001 } else { |
1012 elms->set(k, HeapNumber::cast(arg)->value()); | 1002 elms->set(k, HeapNumber::cast(arg)->value()); |
1013 } | 1003 } |
1014 } | 1004 } |
1015 } else { | 1005 } else { |
1016 FixedArray* elms = FixedArray::cast(elms_obj); | 1006 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
1017 DisallowHeapAllocation no_gc; | 1007 DisallowHeapAllocation no_gc; |
1018 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 1008 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
1019 for (int k = actual_start; k < actual_start + item_count; k++) { | 1009 for (int k = actual_start; k < actual_start + item_count; k++) { |
1020 elms->set(k, args[3 + k - actual_start], mode); | 1010 elms->set(k, args[3 + k - actual_start], mode); |
1021 } | 1011 } |
1022 } | 1012 } |
1023 | 1013 |
1024 if (elms_changed) { | 1014 if (elms_changed) { |
1025 array->set_elements(elms_obj); | 1015 array->set_elements(*elms_obj); |
1026 } | 1016 } |
1027 // Set the length. | 1017 // Set the length. |
1028 array->set_length(Smi::FromInt(new_length)); | 1018 array->set_length(Smi::FromInt(new_length)); |
1029 | 1019 |
1030 return result_array; | 1020 return *result_array; |
1031 } | 1021 } |
1032 | 1022 |
1033 | 1023 |
1034 BUILTIN(ArrayConcat) { | 1024 BUILTIN(ArrayConcat) { |
1035 Heap* heap = isolate->heap(); | 1025 Heap* heap = isolate->heap(); |
1036 Context* native_context = isolate->context()->native_context(); | 1026 Context* native_context = isolate->context()->native_context(); |
1037 JSObject* array_proto = | 1027 JSObject* array_proto = |
1038 JSObject::cast(native_context->array_function()->prototype()); | 1028 JSObject::cast(native_context->array_function()->prototype()); |
1039 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { | 1029 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { |
1040 return CallJsBuiltin(isolate, "ArrayConcat", args); | 1030 return CallJsBuiltin(isolate, "ArrayConcat", args); |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1773 } | 1763 } |
1774 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1764 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1775 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1765 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1776 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1766 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
1777 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1767 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1778 #undef DEFINE_BUILTIN_ACCESSOR_C | 1768 #undef DEFINE_BUILTIN_ACCESSOR_C |
1779 #undef DEFINE_BUILTIN_ACCESSOR_A | 1769 #undef DEFINE_BUILTIN_ACCESSOR_A |
1780 | 1770 |
1781 | 1771 |
1782 } } // namespace v8::internal | 1772 } } // namespace v8::internal |
OLD | NEW |