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

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: adding more 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
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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 return true; 259 return true;
260 } 260 }
261 261
262 // Returns |false| if not applicable. 262 // Returns |false| if not applicable.
263 MUST_USE_RESULT 263 MUST_USE_RESULT
264 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, 264 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
265 Handle<Object> receiver, 265 Handle<Object> receiver,
266 Arguments* args, 266 Arguments* args,
267 int first_added_arg) { 267 int first_added_arg) {
268 if (!receiver->IsJSArray()) return false; 268 if (!receiver->IsJSArray()) return false;
269
269 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 270 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
270 ElementsKind origin_kind = array->GetElementsKind(); 271 ElementsKind origin_kind = array->GetElementsKind();
271 if (IsDictionaryElementsKind(origin_kind)) return false; 272 if (IsDictionaryElementsKind(origin_kind)) return false;
272 if (array->map()->is_observed()) return false; 273 if (array->map()->is_observed()) return false;
273 if (!array->map()->is_extensible()) return false; 274 if (!array->map()->is_extensible()) return false;
274 if (args == nullptr) return true; 275 if (args == nullptr) return true;
275 276
276 // If there may be elements accessors in the prototype chain, the fast path 277 // If there may be elements accessors in the prototype chain, the fast path
277 // cannot be used if there arguments to add to the array. 278 // cannot be used if there arguments to add to the array.
278 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false; 279 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 case FAST_STRING_WRAPPER_ELEMENTS: 1311 case FAST_STRING_WRAPPER_ELEMENTS:
1311 case SLOW_STRING_WRAPPER_ELEMENTS: 1312 case SLOW_STRING_WRAPPER_ELEMENTS:
1312 // |array| is guaranteed to be an array or typed array. 1313 // |array| is guaranteed to be an array or typed array.
1313 UNREACHABLE(); 1314 UNREACHABLE();
1314 break; 1315 break;
1315 } 1316 }
1316 visitor->increase_index_offset(length); 1317 visitor->increase_index_offset(length);
1317 return true; 1318 return true;
1318 } 1319 }
1319 1320
1320
1321 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1322 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1323 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1324 return maybe.FromMaybe(false);
1325 }
1326
1327
1328 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1321 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1329 HandleScope handle_scope(isolate); 1322 HandleScope handle_scope(isolate);
1330 if (!obj->IsJSReceiver()) return Just(false); 1323 if (!obj->IsJSReceiver()) return Just(false);
1331 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1324 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1332 Handle<Object> value; 1325 Handle<Object> value;
1333 MaybeHandle<Object> maybeValue = 1326 MaybeHandle<Object> maybeValue =
1334 i::Runtime::GetObjectProperty(isolate, obj, key); 1327 i::Runtime::GetObjectProperty(isolate, obj, key);
1335 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); 1328 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1336 if (!value->IsUndefined()) return Just(value->BooleanValue()); 1329 if (!value->IsUndefined()) return Just(value->BooleanValue());
1337 return Object::IsArray(obj); 1330 return Object::IsArray(obj);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); 1505 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1513 } 1506 }
1514 1507
1515 if (is_array_species) { 1508 if (is_array_species) {
1516 return *visitor.ToArray(); 1509 return *visitor.ToArray();
1517 } else { 1510 } else {
1518 return *visitor.storage_jsreceiver(); 1511 return *visitor.storage_jsreceiver();
1519 } 1512 }
1520 } 1513 }
1521 1514
1515 bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
1516 {
1517 DisallowHeapAllocation no_gc;
1518 Map* map = obj->map();
1519 if (map->prototype() ==
1520 isolate->native_context()->initial_array_prototype()) {
1521 // If there is only the 'length' property we are fine.
1522 if (map->NumberOfOwnDescriptors() == 1) return false;
1523 }
1524 }
1525 // TODO(cbruni): slower lookup for array subclasses and support slow
1526 // @@IsConcatSpreadable lookup.
1527 return true;
1528 }
1522 1529
1523 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1530 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1531 if (!isolate->IsArrayIsConcatSpreadableLookupChainIntact()) {
1532 return MaybeHandle<JSArray>();
1533 }
1524 int n_arguments = args->length(); 1534 int n_arguments = args->length();
1525 int result_len = 0; 1535 int result_len = 0;
1526 { 1536 {
1527 DisallowHeapAllocation no_gc; 1537 DisallowHeapAllocation no_gc;
1528 // Iterate through all the arguments performing checks 1538 // Iterate through all the arguments performing checks
1529 // and calculating total length. 1539 // and calculating total length.
1530 for (int i = 0; i < n_arguments; i++) { 1540 for (int i = 0; i < n_arguments; i++) {
1531 Object* arg = (*args)[i]; 1541 Object* arg = (*args)[i];
1532 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); 1542 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1533 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { 1543 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1534 return MaybeHandle<JSArray>(); 1544 return MaybeHandle<JSArray>();
1535 } 1545 }
1536 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS. 1546 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1537 if (!JSObject::cast(arg)->HasFastElements()) { 1547 if (!JSObject::cast(arg)->HasFastElements()) {
1538 return MaybeHandle<JSArray>(); 1548 return MaybeHandle<JSArray>();
1539 } 1549 }
1540 Handle<JSArray> array(JSArray::cast(arg), isolate); 1550 Handle<JSArray> array(JSArray::cast(arg), isolate);
1541 if (HasConcatSpreadableModifier(isolate, array)) { 1551 if (IsSimpleArray(isolate, array)) {
1542 return MaybeHandle<JSArray>(); 1552 return MaybeHandle<JSArray>();
1543 } 1553 }
1544 int len = Smi::cast(array->length())->value(); 1554 int len = Smi::cast(array->length())->value();
1545 1555
1546 // We shouldn't overflow when adding another len. 1556 // We shouldn't overflow when adding another len.
1547 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1557 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1548 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1558 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1549 USE(kHalfOfMaxInt); 1559 USE(kHalfOfMaxInt);
1550 result_len += len; 1560 result_len += len;
1551 DCHECK(result_len >= 0); 1561 DCHECK_LE(0, result_len);
1552 // Throw an Error if we overflow the FixedArray limits 1562 // Throw an Error if we overflow the FixedArray limits
1553 if (FixedArray::kMaxLength < result_len) { 1563 if (FixedArray::kMaxLength < result_len) {
1554 THROW_NEW_ERROR(isolate, 1564 THROW_NEW_ERROR(isolate,
1555 NewRangeError(MessageTemplate::kInvalidArrayLength), 1565 NewRangeError(MessageTemplate::kInvalidArrayLength),
1556 JSArray); 1566 JSArray);
1557 } 1567 }
1558 } 1568 }
1559 } 1569 }
1560 return ElementsAccessor::Concat(isolate, args, n_arguments); 1570 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
1561 } 1571 }
1562 1572
1563 } // namespace 1573 } // namespace
1564 1574
1565 1575
1566 // ES6 22.1.3.1 Array.prototype.concat 1576 // ES6 22.1.3.1 Array.prototype.concat
1567 BUILTIN(ArrayConcat) { 1577 BUILTIN(ArrayConcat) {
1568 HandleScope scope(isolate); 1578 HandleScope scope(isolate);
1569 1579
1570 Handle<Object> receiver = args.receiver(); 1580 Handle<Object> receiver = args.receiver();
(...skipping 3196 matching lines...) Expand 10 before | Expand all | Expand 10 after
4767 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) 4777 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
4768 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4778 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4769 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4779 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4770 #undef DEFINE_BUILTIN_ACCESSOR_C 4780 #undef DEFINE_BUILTIN_ACCESSOR_C
4771 #undef DEFINE_BUILTIN_ACCESSOR_A 4781 #undef DEFINE_BUILTIN_ACCESSOR_A
4772 #undef DEFINE_BUILTIN_ACCESSOR_T 4782 #undef DEFINE_BUILTIN_ACCESSOR_T
4773 #undef DEFINE_BUILTIN_ACCESSOR_H 4783 #undef DEFINE_BUILTIN_ACCESSOR_H
4774 4784
4775 } // namespace internal 4785 } // namespace internal
4776 } // namespace v8 4786 } // namespace v8
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/context-measure.cc » ('j') | src/isolate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698