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

Side by Side Diff: src/builtins.cc

Issue 1409123003: [runtime] Avoid @@isConcatSpreadable lookup for fast path Array.prototype.concat (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixing tests Created 4 years, 8 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 | « src/bootstrapper.cc ('k') | src/context-measure.cc » ('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 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/context-measure.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698