Chromium Code Reviews| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
| 9 #include "src/elements.h" | 9 #include "src/elements.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 ElementsAccessorSubclass::ValidateContents(holder, length); | 578 ElementsAccessorSubclass::ValidateContents(holder, length); |
| 579 } | 579 } |
| 580 | 580 |
| 581 void Validate(Handle<JSObject> holder) final { | 581 void Validate(Handle<JSObject> holder) final { |
| 582 DisallowHeapAllocation no_gc; | 582 DisallowHeapAllocation no_gc; |
| 583 ElementsAccessorSubclass::ValidateImpl(holder); | 583 ElementsAccessorSubclass::ValidateImpl(holder); |
| 584 } | 584 } |
| 585 | 585 |
| 586 static bool HasElementImpl(Handle<JSObject> holder, uint32_t key, | 586 static bool HasElementImpl(Handle<JSObject> holder, uint32_t key, |
| 587 Handle<FixedArrayBase> backing_store) { | 587 Handle<FixedArrayBase> backing_store) { |
| 588 return ElementsAccessorSubclass::GetAttributesImpl(holder, key, | 588 return ElementsAccessorSubclass::GetAttributesImpl( |
| 589 backing_store) != ABSENT; | 589 *holder, key, *backing_store) != ABSENT; |
| 590 } | 590 } |
| 591 | 591 |
| 592 virtual bool HasElement(Handle<JSObject> holder, uint32_t key, | 592 virtual bool HasElement(Handle<JSObject> holder, uint32_t key, |
| 593 Handle<FixedArrayBase> backing_store) final { | 593 Handle<FixedArrayBase> backing_store) final { |
| 594 return ElementsAccessorSubclass::HasElementImpl(holder, key, backing_store); | 594 return ElementsAccessorSubclass::HasElementImpl(holder, key, backing_store); |
| 595 } | 595 } |
| 596 | 596 |
| 597 MUST_USE_RESULT virtual MaybeHandle<Object> Get( | 597 virtual Handle<Object> Get(Handle<Object> receiver, Handle<JSObject> holder, |
| 598 Handle<Object> receiver, Handle<JSObject> holder, uint32_t key, | 598 uint32_t key, |
| 599 Handle<FixedArrayBase> backing_store) final { | 599 Handle<FixedArrayBase> backing_store) final { |
| 600 if (!IsExternalArrayElementsKind(ElementsTraits::Kind) && | 600 if (!IsExternalArrayElementsKind(ElementsTraits::Kind) && |
| 601 FLAG_trace_js_array_abuse) { | 601 FLAG_trace_js_array_abuse) { |
| 602 CheckArrayAbuse(holder, "elements read", key); | 602 CheckArrayAbuse(holder, "elements read", key); |
| 603 } | 603 } |
| 604 | 604 |
| 605 if (IsExternalArrayElementsKind(ElementsTraits::Kind) && | 605 if (IsExternalArrayElementsKind(ElementsTraits::Kind) && |
| 606 FLAG_trace_external_array_abuse) { | 606 FLAG_trace_external_array_abuse) { |
| 607 CheckArrayAbuse(holder, "external elements read", key); | 607 CheckArrayAbuse(holder, "external elements read", key); |
| 608 } | 608 } |
| 609 | 609 |
| 610 return ElementsAccessorSubclass::GetImpl( | 610 return ElementsAccessorSubclass::GetImpl( |
| 611 receiver, holder, key, backing_store); | 611 receiver, holder, key, backing_store); |
| 612 } | 612 } |
| 613 | 613 |
| 614 MUST_USE_RESULT static MaybeHandle<Object> GetImpl( | 614 static Handle<Object> GetImpl(Handle<Object> receiver, Handle<JSObject> obj, |
| 615 Handle<Object> receiver, | 615 uint32_t key, |
| 616 Handle<JSObject> obj, | 616 Handle<FixedArrayBase> backing_store) { |
| 617 uint32_t key, | |
| 618 Handle<FixedArrayBase> backing_store) { | |
| 619 if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { | 617 if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { |
| 620 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); | 618 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); |
| 621 } else { | 619 } else { |
| 622 return backing_store->GetIsolate()->factory()->the_hole_value(); | 620 return backing_store->GetIsolate()->factory()->the_hole_value(); |
| 623 } | 621 } |
| 624 } | 622 } |
| 625 | 623 |
| 626 MUST_USE_RESULT virtual PropertyAttributes GetAttributes( | 624 virtual PropertyAttributes GetAttributes( |
| 627 Handle<JSObject> holder, uint32_t key, | 625 JSObject* holder, uint32_t key, FixedArrayBase* backing_store) final { |
| 628 Handle<FixedArrayBase> backing_store) final { | |
| 629 return ElementsAccessorSubclass::GetAttributesImpl(holder, key, | 626 return ElementsAccessorSubclass::GetAttributesImpl(holder, key, |
| 630 backing_store); | 627 backing_store); |
| 631 } | 628 } |
| 632 | 629 |
| 633 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 630 static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key, |
| 634 Handle<JSObject> obj, | 631 FixedArrayBase* backing_store) { |
| 635 uint32_t key, | 632 if (key >= ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) { |
| 636 Handle<FixedArrayBase> backing_store) { | |
| 637 if (key >= | |
| 638 ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { | |
| 639 return ABSENT; | 633 return ABSENT; |
| 640 } | 634 } |
| 641 return | 635 return BackingStore::cast(backing_store)->is_the_hole(key) ? ABSENT : NONE; |
| 642 Handle<BackingStore>::cast(backing_store)->is_the_hole(key) | |
| 643 ? ABSENT : NONE; | |
| 644 } | 636 } |
| 645 | 637 |
| 646 MUST_USE_RESULT virtual MaybeHandle<AccessorPair> GetAccessorPair( | 638 virtual MaybeHandle<AccessorPair> GetAccessorPair( |
| 647 Handle<JSObject> holder, uint32_t key, | 639 Handle<JSObject> holder, uint32_t key, |
| 648 Handle<FixedArrayBase> backing_store) final { | 640 Handle<FixedArrayBase> backing_store) final { |
| 649 return ElementsAccessorSubclass::GetAccessorPairImpl(holder, key, | 641 return ElementsAccessorSubclass::GetAccessorPairImpl(holder, key, |
| 650 backing_store); | 642 backing_store); |
| 651 } | 643 } |
| 652 | 644 |
| 653 MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl( | 645 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
| 654 Handle<JSObject> obj, | 646 Handle<JSObject> obj, uint32_t key, |
| 655 uint32_t key, | |
| 656 Handle<FixedArrayBase> backing_store) { | 647 Handle<FixedArrayBase> backing_store) { |
| 657 return MaybeHandle<AccessorPair>(); | 648 return MaybeHandle<AccessorPair>(); |
| 658 } | 649 } |
| 659 | 650 |
| 660 MUST_USE_RESULT virtual MaybeHandle<Object> SetLength( | 651 MUST_USE_RESULT virtual MaybeHandle<Object> SetLength( |
| 661 Handle<JSArray> array, Handle<Object> length) final { | 652 Handle<JSArray> array, Handle<Object> length) final { |
| 662 return ElementsAccessorSubclass::SetLengthImpl( | 653 return ElementsAccessorSubclass::SetLengthImpl( |
| 663 array, length, handle(array->elements())); | 654 array, length, handle(array->elements())); |
| 664 } | 655 } |
| 665 | 656 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 727 // intentionally to avoid ArrayConcat() builtin performance degradation. | 718 // intentionally to avoid ArrayConcat() builtin performance degradation. |
| 728 // | 719 // |
| 729 // Details: The idea is that allocations actually happen only in case of | 720 // Details: The idea is that allocations actually happen only in case of |
| 730 // copying from object with fast double elements to object with object | 721 // copying from object with fast double elements to object with object |
| 731 // elements. In all the other cases there are no allocations performed and | 722 // elements. In all the other cases there are no allocations performed and |
| 732 // handle creation causes noticeable performance degradation of the builtin. | 723 // handle creation causes noticeable performance degradation of the builtin. |
| 733 ElementsAccessorSubclass::CopyElementsImpl( | 724 ElementsAccessorSubclass::CopyElementsImpl( |
| 734 from, from_start, *to, from_kind, to_start, packed_size, copy_size); | 725 from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
| 735 } | 726 } |
| 736 | 727 |
| 737 virtual MaybeHandle<FixedArray> AddElementsToFixedArray( | 728 virtual Handle<FixedArray> AddElementsToFixedArray( |
| 738 Handle<JSObject> receiver, Handle<FixedArray> to, | 729 Handle<JSObject> receiver, Handle<FixedArray> to, |
| 739 FixedArray::KeyFilter filter) final { | 730 FixedArray::KeyFilter filter) final { |
| 740 Handle<FixedArrayBase> from(receiver->elements()); | 731 Handle<FixedArrayBase> from(receiver->elements()); |
| 741 | 732 |
| 742 int len0 = to->length(); | 733 int len0 = to->length(); |
| 743 #ifdef ENABLE_SLOW_DCHECKS | 734 #ifdef ENABLE_SLOW_DCHECKS |
| 744 if (FLAG_enable_slow_asserts) { | 735 if (FLAG_enable_slow_asserts) { |
| 745 for (int i = 0; i < len0; i++) { | 736 for (int i = 0; i < len0; i++) { |
| 746 DCHECK(!to->get(i)->IsTheHole()); | 737 DCHECK(!to->get(i)->IsTheHole()); |
| 747 } | 738 } |
| 748 } | 739 } |
| 749 #endif | 740 #endif |
| 750 | 741 |
| 751 // Optimize if 'other' is empty. | 742 // Optimize if 'other' is empty. |
| 752 // We cannot optimize if 'this' is empty, as other may have holes. | 743 // We cannot optimize if 'this' is empty, as other may have holes. |
| 753 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); | 744 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); |
| 754 if (len1 == 0) return to; | 745 if (len1 == 0) return to; |
| 755 | 746 |
| 756 Isolate* isolate = from->GetIsolate(); | 747 Isolate* isolate = from->GetIsolate(); |
| 757 | 748 |
| 758 // Compute how many elements are not in other. | 749 // Compute how many elements are not in other. |
| 759 uint32_t extra = 0; | 750 uint32_t extra = 0; |
| 760 for (uint32_t y = 0; y < len1; y++) { | 751 for (uint32_t y = 0; y < len1; y++) { |
| 761 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); | 752 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); |
| 762 if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { | 753 if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { |
| 763 Handle<Object> value; | 754 Handle<Object> value = |
| 764 ASSIGN_RETURN_ON_EXCEPTION( | 755 ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from); |
| 765 isolate, value, | |
| 766 ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from), | |
| 767 FixedArray); | |
| 768 | 756 |
| 769 DCHECK(!value->IsTheHole()); | 757 DCHECK(!value->IsTheHole()); |
| 758 DCHECK(!value->IsAccessorPair()); | |
| 759 DCHECK(!value->IsExecutableAccessorInfo()); | |
| 770 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 760 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
| 771 continue; | 761 continue; |
| 772 } | 762 } |
| 773 if (!HasKey(to, value)) { | 763 if (!HasKey(to, value)) { |
| 774 extra++; | 764 extra++; |
| 775 } | 765 } |
| 776 } | 766 } |
| 777 } | 767 } |
| 778 | 768 |
| 779 if (extra == 0) return to; | 769 if (extra == 0) return to; |
| 780 | 770 |
| 781 // Allocate the result | 771 // Allocate the result |
| 782 Handle<FixedArray> result = isolate->factory()->NewFixedArray(len0 + extra); | 772 Handle<FixedArray> result = isolate->factory()->NewFixedArray(len0 + extra); |
| 783 | 773 |
| 784 // Fill in the content | 774 // Fill in the content |
| 785 { | 775 { |
| 786 DisallowHeapAllocation no_gc; | 776 DisallowHeapAllocation no_gc; |
| 787 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 777 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 788 for (int i = 0; i < len0; i++) { | 778 for (int i = 0; i < len0; i++) { |
| 789 Object* e = to->get(i); | 779 Object* e = to->get(i); |
| 790 DCHECK(e->IsString() || e->IsNumber()); | 780 DCHECK(e->IsString() || e->IsNumber()); |
| 791 result->set(i, e, mode); | 781 result->set(i, e, mode); |
| 792 } | 782 } |
| 793 } | 783 } |
| 794 // Fill in the extra values. | 784 // Fill in the extra values. |
| 795 uint32_t index = 0; | 785 uint32_t index = 0; |
| 796 for (uint32_t y = 0; y < len1; y++) { | 786 for (uint32_t y = 0; y < len1; y++) { |
| 797 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); | 787 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); |
| 798 if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { | 788 if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { |
| 799 Handle<Object> value; | 789 Handle<Object> value = |
| 800 ASSIGN_RETURN_ON_EXCEPTION( | 790 ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from); |
| 801 isolate, value, | 791 DCHECK(!value->IsAccessorPair()); |
| 802 ElementsAccessorSubclass::GetImpl(receiver, receiver, key, from), | 792 DCHECK(!value->IsExecutableAccessorInfo()); |
| 803 FixedArray); | |
| 804 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 793 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
| 805 continue; | 794 continue; |
| 806 } | 795 } |
| 807 if (!value->IsTheHole() && !HasKey(to, value)) { | 796 if (!value->IsTheHole() && !HasKey(to, value)) { |
| 808 result->set(len0 + index, *value); | 797 result->set(len0 + index, *value); |
| 809 index++; | 798 index++; |
| 810 } | 799 } |
| 811 } | 800 } |
| 812 } | 801 } |
| 813 DCHECK(extra == index); | 802 DCHECK(extra == index); |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1267 : ElementsAccessorBase<AccessorClass, | 1256 : ElementsAccessorBase<AccessorClass, |
| 1268 ElementsKindTraits<Kind> >(name) {} | 1257 ElementsKindTraits<Kind> >(name) {} |
| 1269 | 1258 |
| 1270 protected: | 1259 protected: |
| 1271 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1260 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 1272 typedef TypedElementsAccessor<Kind> AccessorClass; | 1261 typedef TypedElementsAccessor<Kind> AccessorClass; |
| 1273 | 1262 |
| 1274 friend class ElementsAccessorBase<AccessorClass, | 1263 friend class ElementsAccessorBase<AccessorClass, |
| 1275 ElementsKindTraits<Kind> >; | 1264 ElementsKindTraits<Kind> >; |
| 1276 | 1265 |
| 1277 MUST_USE_RESULT static MaybeHandle<Object> GetImpl( | 1266 static Handle<Object> GetImpl(Handle<Object> receiver, Handle<JSObject> obj, |
| 1278 Handle<Object> receiver, | 1267 uint32_t key, |
| 1279 Handle<JSObject> obj, | 1268 Handle<FixedArrayBase> backing_store) { |
| 1280 uint32_t key, | |
| 1281 Handle<FixedArrayBase> backing_store) { | |
| 1282 if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { | 1269 if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { |
| 1283 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); | 1270 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); |
| 1284 } else { | 1271 } else { |
| 1285 return backing_store->GetIsolate()->factory()->undefined_value(); | 1272 return backing_store->GetIsolate()->factory()->undefined_value(); |
| 1286 } | 1273 } |
| 1287 } | 1274 } |
| 1288 | 1275 |
| 1289 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 1276 static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key, |
| 1290 Handle<JSObject> obj, | 1277 FixedArrayBase* backing_store) { |
| 1291 uint32_t key, | 1278 return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE |
| 1292 Handle<FixedArrayBase> backing_store) { | 1279 : ABSENT; |
| 1293 return key < AccessorClass::GetCapacityImpl(*obj, *backing_store) ? NONE | |
| 1294 : ABSENT; | |
| 1295 } | 1280 } |
| 1296 | 1281 |
| 1297 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1282 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( |
| 1298 Handle<JSObject> obj, | 1283 Handle<JSObject> obj, |
| 1299 Handle<Object> length, | 1284 Handle<Object> length, |
| 1300 Handle<FixedArrayBase> backing_store) { | 1285 Handle<FixedArrayBase> backing_store) { |
| 1301 // External arrays do not support changing their length. | 1286 // External arrays do not support changing their length. |
| 1302 UNREACHABLE(); | 1287 UNREACHABLE(); |
| 1303 return obj; | 1288 return obj; |
| 1304 } | 1289 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1455 | 1440 |
| 1456 protected: | 1441 protected: |
| 1457 friend class ElementsAccessorBase<DictionaryElementsAccessor, | 1442 friend class ElementsAccessorBase<DictionaryElementsAccessor, |
| 1458 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | 1443 ElementsKindTraits<DICTIONARY_ELEMENTS> >; |
| 1459 | 1444 |
| 1460 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 1445 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( |
| 1461 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { | 1446 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { |
| 1462 return DeleteCommon(obj, key, language_mode); | 1447 return DeleteCommon(obj, key, language_mode); |
| 1463 } | 1448 } |
| 1464 | 1449 |
| 1465 MUST_USE_RESULT static MaybeHandle<Object> GetImpl( | 1450 static Handle<Object> GetImpl(Handle<Object> receiver, Handle<JSObject> obj, |
| 1466 Handle<Object> receiver, | 1451 uint32_t key, Handle<FixedArrayBase> store) { |
| 1467 Handle<JSObject> obj, | |
| 1468 uint32_t key, | |
| 1469 Handle<FixedArrayBase> store) { | |
| 1470 Handle<SeededNumberDictionary> backing_store = | 1452 Handle<SeededNumberDictionary> backing_store = |
| 1471 Handle<SeededNumberDictionary>::cast(store); | 1453 Handle<SeededNumberDictionary>::cast(store); |
| 1472 Isolate* isolate = backing_store->GetIsolate(); | 1454 Isolate* isolate = backing_store->GetIsolate(); |
| 1473 int entry = backing_store->FindEntry(key); | 1455 int entry = backing_store->FindEntry(key); |
| 1474 if (entry != SeededNumberDictionary::kNotFound) { | 1456 if (entry != SeededNumberDictionary::kNotFound) { |
| 1475 Handle<Object> element(backing_store->ValueAt(entry), isolate); | 1457 return handle(backing_store->ValueAt(entry), isolate); |
| 1476 PropertyDetails details = backing_store->DetailsAt(entry); | |
| 1477 if (details.type() == ACCESSOR_CONSTANT) { | |
| 1478 return JSObject::GetElementWithCallback( | |
| 1479 obj, receiver, element, key, obj); | |
| 1480 } else { | |
| 1481 return element; | |
| 1482 } | |
| 1483 } | 1458 } |
| 1484 return isolate->factory()->the_hole_value(); | 1459 return isolate->factory()->the_hole_value(); |
| 1485 } | 1460 } |
| 1486 | 1461 |
| 1487 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 1462 static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key, |
| 1488 Handle<JSObject> obj, | 1463 FixedArrayBase* backing_store) { |
| 1489 uint32_t key, | 1464 SeededNumberDictionary* dictionary = |
| 1490 Handle<FixedArrayBase> backing_store) { | 1465 SeededNumberDictionary::cast(backing_store); |
| 1491 Handle<SeededNumberDictionary> dictionary = | |
| 1492 Handle<SeededNumberDictionary>::cast(backing_store); | |
| 1493 int entry = dictionary->FindEntry(key); | 1466 int entry = dictionary->FindEntry(key); |
| 1494 if (entry != SeededNumberDictionary::kNotFound) { | 1467 if (entry != SeededNumberDictionary::kNotFound) { |
| 1495 return dictionary->DetailsAt(entry).attributes(); | 1468 return dictionary->DetailsAt(entry).attributes(); |
| 1496 } | 1469 } |
| 1497 return ABSENT; | 1470 return ABSENT; |
| 1498 } | 1471 } |
| 1499 | 1472 |
| 1500 MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl( | 1473 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
| 1501 Handle<JSObject> obj, | 1474 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) { |
| 1502 uint32_t key, | |
| 1503 Handle<FixedArrayBase> store) { | |
| 1504 Handle<SeededNumberDictionary> backing_store = | 1475 Handle<SeededNumberDictionary> backing_store = |
| 1505 Handle<SeededNumberDictionary>::cast(store); | 1476 Handle<SeededNumberDictionary>::cast(store); |
| 1506 int entry = backing_store->FindEntry(key); | 1477 int entry = backing_store->FindEntry(key); |
| 1507 if (entry != SeededNumberDictionary::kNotFound && | 1478 if (entry != SeededNumberDictionary::kNotFound && |
| 1508 backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT && | 1479 backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT && |
| 1509 backing_store->ValueAt(entry)->IsAccessorPair()) { | 1480 backing_store->ValueAt(entry)->IsAccessorPair()) { |
| 1510 return handle(AccessorPair::cast(backing_store->ValueAt(entry))); | 1481 return handle(AccessorPair::cast(backing_store->ValueAt(entry))); |
| 1511 } | 1482 } |
| 1512 return MaybeHandle<AccessorPair>(); | 1483 return MaybeHandle<AccessorPair>(); |
| 1513 } | 1484 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1549 public: | 1520 public: |
| 1550 explicit SloppyArgumentsElementsAccessor(const char* name) | 1521 explicit SloppyArgumentsElementsAccessor(const char* name) |
| 1551 : ElementsAccessorBase< | 1522 : ElementsAccessorBase< |
| 1552 SloppyArgumentsElementsAccessor, | 1523 SloppyArgumentsElementsAccessor, |
| 1553 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1524 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1554 protected: | 1525 protected: |
| 1555 friend class ElementsAccessorBase< | 1526 friend class ElementsAccessorBase< |
| 1556 SloppyArgumentsElementsAccessor, | 1527 SloppyArgumentsElementsAccessor, |
| 1557 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >; | 1528 ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >; |
| 1558 | 1529 |
| 1559 MUST_USE_RESULT static MaybeHandle<Object> GetImpl( | 1530 static Handle<Object> GetImpl(Handle<Object> receiver, Handle<JSObject> obj, |
| 1560 Handle<Object> receiver, | 1531 uint32_t key, |
| 1561 Handle<JSObject> obj, | 1532 Handle<FixedArrayBase> parameters) { |
| 1562 uint32_t key, | |
| 1563 Handle<FixedArrayBase> parameters) { | |
| 1564 Isolate* isolate = obj->GetIsolate(); | 1533 Isolate* isolate = obj->GetIsolate(); |
| 1565 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1534 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
| 1566 Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key); | 1535 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
| 1567 if (!probe->IsTheHole()) { | 1536 if (!probe->IsTheHole()) { |
| 1568 DisallowHeapAllocation no_gc; | 1537 DisallowHeapAllocation no_gc; |
| 1569 Context* context = Context::cast(parameter_map->get(0)); | 1538 Context* context = Context::cast(parameter_map->get(0)); |
| 1570 int context_index = Handle<Smi>::cast(probe)->value(); | 1539 int context_index = Handle<Smi>::cast(probe)->value(); |
| 1571 DCHECK(!context->get(context_index)->IsTheHole()); | 1540 DCHECK(!context->get(context_index)->IsTheHole()); |
| 1572 return handle(context->get(context_index), isolate); | 1541 return handle(context->get(context_index), isolate); |
| 1573 } else { | 1542 } else { |
| 1574 // Object is not mapped, defer to the arguments. | 1543 // Object is not mapped, defer to the arguments. |
| 1575 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), | 1544 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), |
| 1576 isolate); | 1545 isolate); |
| 1577 Handle<Object> result; | 1546 Handle<Object> result = ElementsAccessor::ForArray(arguments) |
| 1578 ASSIGN_RETURN_ON_EXCEPTION( | 1547 ->Get(receiver, obj, key, arguments); |
| 1579 isolate, result, | |
| 1580 ElementsAccessor::ForArray(arguments)->Get( | |
| 1581 receiver, obj, key, arguments), | |
| 1582 Object); | |
| 1583 // Elements of the arguments object in slow mode might be slow aliases. | 1548 // Elements of the arguments object in slow mode might be slow aliases. |
| 1584 if (result->IsAliasedArgumentsEntry()) { | 1549 if (result->IsAliasedArgumentsEntry()) { |
| 1585 DisallowHeapAllocation no_gc; | 1550 DisallowHeapAllocation no_gc; |
| 1586 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); | 1551 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); |
| 1587 Context* context = Context::cast(parameter_map->get(0)); | 1552 Context* context = Context::cast(parameter_map->get(0)); |
| 1588 int context_index = entry->aliased_context_slot(); | 1553 int context_index = entry->aliased_context_slot(); |
| 1589 DCHECK(!context->get(context_index)->IsTheHole()); | 1554 DCHECK(!context->get(context_index)->IsTheHole()); |
| 1590 return handle(context->get(context_index), isolate); | 1555 return handle(context->get(context_index), isolate); |
| 1591 } else { | 1556 } else { |
| 1592 return result; | 1557 return result; |
| 1593 } | 1558 } |
| 1594 } | 1559 } |
| 1595 } | 1560 } |
| 1596 | 1561 |
| 1597 MUST_USE_RESULT static PropertyAttributes GetAttributesImpl( | 1562 static PropertyAttributes GetAttributesImpl(JSObject* obj, uint32_t key, |
| 1598 Handle<JSObject> obj, | 1563 FixedArrayBase* backing_store) { |
| 1599 uint32_t key, | 1564 FixedArray* parameter_map = FixedArray::cast(backing_store); |
| 1600 Handle<FixedArrayBase> backing_store) { | 1565 Object* probe = GetParameterMapArg(parameter_map, key); |
| 1601 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(backing_store); | |
| 1602 Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key); | |
| 1603 if (!probe->IsTheHole()) { | 1566 if (!probe->IsTheHole()) { |
| 1604 return NONE; | 1567 return NONE; |
| 1605 } else { | 1568 } else { |
| 1606 // If not aliased, check the arguments. | 1569 // If not aliased, check the arguments. |
| 1607 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1570 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1608 return ElementsAccessor::ForArray(arguments) | 1571 return ElementsAccessor::ForArray(arguments) |
| 1609 ->GetAttributes(obj, key, arguments); | 1572 ->GetAttributes(obj, key, arguments); |
| 1610 } | 1573 } |
| 1611 } | 1574 } |
| 1612 | 1575 |
| 1613 MUST_USE_RESULT static MaybeHandle<AccessorPair> GetAccessorPairImpl( | 1576 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
| 1614 Handle<JSObject> obj, | 1577 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) { |
| 1615 uint32_t key, | |
| 1616 Handle<FixedArrayBase> parameters) { | |
| 1617 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1578 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
| 1618 Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key); | 1579 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), |
| 1580 obj->GetIsolate()); | |
| 1619 if (!probe->IsTheHole()) { | 1581 if (!probe->IsTheHole()) { |
| 1620 return MaybeHandle<AccessorPair>(); | 1582 return MaybeHandle<AccessorPair>(); |
| 1621 } else { | 1583 } else { |
| 1622 // If not aliased, check the arguments. | 1584 // If not aliased, check the arguments. |
| 1623 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1585 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
| 1624 return ElementsAccessor::ForArray(arguments) | 1586 return ElementsAccessor::ForArray(arguments) |
| 1625 ->GetAccessorPair(obj, key, arguments); | 1587 ->GetAccessorPair(obj, key, arguments); |
| 1626 } | 1588 } |
| 1627 } | 1589 } |
| 1628 | 1590 |
| 1629 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( | 1591 MUST_USE_RESULT static MaybeHandle<Object> SetLengthImpl( |
| 1630 Handle<JSObject> obj, | 1592 Handle<JSObject> obj, |
| 1631 Handle<Object> length, | 1593 Handle<Object> length, |
| 1632 Handle<FixedArrayBase> parameter_map) { | 1594 Handle<FixedArrayBase> parameter_map) { |
| 1633 // TODO(mstarzinger): This was never implemented but will be used once we | 1595 // TODO(mstarzinger): This was never implemented but will be used once we |
| 1634 // correctly implement [[DefineOwnProperty]] on arrays. | 1596 // correctly implement [[DefineOwnProperty]] on arrays. |
| 1635 UNIMPLEMENTED(); | 1597 UNIMPLEMENTED(); |
| 1636 return obj; | 1598 return obj; |
| 1637 } | 1599 } |
| 1638 | 1600 |
| 1639 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( | 1601 MUST_USE_RESULT virtual MaybeHandle<Object> Delete( |
| 1640 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { | 1602 Handle<JSObject> obj, uint32_t key, LanguageMode language_mode) final { |
| 1641 Isolate* isolate = obj->GetIsolate(); | 1603 Isolate* isolate = obj->GetIsolate(); |
| 1642 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); | 1604 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); |
| 1643 Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key); | 1605 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
| 1644 if (!probe->IsTheHole()) { | 1606 if (!probe->IsTheHole()) { |
| 1645 // TODO(kmillikin): We could check if this was the last aliased | 1607 // TODO(kmillikin): We could check if this was the last aliased |
| 1646 // parameter, and revert to normal elements in that case. That | 1608 // parameter, and revert to normal elements in that case. That |
| 1647 // would enable GC of the context. | 1609 // would enable GC of the context. |
| 1648 parameter_map->set_the_hole(key + 2); | 1610 parameter_map->set_the_hole(key + 2); |
| 1649 } else { | 1611 } else { |
| 1650 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1612 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
| 1651 if (arguments->IsDictionary()) { | 1613 if (arguments->IsDictionary()) { |
| 1652 return DictionaryElementsAccessor::DeleteCommon(obj, key, | 1614 return DictionaryElementsAccessor::DeleteCommon(obj, key, |
| 1653 language_mode); | 1615 language_mode); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1671 | 1633 |
| 1672 static uint32_t GetCapacityImpl(JSObject* holder, | 1634 static uint32_t GetCapacityImpl(JSObject* holder, |
| 1673 FixedArrayBase* backing_store) { | 1635 FixedArrayBase* backing_store) { |
| 1674 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1636 FixedArray* parameter_map = FixedArray::cast(backing_store); |
| 1675 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1637 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 1676 return Max(static_cast<uint32_t>(parameter_map->length() - 2), | 1638 return Max(static_cast<uint32_t>(parameter_map->length() - 2), |
| 1677 ForArray(arguments)->GetCapacity(holder, arguments)); | 1639 ForArray(arguments)->GetCapacity(holder, arguments)); |
| 1678 } | 1640 } |
| 1679 | 1641 |
| 1680 static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, uint32_t index) { | 1642 static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, uint32_t index) { |
| 1681 return index; | 1643 return index; |
|
Igor Sheludko
2015/05/26 17:11:56
I think we should not break this invariant:
DCHECK
| |
| 1682 } | 1644 } |
| 1683 | 1645 |
| 1684 static uint32_t GetIndexForKeyImpl(FixedArrayBase* dict, uint32_t key) { | 1646 static uint32_t GetIndexForKeyImpl(FixedArrayBase* parameters, uint32_t key) { |
| 1685 return key; | 1647 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1648 Object* probe = GetParameterMapArg(parameter_map, key); | |
| 1649 if (!probe->IsTheHole()) { | |
| 1650 return key; | |
| 1651 } else { | |
| 1652 uint32_t length = parameter_map->length(); | |
| 1653 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 1654 return length + | |
| 1655 ElementsAccessor::ForArray(arguments) | |
| 1656 ->GetIndexForKey(arguments, key); | |
| 1657 } | |
| 1686 } | 1658 } |
| 1687 | 1659 |
| 1688 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1660 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
| 1689 uint32_t index) { | 1661 uint32_t index) { |
| 1690 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1662 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1663 uint32_t length = parameter_map->length(); | |
| 1664 if (index < length) { | |
| 1665 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | |
| 1666 } | |
| 1667 index -= length; | |
| 1668 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 1669 return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index); | |
| 1691 } | 1670 } |
| 1692 | 1671 |
| 1693 | |
| 1694 private: | 1672 private: |
| 1695 static Handle<Object> GetParameterMapArg(Handle<JSObject> holder, | 1673 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { |
| 1696 Handle<FixedArray> parameter_map, | 1674 uint32_t length = parameter_map->length(); |
| 1697 uint32_t key) { | |
| 1698 Isolate* isolate = holder->GetIsolate(); | |
| 1699 uint32_t length = holder->IsJSArray() | |
| 1700 ? Smi::cast(Handle<JSArray>::cast(holder)->length())->value() | |
| 1701 : parameter_map->length(); | |
| 1702 return key < (length - 2) | 1675 return key < (length - 2) |
| 1703 ? handle(parameter_map->get(key + 2), isolate) | 1676 ? parameter_map->get(key + 2) |
| 1704 : Handle<Object>::cast(isolate->factory()->the_hole_value()); | 1677 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
| 1705 } | 1678 } |
| 1706 }; | 1679 }; |
| 1707 | 1680 |
| 1708 | 1681 |
| 1709 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { | 1682 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { |
| 1710 return elements_accessors_[ElementsKindForArray(array)]; | 1683 return elements_accessors_[ElementsKindForArray(array)]; |
| 1711 } | 1684 } |
| 1712 | 1685 |
| 1713 | 1686 |
| 1714 ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) { | 1687 ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1775 } | 1748 } |
| 1776 } else { | 1749 } else { |
| 1777 return ThrowArrayLengthRangeError(isolate); | 1750 return ThrowArrayLengthRangeError(isolate); |
| 1778 } | 1751 } |
| 1779 } | 1752 } |
| 1780 | 1753 |
| 1781 // Slow case: The new length does not fit into a Smi or conversion | 1754 // Slow case: The new length does not fit into a Smi or conversion |
| 1782 // to slow elements is needed for other reasons. | 1755 // to slow elements is needed for other reasons. |
| 1783 if (length->IsNumber()) { | 1756 if (length->IsNumber()) { |
| 1784 uint32_t value; | 1757 uint32_t value; |
| 1785 if (length->ToArrayIndex(&value)) { | 1758 if (length->ToArrayLength(&value)) { |
| 1786 Handle<SeededNumberDictionary> dictionary = | 1759 Handle<SeededNumberDictionary> dictionary = |
| 1787 JSObject::NormalizeElements(array); | 1760 JSObject::NormalizeElements(array); |
| 1788 DCHECK(!dictionary.is_null()); | 1761 DCHECK(!dictionary.is_null()); |
| 1789 | 1762 |
| 1790 Handle<Object> new_length = DictionaryElementsAccessor:: | 1763 Handle<Object> new_length = DictionaryElementsAccessor:: |
| 1791 SetLengthWithoutNormalize(dictionary, array, length, value); | 1764 SetLengthWithoutNormalize(dictionary, array, length, value); |
| 1792 DCHECK(!new_length.is_null()); | 1765 DCHECK(!new_length.is_null()); |
| 1793 | 1766 |
| 1794 DCHECK(new_length->IsNumber()); | 1767 DCHECK(new_length->IsNumber()); |
| 1795 array->set_length(*new_length); | 1768 array->set_length(*new_length); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1894 UNREACHABLE(); | 1867 UNREACHABLE(); |
| 1895 break; | 1868 break; |
| 1896 } | 1869 } |
| 1897 | 1870 |
| 1898 array->set_elements(*elms); | 1871 array->set_elements(*elms); |
| 1899 array->set_length(Smi::FromInt(number_of_elements)); | 1872 array->set_length(Smi::FromInt(number_of_elements)); |
| 1900 return array; | 1873 return array; |
| 1901 } | 1874 } |
| 1902 | 1875 |
| 1903 } } // namespace v8::internal | 1876 } } // namespace v8::internal |
| OLD | NEW |