Chromium Code Reviews| 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-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 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1321 case FAST_STRING_WRAPPER_ELEMENTS: | 1321 case FAST_STRING_WRAPPER_ELEMENTS: |
| 1322 case SLOW_STRING_WRAPPER_ELEMENTS: | 1322 case SLOW_STRING_WRAPPER_ELEMENTS: |
| 1323 // |array| is guaranteed to be an array or typed array. | 1323 // |array| is guaranteed to be an array or typed array. |
| 1324 UNREACHABLE(); | 1324 UNREACHABLE(); |
| 1325 break; | 1325 break; |
| 1326 } | 1326 } |
| 1327 visitor->increase_index_offset(length); | 1327 visitor->increase_index_offset(length); |
| 1328 return true; | 1328 return true; |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 | |
| 1332 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { | |
| 1333 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | |
| 1334 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key); | |
| 1335 return maybe.FromMaybe(false); | |
| 1336 } | |
| 1337 | |
| 1338 | |
| 1339 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { | 1331 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { |
| 1340 HandleScope handle_scope(isolate); | 1332 HandleScope handle_scope(isolate); |
| 1341 if (!obj->IsJSReceiver()) return Just(false); | 1333 if (!obj->IsJSReceiver()) return Just(false); |
| 1342 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | 1334 if (!isolate->IsArrayIsConcatSpreadableLookupChainIntact()) { |
|
Toon Verwaest
2016/04/11 09:30:56
This only guarantees that Array.prototype and Obje
Camillo Bruni
2016/04/11 11:55:12
I think the naming for the protector is confusing.
| |
| 1343 Handle<Object> value; | 1335 // Slow path if @@isConcatSpreadable has been used. |
| 1344 MaybeHandle<Object> maybeValue = | 1336 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); |
| 1345 i::Runtime::GetObjectProperty(isolate, obj, key); | 1337 Handle<Object> value; |
| 1346 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); | 1338 MaybeHandle<Object> maybeValue = |
| 1347 if (!value->IsUndefined()) return Just(value->BooleanValue()); | 1339 i::Runtime::GetObjectProperty(isolate, obj, key); |
| 1340 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); | |
| 1341 if (!value->IsUndefined()) return Just(value->BooleanValue()); | |
| 1342 } | |
| 1348 return Object::IsArray(obj); | 1343 return Object::IsArray(obj); |
| 1349 } | 1344 } |
| 1350 | 1345 |
| 1351 | 1346 |
| 1352 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, | 1347 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, |
| 1353 Isolate* isolate) { | 1348 Isolate* isolate) { |
| 1354 int argument_count = args->length(); | 1349 int argument_count = args->length(); |
| 1355 | 1350 |
| 1356 bool is_array_species = *species == isolate->context()->array_function(); | 1351 bool is_array_species = *species == isolate->context()->array_function(); |
| 1357 | 1352 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1525 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); | 1520 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); |
| 1526 } | 1521 } |
| 1527 | 1522 |
| 1528 if (is_array_species) { | 1523 if (is_array_species) { |
| 1529 return *visitor.ToArray(); | 1524 return *visitor.ToArray(); |
| 1530 } else { | 1525 } else { |
| 1531 return *visitor.storage_jsreceiver(); | 1526 return *visitor.storage_jsreceiver(); |
| 1532 } | 1527 } |
| 1533 } | 1528 } |
| 1534 | 1529 |
| 1530 bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) { | |
| 1531 { | |
| 1532 DisallowHeapAllocation no_gc; | |
| 1533 Map* map = obj->map(); | |
| 1534 // If there is only the 'length' property we are fine. | |
| 1535 if (map->prototype() == | |
| 1536 isolate->native_context()->initial_array_prototype() && | |
| 1537 map->NumberOfOwnDescriptors() == 1) { | |
| 1538 return true; | |
| 1539 } | |
| 1540 } | |
| 1541 // TODO(cbruni): slower lookup for array subclasses and support slow | |
| 1542 // @@IsConcatSpreadable lookup. | |
| 1543 return false; | |
| 1544 } | |
| 1535 | 1545 |
| 1536 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { | 1546 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { |
| 1547 if (!isolate->IsArrayIsConcatSpreadableLookupChainIntact()) { | |
| 1548 return MaybeHandle<JSArray>(); | |
| 1549 } | |
| 1537 // We shouldn't overflow when adding another len. | 1550 // We shouldn't overflow when adding another len. |
| 1538 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 1551 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
| 1539 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 1552 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 1540 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt); | 1553 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt); |
| 1541 USE(kHalfOfMaxInt); | 1554 USE(kHalfOfMaxInt); |
| 1542 | 1555 |
| 1543 int n_arguments = args->length(); | 1556 int n_arguments = args->length(); |
| 1544 int result_len = 0; | 1557 int result_len = 0; |
| 1545 { | 1558 { |
| 1546 DisallowHeapAllocation no_gc; | 1559 DisallowHeapAllocation no_gc; |
| 1547 // Iterate through all the arguments performing checks | 1560 // Iterate through all the arguments performing checks |
| 1548 // and calculating total length. | 1561 // and calculating total length. |
| 1549 for (int i = 0; i < n_arguments; i++) { | 1562 for (int i = 0; i < n_arguments; i++) { |
| 1550 Object* arg = (*args)[i]; | 1563 Object* arg = (*args)[i]; |
| 1551 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); | 1564 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); |
| 1565 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { | |
| 1566 return MaybeHandle<JSArray>(); | |
| 1567 } | |
| 1568 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS. | |
| 1552 if (!JSObject::cast(arg)->HasFastElements()) { | 1569 if (!JSObject::cast(arg)->HasFastElements()) { |
| 1553 return MaybeHandle<JSArray>(); | 1570 return MaybeHandle<JSArray>(); |
| 1554 } | 1571 } |
| 1555 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { | |
| 1556 return MaybeHandle<JSArray>(); | |
| 1557 } | |
| 1558 Handle<JSArray> array(JSArray::cast(arg), isolate); | 1572 Handle<JSArray> array(JSArray::cast(arg), isolate); |
| 1559 if (HasConcatSpreadableModifier(isolate, array)) { | 1573 if (!IsSimpleArray(isolate, array)) { |
| 1560 return MaybeHandle<JSArray>(); | 1574 return MaybeHandle<JSArray>(); |
| 1561 } | 1575 } |
| 1562 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't | 1576 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't |
| 1563 // overflow. | 1577 // overflow. |
| 1564 result_len += Smi::cast(array->length())->value(); | 1578 result_len += Smi::cast(array->length())->value(); |
| 1565 DCHECK(result_len >= 0); | 1579 DCHECK(result_len >= 0); |
| 1566 // Throw an Error if we overflow the FixedArray limits | 1580 // Throw an Error if we overflow the FixedArray limits |
| 1567 if (FixedDoubleArray::kMaxLength < result_len || | 1581 if (FixedArray::kMaxLength < result_len) { |
| 1568 FixedArray::kMaxLength < result_len) { | |
| 1569 AllowHeapAllocation allow_gc; | |
| 1570 THROW_NEW_ERROR(isolate, | 1582 THROW_NEW_ERROR(isolate, |
| 1571 NewRangeError(MessageTemplate::kInvalidArrayLength), | 1583 NewRangeError(MessageTemplate::kInvalidArrayLength), |
| 1572 JSArray); | 1584 JSArray); |
| 1573 } | 1585 } |
| 1574 } | 1586 } |
| 1575 } | 1587 } |
| 1576 return ElementsAccessor::Concat(isolate, args, n_arguments); | 1588 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len); |
| 1577 } | 1589 } |
| 1578 | 1590 |
| 1579 } // namespace | 1591 } // namespace |
| 1580 | 1592 |
| 1581 | 1593 |
| 1582 // ES6 22.1.3.1 Array.prototype.concat | 1594 // ES6 22.1.3.1 Array.prototype.concat |
| 1583 BUILTIN(ArrayConcat) { | 1595 BUILTIN(ArrayConcat) { |
| 1584 HandleScope scope(isolate); | 1596 HandleScope scope(isolate); |
| 1585 | 1597 |
| 1586 Handle<Object> receiver = args.receiver(); | 1598 Handle<Object> receiver = args.receiver(); |
| (...skipping 3361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4948 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) | 4960 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) |
| 4949 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4961 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 4950 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4962 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4951 #undef DEFINE_BUILTIN_ACCESSOR_C | 4963 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 4952 #undef DEFINE_BUILTIN_ACCESSOR_A | 4964 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 4953 #undef DEFINE_BUILTIN_ACCESSOR_T | 4965 #undef DEFINE_BUILTIN_ACCESSOR_T |
| 4954 #undef DEFINE_BUILTIN_ACCESSOR_H | 4966 #undef DEFINE_BUILTIN_ACCESSOR_H |
| 4955 | 4967 |
| 4956 } // namespace internal | 4968 } // namespace internal |
| 4957 } // namespace v8 | 4969 } // namespace v8 |
| OLD | NEW |