| 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( |
| 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 |