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 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 Handle<FixedArrayBase> backing_store) { | 567 Handle<FixedArrayBase> backing_store) { |
568 if (index < | 568 if (index < |
569 ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { | 569 ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { |
570 return BackingStore::get(Handle<BackingStore>::cast(backing_store), | 570 return BackingStore::get(Handle<BackingStore>::cast(backing_store), |
571 index); | 571 index); |
572 } else { | 572 } else { |
573 return backing_store->GetIsolate()->factory()->the_hole_value(); | 573 return backing_store->GetIsolate()->factory()->the_hole_value(); |
574 } | 574 } |
575 } | 575 } |
576 | 576 |
577 virtual void Set(FixedArrayBase* backing_store, uint32_t index, | 577 virtual void Set(FixedArrayBase* backing_store, uint32_t entry, |
578 Object* value) final { | 578 Object* value) final { |
579 ElementsAccessorSubclass::SetImpl(backing_store, index, value); | 579 ElementsAccessorSubclass::SetImpl(backing_store, entry, value); |
580 } | 580 } |
581 | 581 |
582 static void SetImpl(FixedArrayBase* backing_store, uint32_t index, | 582 static void SetImpl(FixedArrayBase* backing_store, uint32_t entry, |
583 Object* value) { | 583 Object* value) { |
584 BackingStore::cast(backing_store)->SetValue(index, value); | 584 BackingStore::cast(backing_store)->SetValue(entry, value); |
585 } | 585 } |
586 | 586 |
587 virtual void Reconfigure(Handle<JSObject> object, | 587 virtual void Reconfigure(Handle<JSObject> object, |
588 Handle<FixedArrayBase> store, uint32_t entry, | 588 Handle<FixedArrayBase> store, uint32_t entry, |
589 Handle<Object> value, | 589 Handle<Object> value, |
590 PropertyAttributes attributes) final { | 590 PropertyAttributes attributes) final { |
591 ElementsAccessorSubclass::ReconfigureImpl(object, store, entry, value, | 591 ElementsAccessorSubclass::ReconfigureImpl(object, store, entry, value, |
592 attributes); | 592 attributes); |
593 } | 593 } |
594 | 594 |
595 static void ReconfigureImpl(Handle<JSObject> object, | 595 static void ReconfigureImpl(Handle<JSObject> object, |
596 Handle<FixedArrayBase> store, uint32_t entry, | 596 Handle<FixedArrayBase> store, uint32_t entry, |
597 Handle<Object> value, | 597 Handle<Object> value, |
598 PropertyAttributes attributes) { | 598 PropertyAttributes attributes) { |
599 UNREACHABLE(); | 599 UNREACHABLE(); |
600 } | 600 } |
601 | 601 |
602 virtual void Add(Handle<JSObject> object, uint32_t entry, | 602 virtual void Add(Handle<JSObject> object, uint32_t index, |
603 Handle<Object> value, PropertyAttributes attributes, | 603 Handle<Object> value, PropertyAttributes attributes, |
604 uint32_t new_capacity) final { | 604 uint32_t new_capacity) final { |
605 ElementsAccessorSubclass::AddImpl(object, entry, value, attributes, | 605 ElementsAccessorSubclass::AddImpl(object, index, value, attributes, |
606 new_capacity); | 606 new_capacity); |
607 } | 607 } |
608 | 608 |
609 static void AddImpl(Handle<JSObject> object, uint32_t entry, | 609 static void AddImpl(Handle<JSObject> object, uint32_t index, |
610 Handle<Object> value, PropertyAttributes attributes, | 610 Handle<Object> value, PropertyAttributes attributes, |
611 uint32_t new_capacity) { | 611 uint32_t new_capacity) { |
612 UNREACHABLE(); | 612 UNREACHABLE(); |
613 } | 613 } |
614 | 614 |
615 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { | 615 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
616 ElementsAccessorSubclass::SetLengthImpl(array, length, | 616 ElementsAccessorSubclass::SetLengthImpl(array, length, |
617 handle(array->elements())); | 617 handle(array->elements())); |
618 } | 618 } |
619 | 619 |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 Handle<SeededNumberDictionary> backing_store = | 950 Handle<SeededNumberDictionary> backing_store = |
951 Handle<SeededNumberDictionary>::cast(store); | 951 Handle<SeededNumberDictionary>::cast(store); |
952 Isolate* isolate = backing_store->GetIsolate(); | 952 Isolate* isolate = backing_store->GetIsolate(); |
953 int entry = backing_store->FindEntry(index); | 953 int entry = backing_store->FindEntry(index); |
954 if (entry != SeededNumberDictionary::kNotFound) { | 954 if (entry != SeededNumberDictionary::kNotFound) { |
955 return handle(backing_store->ValueAt(entry), isolate); | 955 return handle(backing_store->ValueAt(entry), isolate); |
956 } | 956 } |
957 return isolate->factory()->the_hole_value(); | 957 return isolate->factory()->the_hole_value(); |
958 } | 958 } |
959 | 959 |
960 static void SetImpl(FixedArrayBase* store, uint32_t index, Object* value) { | 960 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { |
961 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); | 961 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
962 int entry = dictionary->FindEntry(index); | |
963 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); | |
964 dictionary->ValueAtPut(entry, value); | 962 dictionary->ValueAtPut(entry, value); |
965 } | 963 } |
966 | 964 |
967 static void ReconfigureImpl(Handle<JSObject> object, | 965 static void ReconfigureImpl(Handle<JSObject> object, |
968 Handle<FixedArrayBase> store, uint32_t entry, | 966 Handle<FixedArrayBase> store, uint32_t entry, |
969 Handle<Object> value, | 967 Handle<Object> value, |
970 PropertyAttributes attributes) { | 968 PropertyAttributes attributes) { |
971 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); | 969 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); |
972 if (attributes != NONE) dictionary->set_requires_slow_elements(); | 970 if (attributes != NONE) dictionary->set_requires_slow_elements(); |
973 dictionary->ValueAtPut(entry, *value); | 971 dictionary->ValueAtPut(entry, *value); |
974 PropertyDetails details = dictionary->DetailsAt(entry); | 972 PropertyDetails details = dictionary->DetailsAt(entry); |
975 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | 973 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
976 PropertyCellType::kNoCell); | 974 PropertyCellType::kNoCell); |
977 dictionary->DetailsAtPut(entry, details); | 975 dictionary->DetailsAtPut(entry, details); |
978 } | 976 } |
979 | 977 |
980 static void AddImpl(Handle<JSObject> object, uint32_t entry, | 978 static void AddImpl(Handle<JSObject> object, uint32_t index, |
981 Handle<Object> value, PropertyAttributes attributes, | 979 Handle<Object> value, PropertyAttributes attributes, |
982 uint32_t new_capacity) { | 980 uint32_t new_capacity) { |
983 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 981 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
984 Handle<SeededNumberDictionary> dictionary = | 982 Handle<SeededNumberDictionary> dictionary = |
985 object->HasFastElements() | 983 object->HasFastElements() |
986 ? JSObject::NormalizeElements(object) | 984 ? JSObject::NormalizeElements(object) |
987 : handle(SeededNumberDictionary::cast(object->elements())); | 985 : handle(SeededNumberDictionary::cast(object->elements())); |
988 Handle<SeededNumberDictionary> new_dictionary = | 986 Handle<SeededNumberDictionary> new_dictionary = |
989 SeededNumberDictionary::AddNumberEntry(dictionary, entry, value, | 987 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
990 details); | 988 details); |
991 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | 989 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
992 if (dictionary.is_identical_to(new_dictionary)) return; | 990 if (dictionary.is_identical_to(new_dictionary)) return; |
993 object->set_elements(*new_dictionary); | 991 object->set_elements(*new_dictionary); |
994 } | 992 } |
995 | 993 |
996 static bool HasEntryImpl(FixedArrayBase* store, uint32_t entry) { | 994 static bool HasEntryImpl(FixedArrayBase* store, uint32_t entry) { |
997 DisallowHeapAllocation no_gc; | 995 DisallowHeapAllocation no_gc; |
998 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 996 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
999 Object* index = dict->KeyAt(entry); | 997 Object* index = dict->KeyAt(entry); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 Handle<FixedArrayBase> store, uint32_t entry, | 1112 Handle<FixedArrayBase> store, uint32_t entry, |
1115 Handle<Object> value, | 1113 Handle<Object> value, |
1116 PropertyAttributes attributes) { | 1114 PropertyAttributes attributes) { |
1117 Handle<SeededNumberDictionary> dictionary = | 1115 Handle<SeededNumberDictionary> dictionary = |
1118 JSObject::NormalizeElements(object); | 1116 JSObject::NormalizeElements(object); |
1119 entry = dictionary->FindEntry(entry); | 1117 entry = dictionary->FindEntry(entry); |
1120 DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, entry, | 1118 DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, entry, |
1121 value, attributes); | 1119 value, attributes); |
1122 } | 1120 } |
1123 | 1121 |
1124 static void AddImpl(Handle<JSObject> object, uint32_t entry, | 1122 static void AddImpl(Handle<JSObject> object, uint32_t index, |
1125 Handle<Object> value, PropertyAttributes attributes, | 1123 Handle<Object> value, PropertyAttributes attributes, |
1126 uint32_t new_capacity) { | 1124 uint32_t new_capacity) { |
1127 DCHECK_EQ(NONE, attributes); | 1125 DCHECK_EQ(NONE, attributes); |
1128 ElementsKind from_kind = object->GetElementsKind(); | 1126 ElementsKind from_kind = object->GetElementsKind(); |
1129 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); | 1127 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); |
1130 if (IsDictionaryElementsKind(from_kind) || | 1128 if (IsDictionaryElementsKind(from_kind) || |
1131 IsFastDoubleElementsKind(from_kind) != | 1129 IsFastDoubleElementsKind(from_kind) != |
1132 IsFastDoubleElementsKind(to_kind) || | 1130 IsFastDoubleElementsKind(to_kind) || |
1133 FastElementsAccessorSubclass::GetCapacityImpl( | 1131 FastElementsAccessorSubclass::GetCapacityImpl( |
1134 *object, object->elements()) != new_capacity) { | 1132 *object, object->elements()) != new_capacity) { |
1135 FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, | 1133 FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, |
1136 new_capacity); | 1134 new_capacity); |
1137 } else { | 1135 } else { |
1138 if (from_kind != to_kind) { | 1136 if (from_kind != to_kind) { |
1139 JSObject::TransitionElementsKind(object, to_kind); | 1137 JSObject::TransitionElementsKind(object, to_kind); |
1140 } | 1138 } |
1141 if (IsFastSmiOrObjectElementsKind(from_kind)) { | 1139 if (IsFastSmiOrObjectElementsKind(from_kind)) { |
1142 DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); | 1140 DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); |
1143 JSObject::EnsureWritableFastElements(object); | 1141 JSObject::EnsureWritableFastElements(object); |
1144 } | 1142 } |
1145 } | 1143 } |
1146 FastElementsAccessorSubclass::SetImpl(object->elements(), entry, *value); | 1144 FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value); |
1147 } | 1145 } |
1148 | 1146 |
1149 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { | 1147 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
1150 ElementsKind kind = KindTraits::Kind; | 1148 ElementsKind kind = KindTraits::Kind; |
1151 if (IsFastPackedElementsKind(kind)) { | 1149 if (IsFastPackedElementsKind(kind)) { |
1152 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); | 1150 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); |
1153 } | 1151 } |
1154 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | 1152 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { |
1155 JSObject::EnsureWritableFastElements(obj); | 1153 JSObject::EnsureWritableFastElements(obj); |
1156 } | 1154 } |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1471 return result; | 1469 return result; |
1472 } | 1470 } |
1473 } | 1471 } |
1474 } | 1472 } |
1475 | 1473 |
1476 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 1474 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
1477 uint32_t capacity) { | 1475 uint32_t capacity) { |
1478 UNREACHABLE(); | 1476 UNREACHABLE(); |
1479 } | 1477 } |
1480 | 1478 |
1481 static void SetImpl(FixedArrayBase* store, uint32_t index, Object* value) { | 1479 static void SetImpl(FixedArrayBase* store, uint32_t entry, Object* value) { |
1482 FixedArray* parameter_map = FixedArray::cast(store); | 1480 FixedArray* parameter_map = FixedArray::cast(store); |
1483 Object* probe = GetParameterMapArg(parameter_map, index); | 1481 uint32_t length = parameter_map->length() - 2; |
1484 if (!probe->IsTheHole()) { | 1482 if (entry < length) { |
| 1483 Object* probe = parameter_map->get(entry + 2); |
1485 Context* context = Context::cast(parameter_map->get(0)); | 1484 Context* context = Context::cast(parameter_map->get(0)); |
1486 int context_entry = Smi::cast(probe)->value(); | 1485 int context_entry = Smi::cast(probe)->value(); |
1487 DCHECK(!context->get(context_entry)->IsTheHole()); | 1486 DCHECK(!context->get(context_entry)->IsTheHole()); |
1488 context->set(context_entry, value); | 1487 context->set(context_entry, value); |
1489 } else { | 1488 } else { |
1490 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1489 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1491 ArgumentsAccessor::SetImpl(arguments, index, value); | 1490 ArgumentsAccessor::SetImpl(arguments, entry - length, value); |
1492 } | 1491 } |
1493 } | 1492 } |
1494 | 1493 |
1495 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1494 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
1496 Handle<FixedArrayBase> parameter_map) { | 1495 Handle<FixedArrayBase> parameter_map) { |
1497 // Sloppy arguments objects are not arrays. | 1496 // Sloppy arguments objects are not arrays. |
1498 UNREACHABLE(); | 1497 UNREACHABLE(); |
1499 } | 1498 } |
1500 | 1499 |
1501 static uint32_t GetCapacityImpl(JSObject* holder, | 1500 static uint32_t GetCapacityImpl(JSObject* holder, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1541 return (parameter_map->length() - 2) + entry; | 1540 return (parameter_map->length() - 2) + entry; |
1542 } | 1541 } |
1543 | 1542 |
1544 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, | 1543 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
1545 uint32_t entry) { | 1544 uint32_t entry) { |
1546 FixedArray* parameter_map = FixedArray::cast(parameters); | 1545 FixedArray* parameter_map = FixedArray::cast(parameters); |
1547 uint32_t length = parameter_map->length() - 2; | 1546 uint32_t length = parameter_map->length() - 2; |
1548 if (entry < length) { | 1547 if (entry < length) { |
1549 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1548 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
1550 } | 1549 } |
1551 entry -= length; | |
1552 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1550 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1553 return ArgumentsAccessor::GetDetailsImpl(arguments, entry); | 1551 return ArgumentsAccessor::GetDetailsImpl(arguments, entry - length); |
1554 } | 1552 } |
1555 | 1553 |
1556 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t index) { | 1554 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t index) { |
1557 uint32_t length = parameter_map->length() - 2; | 1555 uint32_t length = parameter_map->length() - 2; |
1558 return index < length | 1556 return index < length |
1559 ? parameter_map->get(index + 2) | 1557 ? parameter_map->get(index + 2) |
1560 : Object::cast(parameter_map->GetHeap()->the_hole_value()); | 1558 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
1561 } | 1559 } |
1562 | 1560 |
1563 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { | 1561 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 Handle<Object> value, PropertyAttributes attributes, | 1677 Handle<Object> value, PropertyAttributes attributes, |
1680 uint32_t new_capacity) { | 1678 uint32_t new_capacity) { |
1681 DCHECK_EQ(NONE, attributes); | 1679 DCHECK_EQ(NONE, attributes); |
1682 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1680 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
1683 Handle<FixedArrayBase> old_elements( | 1681 Handle<FixedArrayBase> old_elements( |
1684 FixedArrayBase::cast(parameter_map->get(1))); | 1682 FixedArrayBase::cast(parameter_map->get(1))); |
1685 if (old_elements->IsSeededNumberDictionary() || | 1683 if (old_elements->IsSeededNumberDictionary() || |
1686 static_cast<uint32_t>(old_elements->length()) < new_capacity) { | 1684 static_cast<uint32_t>(old_elements->length()) < new_capacity) { |
1687 GrowCapacityAndConvertImpl(object, new_capacity); | 1685 GrowCapacityAndConvertImpl(object, new_capacity); |
1688 } | 1686 } |
1689 SetImpl(object->elements(), index, *value); | 1687 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1688 // For fast holey objects, the entry equals the index. The code above made |
| 1689 // sure that there's enough space to store the value. We cannot convert |
| 1690 // index to entry explicitly since the slot still contains the hole, so the |
| 1691 // current EntryForIndex would indicate that it is "absent" by returning |
| 1692 // kMaxUInt32. |
| 1693 FastHoleyObjectElementsAccessor::SetImpl(arguments, index, *value); |
1690 } | 1694 } |
1691 | 1695 |
1692 static void ReconfigureImpl(Handle<JSObject> object, | 1696 static void ReconfigureImpl(Handle<JSObject> object, |
1693 Handle<FixedArrayBase> store, uint32_t entry, | 1697 Handle<FixedArrayBase> store, uint32_t entry, |
1694 Handle<Object> value, | 1698 Handle<Object> value, |
1695 PropertyAttributes attributes) { | 1699 PropertyAttributes attributes) { |
1696 Handle<SeededNumberDictionary> dictionary = | 1700 Handle<SeededNumberDictionary> dictionary = |
1697 JSObject::NormalizeElements(object); | 1701 JSObject::NormalizeElements(object); |
1698 FixedArray::cast(*store)->set(1, *dictionary); | 1702 FixedArray::cast(*store)->set(1, *dictionary); |
1699 uint32_t length = static_cast<uint32_t>(store->length()) - 2; | 1703 uint32_t length = static_cast<uint32_t>(store->length()) - 2; |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1935 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1939 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
1936 ELEMENTS_LIST(ACCESSOR_DELETE) | 1940 ELEMENTS_LIST(ACCESSOR_DELETE) |
1937 #undef ACCESSOR_DELETE | 1941 #undef ACCESSOR_DELETE |
1938 elements_accessors_ = NULL; | 1942 elements_accessors_ = NULL; |
1939 } | 1943 } |
1940 | 1944 |
1941 | 1945 |
1942 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 1946 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
1943 } // namespace internal | 1947 } // namespace internal |
1944 } // namespace v8 | 1948 } // namespace v8 |
OLD | NEW |