OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1721 if (double_array->is_the_hole(i)) { | 1721 if (double_array->is_the_hole(i)) { |
1722 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); | 1722 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); |
1723 return; | 1723 return; |
1724 } | 1724 } |
1725 } | 1725 } |
1726 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); | 1726 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); |
1727 } | 1727 } |
1728 } | 1728 } |
1729 | 1729 |
1730 | 1730 |
1731 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate, | |
1732 ElementsKind to_kind) { | |
1733 Map* current_map = map(); | |
1734 ElementsKind from_kind = current_map->elements_kind(); | |
1735 if (from_kind == to_kind) return current_map; | |
1736 | |
1737 Context* native_context = isolate->context()->native_context(); | |
1738 Object* maybe_array_maps = native_context->js_array_maps(); | |
1739 if (maybe_array_maps->IsFixedArray()) { | |
1740 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); | |
1741 if (array_maps->get(from_kind) == current_map) { | |
1742 Object* maybe_transitioned_map = array_maps->get(to_kind); | |
1743 if (maybe_transitioned_map->IsMap()) { | |
1744 return Map::cast(maybe_transitioned_map); | |
1745 } | |
1746 } | |
1747 } | |
1748 | |
1749 return GetElementsTransitionMapSlow(to_kind); | |
1750 } | |
1751 | |
1752 | |
1753 void JSObject::SetMapAndElements(Handle<JSObject> object, | 1731 void JSObject::SetMapAndElements(Handle<JSObject> object, |
1754 Handle<Map> new_map, | 1732 Handle<Map> new_map, |
1755 Handle<FixedArrayBase> value) { | 1733 Handle<FixedArrayBase> value) { |
1756 JSObject::MigrateToMap(object, new_map); | 1734 JSObject::MigrateToMap(object, new_map); |
1757 ASSERT((object->map()->has_fast_smi_or_object_elements() || | 1735 ASSERT((object->map()->has_fast_smi_or_object_elements() || |
1758 (*value == object->GetHeap()->empty_fixed_array())) == | 1736 (*value == object->GetHeap()->empty_fixed_array())) == |
1759 (value->map() == object->GetHeap()->fixed_array_map() || | 1737 (value->map() == object->GetHeap()->fixed_array_map() || |
1760 value->map() == object->GetHeap()->fixed_cow_array_map())); | 1738 value->map() == object->GetHeap()->fixed_cow_array_map())); |
1761 ASSERT((*value == object->GetHeap()->empty_fixed_array()) || | 1739 ASSERT((*value == object->GetHeap()->empty_fixed_array()) || |
1762 (object->map()->has_fast_double_elements() == | 1740 (object->map()->has_fast_double_elements() == |
1763 value->IsFixedDoubleArray())); | 1741 value->IsFixedDoubleArray())); |
1764 object->set_elements(*value); | 1742 object->set_elements(*value); |
1765 } | 1743 } |
1766 | 1744 |
1767 | 1745 |
1768 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { | 1746 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { |
1769 WRITE_FIELD(this, kElementsOffset, value); | 1747 WRITE_FIELD(this, kElementsOffset, value); |
1770 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); | 1748 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); |
1771 } | 1749 } |
1772 | 1750 |
1773 | 1751 |
1774 void JSObject::initialize_properties() { | 1752 void JSObject::initialize_properties() { |
1775 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1753 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1776 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1754 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
1777 } | 1755 } |
1778 | 1756 |
1779 | 1757 |
1780 void JSObject::initialize_elements() { | 1758 void JSObject::initialize_elements() { |
1781 if (map()->has_fast_smi_or_object_elements() || | 1759 FixedArrayBase* elements = map()->GetInitialElements(); |
1782 map()->has_fast_double_elements()) { | 1760 WRITE_FIELD(this, kElementsOffset, elements); |
1783 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | |
1784 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); | |
1785 } else if (map()->has_external_array_elements()) { | |
1786 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(map()); | |
1787 ASSERT(!GetHeap()->InNewSpace(empty_array)); | |
1788 WRITE_FIELD(this, kElementsOffset, empty_array); | |
1789 } else if (map()->has_fixed_typed_array_elements()) { | |
1790 FixedTypedArrayBase* empty_array = | |
1791 GetHeap()->EmptyFixedTypedArrayForMap(map()); | |
1792 ASSERT(!GetHeap()->InNewSpace(empty_array)); | |
1793 WRITE_FIELD(this, kElementsOffset, empty_array); | |
1794 } else { | |
1795 UNREACHABLE(); | |
1796 } | |
1797 } | 1761 } |
1798 | 1762 |
1799 | 1763 |
1800 MaybeObject* JSObject::ResetElements() { | |
1801 if (map()->is_observed()) { | |
1802 // Maintain invariant that observed elements are always in dictionary mode. | |
1803 SeededNumberDictionary* dictionary; | |
1804 MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0); | |
1805 if (!maybe->To(&dictionary)) return maybe; | |
1806 if (map() == GetHeap()->sloppy_arguments_elements_map()) { | |
1807 FixedArray::cast(elements())->set(1, dictionary); | |
1808 } else { | |
1809 set_elements(dictionary); | |
1810 } | |
1811 return this; | |
1812 } | |
1813 | |
1814 ElementsKind elements_kind = GetInitialFastElementsKind(); | |
1815 if (!FLAG_smi_only_arrays) { | |
1816 elements_kind = FastSmiToObjectElementsKind(elements_kind); | |
1817 } | |
1818 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | |
1819 Map* map; | |
1820 if (!maybe->To(&map)) return maybe; | |
1821 set_map(map); | |
1822 initialize_elements(); | |
1823 | |
1824 return this; | |
1825 } | |
1826 | |
1827 | |
1828 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) { | 1764 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) { |
1829 DisallowHeapAllocation no_gc; | 1765 DisallowHeapAllocation no_gc; |
1830 if (!map->HasTransitionArray()) return Handle<String>::null(); | 1766 if (!map->HasTransitionArray()) return Handle<String>::null(); |
1831 TransitionArray* transitions = map->transitions(); | 1767 TransitionArray* transitions = map->transitions(); |
1832 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); | 1768 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); |
1833 int transition = TransitionArray::kSimpleTransitionIndex; | 1769 int transition = TransitionArray::kSimpleTransitionIndex; |
1834 PropertyDetails details = transitions->GetTargetDetails(transition); | 1770 PropertyDetails details = transitions->GetTargetDetails(transition); |
1835 Name* name = transitions->GetKey(transition); | 1771 Name* name = transitions->GetKey(transition); |
1836 if (details.type() != FIELD) return Handle<String>::null(); | 1772 if (details.type() != FIELD) return Handle<String>::null(); |
1837 if (details.attributes() != NONE) return Handle<String>::null(); | 1773 if (details.attributes() != NONE) return Handle<String>::null(); |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2657 | 2593 |
2658 void Map::LookupTransition(JSObject* holder, | 2594 void Map::LookupTransition(JSObject* holder, |
2659 Name* name, | 2595 Name* name, |
2660 LookupResult* result) { | 2596 LookupResult* result) { |
2661 int transition_index = this->SearchTransition(name); | 2597 int transition_index = this->SearchTransition(name); |
2662 if (transition_index == TransitionArray::kNotFound) return result->NotFound(); | 2598 if (transition_index == TransitionArray::kNotFound) return result->NotFound(); |
2663 result->TransitionResult(holder, this->GetTransition(transition_index)); | 2599 result->TransitionResult(holder, this->GetTransition(transition_index)); |
2664 } | 2600 } |
2665 | 2601 |
2666 | 2602 |
| 2603 FixedArrayBase* Map::GetInitialElements() { |
| 2604 if (has_fast_smi_or_object_elements() || |
| 2605 has_fast_double_elements()) { |
| 2606 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
| 2607 return GetHeap()->empty_fixed_array(); |
| 2608 } else if (has_external_array_elements()) { |
| 2609 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); |
| 2610 ASSERT(!GetHeap()->InNewSpace(empty_array)); |
| 2611 return empty_array; |
| 2612 } else if (has_fixed_typed_array_elements()) { |
| 2613 FixedTypedArrayBase* empty_array = |
| 2614 GetHeap()->EmptyFixedTypedArrayForMap(this); |
| 2615 ASSERT(!GetHeap()->InNewSpace(empty_array)); |
| 2616 return empty_array; |
| 2617 } else { |
| 2618 UNREACHABLE(); |
| 2619 } |
| 2620 return NULL; |
| 2621 } |
| 2622 |
| 2623 |
2667 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 2624 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
2668 ASSERT(descriptor_number < number_of_descriptors()); | 2625 ASSERT(descriptor_number < number_of_descriptors()); |
2669 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); | 2626 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); |
2670 } | 2627 } |
2671 | 2628 |
2672 | 2629 |
2673 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { | 2630 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { |
2674 return GetKeySlot(descriptor_number); | 2631 return GetKeySlot(descriptor_number); |
2675 } | 2632 } |
2676 | 2633 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2761 | 2718 |
2762 | 2719 |
2763 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { | 2720 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { |
2764 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2721 ASSERT(GetType(descriptor_number) == CALLBACKS); |
2765 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); | 2722 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); |
2766 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); | 2723 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); |
2767 } | 2724 } |
2768 | 2725 |
2769 | 2726 |
2770 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { | 2727 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { |
2771 desc->Init(GetKey(descriptor_number), | 2728 desc->Init(handle(GetKey(descriptor_number), GetIsolate()), |
2772 GetValue(descriptor_number), | 2729 handle(GetValue(descriptor_number), GetIsolate()), |
2773 GetDetails(descriptor_number)); | 2730 GetDetails(descriptor_number)); |
2774 } | 2731 } |
2775 | 2732 |
2776 | 2733 |
2777 void DescriptorArray::Set(int descriptor_number, | 2734 void DescriptorArray::Set(int descriptor_number, |
2778 Descriptor* desc, | 2735 Descriptor* desc, |
2779 const WhitenessWitness&) { | 2736 const WhitenessWitness&) { |
2780 // Range check. | 2737 // Range check. |
2781 ASSERT(descriptor_number < number_of_descriptors()); | 2738 ASSERT(descriptor_number < number_of_descriptors()); |
2782 | 2739 |
2783 NoIncrementalWriteBarrierSet(this, | 2740 NoIncrementalWriteBarrierSet(this, |
2784 ToKeyIndex(descriptor_number), | 2741 ToKeyIndex(descriptor_number), |
2785 desc->GetKey()); | 2742 *desc->GetKey()); |
2786 NoIncrementalWriteBarrierSet(this, | 2743 NoIncrementalWriteBarrierSet(this, |
2787 ToValueIndex(descriptor_number), | 2744 ToValueIndex(descriptor_number), |
2788 desc->GetValue()); | 2745 *desc->GetValue()); |
2789 NoIncrementalWriteBarrierSet(this, | 2746 NoIncrementalWriteBarrierSet(this, |
2790 ToDetailsIndex(descriptor_number), | 2747 ToDetailsIndex(descriptor_number), |
2791 desc->GetDetails().AsSmi()); | 2748 desc->GetDetails().AsSmi()); |
2792 } | 2749 } |
2793 | 2750 |
2794 | 2751 |
2795 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { | 2752 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { |
2796 // Range check. | 2753 // Range check. |
2797 ASSERT(descriptor_number < number_of_descriptors()); | 2754 ASSERT(descriptor_number < number_of_descriptors()); |
2798 | 2755 |
2799 set(ToKeyIndex(descriptor_number), desc->GetKey()); | 2756 set(ToKeyIndex(descriptor_number), *desc->GetKey()); |
2800 set(ToValueIndex(descriptor_number), desc->GetValue()); | 2757 set(ToValueIndex(descriptor_number), *desc->GetValue()); |
2801 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); | 2758 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); |
2802 } | 2759 } |
2803 | 2760 |
2804 | 2761 |
2805 void DescriptorArray::Append(Descriptor* desc, | 2762 void DescriptorArray::Append(Descriptor* desc, |
2806 const WhitenessWitness& witness) { | 2763 const WhitenessWitness& witness) { |
| 2764 DisallowHeapAllocation no_gc; |
2807 int descriptor_number = number_of_descriptors(); | 2765 int descriptor_number = number_of_descriptors(); |
2808 SetNumberOfDescriptors(descriptor_number + 1); | 2766 SetNumberOfDescriptors(descriptor_number + 1); |
2809 Set(descriptor_number, desc, witness); | 2767 Set(descriptor_number, desc, witness); |
2810 | 2768 |
2811 uint32_t hash = desc->GetKey()->Hash(); | 2769 uint32_t hash = desc->GetKey()->Hash(); |
2812 | 2770 |
2813 int insertion; | 2771 int insertion; |
2814 | 2772 |
2815 for (insertion = descriptor_number; insertion > 0; --insertion) { | 2773 for (insertion = descriptor_number; insertion > 0; --insertion) { |
2816 Name* key = GetSortedKey(insertion - 1); | 2774 Name* key = GetSortedKey(insertion - 1); |
2817 if (key->Hash() <= hash) break; | 2775 if (key->Hash() <= hash) break; |
2818 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); | 2776 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); |
2819 } | 2777 } |
2820 | 2778 |
2821 SetSortedKey(insertion, descriptor_number); | 2779 SetSortedKey(insertion, descriptor_number); |
2822 } | 2780 } |
2823 | 2781 |
2824 | 2782 |
2825 void DescriptorArray::Append(Descriptor* desc) { | 2783 void DescriptorArray::Append(Descriptor* desc) { |
| 2784 DisallowHeapAllocation no_gc; |
2826 int descriptor_number = number_of_descriptors(); | 2785 int descriptor_number = number_of_descriptors(); |
2827 SetNumberOfDescriptors(descriptor_number + 1); | 2786 SetNumberOfDescriptors(descriptor_number + 1); |
2828 Set(descriptor_number, desc); | 2787 Set(descriptor_number, desc); |
2829 | 2788 |
2830 uint32_t hash = desc->GetKey()->Hash(); | 2789 uint32_t hash = desc->GetKey()->Hash(); |
2831 | 2790 |
2832 int insertion; | 2791 int insertion; |
2833 | 2792 |
2834 for (insertion = descriptor_number; insertion > 0; --insertion) { | 2793 for (insertion = descriptor_number; insertion > 0; --insertion) { |
2835 Name* key = GetSortedKey(insertion - 1); | 2794 Name* key = GetSortedKey(insertion - 1); |
(...skipping 2073 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4909 | 4868 |
4910 | 4869 |
4911 bool Map::CanHaveMoreTransitions() { | 4870 bool Map::CanHaveMoreTransitions() { |
4912 if (!HasTransitionArray()) return true; | 4871 if (!HasTransitionArray()) return true; |
4913 return FixedArray::SizeFor(transitions()->length() + | 4872 return FixedArray::SizeFor(transitions()->length() + |
4914 TransitionArray::kTransitionSize) | 4873 TransitionArray::kTransitionSize) |
4915 <= Page::kMaxRegularHeapObjectSize; | 4874 <= Page::kMaxRegularHeapObjectSize; |
4916 } | 4875 } |
4917 | 4876 |
4918 | 4877 |
4919 MaybeObject* Map::AddTransition(Name* key, | |
4920 Map* target, | |
4921 SimpleTransitionFlag flag) { | |
4922 if (HasTransitionArray()) return transitions()->CopyInsert(key, target); | |
4923 return TransitionArray::NewWith(flag, key, target, GetBackPointer()); | |
4924 } | |
4925 | |
4926 | |
4927 void Map::SetTransition(int transition_index, Map* target) { | 4878 void Map::SetTransition(int transition_index, Map* target) { |
4928 transitions()->SetTarget(transition_index, target); | 4879 transitions()->SetTarget(transition_index, target); |
4929 } | 4880 } |
4930 | 4881 |
4931 | 4882 |
4932 Map* Map::GetTransition(int transition_index) { | 4883 Map* Map::GetTransition(int transition_index) { |
4933 return transitions()->GetTarget(transition_index); | 4884 return transitions()->GetTarget(transition_index); |
4934 } | 4885 } |
4935 | 4886 |
4936 | 4887 |
4937 int Map::SearchTransition(Name* name) { | 4888 int Map::SearchTransition(Name* name) { |
4938 if (HasTransitionArray()) return transitions()->Search(name); | 4889 if (HasTransitionArray()) return transitions()->Search(name); |
4939 return TransitionArray::kNotFound; | 4890 return TransitionArray::kNotFound; |
4940 } | 4891 } |
4941 | 4892 |
4942 | 4893 |
4943 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { | |
4944 TransitionArray* transitions; | |
4945 MaybeObject* maybe_transitions = AddTransition( | |
4946 GetHeap()->elements_transition_symbol(), | |
4947 transitioned_map, | |
4948 FULL_TRANSITION); | |
4949 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
4950 set_transitions(transitions); | |
4951 return transitions; | |
4952 } | |
4953 | |
4954 | |
4955 FixedArray* Map::GetPrototypeTransitions() { | 4894 FixedArray* Map::GetPrototypeTransitions() { |
4956 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); | 4895 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); |
4957 if (!transitions()->HasPrototypeTransitions()) { | 4896 if (!transitions()->HasPrototypeTransitions()) { |
4958 return GetHeap()->empty_fixed_array(); | 4897 return GetHeap()->empty_fixed_array(); |
4959 } | 4898 } |
4960 return transitions()->GetPrototypeTransitions(); | 4899 return transitions()->GetPrototypeTransitions(); |
4961 } | 4900 } |
4962 | 4901 |
4963 | 4902 |
4964 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { | 4903 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { |
(...skipping 1995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6960 #undef READ_UINT32_FIELD | 6899 #undef READ_UINT32_FIELD |
6961 #undef WRITE_UINT32_FIELD | 6900 #undef WRITE_UINT32_FIELD |
6962 #undef READ_SHORT_FIELD | 6901 #undef READ_SHORT_FIELD |
6963 #undef WRITE_SHORT_FIELD | 6902 #undef WRITE_SHORT_FIELD |
6964 #undef READ_BYTE_FIELD | 6903 #undef READ_BYTE_FIELD |
6965 #undef WRITE_BYTE_FIELD | 6904 #undef WRITE_BYTE_FIELD |
6966 | 6905 |
6967 } } // namespace v8::internal | 6906 } } // namespace v8::internal |
6968 | 6907 |
6969 #endif // V8_OBJECTS_INL_H_ | 6908 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |