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

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, 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 926 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 case FAST_STRING_WRAPPER_ELEMENTS: 1206 case FAST_STRING_WRAPPER_ELEMENTS:
1206 case SLOW_STRING_WRAPPER_ELEMENTS: 1207 case SLOW_STRING_WRAPPER_ELEMENTS:
1207 // |array| is guaranteed to be an array or typed array. 1208 // |array| is guaranteed to be an array or typed array.
1208 UNREACHABLE(); 1209 UNREACHABLE();
1209 break; 1210 break;
1210 } 1211 }
1211 visitor->increase_index_offset(length); 1212 visitor->increase_index_offset(length);
1212 return true; 1213 return true;
1213 } 1214 }
1214 1215
1215
1216 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1217 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1218 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1219 return maybe.FromMaybe(false);
1220 }
1221
1222
1223 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1216 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1224 HandleScope handle_scope(isolate); 1217 HandleScope handle_scope(isolate);
1225 if (!obj->IsJSReceiver()) return Just(false); 1218 if (!obj->IsJSReceiver()) return Just(false);
1226 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1219 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1227 Handle<Object> value; 1220 Handle<Object> value;
1228 MaybeHandle<Object> maybeValue = 1221 MaybeHandle<Object> maybeValue =
1229 i::Runtime::GetObjectProperty(isolate, obj, key); 1222 i::Runtime::GetObjectProperty(isolate, obj, key);
1230 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); 1223 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1231 if (!value->IsUndefined()) return Just(value->BooleanValue()); 1224 if (!value->IsUndefined()) return Just(value->BooleanValue());
1232 return Object::IsArray(obj); 1225 return Object::IsArray(obj);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1407 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); 1400 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1408 } 1401 }
1409 1402
1410 if (is_array_species) { 1403 if (is_array_species) {
1411 return *visitor.ToArray(); 1404 return *visitor.ToArray();
1412 } else { 1405 } else {
1413 return *visitor.storage_jsreceiver(); 1406 return *visitor.storage_jsreceiver();
1414 } 1407 }
1415 } 1408 }
1416 1409
1410 bool FastArrayHasIsConcatSpreadable(Isolate* isolate, Handle<JSArray> obj) {
1411 {
1412 DisallowHeapAllocation no_gc;
1413 Map* map = obj->map();
1414 if (!isolate->IsArrayIsConcatSpreadableSet() &&
1415 map->prototype() == *isolate->initial_array_prototype()) {
Toon Verwaest 2016/03/31 08:09:46 isolate->[NATIVE_CONTEXT_FIELD]() does Handle<...>
1416 // If there is only the 'length' property we are fine.
1417 if (map->NumberOfOwnDescriptors() == 1) return false;
1418 }
1419 }
1420 // TODO(cbruni): slower lookup for array subclasses
1421 return true;
1422 }
1417 1423
1418 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1424 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1419 int n_arguments = args->length(); 1425 int n_arguments = args->length();
1420 int result_len = 0; 1426 int result_len = 0;
1421 { 1427 {
1422 DisallowHeapAllocation no_gc; 1428 DisallowHeapAllocation no_gc;
1423 // Iterate through all the arguments performing checks 1429 // Iterate through all the arguments performing checks
1424 // and calculating total length. 1430 // and calculating total length.
1425 for (int i = 0; i < n_arguments; i++) { 1431 for (int i = 0; i < n_arguments; i++) {
1426 Object* arg = (*args)[i]; 1432 Object* arg = (*args)[i];
1427 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); 1433 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1428 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { 1434 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1429 return MaybeHandle<JSArray>(); 1435 return MaybeHandle<JSArray>();
1430 } 1436 }
1431 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS. 1437 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1432 if (!JSObject::cast(arg)->HasFastElements()) { 1438 if (!JSObject::cast(arg)->HasFastElements()) {
1433 return MaybeHandle<JSArray>(); 1439 return MaybeHandle<JSArray>();
1434 } 1440 }
1435 Handle<JSArray> array(JSArray::cast(arg), isolate); 1441 Handle<JSArray> array(JSArray::cast(arg), isolate);
1436 if (HasConcatSpreadableModifier(isolate, array)) { 1442 if (FastArrayHasIsConcatSpreadable(isolate, array)) {
1437 return MaybeHandle<JSArray>(); 1443 return MaybeHandle<JSArray>();
1438 } 1444 }
1439 int len = Smi::cast(array->length())->value(); 1445 int len = Smi::cast(array->length())->value();
1440 1446
1441 // We shouldn't overflow when adding another len. 1447 // We shouldn't overflow when adding another len.
1442 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 1448 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1443 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 1449 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1444 USE(kHalfOfMaxInt); 1450 USE(kHalfOfMaxInt);
1445 result_len += len; 1451 result_len += len;
1446 DCHECK(result_len >= 0); 1452 DCHECK(0 <= result_len);
Toon Verwaest 2016/03/31 08:09:46 DCHECK_LE(...)
1447 // Throw an Error if we overflow the FixedArray limits 1453 // Throw an Error if we overflow the FixedArray limits
1448 if (FixedArray::kMaxLength < result_len) { 1454 if (FixedArray::kMaxLength < result_len) {
1449 THROW_NEW_ERROR(isolate, 1455 THROW_NEW_ERROR(isolate,
1450 NewRangeError(MessageTemplate::kInvalidArrayLength), 1456 NewRangeError(MessageTemplate::kInvalidArrayLength),
1451 JSArray); 1457 JSArray);
1452 } 1458 }
1453 } 1459 }
1454 } 1460 }
1455 return ElementsAccessor::Concat(isolate, args, n_arguments); 1461 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
1456 } 1462 }
1457 1463
1458 } // namespace 1464 } // namespace
1459 1465
1460 1466
1461 // ES6 22.1.3.1 Array.prototype.concat 1467 // ES6 22.1.3.1 Array.prototype.concat
1462 BUILTIN(ArrayConcat) { 1468 BUILTIN(ArrayConcat) {
1463 HandleScope scope(isolate); 1469 HandleScope scope(isolate);
1464 1470
1465 Handle<Object> receiver = args.receiver(); 1471 Handle<Object> receiver = args.receiver();
(...skipping 3166 matching lines...) Expand 10 before | Expand all | Expand 10 after
4632 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) 4638 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
4633 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4639 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4634 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4640 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4635 #undef DEFINE_BUILTIN_ACCESSOR_C 4641 #undef DEFINE_BUILTIN_ACCESSOR_C
4636 #undef DEFINE_BUILTIN_ACCESSOR_A 4642 #undef DEFINE_BUILTIN_ACCESSOR_A
4637 #undef DEFINE_BUILTIN_ACCESSOR_T 4643 #undef DEFINE_BUILTIN_ACCESSOR_T
4638 #undef DEFINE_BUILTIN_ACCESSOR_H 4644 #undef DEFINE_BUILTIN_ACCESSOR_H
4639 4645
4640 } // namespace internal 4646 } // namespace internal
4641 } // namespace v8 4647 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/crankshaft/arm/lithium-codegen-arm.cc » ('j') | src/crankshaft/arm/lithium-codegen-arm.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698