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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |