Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: src/builtins.cc

Issue 1804963002: [builtins] Fix Array.prototype.concat bug (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: polishing corner cases and making tests work Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/api-natives.h" 9 #include "src/api-natives.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 } 215 }
216 216
217 217
218 inline bool PrototypeHasNoElements(PrototypeIterator* iter) { 218 inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
219 DisallowHeapAllocation no_gc; 219 DisallowHeapAllocation no_gc;
220 for (; !iter->IsAtEnd(); iter->Advance()) { 220 for (; !iter->IsAtEnd(); iter->Advance()) {
221 if (iter->GetCurrent()->IsJSProxy()) return false; 221 if (iter->GetCurrent()->IsJSProxy()) return false;
222 JSObject* current = iter->GetCurrent<JSObject>(); 222 JSObject* current = iter->GetCurrent<JSObject>();
223 if (current->IsAccessCheckNeeded()) return false; 223 if (current->IsAccessCheckNeeded()) return false;
224 if (current->HasIndexedInterceptor()) return false; 224 if (current->HasIndexedInterceptor()) return false;
225 if (current->HasStringWrapperElements()) return false;
225 if (current->elements()->length() != 0) return false; 226 if (current->elements()->length() != 0) return false;
226 } 227 }
227 return true; 228 return true;
228 } 229 }
229 230
230
231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, 231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
232 JSArray* receiver) { 232 JSArray* receiver) {
233 DisallowHeapAllocation no_gc; 233 DisallowHeapAllocation no_gc;
234 // If the array prototype chain is intact (and free of elements), and if the 234 // If the array prototype chain is intact (and free of elements), and if the
235 // receiver's prototype is the array prototype, then we are done. 235 // receiver's prototype is the array prototype, then we are done.
236 Object* prototype = receiver->map()->prototype(); 236 Object* prototype = receiver->map()->prototype();
237 if (prototype->IsJSArray() && 237 if (prototype->IsJSArray() &&
238 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && 238 isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
239 isolate->IsFastArrayConstructorPrototypeChainIntact()) { 239 isolate->IsFastArrayConstructorPrototypeChainIntact()) {
240 return true; 240 return true;
241 } 241 }
242
243 // Slow case. 242 // Slow case.
244 PrototypeIterator iter(isolate, receiver); 243 PrototypeIterator iter(isolate, receiver);
245 return PrototypeHasNoElements(&iter); 244 return PrototypeHasNoElements(&iter);
246 } 245 }
247 246
247 inline bool HasSimpleElements(JSObject* current) {
248 if (current->IsAccessCheckNeeded()) return false;
249 if (current->HasIndexedInterceptor()) return false;
250 if (current->HasStringWrapperElements()) return false;
251 if (current->GetElementsAccessor()->HasAccessors(current)) return false;
252 return true;
253 }
254
255 inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
256 JSReceiver* receiver) {
257 // Check that we have no accessors on the receiver's elements.
258 JSObject* object = JSObject::cast(receiver);
259 if (!HasSimpleElements(object)) return false;
260 // Check that ther are not elements on the prototype.
261 DisallowHeapAllocation no_gc;
262 PrototypeIterator iter(isolate, receiver);
263 return PrototypeHasNoElements(&iter);
264 }
265
266 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
267 // Check that ther are not elements on the prototype.
268 DisallowHeapAllocation no_gc;
269 PrototypeIterator iter(isolate, receiver,
270 PrototypeIterator::START_AT_RECEIVER);
271 for (; !iter.IsAtEnd(); iter.Advance()) {
272 if (iter.GetCurrent()->IsJSProxy()) return false;
273 JSObject* current = iter.GetCurrent<JSObject>();
274 if (!HasSimpleElements(current)) return false;
275 }
276 return true;
277 }
278
248 // Returns |false| if not applicable. 279 // Returns |false| if not applicable.
249 MUST_USE_RESULT 280 MUST_USE_RESULT
250 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, 281 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
251 Handle<Object> receiver, 282 Handle<Object> receiver,
252 Arguments* args, 283 Arguments* args,
253 int first_added_arg) { 284 int first_added_arg) {
254 if (!receiver->IsJSArray()) return false; 285 if (!receiver->IsJSArray()) return false;
255 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 286 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
256 // If there may be elements accessors in the prototype chain, the fast path 287 // If there may be elements accessors in the prototype chain, the fast path
257 // cannot be used if there arguments to add to the array. 288 // cannot be used if there arguments to add to the array.
258 if (args != nullptr && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { 289 if (args != nullptr && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
259 return false; 290 return false;
260 } 291 }
261 ElementsKind origin_kind = array->map()->elements_kind(); 292 ElementsKind origin_kind = array->GetElementsKind();
262 if (IsDictionaryElementsKind(origin_kind)) return false; 293 if (IsDictionaryElementsKind(origin_kind)) return false;
263 if (array->map()->is_observed()) return false; 294 if (array->map()->is_observed()) return false;
264 if (!array->map()->is_extensible()) return false; 295 if (!array->map()->is_extensible()) return false;
265 if (args == nullptr) return true; 296 if (args == nullptr) return true;
266 297
267 // Adding elements to the array prototype would break code that makes sure 298 // Adding elements to the array prototype would break code that makes sure
268 // it has no elements. Handle that elsewhere. 299 // it has no elements. Handle that elsewhere.
269 if (isolate->IsAnyInitialArrayPrototype(array)) return false; 300 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
270 301
271 // Need to ensure that the arguments passed in args can be contained in 302 // Need to ensure that the arguments passed in args can be contained in
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 Handle<Object> key = isolate->factory()->length_string(); 1087 Handle<Object> key = isolate->factory()->length_string();
1057 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1088 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1058 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), 1089 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1059 false); 1090 false);
1060 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, 1091 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1061 Object::ToLength(isolate, val), false); 1092 Object::ToLength(isolate, val), false);
1062 // TODO(caitp): Support larger element indexes (up to 2^53-1). 1093 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1063 if (!val->ToUint32(&length)) { 1094 if (!val->ToUint32(&length)) {
1064 length = 0; 1095 length = 0;
1065 } 1096 }
1097 // TODO(cbruni): handle other element kind as well
1098 return IterateElementsSlow(isolate, receiver, length, visitor);
1066 } 1099 }
1067 1100
1068 if (!receiver->IsJSArray()) { 1101 if (!HasOnlySimpleElements(isolate, *receiver)) {
1069 // For classes which are not known to be safe to access via elements alone,
1070 // use the slow case.
1071 return IterateElementsSlow(isolate, receiver, length, visitor); 1102 return IterateElementsSlow(isolate, receiver, length, visitor);
1072 } 1103 }
1073 Handle<JSObject> array = Handle<JSObject>::cast(receiver); 1104 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1074 1105
1075 switch (array->GetElementsKind()) { 1106 switch (array->GetElementsKind()) {
1076 case FAST_SMI_ELEMENTS: 1107 case FAST_SMI_ELEMENTS:
1077 case FAST_ELEMENTS: 1108 case FAST_ELEMENTS:
1078 case FAST_HOLEY_SMI_ELEMENTS: 1109 case FAST_HOLEY_SMI_ELEMENTS:
1079 case FAST_HOLEY_ELEMENTS: { 1110 case FAST_HOLEY_ELEMENTS: {
1080 // Run through the elements FixedArray and use HasElement and GetElement 1111 // Run through the elements FixedArray and use HasElement and GetElement
1081 // to check the prototype for missing elements. 1112 // to check the prototype for missing elements.
1082 Handle<FixedArray> elements(FixedArray::cast(array->elements())); 1113 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1083 int fast_length = static_cast<int>(length); 1114 int fast_length = static_cast<int>(length);
1084 DCHECK(fast_length <= elements->length()); 1115 DCHECK_LE(fast_length, elements->length());
1085 for (int j = 0; j < fast_length; j++) { 1116 for (int j = 0; j < fast_length; j++) {
1086 HandleScope loop_scope(isolate); 1117 HandleScope loop_scope(isolate);
1087 Handle<Object> element_value(elements->get(j), isolate); 1118 Handle<Object> element_value(elements->get(j), isolate);
1088 if (!element_value->IsTheHole()) { 1119 if (!element_value->IsTheHole()) {
1089 if (!visitor->visit(j, element_value)) return false; 1120 if (!visitor->visit(j, element_value)) return false;
1090 } else { 1121 } else {
1091 Maybe<bool> maybe = JSReceiver::HasElement(array, j); 1122 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1092 if (!maybe.IsJust()) return false; 1123 if (!maybe.IsJust()) return false;
1093 if (maybe.FromJust()) { 1124 if (maybe.FromJust()) {
1094 // Call GetElement on array, not its prototype, or getters won't 1125 // Call GetElement on array, not its prototype, or getters won't
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 isolate, element_value, 1165 isolate, element_value,
1135 JSReceiver::GetElement(isolate, array, j), false); 1166 JSReceiver::GetElement(isolate, array, j), false);
1136 if (!visitor->visit(j, element_value)) return false; 1167 if (!visitor->visit(j, element_value)) return false;
1137 } 1168 }
1138 } 1169 }
1139 } 1170 }
1140 break; 1171 break;
1141 } 1172 }
1142 1173
1143 case DICTIONARY_ELEMENTS: { 1174 case DICTIONARY_ELEMENTS: {
1144 // CollectElementIndices() can't be called when there's a JSProxy
1145 // on the prototype chain.
1146 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
1147 iter.Advance()) {
1148 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1149 return IterateElementsSlow(isolate, array, length, visitor);
1150 }
1151 }
1152 Handle<SeededNumberDictionary> dict(array->element_dictionary()); 1175 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1153 List<uint32_t> indices(dict->Capacity() / 2); 1176 List<uint32_t> indices(dict->Capacity() / 2);
1154 // Collect all indices in the object and the prototypes less 1177 // Collect all indices in the object and the prototypes less
1155 // than length. This might introduce duplicates in the indices list. 1178 // than length. This might introduce duplicates in the indices list.
1156 CollectElementIndices(array, length, &indices); 1179 CollectElementIndices(array, length, &indices);
1157 indices.Sort(&compareUInt32); 1180 indices.Sort(&compareUInt32);
1158 int j = 0; 1181 int j = 0;
1159 int n = indices.length(); 1182 int n = indices.length();
1160 while (j < n) { 1183 while (j < n) {
1161 HandleScope loop_scope(isolate); 1184 HandleScope loop_scope(isolate);
(...skipping 20 matching lines...) Expand all
1182 false); 1205 false);
1183 if (!visitor->visit(index, element)) return false; 1206 if (!visitor->visit(index, element)) return false;
1184 } 1207 }
1185 break; 1208 break;
1186 } 1209 }
1187 case NO_ELEMENTS: 1210 case NO_ELEMENTS:
1188 break; 1211 break;
1189 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: 1212 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1190 TYPED_ARRAYS(TYPED_ARRAY_CASE) 1213 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1191 #undef TYPED_ARRAY_CASE 1214 #undef TYPED_ARRAY_CASE
1215 return IterateElementsSlow(isolate, receiver, length, visitor);
1192 case FAST_STRING_WRAPPER_ELEMENTS: 1216 case FAST_STRING_WRAPPER_ELEMENTS:
1193 case SLOW_STRING_WRAPPER_ELEMENTS: 1217 case SLOW_STRING_WRAPPER_ELEMENTS:
1194 // |array| is guaranteed to be an array or typed array. 1218 // |array| is guaranteed to be an array or typed array.
1195 UNREACHABLE(); 1219 UNREACHABLE();
1196 break; 1220 break;
1197 } 1221 }
1198 visitor->increase_index_offset(length); 1222 visitor->increase_index_offset(length);
1199 return true; 1223 return true;
1200 } 1224 }
1201 1225
1202 1226
1203 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { 1227 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1204 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
1205 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1228 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1206 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); 1229 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1207 return maybe.FromMaybe(false); 1230 return maybe.FromMaybe(false);
1208 } 1231 }
1209 1232
1210 1233
1211 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1234 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1212 HandleScope handle_scope(isolate); 1235 HandleScope handle_scope(isolate);
1213 if (!obj->IsJSReceiver()) return Just(false); 1236 if (!obj->IsJSReceiver()) return Just(false);
1214 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1237 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
(...skipping 24 matching lines...) Expand all
1239 for (int i = 0; i < argument_count; i++) { 1262 for (int i = 0; i < argument_count; i++) {
1240 HandleScope loop_scope(isolate); 1263 HandleScope loop_scope(isolate);
1241 Handle<Object> obj((*args)[i], isolate); 1264 Handle<Object> obj((*args)[i], isolate);
1242 uint32_t length_estimate; 1265 uint32_t length_estimate;
1243 uint32_t element_estimate; 1266 uint32_t element_estimate;
1244 if (obj->IsJSArray()) { 1267 if (obj->IsJSArray()) {
1245 Handle<JSArray> array(Handle<JSArray>::cast(obj)); 1268 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1246 length_estimate = static_cast<uint32_t>(array->length()->Number()); 1269 length_estimate = static_cast<uint32_t>(array->length()->Number());
1247 if (length_estimate != 0) { 1270 if (length_estimate != 0) {
1248 ElementsKind array_kind = 1271 ElementsKind array_kind =
1249 GetPackedElementsKind(array->map()->elements_kind()); 1272 GetPackedElementsKind(array->GetElementsKind());
1250 kind = GetMoreGeneralElementsKind(kind, array_kind); 1273 kind = GetMoreGeneralElementsKind(kind, array_kind);
1251 } 1274 }
1252 element_estimate = EstimateElementCount(array); 1275 element_estimate = EstimateElementCount(array);
1253 } else { 1276 } else {
1254 if (obj->IsHeapObject()) { 1277 if (obj->IsHeapObject()) {
1255 if (obj->IsNumber()) { 1278 kind = GetMoreGeneralElementsKind(
1256 kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS); 1279 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
1257 } else {
1258 kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS);
1259 }
1260 } 1280 }
1261 length_estimate = 1; 1281 length_estimate = 1;
1262 element_estimate = 1; 1282 element_estimate = 1;
1263 } 1283 }
1264 // Avoid overflows by capping at kMaxElementCount. 1284 // Avoid overflows by capping at kMaxElementCount.
1265 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) { 1285 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1266 estimate_result_length = JSObject::kMaxElementCount; 1286 estimate_result_length = JSObject::kMaxElementCount;
1267 } else { 1287 } else {
1268 estimate_result_length += length_estimate; 1288 estimate_result_length += length_estimate;
1269 } 1289 }
(...skipping 22 matching lines...) Expand all
1292 Handle<Object> obj((*args)[i], isolate); 1312 Handle<Object> obj((*args)[i], isolate);
1293 if (obj->IsSmi()) { 1313 if (obj->IsSmi()) {
1294 double_storage->set(j, Smi::cast(*obj)->value()); 1314 double_storage->set(j, Smi::cast(*obj)->value());
1295 j++; 1315 j++;
1296 } else if (obj->IsNumber()) { 1316 } else if (obj->IsNumber()) {
1297 double_storage->set(j, obj->Number()); 1317 double_storage->set(j, obj->Number());
1298 j++; 1318 j++;
1299 } else { 1319 } else {
1300 JSArray* array = JSArray::cast(*obj); 1320 JSArray* array = JSArray::cast(*obj);
1301 uint32_t length = static_cast<uint32_t>(array->length()->Number()); 1321 uint32_t length = static_cast<uint32_t>(array->length()->Number());
1302 switch (array->map()->elements_kind()) { 1322 switch (array->GetElementsKind()) {
1303 case FAST_HOLEY_DOUBLE_ELEMENTS: 1323 case FAST_HOLEY_DOUBLE_ELEMENTS:
1304 case FAST_DOUBLE_ELEMENTS: { 1324 case FAST_DOUBLE_ELEMENTS: {
1305 // Empty array is FixedArray but not FixedDoubleArray. 1325 // Empty array is FixedArray but not FixedDoubleArray.
1306 if (length == 0) break; 1326 if (length == 0) break;
1307 FixedDoubleArray* elements = 1327 FixedDoubleArray* elements =
1308 FixedDoubleArray::cast(array->elements()); 1328 FixedDoubleArray::cast(array->elements());
1309 for (uint32_t i = 0; i < length; i++) { 1329 for (uint32_t i = 0; i < length; i++) {
1310 if (elements->is_the_hole(i)) { 1330 if (elements->is_the_hole(i)) {
1311 // TODO(jkummerow/verwaest): We could be a bit more clever 1331 // TODO(jkummerow/verwaest): We could be a bit more clever
1312 // here: Check if there are no elements/getters on the 1332 // here: Check if there are no elements/getters on the
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 DCHECK_EQ(0u, length); 1364 DCHECK_EQ(0u, length);
1345 break; 1365 break;
1346 default: 1366 default:
1347 UNREACHABLE(); 1367 UNREACHABLE();
1348 } 1368 }
1349 } 1369 }
1350 if (failure) break; 1370 if (failure) break;
1351 } 1371 }
1352 } 1372 }
1353 if (!failure) { 1373 if (!failure) {
1354 Handle<JSArray> array = isolate->factory()->NewJSArray(0); 1374 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
1355 Smi* length = Smi::FromInt(j);
1356 Handle<Map> map;
1357 map = JSObject::GetElementsTransitionMap(array, kind);
1358 array->set_map(*map);
1359 array->set_length(length);
1360 array->set_elements(*storage);
1361 return *array;
1362 } 1375 }
1363 // In case of failure, fall through. 1376 // In case of failure, fall through.
1364 } 1377 }
1365 1378
1366 Handle<Object> storage; 1379 Handle<Object> storage;
1367 if (fast_case) { 1380 if (fast_case) {
1368 // The backing storage array must have non-existing elements to preserve 1381 // The backing storage array must have non-existing elements to preserve
1369 // holes across concat operations. 1382 // holes across concat operations.
1370 storage = 1383 storage =
1371 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); 1384 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 1421
1409 if (is_array_species) { 1422 if (is_array_species) {
1410 return *visitor.ToArray(); 1423 return *visitor.ToArray();
1411 } else { 1424 } else {
1412 return *visitor.storage_jsreceiver(); 1425 return *visitor.storage_jsreceiver();
1413 } 1426 }
1414 } 1427 }
1415 1428
1416 1429
1417 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1430 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1418 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
1419 return MaybeHandle<JSArray>();
1420 }
1421 int n_arguments = args->length(); 1431 int n_arguments = args->length();
1422 int result_len = 0; 1432 int result_len = 0;
1423 { 1433 {
1424 DisallowHeapAllocation no_gc; 1434 DisallowHeapAllocation no_gc;
1425 Object* array_proto = isolate->array_function()->prototype();
1426 // Iterate through all the arguments performing checks 1435 // Iterate through all the arguments performing checks
1427 // and calculating total length. 1436 // and calculating total length.
1428 for (int i = 0; i < n_arguments; i++) { 1437 for (int i = 0; i < n_arguments; i++) {
1429 Object* arg = (*args)[i]; 1438 Object* arg = (*args)[i];
1430 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); 1439 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1440 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1441 return MaybeHandle<JSArray>();
1442 }
1443 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1444 if (!JSObject::cast(arg)->HasFastElements()) {
1445 return MaybeHandle<JSArray>();
1446 }
1431 Handle<JSArray> array(JSArray::cast(arg), isolate); 1447 Handle<JSArray> array(JSArray::cast(arg), isolate);
1432 if (!array->HasFastElements()) return MaybeHandle<JSArray>();
1433 PrototypeIterator iter(isolate, *array);
1434 if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>();
1435 if (HasConcatSpreadableModifier(isolate, array)) { 1448 if (HasConcatSpreadableModifier(isolate, array)) {
1436 return MaybeHandle<JSArray>(); 1449 return MaybeHandle<JSArray>();
1437 } 1450 }
1438 int len = Smi::cast(array->length())->value(); 1451 int len = Smi::cast(array->length())->value();
1439 1452
1440 // We shouldn't overflow when adding another len. 1453 // We shouldn't overflow when adding another len.
1441 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1454 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1442 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1455 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1443 USE(kHalfOfMaxInt); 1456 USE(kHalfOfMaxInt);
1444 result_len += len; 1457 result_len += len;
(...skipping 3088 matching lines...) Expand 10 before | Expand all | Expand 10 after
4533 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 4546 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
4534 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 4547 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
4535 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4548 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4536 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4549 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4537 #undef DEFINE_BUILTIN_ACCESSOR_C 4550 #undef DEFINE_BUILTIN_ACCESSOR_C
4538 #undef DEFINE_BUILTIN_ACCESSOR_A 4551 #undef DEFINE_BUILTIN_ACCESSOR_A
4539 4552
4540 4553
4541 } // namespace internal 4554 } // namespace internal
4542 } // namespace v8 4555 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/elements.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698