| 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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| 211 inline bool PrototypeHasNoElements(PrototypeIterator* iter) { | 211 inline bool PrototypeHasNoElements(PrototypeIterator* iter) { |
| 212 DisallowHeapAllocation no_gc; | 212 DisallowHeapAllocation no_gc; |
| 213 for (; !iter->IsAtEnd(); iter->Advance()) { | 213 for (; !iter->IsAtEnd(); iter->Advance()) { |
| 214 if (iter->GetCurrent()->IsJSProxy()) return false; | 214 if (iter->GetCurrent()->IsJSProxy()) return false; |
| 215 JSObject* current = iter->GetCurrent<JSObject>(); | 215 JSObject* current = iter->GetCurrent<JSObject>(); |
| 216 if (current->IsAccessCheckNeeded()) return false; | 216 if (current->IsAccessCheckNeeded()) return false; |
| 217 if (current->HasIndexedInterceptor()) return false; | 217 if (current->HasIndexedInterceptor()) return false; |
| 218 if (current->HasStringWrapperElements()) return false; |
| 218 if (current->elements()->length() != 0) return false; | 219 if (current->elements()->length() != 0) return false; |
| 219 } | 220 } |
| 220 return true; | 221 return true; |
| 221 } | 222 } |
| 222 | 223 |
| 223 | |
| 224 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, | 224 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, |
| 225 JSArray* receiver) { | 225 JSArray* receiver) { |
| 226 DisallowHeapAllocation no_gc; | 226 DisallowHeapAllocation no_gc; |
| 227 // If the array prototype chain is intact (and free of elements), and if the | 227 // If the array prototype chain is intact (and free of elements), and if the |
| 228 // receiver's prototype is the array prototype, then we are done. | 228 // receiver's prototype is the array prototype, then we are done. |
| 229 Object* prototype = receiver->map()->prototype(); | 229 Object* prototype = receiver->map()->prototype(); |
| 230 if (prototype->IsJSArray() && | 230 if (prototype->IsJSArray() && |
| 231 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && | 231 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && |
| 232 isolate->IsFastArrayConstructorPrototypeChainIntact()) { | 232 isolate->IsFastArrayConstructorPrototypeChainIntact()) { |
| 233 return true; | 233 return true; |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Slow case. | 236 // Slow case. |
| 237 PrototypeIterator iter(isolate, receiver); | 237 PrototypeIterator iter(isolate, receiver); |
| 238 return PrototypeHasNoElements(&iter); | 238 return PrototypeHasNoElements(&iter); |
| 239 } | 239 } |
| 240 | 240 |
| 241 inline bool HasSimpleElements(JSObject* current) { |
| 242 if (current->IsAccessCheckNeeded()) return false; |
| 243 if (current->HasIndexedInterceptor()) return false; |
| 244 if (current->HasStringWrapperElements()) return false; |
| 245 if (current->GetElementsAccessor()->HasAccessors(current)) return false; |
| 246 return true; |
| 247 } |
| 248 |
| 249 inline bool HasOnlySimpleReceiverElements(Isolate* isolate, |
| 250 JSReceiver* receiver) { |
| 251 // Check that we have no accessors on the receiver's elements. |
| 252 JSObject* object = JSObject::cast(receiver); |
| 253 if (!HasSimpleElements(object)) return false; |
| 254 // Check that ther are not elements on the prototype. |
| 255 DisallowHeapAllocation no_gc; |
| 256 PrototypeIterator iter(isolate, receiver); |
| 257 return PrototypeHasNoElements(&iter); |
| 258 } |
| 259 |
| 260 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) { |
| 261 // Check that ther are not elements on the prototype. |
| 262 DisallowHeapAllocation no_gc; |
| 263 PrototypeIterator iter(isolate, receiver, |
| 264 PrototypeIterator::START_AT_RECEIVER); |
| 265 for (; !iter.IsAtEnd(); iter.Advance()) { |
| 266 if (iter.GetCurrent()->IsJSProxy()) return false; |
| 267 JSObject* current = iter.GetCurrent<JSObject>(); |
| 268 if (!HasSimpleElements(current)) return false; |
| 269 } |
| 270 return true; |
| 271 } |
| 241 | 272 |
| 242 // Returns empty handle if not applicable. | 273 // Returns empty handle if not applicable. |
| 243 MUST_USE_RESULT | 274 MUST_USE_RESULT |
| 244 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 275 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
| 245 Isolate* isolate, Handle<Object> receiver, Arguments* args, | 276 Isolate* isolate, Handle<Object> receiver, Arguments* args, |
| 246 int first_added_arg) { | 277 int first_added_arg) { |
| 247 // We explicitly add a HandleScope to avoid creating several copies of the | 278 // We explicitly add a HandleScope to avoid creating several copies of the |
| 248 // same handle which would otherwise cause issue when left-trimming later-on. | 279 // same handle which would otherwise cause issue when left-trimming later-on. |
| 249 HandleScope scope(isolate); | 280 HandleScope scope(isolate); |
| 250 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); | 281 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); |
| (...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 Handle<Object> key = isolate->factory()->length_string(); | 1061 Handle<Object> key = isolate->factory()->length_string(); |
| 1031 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1062 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1032 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), | 1063 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), |
| 1033 false); | 1064 false); |
| 1034 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, | 1065 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, |
| 1035 Object::ToLength(isolate, val), false); | 1066 Object::ToLength(isolate, val), false); |
| 1036 // TODO(caitp): Support larger element indexes (up to 2^53-1). | 1067 // TODO(caitp): Support larger element indexes (up to 2^53-1). |
| 1037 if (!val->ToUint32(&length)) { | 1068 if (!val->ToUint32(&length)) { |
| 1038 length = 0; | 1069 length = 0; |
| 1039 } | 1070 } |
| 1071 // TODO(cbruni): handle other element kind as well |
| 1072 return IterateElementsSlow(isolate, receiver, length, visitor); |
| 1040 } | 1073 } |
| 1041 | 1074 |
| 1042 if (!receiver->IsJSArray()) { | 1075 if (!HasOnlySimpleElements(isolate, *receiver)) { |
| 1043 // For classes which are not known to be safe to access via elements alone, | |
| 1044 // use the slow case. | |
| 1045 return IterateElementsSlow(isolate, receiver, length, visitor); | 1076 return IterateElementsSlow(isolate, receiver, length, visitor); |
| 1046 } | 1077 } |
| 1047 Handle<JSObject> array = Handle<JSObject>::cast(receiver); | 1078 Handle<JSObject> array = Handle<JSObject>::cast(receiver); |
| 1048 | 1079 |
| 1049 switch (array->GetElementsKind()) { | 1080 switch (array->GetElementsKind()) { |
| 1050 case FAST_SMI_ELEMENTS: | 1081 case FAST_SMI_ELEMENTS: |
| 1051 case FAST_ELEMENTS: | 1082 case FAST_ELEMENTS: |
| 1052 case FAST_HOLEY_SMI_ELEMENTS: | 1083 case FAST_HOLEY_SMI_ELEMENTS: |
| 1053 case FAST_HOLEY_ELEMENTS: { | 1084 case FAST_HOLEY_ELEMENTS: { |
| 1054 // Run through the elements FixedArray and use HasElement and GetElement | 1085 // Run through the elements FixedArray and use HasElement and GetElement |
| 1055 // to check the prototype for missing elements. | 1086 // to check the prototype for missing elements. |
| 1056 Handle<FixedArray> elements(FixedArray::cast(array->elements())); | 1087 Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
| 1057 int fast_length = static_cast<int>(length); | 1088 int fast_length = static_cast<int>(length); |
| 1058 DCHECK(fast_length <= elements->length()); | 1089 DCHECK_LE(fast_length, elements->length()); |
| 1059 for (int j = 0; j < fast_length; j++) { | 1090 for (int j = 0; j < fast_length; j++) { |
| 1060 HandleScope loop_scope(isolate); | 1091 HandleScope loop_scope(isolate); |
| 1061 Handle<Object> element_value(elements->get(j), isolate); | 1092 Handle<Object> element_value(elements->get(j), isolate); |
| 1062 if (!element_value->IsTheHole()) { | 1093 if (!element_value->IsTheHole()) { |
| 1063 if (!visitor->visit(j, element_value)) return false; | 1094 if (!visitor->visit(j, element_value)) return false; |
| 1064 } else { | 1095 } else { |
| 1065 Maybe<bool> maybe = JSReceiver::HasElement(array, j); | 1096 Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
| 1066 if (!maybe.IsJust()) return false; | 1097 if (!maybe.IsJust()) return false; |
| 1067 if (maybe.FromJust()) { | 1098 if (maybe.FromJust()) { |
| 1068 // Call GetElement on array, not its prototype, or getters won't | 1099 // Call GetElement on array, not its prototype, or getters won't |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 isolate, element_value, Object::GetElement(isolate, array, j), | 1139 isolate, element_value, Object::GetElement(isolate, array, j), |
| 1109 false); | 1140 false); |
| 1110 if (!visitor->visit(j, element_value)) return false; | 1141 if (!visitor->visit(j, element_value)) return false; |
| 1111 } | 1142 } |
| 1112 } | 1143 } |
| 1113 } | 1144 } |
| 1114 break; | 1145 break; |
| 1115 } | 1146 } |
| 1116 | 1147 |
| 1117 case DICTIONARY_ELEMENTS: { | 1148 case DICTIONARY_ELEMENTS: { |
| 1118 // CollectElementIndices() can't be called when there's a JSProxy | |
| 1119 // on the prototype chain. | |
| 1120 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); | |
| 1121 iter.Advance()) { | |
| 1122 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
| 1123 return IterateElementsSlow(isolate, array, length, visitor); | |
| 1124 } | |
| 1125 } | |
| 1126 Handle<SeededNumberDictionary> dict(array->element_dictionary()); | 1149 Handle<SeededNumberDictionary> dict(array->element_dictionary()); |
| 1127 List<uint32_t> indices(dict->Capacity() / 2); | 1150 List<uint32_t> indices(dict->Capacity() / 2); |
| 1128 // Collect all indices in the object and the prototypes less | 1151 // Collect all indices in the object and the prototypes less |
| 1129 // than length. This might introduce duplicates in the indices list. | 1152 // than length. This might introduce duplicates in the indices list. |
| 1130 CollectElementIndices(array, length, &indices); | 1153 CollectElementIndices(array, length, &indices); |
| 1131 indices.Sort(&compareUInt32); | 1154 indices.Sort(&compareUInt32); |
| 1132 int j = 0; | 1155 int j = 0; |
| 1133 int n = indices.length(); | 1156 int n = indices.length(); |
| 1134 while (j < n) { | 1157 while (j < n) { |
| 1135 HandleScope loop_scope(isolate); | 1158 HandleScope loop_scope(isolate); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1154 isolate, element, Object::GetElement(isolate, array, index), false); | 1177 isolate, element, Object::GetElement(isolate, array, index), false); |
| 1155 if (!visitor->visit(index, element)) return false; | 1178 if (!visitor->visit(index, element)) return false; |
| 1156 } | 1179 } |
| 1157 break; | 1180 break; |
| 1158 } | 1181 } |
| 1159 case NO_ELEMENTS: | 1182 case NO_ELEMENTS: |
| 1160 break; | 1183 break; |
| 1161 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: | 1184 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: |
| 1162 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1185 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 1163 #undef TYPED_ARRAY_CASE | 1186 #undef TYPED_ARRAY_CASE |
| 1187 return IterateElementsSlow(isolate, receiver, length, visitor); |
| 1164 case FAST_STRING_WRAPPER_ELEMENTS: | 1188 case FAST_STRING_WRAPPER_ELEMENTS: |
| 1165 case SLOW_STRING_WRAPPER_ELEMENTS: | 1189 case SLOW_STRING_WRAPPER_ELEMENTS: |
| 1166 // |array| is guaranteed to be an array or typed array. | 1190 // |array| is guaranteed to be an array or typed array. |
| 1167 UNREACHABLE(); | 1191 UNREACHABLE(); |
| 1168 break; | 1192 break; |
| 1169 } | 1193 } |
| 1170 visitor->increase_index_offset(length); | 1194 visitor->increase_index_offset(length); |
| 1171 return true; | 1195 return true; |
| 1172 } | 1196 } |
| 1173 | 1197 |
| 1174 | 1198 |
| 1175 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { | 1199 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { |
| 1176 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact()); | |
| 1177 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | 1200 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
| 1178 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); | 1201 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); |
| 1179 return maybe.FromMaybe(false); | 1202 return maybe.FromMaybe(false); |
| 1180 } | 1203 } |
| 1181 | 1204 |
| 1182 | 1205 |
| 1183 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { | 1206 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { |
| 1184 HandleScope handle_scope(isolate); | 1207 HandleScope handle_scope(isolate); |
| 1185 if (!obj->IsJSReceiver()) return Just(false); | 1208 if (!obj->IsJSReceiver()) return Just(false); |
| 1186 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | 1209 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1211 for (int i = 0; i < argument_count; i++) { | 1234 for (int i = 0; i < argument_count; i++) { |
| 1212 HandleScope loop_scope(isolate); | 1235 HandleScope loop_scope(isolate); |
| 1213 Handle<Object> obj((*args)[i], isolate); | 1236 Handle<Object> obj((*args)[i], isolate); |
| 1214 uint32_t length_estimate; | 1237 uint32_t length_estimate; |
| 1215 uint32_t element_estimate; | 1238 uint32_t element_estimate; |
| 1216 if (obj->IsJSArray()) { | 1239 if (obj->IsJSArray()) { |
| 1217 Handle<JSArray> array(Handle<JSArray>::cast(obj)); | 1240 Handle<JSArray> array(Handle<JSArray>::cast(obj)); |
| 1218 length_estimate = static_cast<uint32_t>(array->length()->Number()); | 1241 length_estimate = static_cast<uint32_t>(array->length()->Number()); |
| 1219 if (length_estimate != 0) { | 1242 if (length_estimate != 0) { |
| 1220 ElementsKind array_kind = | 1243 ElementsKind array_kind = |
| 1221 GetPackedElementsKind(array->map()->elements_kind()); | 1244 GetPackedElementsKind(array->GetElementsKind()); |
| 1222 kind = GetMoreGeneralElementsKind(kind, array_kind); | 1245 kind = GetMoreGeneralElementsKind(kind, array_kind); |
| 1223 } | 1246 } |
| 1224 element_estimate = EstimateElementCount(array); | 1247 element_estimate = EstimateElementCount(array); |
| 1225 } else { | 1248 } else { |
| 1226 if (obj->IsHeapObject()) { | 1249 if (obj->IsHeapObject()) { |
| 1227 if (obj->IsNumber()) { | 1250 kind = GetMoreGeneralElementsKind( |
| 1228 kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS); | 1251 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS); |
| 1229 } else { | |
| 1230 kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS); | |
| 1231 } | |
| 1232 } | 1252 } |
| 1233 length_estimate = 1; | 1253 length_estimate = 1; |
| 1234 element_estimate = 1; | 1254 element_estimate = 1; |
| 1235 } | 1255 } |
| 1236 // Avoid overflows by capping at kMaxElementCount. | 1256 // Avoid overflows by capping at kMaxElementCount. |
| 1237 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) { | 1257 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) { |
| 1238 estimate_result_length = JSObject::kMaxElementCount; | 1258 estimate_result_length = JSObject::kMaxElementCount; |
| 1239 } else { | 1259 } else { |
| 1240 estimate_result_length += length_estimate; | 1260 estimate_result_length += length_estimate; |
| 1241 } | 1261 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1264 Handle<Object> obj((*args)[i], isolate); | 1284 Handle<Object> obj((*args)[i], isolate); |
| 1265 if (obj->IsSmi()) { | 1285 if (obj->IsSmi()) { |
| 1266 double_storage->set(j, Smi::cast(*obj)->value()); | 1286 double_storage->set(j, Smi::cast(*obj)->value()); |
| 1267 j++; | 1287 j++; |
| 1268 } else if (obj->IsNumber()) { | 1288 } else if (obj->IsNumber()) { |
| 1269 double_storage->set(j, obj->Number()); | 1289 double_storage->set(j, obj->Number()); |
| 1270 j++; | 1290 j++; |
| 1271 } else { | 1291 } else { |
| 1272 JSArray* array = JSArray::cast(*obj); | 1292 JSArray* array = JSArray::cast(*obj); |
| 1273 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 1293 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
| 1274 switch (array->map()->elements_kind()) { | 1294 switch (array->GetElementsKind()) { |
| 1275 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1295 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1276 case FAST_DOUBLE_ELEMENTS: { | 1296 case FAST_DOUBLE_ELEMENTS: { |
| 1277 // Empty array is FixedArray but not FixedDoubleArray. | 1297 // Empty array is FixedArray but not FixedDoubleArray. |
| 1278 if (length == 0) break; | 1298 if (length == 0) break; |
| 1279 FixedDoubleArray* elements = | 1299 FixedDoubleArray* elements = |
| 1280 FixedDoubleArray::cast(array->elements()); | 1300 FixedDoubleArray::cast(array->elements()); |
| 1281 for (uint32_t i = 0; i < length; i++) { | 1301 for (uint32_t i = 0; i < length; i++) { |
| 1282 if (elements->is_the_hole(i)) { | 1302 if (elements->is_the_hole(i)) { |
| 1283 // TODO(jkummerow/verwaest): We could be a bit more clever | 1303 // TODO(jkummerow/verwaest): We could be a bit more clever |
| 1284 // here: Check if there are no elements/getters on the | 1304 // here: Check if there are no elements/getters on the |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 DCHECK_EQ(0u, length); | 1336 DCHECK_EQ(0u, length); |
| 1317 break; | 1337 break; |
| 1318 default: | 1338 default: |
| 1319 UNREACHABLE(); | 1339 UNREACHABLE(); |
| 1320 } | 1340 } |
| 1321 } | 1341 } |
| 1322 if (failure) break; | 1342 if (failure) break; |
| 1323 } | 1343 } |
| 1324 } | 1344 } |
| 1325 if (!failure) { | 1345 if (!failure) { |
| 1326 Handle<JSArray> array = isolate->factory()->NewJSArray(0); | 1346 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j); |
| 1327 Smi* length = Smi::FromInt(j); | |
| 1328 Handle<Map> map; | |
| 1329 map = JSObject::GetElementsTransitionMap(array, kind); | |
| 1330 array->set_map(*map); | |
| 1331 array->set_length(length); | |
| 1332 array->set_elements(*storage); | |
| 1333 return *array; | |
| 1334 } | 1347 } |
| 1335 // In case of failure, fall through. | 1348 // In case of failure, fall through. |
| 1336 } | 1349 } |
| 1337 | 1350 |
| 1338 Handle<Object> storage; | 1351 Handle<Object> storage; |
| 1339 if (fast_case) { | 1352 if (fast_case) { |
| 1340 // The backing storage array must have non-existing elements to preserve | 1353 // The backing storage array must have non-existing elements to preserve |
| 1341 // holes across concat operations. | 1354 // holes across concat operations. |
| 1342 storage = | 1355 storage = |
| 1343 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); | 1356 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 | 1393 |
| 1381 if (is_array_species) { | 1394 if (is_array_species) { |
| 1382 return *visitor.ToArray(); | 1395 return *visitor.ToArray(); |
| 1383 } else { | 1396 } else { |
| 1384 return *visitor.storage_jsreceiver(); | 1397 return *visitor.storage_jsreceiver(); |
| 1385 } | 1398 } |
| 1386 } | 1399 } |
| 1387 | 1400 |
| 1388 | 1401 |
| 1389 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { | 1402 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { |
| 1390 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { | |
| 1391 return MaybeHandle<JSArray>(); | |
| 1392 } | |
| 1393 int n_arguments = args->length(); | 1403 int n_arguments = args->length(); |
| 1394 int result_len = 0; | 1404 int result_len = 0; |
| 1395 { | 1405 { |
| 1396 DisallowHeapAllocation no_gc; | 1406 DisallowHeapAllocation no_gc; |
| 1397 Object* array_proto = isolate->array_function()->prototype(); | |
| 1398 // Iterate through all the arguments performing checks | 1407 // Iterate through all the arguments performing checks |
| 1399 // and calculating total length. | 1408 // and calculating total length. |
| 1400 for (int i = 0; i < n_arguments; i++) { | 1409 for (int i = 0; i < n_arguments; i++) { |
| 1401 Object* arg = (*args)[i]; | 1410 Object* arg = (*args)[i]; |
| 1402 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); | 1411 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); |
| 1412 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { |
| 1413 return MaybeHandle<JSArray>(); |
| 1414 } |
| 1415 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS. |
| 1416 if (!JSObject::cast(arg)->HasFastElements()) { |
| 1417 return MaybeHandle<JSArray>(); |
| 1418 } |
| 1403 Handle<JSArray> array(JSArray::cast(arg), isolate); | 1419 Handle<JSArray> array(JSArray::cast(arg), isolate); |
| 1404 if (!array->HasFastElements()) return MaybeHandle<JSArray>(); | |
| 1405 PrototypeIterator iter(isolate, *array); | |
| 1406 if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>(); | |
| 1407 if (HasConcatSpreadableModifier(isolate, array)) { | 1420 if (HasConcatSpreadableModifier(isolate, array)) { |
| 1408 return MaybeHandle<JSArray>(); | 1421 return MaybeHandle<JSArray>(); |
| 1409 } | 1422 } |
| 1410 int len = Smi::cast(array->length())->value(); | 1423 int len = Smi::cast(array->length())->value(); |
| 1411 | 1424 |
| 1412 // We shouldn't overflow when adding another len. | 1425 // We shouldn't overflow when adding another len. |
| 1413 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 1426 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
| 1414 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 1427 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 1415 USE(kHalfOfMaxInt); | 1428 USE(kHalfOfMaxInt); |
| 1416 result_len += len; | 1429 result_len += len; |
| (...skipping 3033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4450 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 4463 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 4451 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 4464 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4452 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4465 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 4453 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4466 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4454 #undef DEFINE_BUILTIN_ACCESSOR_C | 4467 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 4455 #undef DEFINE_BUILTIN_ACCESSOR_A | 4468 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 4456 | 4469 |
| 4457 | 4470 |
| 4458 } // namespace internal | 4471 } // namespace internal |
| 4459 } // namespace v8 | 4472 } // namespace v8 |
| OLD | NEW |