OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 PrototypeIterator iter(isolate, object); | 922 PrototypeIterator iter(isolate, object); |
923 if (!iter.IsAtEnd()) { | 923 if (!iter.IsAtEnd()) { |
924 // The prototype will usually have no inherited element indices, | 924 // The prototype will usually have no inherited element indices, |
925 // but we have to check. | 925 // but we have to check. |
926 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range, | 926 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range, |
927 indices); | 927 indices); |
928 } | 928 } |
929 } | 929 } |
930 | 930 |
931 | 931 |
932 bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, | 932 bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver, |
933 uint32_t length, ArrayConcatVisitor* visitor) { | 933 uint32_t length, ArrayConcatVisitor* visitor) { |
934 for (uint32_t i = 0; i < length; ++i) { | 934 for (uint32_t i = 0; i < length; ++i) { |
935 HandleScope loop_scope(isolate); | 935 HandleScope loop_scope(isolate); |
936 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); | 936 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); |
937 if (!maybe.IsJust()) return false; | 937 if (!maybe.IsJust()) return false; |
938 if (maybe.FromJust()) { | 938 if (maybe.FromJust()) { |
939 Handle<Object> element_value; | 939 Handle<Object> element_value; |
940 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, | 940 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, |
941 Object::GetElement(isolate, receiver, i), | 941 Object::GetElement(isolate, receiver, i), |
942 false); | 942 false); |
943 visitor->visit(i, element_value); | 943 visitor->visit(i, element_value); |
944 } | 944 } |
945 } | 945 } |
946 visitor->increase_index_offset(length); | 946 visitor->increase_index_offset(length); |
947 return true; | 947 return true; |
948 } | 948 } |
949 | 949 |
950 | 950 |
951 /** | 951 /** |
952 * A helper function that visits elements of a JSObject in numerical | 952 * A helper function that visits "array" elements of a JSReceiver in numerical |
953 * order. | 953 * order. |
954 * | 954 * |
955 * The visitor argument called for each existing element in the array | 955 * The visitor argument called for each existing element in the array |
956 * with the element index and the element's value. | 956 * with the element index and the element's value. |
957 * Afterwards it increments the base-index of the visitor by the array | 957 * Afterwards it increments the base-index of the visitor by the array |
958 * length. | 958 * length. |
959 * Returns false if any access threw an exception, otherwise true. | 959 * Returns false if any access threw an exception, otherwise true. |
960 */ | 960 */ |
961 bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, | 961 bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, |
962 ArrayConcatVisitor* visitor) { | 962 ArrayConcatVisitor* visitor) { |
963 uint32_t length = 0; | 963 uint32_t length = 0; |
964 | 964 |
965 if (receiver->IsJSArray()) { | 965 if (receiver->IsJSArray()) { |
966 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 966 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
967 length = static_cast<uint32_t>(array->length()->Number()); | 967 length = static_cast<uint32_t>(array->length()->Number()); |
968 } else { | 968 } else { |
969 Handle<Object> val; | 969 Handle<Object> val; |
970 Handle<Object> key = isolate->factory()->length_string(); | 970 Handle<Object> key = isolate->factory()->length_string(); |
971 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 971 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
972 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), | 972 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), |
973 false); | 973 false); |
974 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, | 974 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, |
975 Object::ToLength(isolate, val), false); | 975 Object::ToLength(isolate, val), false); |
976 // TODO(caitp): Support larger element indexes (up to 2^53-1). | 976 // TODO(caitp): Support larger element indexes (up to 2^53-1). |
977 if (!val->ToUint32(&length)) { | 977 if (!val->ToUint32(&length)) { |
978 length = 0; | 978 length = 0; |
979 } | 979 } |
980 } | 980 } |
981 | 981 |
982 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) { | 982 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) { |
983 // For classes which are not known to be safe to access via elements alone, | 983 // For classes which are not known to be safe to access via elements alone, |
984 // use the slow case. | 984 // use the slow case. |
985 return IterateElementsSlow(isolate, receiver, length, visitor); | 985 return IterateElementsSlow(isolate, receiver, length, visitor); |
986 } | 986 } |
| 987 Handle<JSObject> array = Handle<JSObject>::cast(receiver); |
987 | 988 |
988 switch (receiver->GetElementsKind()) { | 989 switch (array->GetElementsKind()) { |
989 case FAST_SMI_ELEMENTS: | 990 case FAST_SMI_ELEMENTS: |
990 case FAST_ELEMENTS: | 991 case FAST_ELEMENTS: |
991 case FAST_HOLEY_SMI_ELEMENTS: | 992 case FAST_HOLEY_SMI_ELEMENTS: |
992 case FAST_HOLEY_ELEMENTS: { | 993 case FAST_HOLEY_ELEMENTS: { |
993 // Run through the elements FixedArray and use HasElement and GetElement | 994 // Run through the elements FixedArray and use HasElement and GetElement |
994 // to check the prototype for missing elements. | 995 // to check the prototype for missing elements. |
995 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 996 Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
996 int fast_length = static_cast<int>(length); | 997 int fast_length = static_cast<int>(length); |
997 DCHECK(fast_length <= elements->length()); | 998 DCHECK(fast_length <= elements->length()); |
998 for (int j = 0; j < fast_length; j++) { | 999 for (int j = 0; j < fast_length; j++) { |
999 HandleScope loop_scope(isolate); | 1000 HandleScope loop_scope(isolate); |
1000 Handle<Object> element_value(elements->get(j), isolate); | 1001 Handle<Object> element_value(elements->get(j), isolate); |
1001 if (!element_value->IsTheHole()) { | 1002 if (!element_value->IsTheHole()) { |
1002 visitor->visit(j, element_value); | 1003 visitor->visit(j, element_value); |
1003 } else { | 1004 } else { |
1004 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); | 1005 Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
1005 if (!maybe.IsJust()) return false; | 1006 if (!maybe.IsJust()) return false; |
1006 if (maybe.FromJust()) { | 1007 if (maybe.FromJust()) { |
1007 // Call GetElement on receiver, not its prototype, or getters won't | 1008 // Call GetElement on array, not its prototype, or getters won't |
1008 // have the correct receiver. | 1009 // have the correct receiver. |
1009 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1010 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
1010 isolate, element_value, | 1011 isolate, element_value, Object::GetElement(isolate, array, j), |
1011 Object::GetElement(isolate, receiver, j), false); | 1012 false); |
1012 visitor->visit(j, element_value); | 1013 visitor->visit(j, element_value); |
1013 } | 1014 } |
1014 } | 1015 } |
1015 } | 1016 } |
1016 break; | 1017 break; |
1017 } | 1018 } |
1018 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1019 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1019 case FAST_DOUBLE_ELEMENTS: { | 1020 case FAST_DOUBLE_ELEMENTS: { |
1020 // Empty array is FixedArray but not FixedDoubleArray. | 1021 // Empty array is FixedArray but not FixedDoubleArray. |
1021 if (length == 0) break; | 1022 if (length == 0) break; |
1022 // Run through the elements FixedArray and use HasElement and GetElement | 1023 // Run through the elements FixedArray and use HasElement and GetElement |
1023 // to check the prototype for missing elements. | 1024 // to check the prototype for missing elements. |
1024 if (receiver->elements()->IsFixedArray()) { | 1025 if (array->elements()->IsFixedArray()) { |
1025 DCHECK(receiver->elements()->length() == 0); | 1026 DCHECK(array->elements()->length() == 0); |
1026 break; | 1027 break; |
1027 } | 1028 } |
1028 Handle<FixedDoubleArray> elements( | 1029 Handle<FixedDoubleArray> elements( |
1029 FixedDoubleArray::cast(receiver->elements())); | 1030 FixedDoubleArray::cast(array->elements())); |
1030 int fast_length = static_cast<int>(length); | 1031 int fast_length = static_cast<int>(length); |
1031 DCHECK(fast_length <= elements->length()); | 1032 DCHECK(fast_length <= elements->length()); |
1032 for (int j = 0; j < fast_length; j++) { | 1033 for (int j = 0; j < fast_length; j++) { |
1033 HandleScope loop_scope(isolate); | 1034 HandleScope loop_scope(isolate); |
1034 if (!elements->is_the_hole(j)) { | 1035 if (!elements->is_the_hole(j)) { |
1035 double double_value = elements->get_scalar(j); | 1036 double double_value = elements->get_scalar(j); |
1036 Handle<Object> element_value = | 1037 Handle<Object> element_value = |
1037 isolate->factory()->NewNumber(double_value); | 1038 isolate->factory()->NewNumber(double_value); |
1038 visitor->visit(j, element_value); | 1039 visitor->visit(j, element_value); |
1039 } else { | 1040 } else { |
1040 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); | 1041 Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
1041 if (!maybe.IsJust()) return false; | 1042 if (!maybe.IsJust()) return false; |
1042 if (maybe.FromJust()) { | 1043 if (maybe.FromJust()) { |
1043 // Call GetElement on receiver, not its prototype, or getters won't | 1044 // Call GetElement on array, not its prototype, or getters won't |
1044 // have the correct receiver. | 1045 // have the correct receiver. |
1045 Handle<Object> element_value; | 1046 Handle<Object> element_value; |
1046 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1047 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
1047 isolate, element_value, | 1048 isolate, element_value, Object::GetElement(isolate, array, j), |
1048 Object::GetElement(isolate, receiver, j), false); | 1049 false); |
1049 visitor->visit(j, element_value); | 1050 visitor->visit(j, element_value); |
1050 } | 1051 } |
1051 } | 1052 } |
1052 } | 1053 } |
1053 break; | 1054 break; |
1054 } | 1055 } |
1055 case DICTIONARY_ELEMENTS: { | 1056 case DICTIONARY_ELEMENTS: { |
1056 // CollectElementIndices() can't be called when there's a JSProxy | 1057 // CollectElementIndices() can't be called when there's a JSProxy |
1057 // on the prototype chain. | 1058 // on the prototype chain. |
1058 for (PrototypeIterator iter(isolate, receiver); !iter.IsAtEnd(); | 1059 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); |
1059 iter.Advance()) { | 1060 iter.Advance()) { |
1060 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 1061 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
1061 return IterateElementsSlow(isolate, receiver, length, visitor); | 1062 return IterateElementsSlow(isolate, array, length, visitor); |
1062 } | 1063 } |
1063 } | 1064 } |
1064 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); | 1065 Handle<SeededNumberDictionary> dict(array->element_dictionary()); |
1065 List<uint32_t> indices(dict->Capacity() / 2); | 1066 List<uint32_t> indices(dict->Capacity() / 2); |
1066 // Collect all indices in the object and the prototypes less | 1067 // Collect all indices in the object and the prototypes less |
1067 // than length. This might introduce duplicates in the indices list. | 1068 // than length. This might introduce duplicates in the indices list. |
1068 CollectElementIndices(receiver, length, &indices); | 1069 CollectElementIndices(array, length, &indices); |
1069 indices.Sort(&compareUInt32); | 1070 indices.Sort(&compareUInt32); |
1070 int j = 0; | 1071 int j = 0; |
1071 int n = indices.length(); | 1072 int n = indices.length(); |
1072 while (j < n) { | 1073 while (j < n) { |
1073 HandleScope loop_scope(isolate); | 1074 HandleScope loop_scope(isolate); |
1074 uint32_t index = indices[j]; | 1075 uint32_t index = indices[j]; |
1075 Handle<Object> element; | 1076 Handle<Object> element; |
1076 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1077 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
1077 isolate, element, Object::GetElement(isolate, receiver, index), | 1078 isolate, element, Object::GetElement(isolate, array, index), false); |
1078 false); | |
1079 visitor->visit(index, element); | 1079 visitor->visit(index, element); |
1080 // Skip to next different index (i.e., omit duplicates). | 1080 // Skip to next different index (i.e., omit duplicates). |
1081 do { | 1081 do { |
1082 j++; | 1082 j++; |
1083 } while (j < n && indices[j] == index); | 1083 } while (j < n && indices[j] == index); |
1084 } | 1084 } |
1085 break; | 1085 break; |
1086 } | 1086 } |
1087 case UINT8_CLAMPED_ELEMENTS: { | 1087 case UINT8_CLAMPED_ELEMENTS: { |
1088 Handle<FixedUint8ClampedArray> pixels( | 1088 Handle<FixedUint8ClampedArray> pixels( |
1089 FixedUint8ClampedArray::cast(receiver->elements())); | 1089 FixedUint8ClampedArray::cast(array->elements())); |
1090 for (uint32_t j = 0; j < length; j++) { | 1090 for (uint32_t j = 0; j < length; j++) { |
1091 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); | 1091 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); |
1092 visitor->visit(j, e); | 1092 visitor->visit(j, e); |
1093 } | 1093 } |
1094 break; | 1094 break; |
1095 } | 1095 } |
1096 case INT8_ELEMENTS: { | 1096 case INT8_ELEMENTS: { |
1097 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, receiver, true, | 1097 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true, |
1098 true, visitor); | 1098 true, visitor); |
1099 break; | 1099 break; |
1100 } | 1100 } |
1101 case UINT8_ELEMENTS: { | 1101 case UINT8_ELEMENTS: { |
1102 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, receiver, | 1102 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true, |
1103 true, true, visitor); | 1103 true, visitor); |
1104 break; | 1104 break; |
1105 } | 1105 } |
1106 case INT16_ELEMENTS: { | 1106 case INT16_ELEMENTS: { |
1107 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, receiver, | 1107 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true, |
1108 true, true, visitor); | 1108 true, visitor); |
1109 break; | 1109 break; |
1110 } | 1110 } |
1111 case UINT16_ELEMENTS: { | 1111 case UINT16_ELEMENTS: { |
1112 IterateTypedArrayElements<FixedUint16Array, uint16_t>( | 1112 IterateTypedArrayElements<FixedUint16Array, uint16_t>( |
1113 isolate, receiver, true, true, visitor); | 1113 isolate, array, true, true, visitor); |
1114 break; | 1114 break; |
1115 } | 1115 } |
1116 case INT32_ELEMENTS: { | 1116 case INT32_ELEMENTS: { |
1117 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, receiver, | 1117 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true, |
1118 true, false, visitor); | 1118 false, visitor); |
1119 break; | 1119 break; |
1120 } | 1120 } |
1121 case UINT32_ELEMENTS: { | 1121 case UINT32_ELEMENTS: { |
1122 IterateTypedArrayElements<FixedUint32Array, uint32_t>( | 1122 IterateTypedArrayElements<FixedUint32Array, uint32_t>( |
1123 isolate, receiver, true, false, visitor); | 1123 isolate, array, true, false, visitor); |
1124 break; | 1124 break; |
1125 } | 1125 } |
1126 case FLOAT32_ELEMENTS: { | 1126 case FLOAT32_ELEMENTS: { |
1127 IterateTypedArrayElements<FixedFloat32Array, float>( | 1127 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false, |
1128 isolate, receiver, false, false, visitor); | 1128 false, visitor); |
1129 break; | 1129 break; |
1130 } | 1130 } |
1131 case FLOAT64_ELEMENTS: { | 1131 case FLOAT64_ELEMENTS: { |
1132 IterateTypedArrayElements<FixedFloat64Array, double>( | 1132 IterateTypedArrayElements<FixedFloat64Array, double>( |
1133 isolate, receiver, false, false, visitor); | 1133 isolate, array, false, false, visitor); |
1134 break; | 1134 break; |
1135 } | 1135 } |
1136 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 1136 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
1137 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | 1137 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
1138 for (uint32_t index = 0; index < length; index++) { | 1138 for (uint32_t index = 0; index < length; index++) { |
1139 HandleScope loop_scope(isolate); | 1139 HandleScope loop_scope(isolate); |
1140 Handle<Object> element; | 1140 Handle<Object> element; |
1141 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1141 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
1142 isolate, element, Object::GetElement(isolate, receiver, index), | 1142 isolate, element, Object::GetElement(isolate, array, index), false); |
1143 false); | |
1144 visitor->visit(index, element); | 1143 visitor->visit(index, element); |
1145 } | 1144 } |
1146 break; | 1145 break; |
1147 } | 1146 } |
1148 } | 1147 } |
1149 visitor->increase_index_offset(length); | 1148 visitor->increase_index_offset(length); |
1150 return true; | 1149 return true; |
1151 } | 1150 } |
1152 | 1151 |
1153 | 1152 |
1154 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { | 1153 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { |
| 1154 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact()); |
1155 if (!FLAG_harmony_concat_spreadable) return false; | 1155 if (!FLAG_harmony_concat_spreadable) return false; |
1156 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | 1156 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
1157 Maybe<bool> maybe = | 1157 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); |
1158 JSReceiver::HasProperty(Handle<JSReceiver>::cast(obj), key); | 1158 return maybe.FromMaybe(false); |
1159 if (!maybe.IsJust()) return false; | |
1160 return maybe.FromJust(); | |
1161 } | 1159 } |
1162 | 1160 |
1163 | 1161 |
1164 bool IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { | 1162 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { |
1165 HandleScope handle_scope(isolate); | 1163 HandleScope handle_scope(isolate); |
1166 if (!obj->IsJSReceiver()) return false; | 1164 if (!obj->IsJSReceiver()) return Just(false); |
1167 if (FLAG_harmony_concat_spreadable) { | 1165 if (FLAG_harmony_concat_spreadable) { |
1168 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | 1166 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
1169 Handle<Object> value; | 1167 Handle<Object> value; |
1170 MaybeHandle<Object> maybeValue = | 1168 MaybeHandle<Object> maybeValue = |
1171 i::Runtime::GetObjectProperty(isolate, obj, key); | 1169 i::Runtime::GetObjectProperty(isolate, obj, key); |
1172 if (maybeValue.ToHandle(&value) && !value->IsUndefined()) { | 1170 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); |
1173 return value->BooleanValue(); | 1171 if (!value->IsUndefined()) return Just(value->BooleanValue()); |
1174 } | |
1175 } | 1172 } |
1176 return obj->IsJSArray(); | 1173 return Object::IsArray(obj); |
1177 } | 1174 } |
1178 | 1175 |
1179 | 1176 |
1180 /** | |
1181 * Array::concat implementation. | |
1182 * See ECMAScript 262, 15.4.4.4. | |
1183 * TODO(581): Fix non-compliance for very large concatenations and update to | |
1184 * following the ECMAScript 5 specification. | |
1185 */ | |
1186 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { | 1177 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { |
1187 int argument_count = args->length(); | 1178 int argument_count = args->length(); |
1188 | 1179 |
1189 // Pass 1: estimate the length and number of elements of the result. | 1180 // Pass 1: estimate the length and number of elements of the result. |
1190 // The actual length can be larger if any of the arguments have getters | 1181 // The actual length can be larger if any of the arguments have getters |
1191 // that mutate other arguments (but will otherwise be precise). | 1182 // that mutate other arguments (but will otherwise be precise). |
1192 // The number of elements is precise if there are no inherited elements. | 1183 // The number of elements is precise if there are no inherited elements. |
1193 | 1184 |
1194 ElementsKind kind = FAST_SMI_ELEMENTS; | 1185 ElementsKind kind = FAST_SMI_ELEMENTS; |
1195 | 1186 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 uint32_t at_least_space_for = | 1322 uint32_t at_least_space_for = |
1332 estimate_nof_elements + (estimate_nof_elements >> 2); | 1323 estimate_nof_elements + (estimate_nof_elements >> 2); |
1333 storage = Handle<FixedArray>::cast( | 1324 storage = Handle<FixedArray>::cast( |
1334 SeededNumberDictionary::New(isolate, at_least_space_for)); | 1325 SeededNumberDictionary::New(isolate, at_least_space_for)); |
1335 } | 1326 } |
1336 | 1327 |
1337 ArrayConcatVisitor visitor(isolate, storage, fast_case); | 1328 ArrayConcatVisitor visitor(isolate, storage, fast_case); |
1338 | 1329 |
1339 for (int i = 0; i < argument_count; i++) { | 1330 for (int i = 0; i < argument_count; i++) { |
1340 Handle<Object> obj((*args)[i], isolate); | 1331 Handle<Object> obj((*args)[i], isolate); |
1341 bool spreadable = IsConcatSpreadable(isolate, obj); | 1332 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); |
1342 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 1333 MAYBE_RETURN(spreadable, isolate->heap()->exception()); |
1343 if (spreadable) { | 1334 if (spreadable.FromJust()) { |
1344 Handle<JSObject> object = Handle<JSObject>::cast(obj); | 1335 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); |
1345 if (!IterateElements(isolate, object, &visitor)) { | 1336 if (!IterateElements(isolate, object, &visitor)) { |
1346 return isolate->heap()->exception(); | 1337 return isolate->heap()->exception(); |
1347 } | 1338 } |
1348 } else { | 1339 } else { |
1349 visitor.visit(0, obj); | 1340 visitor.visit(0, obj); |
1350 visitor.increase_index_offset(1); | 1341 visitor.increase_index_offset(1); |
1351 } | 1342 } |
1352 } | 1343 } |
1353 | 1344 |
1354 if (visitor.exceeds_array_limit()) { | 1345 if (visitor.exceeds_array_limit()) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 NewRangeError(MessageTemplate::kInvalidArrayLength), | 1385 NewRangeError(MessageTemplate::kInvalidArrayLength), |
1395 JSArray); | 1386 JSArray); |
1396 } | 1387 } |
1397 } | 1388 } |
1398 } | 1389 } |
1399 return ElementsAccessor::Concat(isolate, args, n_arguments); | 1390 return ElementsAccessor::Concat(isolate, args, n_arguments); |
1400 } | 1391 } |
1401 | 1392 |
1402 } // namespace | 1393 } // namespace |
1403 | 1394 |
| 1395 // ES6 22.1.3.1 Array.prototype.concat |
1404 BUILTIN(ArrayConcat) { | 1396 BUILTIN(ArrayConcat) { |
1405 HandleScope scope(isolate); | 1397 HandleScope scope(isolate); |
1406 | 1398 |
1407 Handle<Object> receiver; | 1399 Handle<Object> receiver; |
1408 if (!Object::ToObject(isolate, handle(args[0], isolate)) | 1400 if (!Object::ToObject(isolate, handle(args[0], isolate)) |
1409 .ToHandle(&receiver)) { | 1401 .ToHandle(&receiver)) { |
1410 THROW_NEW_ERROR_RETURN_FAILURE( | 1402 THROW_NEW_ERROR_RETURN_FAILURE( |
1411 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, | 1403 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, |
1412 isolate->factory()->NewStringFromAsciiChecked( | 1404 isolate->factory()->NewStringFromAsciiChecked( |
1413 "Array.prototype.concat"))); | 1405 "Array.prototype.concat"))); |
1414 } | 1406 } |
1415 args[0] = *receiver; | 1407 args[0] = *receiver; |
1416 | 1408 |
1417 Handle<JSArray> result_array; | 1409 Handle<JSArray> result_array; |
1418 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { | 1410 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { |
1419 return *result_array; | 1411 return *result_array; |
1420 } | 1412 } |
1421 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 1413 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
1422 return Slow_ArrayConcat(&args, isolate); | 1414 return Slow_ArrayConcat(&args, isolate); |
1423 } | 1415 } |
1424 | 1416 |
1425 | 1417 |
1426 // ES6 section 22.1.2.2 Array.isArray | 1418 // ES6 22.1.2.2 Array.isArray |
1427 BUILTIN(ArrayIsArray) { | 1419 BUILTIN(ArrayIsArray) { |
1428 HandleScope scope(isolate); | 1420 HandleScope scope(isolate); |
1429 DCHECK_EQ(2, args.length()); | 1421 DCHECK_EQ(2, args.length()); |
1430 Handle<Object> object = args.at<Object>(1); | 1422 Handle<Object> object = args.at<Object>(1); |
1431 Maybe<bool> result = Object::IsArray(object); | 1423 Maybe<bool> result = Object::IsArray(object); |
1432 MAYBE_RETURN(result, isolate->heap()->exception()); | 1424 MAYBE_RETURN(result, isolate->heap()->exception()); |
1433 return *isolate->factory()->ToBoolean(result.FromJust()); | 1425 return *isolate->factory()->ToBoolean(result.FromJust()); |
1434 } | 1426 } |
1435 | 1427 |
1436 | 1428 |
(...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 2506 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
2515 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 2507 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
2516 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 2508 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
2517 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 2509 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
2518 #undef DEFINE_BUILTIN_ACCESSOR_C | 2510 #undef DEFINE_BUILTIN_ACCESSOR_C |
2519 #undef DEFINE_BUILTIN_ACCESSOR_A | 2511 #undef DEFINE_BUILTIN_ACCESSOR_A |
2520 | 2512 |
2521 | 2513 |
2522 } // namespace internal | 2514 } // namespace internal |
2523 } // namespace v8 | 2515 } // namespace v8 |
OLD | NEW |