| 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 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 // to store distinct descriptor arrays. | 1770 // to store distinct descriptor arrays. |
| 1771 | 1771 |
| 1772 // If the old_target did not yet store its own descriptors, the new | 1772 // If the old_target did not yet store its own descriptors, the new |
| 1773 // descriptors pointer is created for the old_target by temporarily clearing | 1773 // descriptors pointer is created for the old_target by temporarily clearing |
| 1774 // the back pointer and setting its descriptor array. | 1774 // the back pointer and setting its descriptor array. |
| 1775 | 1775 |
| 1776 // This phase is executed before creating the new map since it requires | 1776 // This phase is executed before creating the new map since it requires |
| 1777 // allocation that may fail. | 1777 // allocation that may fail. |
| 1778 if (!old_target->StoresOwnDescriptors()) { | 1778 if (!old_target->StoresOwnDescriptors()) { |
| 1779 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 1779 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 1780 | |
| 1781 old_target->SetBackPointer(GetHeap()->undefined_value()); | |
| 1782 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); | 1780 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); |
| 1783 // Reset the backpointer before returning failure, otherwise the map ends up | |
| 1784 // with an undefined backpointer and no descriptors, losing its own | |
| 1785 // descriptors. Setting the backpointer always succeeds. | |
| 1786 old_target->SetBackPointer(old_map); | |
| 1787 if (maybe_failure->IsFailure()) return maybe_failure; | 1781 if (maybe_failure->IsFailure()) return maybe_failure; |
| 1788 } | 1782 } |
| 1789 | 1783 |
| 1790 MaybeObject* maybe_result = | 1784 MaybeObject* maybe_result = |
| 1791 ConvertDescriptorToField(name, new_value, attributes); | 1785 ConvertDescriptorToField(name, new_value, attributes); |
| 1792 if (!maybe_result->To(&result)) return maybe_result; | 1786 if (!maybe_result->To(&result)) return maybe_result; |
| 1793 | 1787 |
| 1794 if (!HasFastProperties()) return result; | 1788 if (!HasFastProperties()) return result; |
| 1795 | 1789 |
| 1796 // This method should only be used to convert existing transitions. Objects | 1790 // This method should only be used to convert existing transitions. Objects |
| 1797 // with the map of "new Object()" cannot have transitions in the first place. | 1791 // with the map of "new Object()" cannot have transitions in the first place. |
| 1798 Map* new_map = map(); | 1792 Map* new_map = map(); |
| 1799 ASSERT(new_map != GetIsolate()->empty_object_map()); | 1793 ASSERT(new_map != GetIsolate()->empty_object_map()); |
| 1800 | 1794 |
| 1801 // TODO(verwaest): From here on we lose existing map transitions, causing | 1795 // TODO(verwaest): From here on we lose existing map transitions, causing |
| 1802 // invalid back pointers. This will change once we can store multiple | 1796 // invalid back pointers. This will change once we can store multiple |
| 1803 // transitions with the same key. | 1797 // transitions with the same key. |
| 1804 | 1798 |
| 1805 if (old_map->owns_descriptors()) { | 1799 bool owned_descriptors = old_map->owns_descriptors(); |
| 1806 // If the old map owns its own descriptors, transfer ownership to the | 1800 if (owned_descriptors || |
| 1807 // new_map and install its descriptors in the old_map. Since the old_map | 1801 old_target->instance_descriptors() == old_map->instance_descriptors()) { |
| 1808 // stores the descriptors for the new_map, remove the transition array of | |
| 1809 // the new_map that is only in place to store the descriptors. | |
| 1810 old_map->transitions()->descriptors_pointer()->set_value( | |
| 1811 new_map->instance_descriptors()); | |
| 1812 new_map->ClearTransitions(GetHeap()); | |
| 1813 old_map->set_owns_descriptors(false); | |
| 1814 } else if (old_target->instance_descriptors() == | |
| 1815 old_map->instance_descriptors()) { | |
| 1816 // Since the conversion above generated a new fast map with an additional | 1802 // Since the conversion above generated a new fast map with an additional |
| 1817 // property which can be shared as well, install this descriptor pointer | 1803 // property which can be shared as well, install this descriptor pointer |
| 1818 // along the entire chain of smaller maps; and remove the transition array | 1804 // along the entire chain of smaller maps; and remove the transition array |
| 1819 // that is only in place to hold the descriptor array in the new map. | 1805 // that is only in place to hold the descriptor array in the new map. |
| 1820 Map* map; | 1806 Map* map; |
| 1821 JSGlobalPropertyCell* new_pointer = | 1807 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
| 1822 new_map->transitions()->descriptors_pointer(); | 1808 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 1823 JSGlobalPropertyCell* old_pointer = | |
| 1824 old_map->transitions()->descriptors_pointer(); | |
| 1825 for (Object* current = old_map; | 1809 for (Object* current = old_map; |
| 1826 !current->IsUndefined(); | 1810 !current->IsUndefined(); |
| 1827 current = map->GetBackPointer()) { | 1811 current = map->GetBackPointer()) { |
| 1828 map = Map::cast(current); | 1812 map = Map::cast(current); |
| 1829 if (!map->HasTransitionArray()) break; | 1813 if (!map->HasTransitionArray()) break; |
| 1830 TransitionArray* transitions = map->transitions(); | 1814 TransitionArray* transitions = map->transitions(); |
| 1831 if (transitions->descriptors_pointer() != old_pointer) break; | 1815 if (transitions->descriptors() != old_descriptors) break; |
| 1832 map->SetEnumLength(Map::kInvalidEnumCache); | 1816 // Invalidate the enum caches only if the map did not own its descriptors. |
| 1833 transitions->set_descriptors_pointer(new_pointer); | 1817 if (!owned_descriptors) map->SetEnumLength(Map::kInvalidEnumCache); |
| 1818 transitions->set_descriptors(new_descriptors); |
| 1834 } | 1819 } |
| 1820 old_map->set_owns_descriptors(false); |
| 1835 new_map->ClearTransitions(GetHeap()); | 1821 new_map->ClearTransitions(GetHeap()); |
| 1836 } | 1822 } |
| 1837 | 1823 |
| 1838 old_map->SetTransition(transition_index, new_map); | 1824 old_map->SetTransition(transition_index, new_map); |
| 1839 new_map->SetBackPointer(old_map); | 1825 new_map->SetBackPointer(old_map); |
| 1840 return result; | 1826 return result; |
| 1841 } | 1827 } |
| 1842 | 1828 |
| 1843 | 1829 |
| 1844 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1830 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
| (...skipping 3123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4968 result->set_inobject_properties(inobject_properties()); | 4954 result->set_inobject_properties(inobject_properties()); |
| 4969 result->set_unused_property_fields(unused_property_fields()); | 4955 result->set_unused_property_fields(unused_property_fields()); |
| 4970 | 4956 |
| 4971 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 4957 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
| 4972 result->set_is_shared(false); | 4958 result->set_is_shared(false); |
| 4973 result->ClearCodeCache(GetHeap()); | 4959 result->ClearCodeCache(GetHeap()); |
| 4974 return result; | 4960 return result; |
| 4975 } | 4961 } |
| 4976 | 4962 |
| 4977 | 4963 |
| 4978 MaybeObject* Map::ShareDescriptor(Descriptor* descriptor) { | 4964 MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors, |
| 4965 Descriptor* descriptor) { |
| 4979 // Sanity check. This path is only to be taken if the map owns its descriptor | 4966 // Sanity check. This path is only to be taken if the map owns its descriptor |
| 4980 // array, implying that its NumberOfOwnDescriptors equals the number of | 4967 // array, implying that its NumberOfOwnDescriptors equals the number of |
| 4981 // descriptors in the descriptor array. | 4968 // descriptors in the descriptor array. |
| 4982 if (NumberOfOwnDescriptors() != | 4969 ASSERT(NumberOfOwnDescriptors() == |
| 4983 instance_descriptors()->number_of_descriptors()) { | 4970 instance_descriptors()->number_of_descriptors()); |
| 4984 Isolate::Current()->PushStackTraceAndDie( | |
| 4985 0xDEAD0002, GetBackPointer(), this, 0xDEAD0003); | |
| 4986 } | |
| 4987 Map* result; | 4971 Map* result; |
| 4988 MaybeObject* maybe_result = CopyDropDescriptors(); | 4972 MaybeObject* maybe_result = CopyDropDescriptors(); |
| 4989 if (!maybe_result->To(&result)) return maybe_result; | 4973 if (!maybe_result->To(&result)) return maybe_result; |
| 4990 | 4974 |
| 4991 String* name = descriptor->GetKey(); | 4975 String* name = descriptor->GetKey(); |
| 4992 | 4976 |
| 4993 TransitionArray* transitions; | 4977 TransitionArray* transitions; |
| 4994 MaybeObject* maybe_transitions = | 4978 MaybeObject* maybe_transitions = |
| 4995 AddTransition(name, result, SIMPLE_TRANSITION); | 4979 AddTransition(name, result, SIMPLE_TRANSITION); |
| 4996 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 4980 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 4997 | 4981 |
| 4998 DescriptorArray* descriptors = instance_descriptors(); | |
| 4999 int old_size = descriptors->number_of_descriptors(); | 4982 int old_size = descriptors->number_of_descriptors(); |
| 5000 | 4983 |
| 5001 DescriptorArray* new_descriptors; | 4984 DescriptorArray* new_descriptors; |
| 5002 | 4985 |
| 5003 if (descriptors->NumberOfSlackDescriptors() > 0) { | 4986 if (descriptors->NumberOfSlackDescriptors() > 0) { |
| 5004 new_descriptors = descriptors; | 4987 new_descriptors = descriptors; |
| 5005 new_descriptors->Append(descriptor); | 4988 new_descriptors->Append(descriptor); |
| 5006 } else { | 4989 } else { |
| 5007 // Descriptor arrays grow by 50%. | 4990 // Descriptor arrays grow by 50%. |
| 5008 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( | 4991 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5019 new_descriptors->Append(descriptor, witness); | 5002 new_descriptors->Append(descriptor, witness); |
| 5020 | 5003 |
| 5021 // If the source descriptors had an enum cache we copy it. This ensures that | 5004 // If the source descriptors had an enum cache we copy it. This ensures that |
| 5022 // the maps to which we push the new descriptor array back can rely on a | 5005 // the maps to which we push the new descriptor array back can rely on a |
| 5023 // cache always being available once it is set. If the map has more | 5006 // cache always being available once it is set. If the map has more |
| 5024 // enumerated descriptors than available in the original cache, the cache | 5007 // enumerated descriptors than available in the original cache, the cache |
| 5025 // will be lazily replaced by the extended cache when needed. | 5008 // will be lazily replaced by the extended cache when needed. |
| 5026 if (descriptors->HasEnumCache()) { | 5009 if (descriptors->HasEnumCache()) { |
| 5027 new_descriptors->CopyEnumCacheFrom(descriptors); | 5010 new_descriptors->CopyEnumCacheFrom(descriptors); |
| 5028 } | 5011 } |
| 5012 |
| 5013 Map* map; |
| 5014 // Replace descriptors by new_descriptors in all maps that share it. |
| 5015 for (Object* current = GetBackPointer(); |
| 5016 !current->IsUndefined(); |
| 5017 current = map->GetBackPointer()) { |
| 5018 map = Map::cast(current); |
| 5019 if (!map->HasTransitionArray()) break; |
| 5020 TransitionArray* transitions = map->transitions(); |
| 5021 if (transitions->descriptors() != descriptors) break; |
| 5022 transitions->set_descriptors(new_descriptors); |
| 5023 } |
| 5024 |
| 5025 transitions->set_descriptors(new_descriptors); |
| 5029 } | 5026 } |
| 5030 | 5027 |
| 5031 transitions->set_descriptors(new_descriptors); | |
| 5032 | |
| 5033 set_transitions(transitions); | 5028 set_transitions(transitions); |
| 5034 result->SetBackPointer(this); | 5029 result->SetBackPointer(this); |
| 5035 set_owns_descriptors(false); | 5030 set_owns_descriptors(false); |
| 5036 | 5031 |
| 5037 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); | 5032 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); |
| 5038 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | 5033 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 5039 | 5034 |
| 5040 return result; | 5035 return result; |
| 5041 } | 5036 } |
| 5042 | 5037 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5066 ? SIMPLE_TRANSITION | 5061 ? SIMPLE_TRANSITION |
| 5067 : FULL_TRANSITION; | 5062 : FULL_TRANSITION; |
| 5068 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 5063 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
| 5069 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5064 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 5070 | 5065 |
| 5071 if (descriptors->IsEmpty()) { | 5066 if (descriptors->IsEmpty()) { |
| 5072 if (owns_descriptors()) { | 5067 if (owns_descriptors()) { |
| 5073 // If the copied map has no added fields, and the parent map owns its | 5068 // If the copied map has no added fields, and the parent map owns its |
| 5074 // descriptors, those descriptors have to be empty. In that case, | 5069 // descriptors, those descriptors have to be empty. In that case, |
| 5075 // transfer ownership of the descriptors to the new child. | 5070 // transfer ownership of the descriptors to the new child. |
| 5076 CHECK(instance_descriptors()->IsEmpty()); | 5071 ASSERT(instance_descriptors()->IsEmpty()); |
| 5077 set_owns_descriptors(false); | 5072 set_owns_descriptors(false); |
| 5078 } else { | 5073 } else { |
| 5079 // If the parent did not own its own descriptors, it may share a larger | 5074 // If the parent did not own its own descriptors, it may share a larger |
| 5080 // descriptors array already. In that case, force a split by setting | 5075 // descriptors array already. In that case, force a split by setting |
| 5081 // the descriptor array of the new map to the empty descriptor array. | 5076 // the descriptor array of the new map to the empty descriptor array. |
| 5082 MaybeObject* maybe_failure = | 5077 MaybeObject* maybe_failure = |
| 5083 result->SetDescriptors(GetHeap()->empty_descriptor_array()); | 5078 result->SetDescriptors(GetHeap()->empty_descriptor_array()); |
| 5084 if (maybe_failure->IsFailure()) return maybe_failure; | 5079 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5085 } | 5080 } |
| 5086 } | 5081 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5194 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); | 5189 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
| 5195 if (maybe_failure->IsFailure()) return maybe_failure; | 5190 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5196 | 5191 |
| 5197 int old_size = NumberOfOwnDescriptors(); | 5192 int old_size = NumberOfOwnDescriptors(); |
| 5198 int new_size = old_size + 1; | 5193 int new_size = old_size + 1; |
| 5199 descriptor->SetEnumerationIndex(new_size); | 5194 descriptor->SetEnumerationIndex(new_size); |
| 5200 | 5195 |
| 5201 if (flag == INSERT_TRANSITION && | 5196 if (flag == INSERT_TRANSITION && |
| 5202 owns_descriptors() && | 5197 owns_descriptors() && |
| 5203 CanHaveMoreTransitions()) { | 5198 CanHaveMoreTransitions()) { |
| 5204 return ShareDescriptor(descriptor); | 5199 return ShareDescriptor(descriptors, descriptor); |
| 5205 } | 5200 } |
| 5206 | 5201 |
| 5207 DescriptorArray* new_descriptors; | 5202 DescriptorArray* new_descriptors; |
| 5208 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1); | 5203 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1); |
| 5209 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 5204 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 5210 | 5205 |
| 5211 DescriptorArray::WhitenessWitness witness(new_descriptors); | 5206 DescriptorArray::WhitenessWitness witness(new_descriptors); |
| 5212 | 5207 |
| 5213 // Copy the descriptors, inserting a descriptor. | 5208 // Copy the descriptors, inserting a descriptor. |
| 5214 for (int i = 0; i < old_size; ++i) { | 5209 for (int i = 0; i < old_size; ++i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5234 TransitionFlag flag) { | 5229 TransitionFlag flag) { |
| 5235 DescriptorArray* old_descriptors = instance_descriptors(); | 5230 DescriptorArray* old_descriptors = instance_descriptors(); |
| 5236 | 5231 |
| 5237 // Ensure the key is a symbol. | 5232 // Ensure the key is a symbol. |
| 5238 MaybeObject* maybe_result = descriptor->KeyToSymbol(); | 5233 MaybeObject* maybe_result = descriptor->KeyToSymbol(); |
| 5239 if (maybe_result->IsFailure()) return maybe_result; | 5234 if (maybe_result->IsFailure()) return maybe_result; |
| 5240 | 5235 |
| 5241 // We replace the key if it is already present. | 5236 // We replace the key if it is already present. |
| 5242 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); | 5237 int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this); |
| 5243 if (index != DescriptorArray::kNotFound) { | 5238 if (index != DescriptorArray::kNotFound) { |
| 5244 return CopyReplaceDescriptor(descriptor, index, flag); | 5239 return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag); |
| 5245 } | 5240 } |
| 5246 return CopyAddDescriptor(descriptor, flag); | 5241 return CopyAddDescriptor(descriptor, flag); |
| 5247 } | 5242 } |
| 5248 | 5243 |
| 5249 | 5244 |
| 5250 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { | 5245 MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) { |
| 5251 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); | 5246 if (enumeration_index == 0) return GetHeap()->empty_descriptor_array(); |
| 5252 | 5247 |
| 5253 int size = enumeration_index; | 5248 int size = enumeration_index; |
| 5254 | 5249 |
| 5255 DescriptorArray* descriptors; | 5250 DescriptorArray* descriptors; |
| 5256 MaybeObject* maybe_descriptors = Allocate(size); | 5251 MaybeObject* maybe_descriptors = Allocate(size); |
| 5257 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | 5252 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 5258 DescriptorArray::WhitenessWitness witness(descriptors); | 5253 DescriptorArray::WhitenessWitness witness(descriptors); |
| 5259 | 5254 |
| 5260 for (int i = 0; i < size; ++i) { | 5255 for (int i = 0; i < size; ++i) { |
| 5261 descriptors->CopyFrom(i, this, i, witness); | 5256 descriptors->CopyFrom(i, this, i, witness); |
| 5262 } | 5257 } |
| 5263 | 5258 |
| 5264 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); | 5259 if (number_of_descriptors() != enumeration_index) descriptors->Sort(); |
| 5265 | 5260 |
| 5266 return descriptors; | 5261 return descriptors; |
| 5267 } | 5262 } |
| 5268 | 5263 |
| 5269 | 5264 |
| 5270 MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, | 5265 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors, |
| 5266 Descriptor* descriptor, |
| 5271 int insertion_index, | 5267 int insertion_index, |
| 5272 TransitionFlag flag) { | 5268 TransitionFlag flag) { |
| 5273 // Ensure the key is a symbol. | 5269 // Ensure the key is a symbol. |
| 5274 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); | 5270 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); |
| 5275 if (maybe_failure->IsFailure()) return maybe_failure; | 5271 if (maybe_failure->IsFailure()) return maybe_failure; |
| 5276 | 5272 |
| 5277 DescriptorArray* descriptors = instance_descriptors(); | |
| 5278 | |
| 5279 String* key = descriptor->GetKey(); | 5273 String* key = descriptor->GetKey(); |
| 5280 ASSERT(key == descriptors->GetKey(insertion_index)); | 5274 ASSERT(key == descriptors->GetKey(insertion_index)); |
| 5281 | 5275 |
| 5282 int new_size = NumberOfOwnDescriptors(); | 5276 int new_size = NumberOfOwnDescriptors(); |
| 5283 ASSERT(0 <= insertion_index && insertion_index < new_size); | 5277 ASSERT(0 <= insertion_index && insertion_index < new_size); |
| 5284 | 5278 |
| 5285 PropertyDetails details = descriptors->GetDetails(insertion_index); | 5279 PropertyDetails details = descriptors->GetDetails(insertion_index); |
| 5286 ASSERT_LE(details.descriptor_index(), new_size); | 5280 ASSERT_LE(details.descriptor_index(), new_size); |
| 5287 descriptor->SetEnumerationIndex(details.descriptor_index()); | 5281 descriptor->SetEnumerationIndex(details.descriptor_index()); |
| 5288 | 5282 |
| (...skipping 2162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7451 | 7445 |
| 7452 | 7446 |
| 7453 static void TrimDescriptorArray(Heap* heap, | 7447 static void TrimDescriptorArray(Heap* heap, |
| 7454 Map* map, | 7448 Map* map, |
| 7455 DescriptorArray* descriptors, | 7449 DescriptorArray* descriptors, |
| 7456 int number_of_own_descriptors) { | 7450 int number_of_own_descriptors) { |
| 7457 int number_of_descriptors = descriptors->number_of_descriptors(); | 7451 int number_of_descriptors = descriptors->number_of_descriptors(); |
| 7458 int to_trim = number_of_descriptors - number_of_own_descriptors; | 7452 int to_trim = number_of_descriptors - number_of_own_descriptors; |
| 7459 if (to_trim <= 0) return; | 7453 if (to_trim <= 0) return; |
| 7460 | 7454 |
| 7461 // Maximally keep 50% of unused descriptors. | 7455 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim); |
| 7462 int keep = Min(to_trim, number_of_own_descriptors / 2); | |
| 7463 for (int i = number_of_own_descriptors; | |
| 7464 i < number_of_own_descriptors + keep; | |
| 7465 ++i) { | |
| 7466 descriptors->EraseDescriptor(heap, i); | |
| 7467 } | |
| 7468 | |
| 7469 if (to_trim > keep) { | |
| 7470 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep); | |
| 7471 } | |
| 7472 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | 7456 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); |
| 7473 | 7457 |
| 7474 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); | 7458 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); |
| 7475 descriptors->Sort(); | 7459 descriptors->Sort(); |
| 7476 } | 7460 } |
| 7477 | 7461 |
| 7478 | 7462 |
| 7479 // Clear a possible back pointer in case the transition leads to a dead map. | 7463 // Clear a possible back pointer in case the transition leads to a dead map. |
| 7480 // Return true in case a back pointer has been cleared and false otherwise. | 7464 // Return true in case a back pointer has been cleared and false otherwise. |
| 7481 static bool ClearBackPointer(Heap* heap, | 7465 static bool ClearBackPointer(Heap* heap, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7539 | 7523 |
| 7540 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 7524 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 7541 | 7525 |
| 7542 if (descriptors_owner_died) { | 7526 if (descriptors_owner_died) { |
| 7543 if (number_of_own_descriptors > 0) { | 7527 if (number_of_own_descriptors > 0) { |
| 7544 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 7528 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
| 7545 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 7529 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
| 7546 } else { | 7530 } else { |
| 7547 t->set_descriptors(heap->empty_descriptor_array()); | 7531 t->set_descriptors(heap->empty_descriptor_array()); |
| 7548 } | 7532 } |
| 7549 set_owns_descriptors(true); | |
| 7550 } | 7533 } |
| 7551 | 7534 |
| 7552 int trim = t->number_of_transitions() - transition_index; | 7535 int trim = t->number_of_transitions() - transition_index; |
| 7553 if (trim > 0) { | 7536 if (trim > 0) { |
| 7554 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() | 7537 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() |
| 7555 ? trim : trim * TransitionArray::kTransitionSize); | 7538 ? trim : trim * TransitionArray::kTransitionSize); |
| 7556 } | 7539 } |
| 7557 } | 7540 } |
| 7558 | 7541 |
| 7559 | 7542 |
| (...skipping 5965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13525 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13508 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
| 13526 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13509 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
| 13527 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13510 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
| 13528 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13511 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
| 13529 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13512 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
| 13530 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13513 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
| 13531 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13514 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
| 13532 } | 13515 } |
| 13533 | 13516 |
| 13534 } } // namespace v8::internal | 13517 } } // namespace v8::internal |
| OLD | NEW |