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 1732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1743 if (double_array->is_the_hole(i)) { | 1743 if (double_array->is_the_hole(i)) { |
1744 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); | 1744 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); |
1745 return; | 1745 return; |
1746 } | 1746 } |
1747 } | 1747 } |
1748 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); | 1748 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); |
1749 } | 1749 } |
1750 } | 1750 } |
1751 | 1751 |
1752 | 1752 |
1753 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate, | |
1754 ElementsKind to_kind) { | |
1755 Map* current_map = map(); | |
1756 ElementsKind from_kind = current_map->elements_kind(); | |
1757 if (from_kind == to_kind) return current_map; | |
1758 | |
1759 Context* native_context = isolate->context()->native_context(); | |
1760 Object* maybe_array_maps = native_context->js_array_maps(); | |
1761 if (maybe_array_maps->IsFixedArray()) { | |
1762 FixedArray* array_maps = FixedArray::cast(maybe_array_maps); | |
1763 if (array_maps->get(from_kind) == current_map) { | |
1764 Object* maybe_transitioned_map = array_maps->get(to_kind); | |
1765 if (maybe_transitioned_map->IsMap()) { | |
1766 return Map::cast(maybe_transitioned_map); | |
1767 } | |
1768 } | |
1769 } | |
1770 | |
1771 return GetElementsTransitionMapSlow(to_kind); | |
1772 } | |
1773 | |
1774 | |
1775 void JSObject::SetMapAndElements(Handle<JSObject> object, | 1753 void JSObject::SetMapAndElements(Handle<JSObject> object, |
1776 Handle<Map> new_map, | 1754 Handle<Map> new_map, |
1777 Handle<FixedArrayBase> value) { | 1755 Handle<FixedArrayBase> value) { |
1778 JSObject::MigrateToMap(object, new_map); | 1756 JSObject::MigrateToMap(object, new_map); |
1779 ASSERT((object->map()->has_fast_smi_or_object_elements() || | 1757 ASSERT((object->map()->has_fast_smi_or_object_elements() || |
1780 (*value == object->GetHeap()->empty_fixed_array())) == | 1758 (*value == object->GetHeap()->empty_fixed_array())) == |
1781 (value->map() == object->GetHeap()->fixed_array_map() || | 1759 (value->map() == object->GetHeap()->fixed_array_map() || |
1782 value->map() == object->GetHeap()->fixed_cow_array_map())); | 1760 value->map() == object->GetHeap()->fixed_cow_array_map())); |
1783 ASSERT((*value == object->GetHeap()->empty_fixed_array()) || | 1761 ASSERT((*value == object->GetHeap()->empty_fixed_array()) || |
1784 (object->map()->has_fast_double_elements() == | 1762 (object->map()->has_fast_double_elements() == |
1785 value->IsFixedDoubleArray())); | 1763 value->IsFixedDoubleArray())); |
1786 object->set_elements(*value); | 1764 object->set_elements(*value); |
1787 } | 1765 } |
1788 | 1766 |
1789 | 1767 |
1790 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { | 1768 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { |
1791 WRITE_FIELD(this, kElementsOffset, value); | 1769 WRITE_FIELD(this, kElementsOffset, value); |
1792 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); | 1770 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); |
1793 } | 1771 } |
1794 | 1772 |
1795 | 1773 |
1796 void JSObject::initialize_properties() { | 1774 void JSObject::initialize_properties() { |
1797 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1775 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1798 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1776 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
1799 } | 1777 } |
1800 | 1778 |
1801 | 1779 |
1802 void JSObject::initialize_elements() { | 1780 void JSObject::initialize_elements() { |
1803 if (map()->has_fast_smi_or_object_elements() || | 1781 FixedArrayBase* elements = map()->GetInitialElements(); |
1804 map()->has_fast_double_elements()) { | 1782 WRITE_FIELD(this, kElementsOffset, elements); |
1805 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | |
1806 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); | |
1807 } else if (map()->has_external_array_elements()) { | |
1808 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(map()); | |
1809 ASSERT(!GetHeap()->InNewSpace(empty_array)); | |
1810 WRITE_FIELD(this, kElementsOffset, empty_array); | |
1811 } else if (map()->has_fixed_typed_array_elements()) { | |
1812 FixedTypedArrayBase* empty_array = | |
1813 GetHeap()->EmptyFixedTypedArrayForMap(map()); | |
1814 ASSERT(!GetHeap()->InNewSpace(empty_array)); | |
1815 WRITE_FIELD(this, kElementsOffset, empty_array); | |
1816 } else { | |
1817 UNREACHABLE(); | |
1818 } | |
1819 } | 1783 } |
1820 | 1784 |
1821 | 1785 |
1822 MaybeObject* JSObject::ResetElements() { | |
1823 if (map()->is_observed()) { | |
1824 // Maintain invariant that observed elements are always in dictionary mode. | |
1825 SeededNumberDictionary* dictionary; | |
1826 MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0); | |
1827 if (!maybe->To(&dictionary)) return maybe; | |
1828 if (map() == GetHeap()->sloppy_arguments_elements_map()) { | |
1829 FixedArray::cast(elements())->set(1, dictionary); | |
1830 } else { | |
1831 set_elements(dictionary); | |
1832 } | |
1833 return this; | |
1834 } | |
1835 | |
1836 ElementsKind elements_kind = GetInitialFastElementsKind(); | |
1837 if (!FLAG_smi_only_arrays) { | |
1838 elements_kind = FastSmiToObjectElementsKind(elements_kind); | |
1839 } | |
1840 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); | |
1841 Map* map; | |
1842 if (!maybe->To(&map)) return maybe; | |
1843 set_map(map); | |
1844 initialize_elements(); | |
1845 | |
1846 return this; | |
1847 } | |
1848 | |
1849 | |
1850 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) { | 1786 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) { |
1851 DisallowHeapAllocation no_gc; | 1787 DisallowHeapAllocation no_gc; |
1852 if (!map->HasTransitionArray()) return Handle<String>::null(); | 1788 if (!map->HasTransitionArray()) return Handle<String>::null(); |
1853 TransitionArray* transitions = map->transitions(); | 1789 TransitionArray* transitions = map->transitions(); |
1854 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); | 1790 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); |
1855 int transition = TransitionArray::kSimpleTransitionIndex; | 1791 int transition = TransitionArray::kSimpleTransitionIndex; |
1856 PropertyDetails details = transitions->GetTargetDetails(transition); | 1792 PropertyDetails details = transitions->GetTargetDetails(transition); |
1857 Name* name = transitions->GetKey(transition); | 1793 Name* name = transitions->GetKey(transition); |
1858 if (details.type() != FIELD) return Handle<String>::null(); | 1794 if (details.type() != FIELD) return Handle<String>::null(); |
1859 if (details.attributes() != NONE) return Handle<String>::null(); | 1795 if (details.attributes() != NONE) return Handle<String>::null(); |
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2685 | 2621 |
2686 void Map::LookupTransition(JSObject* holder, | 2622 void Map::LookupTransition(JSObject* holder, |
2687 Name* name, | 2623 Name* name, |
2688 LookupResult* result) { | 2624 LookupResult* result) { |
2689 int transition_index = this->SearchTransition(name); | 2625 int transition_index = this->SearchTransition(name); |
2690 if (transition_index == TransitionArray::kNotFound) return result->NotFound(); | 2626 if (transition_index == TransitionArray::kNotFound) return result->NotFound(); |
2691 result->TransitionResult(holder, this->GetTransition(transition_index)); | 2627 result->TransitionResult(holder, this->GetTransition(transition_index)); |
2692 } | 2628 } |
2693 | 2629 |
2694 | 2630 |
| 2631 FixedArrayBase* Map::GetInitialElements() { |
| 2632 if (has_fast_smi_or_object_elements() || |
| 2633 has_fast_double_elements()) { |
| 2634 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
| 2635 return GetHeap()->empty_fixed_array(); |
| 2636 } else if (has_external_array_elements()) { |
| 2637 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); |
| 2638 ASSERT(!GetHeap()->InNewSpace(empty_array)); |
| 2639 return empty_array; |
| 2640 } else if (has_fixed_typed_array_elements()) { |
| 2641 FixedTypedArrayBase* empty_array = |
| 2642 GetHeap()->EmptyFixedTypedArrayForMap(this); |
| 2643 ASSERT(!GetHeap()->InNewSpace(empty_array)); |
| 2644 return empty_array; |
| 2645 } else { |
| 2646 UNREACHABLE(); |
| 2647 } |
| 2648 return NULL; |
| 2649 } |
| 2650 |
| 2651 |
2695 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 2652 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
2696 ASSERT(descriptor_number < number_of_descriptors()); | 2653 ASSERT(descriptor_number < number_of_descriptors()); |
2697 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); | 2654 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); |
2698 } | 2655 } |
2699 | 2656 |
2700 | 2657 |
2701 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { | 2658 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { |
2702 return GetKeySlot(descriptor_number); | 2659 return GetKeySlot(descriptor_number); |
2703 } | 2660 } |
2704 | 2661 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2789 | 2746 |
2790 | 2747 |
2791 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { | 2748 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { |
2792 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2749 ASSERT(GetType(descriptor_number) == CALLBACKS); |
2793 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); | 2750 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); |
2794 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); | 2751 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); |
2795 } | 2752 } |
2796 | 2753 |
2797 | 2754 |
2798 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { | 2755 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { |
2799 desc->Init(GetKey(descriptor_number), | 2756 desc->Init(handle(GetKey(descriptor_number), GetIsolate()), |
2800 GetValue(descriptor_number), | 2757 handle(GetValue(descriptor_number), GetIsolate()), |
2801 GetDetails(descriptor_number)); | 2758 GetDetails(descriptor_number)); |
2802 } | 2759 } |
2803 | 2760 |
2804 | 2761 |
2805 void DescriptorArray::Set(int descriptor_number, | 2762 void DescriptorArray::Set(int descriptor_number, |
2806 Descriptor* desc, | 2763 Descriptor* desc, |
2807 const WhitenessWitness&) { | 2764 const WhitenessWitness&) { |
2808 // Range check. | 2765 // Range check. |
2809 ASSERT(descriptor_number < number_of_descriptors()); | 2766 ASSERT(descriptor_number < number_of_descriptors()); |
2810 | 2767 |
2811 NoIncrementalWriteBarrierSet(this, | 2768 NoIncrementalWriteBarrierSet(this, |
2812 ToKeyIndex(descriptor_number), | 2769 ToKeyIndex(descriptor_number), |
2813 desc->GetKey()); | 2770 *desc->GetKey()); |
2814 NoIncrementalWriteBarrierSet(this, | 2771 NoIncrementalWriteBarrierSet(this, |
2815 ToValueIndex(descriptor_number), | 2772 ToValueIndex(descriptor_number), |
2816 desc->GetValue()); | 2773 *desc->GetValue()); |
2817 NoIncrementalWriteBarrierSet(this, | 2774 NoIncrementalWriteBarrierSet(this, |
2818 ToDetailsIndex(descriptor_number), | 2775 ToDetailsIndex(descriptor_number), |
2819 desc->GetDetails().AsSmi()); | 2776 desc->GetDetails().AsSmi()); |
2820 } | 2777 } |
2821 | 2778 |
2822 | 2779 |
2823 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { | 2780 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { |
2824 // Range check. | 2781 // Range check. |
2825 ASSERT(descriptor_number < number_of_descriptors()); | 2782 ASSERT(descriptor_number < number_of_descriptors()); |
2826 | 2783 |
2827 set(ToKeyIndex(descriptor_number), desc->GetKey()); | 2784 set(ToKeyIndex(descriptor_number), *desc->GetKey()); |
2828 set(ToValueIndex(descriptor_number), desc->GetValue()); | 2785 set(ToValueIndex(descriptor_number), *desc->GetValue()); |
2829 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); | 2786 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); |
2830 } | 2787 } |
2831 | 2788 |
2832 | 2789 |
2833 void DescriptorArray::Append(Descriptor* desc, | 2790 void DescriptorArray::Append(Descriptor* desc, |
2834 const WhitenessWitness& witness) { | 2791 const WhitenessWitness& witness) { |
| 2792 DisallowHeapAllocation no_gc; |
2835 int descriptor_number = number_of_descriptors(); | 2793 int descriptor_number = number_of_descriptors(); |
2836 SetNumberOfDescriptors(descriptor_number + 1); | 2794 SetNumberOfDescriptors(descriptor_number + 1); |
2837 Set(descriptor_number, desc, witness); | 2795 Set(descriptor_number, desc, witness); |
2838 | 2796 |
2839 uint32_t hash = desc->GetKey()->Hash(); | 2797 uint32_t hash = desc->GetKey()->Hash(); |
2840 | 2798 |
2841 int insertion; | 2799 int insertion; |
2842 | 2800 |
2843 for (insertion = descriptor_number; insertion > 0; --insertion) { | 2801 for (insertion = descriptor_number; insertion > 0; --insertion) { |
2844 Name* key = GetSortedKey(insertion - 1); | 2802 Name* key = GetSortedKey(insertion - 1); |
2845 if (key->Hash() <= hash) break; | 2803 if (key->Hash() <= hash) break; |
2846 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); | 2804 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); |
2847 } | 2805 } |
2848 | 2806 |
2849 SetSortedKey(insertion, descriptor_number); | 2807 SetSortedKey(insertion, descriptor_number); |
2850 } | 2808 } |
2851 | 2809 |
2852 | 2810 |
2853 void DescriptorArray::Append(Descriptor* desc) { | 2811 void DescriptorArray::Append(Descriptor* desc) { |
| 2812 DisallowHeapAllocation no_gc; |
2854 int descriptor_number = number_of_descriptors(); | 2813 int descriptor_number = number_of_descriptors(); |
2855 SetNumberOfDescriptors(descriptor_number + 1); | 2814 SetNumberOfDescriptors(descriptor_number + 1); |
2856 Set(descriptor_number, desc); | 2815 Set(descriptor_number, desc); |
2857 | 2816 |
2858 uint32_t hash = desc->GetKey()->Hash(); | 2817 uint32_t hash = desc->GetKey()->Hash(); |
2859 | 2818 |
2860 int insertion; | 2819 int insertion; |
2861 | 2820 |
2862 for (insertion = descriptor_number; insertion > 0; --insertion) { | 2821 for (insertion = descriptor_number; insertion > 0; --insertion) { |
2863 Name* key = GetSortedKey(insertion - 1); | 2822 Name* key = GetSortedKey(insertion - 1); |
(...skipping 2195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5059 | 5018 |
5060 | 5019 |
5061 bool Map::CanHaveMoreTransitions() { | 5020 bool Map::CanHaveMoreTransitions() { |
5062 if (!HasTransitionArray()) return true; | 5021 if (!HasTransitionArray()) return true; |
5063 return FixedArray::SizeFor(transitions()->length() + | 5022 return FixedArray::SizeFor(transitions()->length() + |
5064 TransitionArray::kTransitionSize) | 5023 TransitionArray::kTransitionSize) |
5065 <= Page::kMaxRegularHeapObjectSize; | 5024 <= Page::kMaxRegularHeapObjectSize; |
5066 } | 5025 } |
5067 | 5026 |
5068 | 5027 |
5069 MaybeObject* Map::AddTransition(Name* key, | |
5070 Map* target, | |
5071 SimpleTransitionFlag flag) { | |
5072 if (HasTransitionArray()) return transitions()->CopyInsert(key, target); | |
5073 return TransitionArray::NewWith(flag, key, target, GetBackPointer()); | |
5074 } | |
5075 | |
5076 | |
5077 void Map::SetTransition(int transition_index, Map* target) { | 5028 void Map::SetTransition(int transition_index, Map* target) { |
5078 transitions()->SetTarget(transition_index, target); | 5029 transitions()->SetTarget(transition_index, target); |
5079 } | 5030 } |
5080 | 5031 |
5081 | 5032 |
5082 Map* Map::GetTransition(int transition_index) { | 5033 Map* Map::GetTransition(int transition_index) { |
5083 return transitions()->GetTarget(transition_index); | 5034 return transitions()->GetTarget(transition_index); |
5084 } | 5035 } |
5085 | 5036 |
5086 | 5037 |
5087 int Map::SearchTransition(Name* name) { | 5038 int Map::SearchTransition(Name* name) { |
5088 if (HasTransitionArray()) return transitions()->Search(name); | 5039 if (HasTransitionArray()) return transitions()->Search(name); |
5089 return TransitionArray::kNotFound; | 5040 return TransitionArray::kNotFound; |
5090 } | 5041 } |
5091 | 5042 |
5092 | 5043 |
5093 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { | |
5094 TransitionArray* transitions; | |
5095 MaybeObject* maybe_transitions = AddTransition( | |
5096 GetHeap()->elements_transition_symbol(), | |
5097 transitioned_map, | |
5098 FULL_TRANSITION); | |
5099 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
5100 set_transitions(transitions); | |
5101 return transitions; | |
5102 } | |
5103 | |
5104 | |
5105 FixedArray* Map::GetPrototypeTransitions() { | 5044 FixedArray* Map::GetPrototypeTransitions() { |
5106 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); | 5045 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); |
5107 if (!transitions()->HasPrototypeTransitions()) { | 5046 if (!transitions()->HasPrototypeTransitions()) { |
5108 return GetHeap()->empty_fixed_array(); | 5047 return GetHeap()->empty_fixed_array(); |
5109 } | 5048 } |
5110 return transitions()->GetPrototypeTransitions(); | 5049 return transitions()->GetPrototypeTransitions(); |
5111 } | 5050 } |
5112 | 5051 |
5113 | 5052 |
5114 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { | 5053 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) { |
(...skipping 1995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7110 #undef READ_SHORT_FIELD | 7049 #undef READ_SHORT_FIELD |
7111 #undef WRITE_SHORT_FIELD | 7050 #undef WRITE_SHORT_FIELD |
7112 #undef READ_BYTE_FIELD | 7051 #undef READ_BYTE_FIELD |
7113 #undef WRITE_BYTE_FIELD | 7052 #undef WRITE_BYTE_FIELD |
7114 #undef NOBARRIER_READ_BYTE_FIELD | 7053 #undef NOBARRIER_READ_BYTE_FIELD |
7115 #undef NOBARRIER_WRITE_BYTE_FIELD | 7054 #undef NOBARRIER_WRITE_BYTE_FIELD |
7116 | 7055 |
7117 } } // namespace v8::internal | 7056 } } // namespace v8::internal |
7118 | 7057 |
7119 #endif // V8_OBJECTS_INL_H_ | 7058 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |