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

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: merging with master Created 4 years, 7 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-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 case FAST_STRING_WRAPPER_ELEMENTS: 1215 case FAST_STRING_WRAPPER_ELEMENTS:
1216 case SLOW_STRING_WRAPPER_ELEMENTS: 1216 case SLOW_STRING_WRAPPER_ELEMENTS:
1217 // |array| is guaranteed to be an array or typed array. 1217 // |array| is guaranteed to be an array or typed array.
1218 UNREACHABLE(); 1218 UNREACHABLE();
1219 break; 1219 break;
1220 } 1220 }
1221 visitor->increase_index_offset(length); 1221 visitor->increase_index_offset(length);
1222 return true; 1222 return true;
1223 } 1223 }
1224 1224
1225
1226 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1227 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1228 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1229 return maybe.FromMaybe(false);
1230 }
1231
1232
1233 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1225 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1234 HandleScope handle_scope(isolate); 1226 HandleScope handle_scope(isolate);
1235 if (!obj->IsJSReceiver()) return Just(false); 1227 if (!obj->IsJSReceiver()) return Just(false);
1236 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1228 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1237 Handle<Object> value; 1229 // Slow path if @@isConcatSpreadable has been used.
1238 MaybeHandle<Object> maybeValue = 1230 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1239 i::Runtime::GetObjectProperty(isolate, obj, key); 1231 Handle<Object> value;
1240 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); 1232 MaybeHandle<Object> maybeValue =
1241 if (!value->IsUndefined()) return Just(value->BooleanValue()); 1233 i::Runtime::GetObjectProperty(isolate, obj, key);
1234 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1235 if (!value->IsUndefined()) return Just(value->BooleanValue());
1236 }
1242 return Object::IsArray(obj); 1237 return Object::IsArray(obj);
1243 } 1238 }
1244 1239
1245 1240
1246 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, 1241 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
1247 Isolate* isolate) { 1242 Isolate* isolate) {
1248 int argument_count = args->length(); 1243 int argument_count = args->length();
1249 1244
1250 bool is_array_species = *species == isolate->context()->array_function(); 1245 bool is_array_species = *species == isolate->context()->array_function();
1251 1246
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1419 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); 1414 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1420 } 1415 }
1421 1416
1422 if (is_array_species) { 1417 if (is_array_species) {
1423 return *visitor.ToArray(); 1418 return *visitor.ToArray();
1424 } else { 1419 } else {
1425 return *visitor.storage_jsreceiver(); 1420 return *visitor.storage_jsreceiver();
1426 } 1421 }
1427 } 1422 }
1428 1423
1424 bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
1425 DisallowHeapAllocation no_gc;
1426 Map* map = obj->map();
1427 // If there is only the 'length' property we are fine.
1428 if (map->prototype() ==
1429 isolate->native_context()->initial_array_prototype() &&
1430 map->NumberOfOwnDescriptors() == 1) {
1431 return true;
1432 }
1433 // TODO(cbruni): slower lookup for array subclasses and support slow
1434 // @@IsConcatSpreadable lookup.
1435 return false;
1436 }
1429 1437
1430 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1438 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1439 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1440 return MaybeHandle<JSArray>();
1441 }
1431 // We shouldn't overflow when adding another len. 1442 // We shouldn't overflow when adding another len.
1432 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1443 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1433 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1444 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1434 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt); 1445 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
1435 USE(kHalfOfMaxInt); 1446 USE(kHalfOfMaxInt);
1436 1447
1437 int n_arguments = args->length(); 1448 int n_arguments = args->length();
1438 int result_len = 0; 1449 int result_len = 0;
1439 { 1450 {
1440 DisallowHeapAllocation no_gc; 1451 DisallowHeapAllocation no_gc;
1441 // Iterate through all the arguments performing checks 1452 // Iterate through all the arguments performing checks
1442 // and calculating total length. 1453 // and calculating total length.
1443 for (int i = 0; i < n_arguments; i++) { 1454 for (int i = 0; i < n_arguments; i++) {
1444 Object* arg = (*args)[i]; 1455 Object* arg = (*args)[i];
1445 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); 1456 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1457 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1458 return MaybeHandle<JSArray>();
1459 }
1460 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1446 if (!JSObject::cast(arg)->HasFastElements()) { 1461 if (!JSObject::cast(arg)->HasFastElements()) {
1447 return MaybeHandle<JSArray>(); 1462 return MaybeHandle<JSArray>();
1448 } 1463 }
1449 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1450 return MaybeHandle<JSArray>();
1451 }
1452 Handle<JSArray> array(JSArray::cast(arg), isolate); 1464 Handle<JSArray> array(JSArray::cast(arg), isolate);
1453 if (HasConcatSpreadableModifier(isolate, array)) { 1465 if (!IsSimpleArray(isolate, array)) {
1454 return MaybeHandle<JSArray>(); 1466 return MaybeHandle<JSArray>();
1455 } 1467 }
1456 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't 1468 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
1457 // overflow. 1469 // overflow.
1458 result_len += Smi::cast(array->length())->value(); 1470 result_len += Smi::cast(array->length())->value();
1459 DCHECK(result_len >= 0); 1471 DCHECK(result_len >= 0);
1460 // Throw an Error if we overflow the FixedArray limits 1472 // Throw an Error if we overflow the FixedArray limits
1461 if (FixedDoubleArray::kMaxLength < result_len || 1473 if (FixedArray::kMaxLength < result_len) {
1462 FixedArray::kMaxLength < result_len) { 1474 AllowHeapAllocation gc;
1463 AllowHeapAllocation allow_gc;
1464 THROW_NEW_ERROR(isolate, 1475 THROW_NEW_ERROR(isolate,
1465 NewRangeError(MessageTemplate::kInvalidArrayLength), 1476 NewRangeError(MessageTemplate::kInvalidArrayLength),
1466 JSArray); 1477 JSArray);
1467 } 1478 }
1468 } 1479 }
1469 } 1480 }
1470 return ElementsAccessor::Concat(isolate, args, n_arguments); 1481 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
1471 } 1482 }
1472 1483
1473 } // namespace 1484 } // namespace
1474 1485
1475 1486
1476 // ES6 22.1.3.1 Array.prototype.concat 1487 // ES6 22.1.3.1 Array.prototype.concat
1477 BUILTIN(ArrayConcat) { 1488 BUILTIN(ArrayConcat) {
1478 HandleScope scope(isolate); 1489 HandleScope scope(isolate);
1479 1490
1480 Handle<Object> receiver = args.receiver(); 1491 Handle<Object> receiver = args.receiver();
(...skipping 3984 matching lines...) Expand 10 before | Expand all | Expand 10 after
5465 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) 5476 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
5466 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 5477 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
5467 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 5478 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
5468 #undef DEFINE_BUILTIN_ACCESSOR_C 5479 #undef DEFINE_BUILTIN_ACCESSOR_C
5469 #undef DEFINE_BUILTIN_ACCESSOR_A 5480 #undef DEFINE_BUILTIN_ACCESSOR_A
5470 #undef DEFINE_BUILTIN_ACCESSOR_T 5481 #undef DEFINE_BUILTIN_ACCESSOR_T
5471 #undef DEFINE_BUILTIN_ACCESSOR_H 5482 #undef DEFINE_BUILTIN_ACCESSOR_H
5472 5483
5473 } // namespace internal 5484 } // namespace internal
5474 } // namespace v8 5485 } // 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