Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/runtime/runtime-utils.h" | 8 #include "src/runtime/runtime-utils.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 // The prototype will usually have no inherited element indices, | 433 // The prototype will usually have no inherited element indices, |
| 434 // but we have to check. | 434 // but we have to check. |
| 435 CollectElementIndices( | 435 CollectElementIndices( |
| 436 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), range, | 436 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), range, |
| 437 indices); | 437 indices); |
| 438 } | 438 } |
| 439 } | 439 } |
| 440 | 440 |
| 441 | 441 |
| 442 /** | 442 /** |
| 443 * A helper function that visits elements of a JSArray in numerical | 443 * A helper function that visits elements of a JSObject in numerical |
| 444 * order. | 444 * order. |
| 445 * | 445 * |
| 446 * The visitor argument called for each existing element in the array | 446 * The visitor argument called for each existing element in the array |
| 447 * with the element index and the element's value. | 447 * with the element index and the element's value. |
| 448 * Afterwards it increments the base-index of the visitor by the array | 448 * Afterwards it increments the base-index of the visitor by the array |
| 449 * length. | 449 * length. |
| 450 * Returns false if any access threw an exception, otherwise true. | 450 * Returns false if any access threw an exception, otherwise true. |
| 451 */ | 451 */ |
| 452 static bool IterateElements(Isolate* isolate, Handle<JSArray> receiver, | 452 static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, |
| 453 ArrayConcatVisitor* visitor) { | 453 ArrayConcatVisitor* visitor) { |
| 454 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); | 454 uint32_t length = 0; |
| 455 | |
| 456 if (receiver->IsJSArray()) { | |
| 457 Handle<JSArray> array(Handle<JSArray>::cast(receiver)); | |
| 458 length = static_cast<uint32_t>(array->length()->Number()); | |
| 459 } else { | |
| 460 Handle<Object> val; | |
| 461 Handle<Object> key(isolate->heap()->length_string(), isolate); | |
| 462 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, | |
| 463 Runtime::GetObjectProperty(isolate, receiver, key), false); | |
|
Dmitry Lomov (no reviews)
2014/12/10 10:58:20
Here you use whatever length the incoming object g
Dmitry Lomov (no reviews)
2014/12/10 14:41:59
Ah ok sorry I jumped the gun here, FAST_(SMI|DOUBL
| |
| 464 // TODO(caitp): implement ToLength() abstract operation for C++ | |
| 465 val->ToUint32(&length); | |
| 466 } | |
| 467 | |
| 455 switch (receiver->GetElementsKind()) { | 468 switch (receiver->GetElementsKind()) { |
| 456 case FAST_SMI_ELEMENTS: | 469 case FAST_SMI_ELEMENTS: |
| 457 case FAST_ELEMENTS: | 470 case FAST_ELEMENTS: |
| 458 case FAST_HOLEY_SMI_ELEMENTS: | 471 case FAST_HOLEY_SMI_ELEMENTS: |
| 459 case FAST_HOLEY_ELEMENTS: { | 472 case FAST_HOLEY_ELEMENTS: { |
| 460 // Run through the elements FixedArray and use HasElement and GetElement | 473 // Run through the elements FixedArray and use HasElement and GetElement |
| 461 // to check the prototype for missing elements. | 474 // to check the prototype for missing elements. |
| 462 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 475 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
| 463 int fast_length = static_cast<int>(length); | 476 int fast_length = static_cast<int>(length); |
| 464 DCHECK(fast_length <= elements->length()); | 477 DCHECK(fast_length <= elements->length()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 } | 607 } |
| 595 default: | 608 default: |
| 596 UNREACHABLE(); | 609 UNREACHABLE(); |
| 597 break; | 610 break; |
| 598 } | 611 } |
| 599 visitor->increase_index_offset(length); | 612 visitor->increase_index_offset(length); |
| 600 return true; | 613 return true; |
| 601 } | 614 } |
| 602 | 615 |
| 603 | 616 |
| 617 static bool IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { | |
| 618 HandleScope handle_scope(isolate); | |
| 619 if (!obj->IsSpecObject()) return false; | |
| 620 if (obj->IsJSArray()) return true; | |
| 621 if (FLAG_harmony_arrays) { | |
| 622 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); | |
| 623 Handle<Object> value; | |
| 624 MaybeHandle<Object> maybeValue = | |
| 625 i::Runtime::GetObjectProperty(isolate, obj, key); | |
| 626 if (maybeValue.ToHandle(&value)) { | |
| 627 return value->BooleanValue(); | |
| 628 } | |
| 629 } | |
| 630 return false; | |
| 631 } | |
| 632 | |
| 633 | |
| 604 /** | 634 /** |
| 605 * Array::concat implementation. | 635 * Array::concat implementation. |
| 606 * See ECMAScript 262, 15.4.4.4. | 636 * See ECMAScript 262, 15.4.4.4. |
| 607 * TODO(581): Fix non-compliance for very large concatenations and update to | 637 * TODO(581): Fix non-compliance for very large concatenations and update to |
| 608 * following the ECMAScript 5 specification. | 638 * following the ECMAScript 5 specification. |
| 609 */ | 639 */ |
| 610 RUNTIME_FUNCTION(Runtime_ArrayConcat) { | 640 RUNTIME_FUNCTION(Runtime_ArrayConcat) { |
| 611 HandleScope handle_scope(isolate); | 641 HandleScope handle_scope(isolate); |
| 612 DCHECK(args.length() == 1); | 642 DCHECK(args.length() == 1); |
| 613 | 643 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 uint32_t at_least_space_for = | 794 uint32_t at_least_space_for = |
| 765 estimate_nof_elements + (estimate_nof_elements >> 2); | 795 estimate_nof_elements + (estimate_nof_elements >> 2); |
| 766 storage = Handle<FixedArray>::cast( | 796 storage = Handle<FixedArray>::cast( |
| 767 SeededNumberDictionary::New(isolate, at_least_space_for)); | 797 SeededNumberDictionary::New(isolate, at_least_space_for)); |
| 768 } | 798 } |
| 769 | 799 |
| 770 ArrayConcatVisitor visitor(isolate, storage, fast_case); | 800 ArrayConcatVisitor visitor(isolate, storage, fast_case); |
| 771 | 801 |
| 772 for (int i = 0; i < argument_count; i++) { | 802 for (int i = 0; i < argument_count; i++) { |
| 773 Handle<Object> obj(elements->get(i), isolate); | 803 Handle<Object> obj(elements->get(i), isolate); |
| 774 if (obj->IsJSArray()) { | 804 bool spreadable = IsConcatSpreadable(isolate, obj); |
| 775 Handle<JSArray> array = Handle<JSArray>::cast(obj); | 805 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| 776 if (!IterateElements(isolate, array, &visitor)) { | 806 if (spreadable) { |
| 807 Handle<JSObject> object = Handle<JSObject>::cast(obj); | |
| 808 if (!IterateElements(isolate, object, &visitor)) { | |
| 777 return isolate->heap()->exception(); | 809 return isolate->heap()->exception(); |
| 778 } | 810 } |
| 779 } else { | 811 } else { |
| 780 visitor.visit(0, obj); | 812 visitor.visit(0, obj); |
| 781 visitor.increase_index_offset(1); | 813 visitor.increase_index_offset(1); |
| 782 } | 814 } |
| 783 } | 815 } |
| 784 | 816 |
| 785 if (visitor.exceeds_array_limit()) { | 817 if (visitor.exceeds_array_limit()) { |
| 786 THROW_NEW_ERROR_RETURN_FAILURE( | 818 THROW_NEW_ERROR_RETURN_FAILURE( |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1187 } | 1219 } |
| 1188 | 1220 |
| 1189 | 1221 |
| 1190 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { | 1222 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { |
| 1191 SealHandleScope shs(isolate); | 1223 SealHandleScope shs(isolate); |
| 1192 DCHECK(args.length() == 2); | 1224 DCHECK(args.length() == 2); |
| 1193 return isolate->heap()->undefined_value(); | 1225 return isolate->heap()->undefined_value(); |
| 1194 } | 1226 } |
| 1195 } | 1227 } |
| 1196 } // namespace v8::internal | 1228 } // namespace v8::internal |
| OLD | NEW |