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 1746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1757 | 1757 |
1758 MaybeObject* JSObject::ConvertTransitionToMapTransition( | 1758 MaybeObject* JSObject::ConvertTransitionToMapTransition( |
1759 int transition_index, | 1759 int transition_index, |
1760 String* name, | 1760 String* name, |
1761 Object* new_value, | 1761 Object* new_value, |
1762 PropertyAttributes attributes) { | 1762 PropertyAttributes attributes) { |
1763 Map* old_map = map(); | 1763 Map* old_map = map(); |
1764 Map* old_target = old_map->GetTransition(transition_index); | 1764 Map* old_target = old_map->GetTransition(transition_index); |
1765 Object* result; | 1765 Object* result; |
1766 | 1766 |
1767 // To sever a transition to a map with which the descriptors are shared, the | |
1768 // larger map (more descriptors) needs to store its own descriptors array. | |
1769 // Both sides of the severed chain need to have their own descriptors pointer | |
1770 // to store distinct descriptor arrays. | |
1771 | |
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 | |
1774 // the back pointer and setting its descriptor array. | |
1775 | |
1776 // This phase is executed before creating the new map since it requires | |
1777 // allocation that may fail. | |
1778 if (!old_target->StoresOwnDescriptors()) { | |
1779 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | |
1780 MaybeObject* maybe_failure = old_target->SetDescriptors(old_descriptors); | |
1781 if (maybe_failure->IsFailure()) return maybe_failure; | |
1782 } | |
1783 | |
1784 MaybeObject* maybe_result = | 1767 MaybeObject* maybe_result = |
1785 ConvertDescriptorToField(name, new_value, attributes); | 1768 ConvertDescriptorToField(name, new_value, attributes); |
1786 if (!maybe_result->To(&result)) return maybe_result; | 1769 if (!maybe_result->To(&result)) return maybe_result; |
1787 | 1770 |
1788 if (!HasFastProperties()) return result; | 1771 if (!HasFastProperties()) return result; |
1789 | 1772 |
1790 // This method should only be used to convert existing transitions. Objects | 1773 // This method should only be used to convert existing transitions. Objects |
1791 // with the map of "new Object()" cannot have transitions in the first place. | 1774 // with the map of "new Object()" cannot have transitions in the first place. |
1792 Map* new_map = map(); | 1775 Map* new_map = map(); |
1793 ASSERT(new_map != GetIsolate()->empty_object_map()); | 1776 ASSERT(new_map != GetIsolate()->empty_object_map()); |
1794 | 1777 |
1795 // TODO(verwaest): From here on we lose existing map transitions, causing | 1778 // TODO(verwaest): From here on we lose existing map transitions, causing |
1796 // invalid back pointers. This will change once we can store multiple | 1779 // invalid back pointers. This will change once we can store multiple |
1797 // transitions with the same key. | 1780 // transitions with the same key. |
1798 | 1781 |
1799 bool owned_descriptors = old_map->owns_descriptors(); | 1782 bool owned_descriptors = old_map->owns_descriptors(); |
1800 if (owned_descriptors || | 1783 if (owned_descriptors || |
1801 old_target->instance_descriptors() == old_map->instance_descriptors()) { | 1784 old_target->instance_descriptors() == old_map->instance_descriptors()) { |
1802 // Since the conversion above generated a new fast map with an additional | 1785 // Since the conversion above generated a new fast map with an additional |
1803 // property which can be shared as well, install this descriptor pointer | 1786 // property which can be shared as well, install this descriptor pointer |
1804 // along the entire chain of smaller maps; and remove the transition array | 1787 // along the entire chain of smaller maps. |
1805 // that is only in place to hold the descriptor array in the new map. | |
1806 Map* map; | 1788 Map* map; |
1807 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 1789 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
1808 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 1790 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
1809 for (Object* current = old_map; | 1791 for (Object* current = old_map; |
1810 !current->IsUndefined(); | 1792 !current->IsUndefined(); |
1811 current = map->GetBackPointer()) { | 1793 current = map->GetBackPointer()) { |
1812 map = Map::cast(current); | 1794 map = Map::cast(current); |
1813 if (!map->HasTransitionArray()) break; | 1795 if (map->instance_descriptors() != old_descriptors) break; |
1814 TransitionArray* transitions = map->transitions(); | |
1815 if (transitions->descriptors() != old_descriptors) break; | |
1816 map->SetEnumLength(Map::kInvalidEnumCache); | 1796 map->SetEnumLength(Map::kInvalidEnumCache); |
1817 transitions->set_descriptors(new_descriptors); | 1797 map->set_instance_descriptors(new_descriptors); |
1818 } | 1798 } |
1819 old_map->set_owns_descriptors(false); | 1799 old_map->set_owns_descriptors(false); |
1820 new_map->ClearTransitions(GetHeap()); | |
1821 } | 1800 } |
1822 | 1801 |
1823 old_map->SetTransition(transition_index, new_map); | 1802 old_map->SetTransition(transition_index, new_map); |
1824 new_map->SetBackPointer(old_map); | 1803 new_map->SetBackPointer(old_map); |
1825 return result; | 1804 return result; |
1826 } | 1805 } |
1827 | 1806 |
1828 | 1807 |
1829 MaybeObject* JSObject::ConvertDescriptorToField(String* name, | 1808 MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
1830 Object* new_value, | 1809 Object* new_value, |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2194 int number_of_descriptors = descriptors->number_of_descriptors(); | 2173 int number_of_descriptors = descriptors->number_of_descriptors(); |
2195 Isolate* isolate = map->GetIsolate(); | 2174 Isolate* isolate = map->GetIsolate(); |
2196 Handle<DescriptorArray> new_descriptors = | 2175 Handle<DescriptorArray> new_descriptors = |
2197 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); | 2176 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
2198 DescriptorArray::WhitenessWitness witness(*new_descriptors); | 2177 DescriptorArray::WhitenessWitness witness(*new_descriptors); |
2199 | 2178 |
2200 for (int i = 0; i < number_of_descriptors; ++i) { | 2179 for (int i = 0; i < number_of_descriptors; ++i) { |
2201 new_descriptors->CopyFrom(i, *descriptors, i, witness); | 2180 new_descriptors->CopyFrom(i, *descriptors, i, witness); |
2202 } | 2181 } |
2203 | 2182 |
2204 Map::SetDescriptors(map, new_descriptors); | 2183 map->set_instance_descriptors(*new_descriptors); |
2205 } | 2184 } |
2206 | 2185 |
2207 | 2186 |
2208 void Map::AppendCallbackDescriptors(Handle<Map> map, | 2187 void Map::AppendCallbackDescriptors(Handle<Map> map, |
2209 Handle<Object> descriptors) { | 2188 Handle<Object> descriptors) { |
2210 Isolate* isolate = map->GetIsolate(); | 2189 Isolate* isolate = map->GetIsolate(); |
2211 Handle<DescriptorArray> array(map->instance_descriptors()); | 2190 Handle<DescriptorArray> array(map->instance_descriptors()); |
2212 NeanderArray callbacks(descriptors); | 2191 NeanderArray callbacks(descriptors); |
2213 int nof_callbacks = callbacks.length(); | 2192 int nof_callbacks = callbacks.length(); |
2214 | 2193 |
(...skipping 2007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4222 ASSERT(!curr->HasNamedInterceptor()); | 4201 ASSERT(!curr->HasNamedInterceptor()); |
4223 ASSERT(!curr->HasIndexedInterceptor()); | 4202 ASSERT(!curr->HasIndexedInterceptor()); |
4224 ASSERT(!curr->IsAccessCheckNeeded()); | 4203 ASSERT(!curr->IsAccessCheckNeeded()); |
4225 if (curr->NumberOfEnumElements() > 0) return false; | 4204 if (curr->NumberOfEnumElements() > 0) return false; |
4226 if (curr != this && enum_length != 0) return false; | 4205 if (curr != this && enum_length != 0) return false; |
4227 } | 4206 } |
4228 return true; | 4207 return true; |
4229 } | 4208 } |
4230 | 4209 |
4231 | 4210 |
4232 void Map::SetDescriptors(Handle<Map> map, | |
4233 Handle<DescriptorArray> descriptors) { | |
4234 Isolate* isolate = map->GetIsolate(); | |
4235 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); | |
4236 } | |
4237 | |
4238 | |
4239 int Map::NumberOfDescribedProperties(DescriptorFlag which, | 4211 int Map::NumberOfDescribedProperties(DescriptorFlag which, |
4240 PropertyAttributes filter) { | 4212 PropertyAttributes filter) { |
4241 int result = 0; | 4213 int result = 0; |
4242 DescriptorArray* descs = instance_descriptors(); | 4214 DescriptorArray* descs = instance_descriptors(); |
4243 int limit = which == ALL_DESCRIPTORS | 4215 int limit = which == ALL_DESCRIPTORS |
4244 ? descs->number_of_descriptors() | 4216 ? descs->number_of_descriptors() |
4245 : NumberOfOwnDescriptors(); | 4217 : NumberOfOwnDescriptors(); |
4246 for (int i = 0; i < limit; i++) { | 4218 for (int i = 0; i < limit; i++) { |
4247 if ((descs->GetDetails(i).attributes() & filter) == 0) result++; | 4219 if ((descs->GetDetails(i).attributes() & filter) == 0) result++; |
4248 } | 4220 } |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5006 | 4978 |
5007 DescriptorArray::WhitenessWitness witness(new_descriptors); | 4979 DescriptorArray::WhitenessWitness witness(new_descriptors); |
5008 | 4980 |
5009 // Copy the descriptors, inserting a descriptor. | 4981 // Copy the descriptors, inserting a descriptor. |
5010 for (int i = 0; i < old_size; ++i) { | 4982 for (int i = 0; i < old_size; ++i) { |
5011 new_descriptors->CopyFrom(i, descriptors, i, witness); | 4983 new_descriptors->CopyFrom(i, descriptors, i, witness); |
5012 } | 4984 } |
5013 | 4985 |
5014 new_descriptors->Append(descriptor, witness); | 4986 new_descriptors->Append(descriptor, witness); |
5015 | 4987 |
5016 // If the source descriptors had an enum cache we copy it. This ensures that | 4988 if (old_size > 0) { |
5017 // the maps to which we push the new descriptor array back can rely on a | 4989 // If the source descriptors had an enum cache we copy it. This ensures |
5018 // cache always being available once it is set. If the map has more | 4990 // that the maps to which we push the new descriptor array back can rely |
5019 // enumerated descriptors than available in the original cache, the cache | 4991 // on a cache always being available once it is set. If the map has more |
5020 // will be lazily replaced by the extended cache when needed. | 4992 // enumerated descriptors than available in the original cache, the cache |
5021 if (descriptors->HasEnumCache()) { | 4993 // will be lazily replaced by the extended cache when needed. |
5022 new_descriptors->CopyEnumCacheFrom(descriptors); | 4994 if (descriptors->HasEnumCache()) { |
| 4995 new_descriptors->CopyEnumCacheFrom(descriptors); |
| 4996 } |
| 4997 |
| 4998 Map* map; |
| 4999 // Replace descriptors by new_descriptors in all maps that share it. |
| 5000 for (Object* current = GetBackPointer(); |
| 5001 !current->IsUndefined(); |
| 5002 current = map->GetBackPointer()) { |
| 5003 map = Map::cast(current); |
| 5004 if (map->instance_descriptors() != descriptors) break; |
| 5005 map->set_instance_descriptors(new_descriptors); |
| 5006 } |
| 5007 |
| 5008 set_instance_descriptors(new_descriptors); |
5023 } | 5009 } |
5024 | |
5025 Map* map; | |
5026 // Replace descriptors by new_descriptors in all maps that share it. | |
5027 for (Object* current = GetBackPointer(); | |
5028 !current->IsUndefined(); | |
5029 current = map->GetBackPointer()) { | |
5030 map = Map::cast(current); | |
5031 if (!map->HasTransitionArray()) break; | |
5032 TransitionArray* transitions = map->transitions(); | |
5033 if (transitions->descriptors() != descriptors) break; | |
5034 transitions->set_descriptors(new_descriptors); | |
5035 } | |
5036 | |
5037 transitions->set_descriptors(new_descriptors); | |
5038 } | 5010 } |
5039 | 5011 |
| 5012 result->SetBackPointer(this); |
| 5013 result->InitializeDescriptors(new_descriptors); |
| 5014 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); |
| 5015 |
5040 set_transitions(transitions); | 5016 set_transitions(transitions); |
5041 result->SetBackPointer(this); | |
5042 set_owns_descriptors(false); | 5017 set_owns_descriptors(false); |
5043 | 5018 |
5044 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); | |
5045 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); | |
5046 | |
5047 return result; | 5019 return result; |
5048 } | 5020 } |
5049 | 5021 |
5050 | 5022 |
5051 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, | 5023 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
5052 String* name, | 5024 String* name, |
5053 TransitionFlag flag, | 5025 TransitionFlag flag, |
5054 int descriptor_index) { | 5026 int descriptor_index) { |
5055 ASSERT(descriptors->IsSortedNoDuplicates()); | 5027 ASSERT(descriptors->IsSortedNoDuplicates()); |
5056 | 5028 |
5057 Map* result; | 5029 Map* result; |
5058 MaybeObject* maybe_result = CopyDropDescriptors(); | 5030 MaybeObject* maybe_result = CopyDropDescriptors(); |
5059 if (!maybe_result->To(&result)) return maybe_result; | 5031 if (!maybe_result->To(&result)) return maybe_result; |
5060 | 5032 |
5061 // Unless we are creating a map with no descriptors and no back pointer, we | 5033 result->InitializeDescriptors(descriptors); |
5062 // insert the descriptor array locally. | |
5063 if (!descriptors->IsEmpty()) { | |
5064 MaybeObject* maybe_failure = result->SetDescriptors(descriptors); | |
5065 if (maybe_failure->IsFailure()) return maybe_failure; | |
5066 result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors()); | |
5067 } | |
5068 | 5034 |
5069 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 5035 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
5070 TransitionArray* transitions; | 5036 TransitionArray* transitions; |
5071 SimpleTransitionFlag simple_flag = | 5037 SimpleTransitionFlag simple_flag = |
5072 (descriptor_index == descriptors->number_of_descriptors() - 1) | 5038 (descriptor_index == descriptors->number_of_descriptors() - 1) |
5073 ? SIMPLE_TRANSITION | 5039 ? SIMPLE_TRANSITION |
5074 : FULL_TRANSITION; | 5040 : FULL_TRANSITION; |
5075 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 5041 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
5076 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 5042 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
5077 | 5043 |
5078 if (descriptors->IsEmpty()) { | |
5079 if (owns_descriptors()) { | |
5080 // If the copied map has no added fields, and the parent map owns its | |
5081 // descriptors, those descriptors have to be empty. In that case, | |
5082 // transfer ownership of the descriptors to the new child. | |
5083 ASSERT(instance_descriptors()->IsEmpty()); | |
5084 set_owns_descriptors(false); | |
5085 } else { | |
5086 // If the parent did not own its own descriptors, it may share a larger | |
5087 // descriptors array already. In that case, force a split by setting | |
5088 // the descriptor array of the new map to the empty descriptor array. | |
5089 MaybeObject* maybe_failure = | |
5090 result->SetDescriptors(GetHeap()->empty_descriptor_array()); | |
5091 if (maybe_failure->IsFailure()) return maybe_failure; | |
5092 } | |
5093 } | |
5094 | |
5095 set_transitions(transitions); | 5044 set_transitions(transitions); |
5096 result->SetBackPointer(this); | 5045 result->SetBackPointer(this); |
5097 } | 5046 } |
5098 | 5047 |
5099 return result; | 5048 return result; |
5100 } | 5049 } |
5101 | 5050 |
5102 | 5051 |
5103 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { | 5052 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
5104 if (flag == INSERT_TRANSITION) { | 5053 if (flag == INSERT_TRANSITION) { |
5105 ASSERT(!HasElementsTransition() || | 5054 ASSERT(!HasElementsTransition() || |
5106 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || | 5055 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || |
5107 IsExternalArrayElementsKind( | 5056 IsExternalArrayElementsKind( |
5108 elements_transition_map()->elements_kind())) && | 5057 elements_transition_map()->elements_kind())) && |
5109 (kind == DICTIONARY_ELEMENTS || | 5058 (kind == DICTIONARY_ELEMENTS || |
5110 IsExternalArrayElementsKind(kind)))); | 5059 IsExternalArrayElementsKind(kind)))); |
5111 ASSERT(!IsFastElementsKind(kind) || | 5060 ASSERT(!IsFastElementsKind(kind) || |
5112 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); | 5061 IsMoreGeneralElementsKindTransition(elements_kind(), kind)); |
5113 ASSERT(kind != elements_kind()); | 5062 ASSERT(kind != elements_kind()); |
5114 } | 5063 } |
5115 | 5064 |
5116 if (flag == INSERT_TRANSITION && owns_descriptors()) { | 5065 bool insert_transition = |
| 5066 flag == INSERT_TRANSITION && !HasElementsTransition(); |
| 5067 |
| 5068 if (insert_transition && owns_descriptors()) { |
5117 // In case the map owned its own descriptors, share the descriptors and | 5069 // In case the map owned its own descriptors, share the descriptors and |
5118 // transfer ownership to the new map. | 5070 // transfer ownership to the new map. |
5119 Map* new_map; | 5071 Map* new_map; |
5120 MaybeObject* maybe_new_map = CopyDropDescriptors(); | 5072 MaybeObject* maybe_new_map = CopyDropDescriptors(); |
5121 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 5073 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
5122 | 5074 |
5123 MaybeObject* added_elements = set_elements_transition_map(new_map); | 5075 MaybeObject* added_elements = set_elements_transition_map(new_map); |
5124 if (added_elements->IsFailure()) return added_elements; | 5076 if (added_elements->IsFailure()) return added_elements; |
5125 | 5077 |
5126 new_map->set_elements_kind(kind); | 5078 new_map->set_elements_kind(kind); |
| 5079 new_map->InitializeDescriptors(instance_descriptors()); |
5127 new_map->SetBackPointer(this); | 5080 new_map->SetBackPointer(this); |
5128 new_map->SetNumberOfOwnDescriptors(NumberOfOwnDescriptors()); | |
5129 set_owns_descriptors(false); | 5081 set_owns_descriptors(false); |
5130 return new_map; | 5082 return new_map; |
5131 } | 5083 } |
5132 | 5084 |
5133 // In case the map did not own its own descriptors, a split is forced by | 5085 // In case the map did not own its own descriptors, a split is forced by |
5134 // copying the map; creating a new descriptor array cell. | 5086 // copying the map; creating a new descriptor array cell. |
5135 // Create a new free-floating map only if we are not allowed to store it. | 5087 // Create a new free-floating map only if we are not allowed to store it. |
5136 Map* new_map; | 5088 Map* new_map; |
5137 MaybeObject* maybe_new_map = Copy(); | 5089 MaybeObject* maybe_new_map = Copy(); |
5138 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 5090 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
5139 ASSERT(new_map->NumberOfOwnDescriptors() == NumberOfOwnDescriptors()); | 5091 |
5140 new_map->set_elements_kind(kind); | 5092 new_map->set_elements_kind(kind); |
5141 | 5093 |
5142 if (flag == INSERT_TRANSITION && !HasElementsTransition()) { | 5094 if (insert_transition) { |
5143 // Map::Copy does not store the descriptor array in case it is empty, since | |
5144 // it does not insert a back pointer; implicitly indicating that its | |
5145 // descriptor array is empty. Since in this case we do want to insert a back | |
5146 // pointer, we have to manually set the empty descriptor array to force a | |
5147 // split. | |
5148 if (!new_map->StoresOwnDescriptors()) { | |
5149 ASSERT(new_map->NumberOfOwnDescriptors() == 0); | |
5150 MaybeObject* maybe_failure = | |
5151 new_map->SetDescriptors(GetHeap()->empty_descriptor_array()); | |
5152 if (maybe_failure->IsFailure()) return maybe_failure; | |
5153 } | |
5154 MaybeObject* added_elements = set_elements_transition_map(new_map); | 5095 MaybeObject* added_elements = set_elements_transition_map(new_map); |
5155 if (added_elements->IsFailure()) return added_elements; | 5096 if (added_elements->IsFailure()) return added_elements; |
5156 | |
5157 new_map->SetBackPointer(this); | 5097 new_map->SetBackPointer(this); |
5158 } | 5098 } |
5159 | 5099 |
5160 return new_map; | 5100 return new_map; |
5161 } | 5101 } |
5162 | 5102 |
5163 | 5103 |
5164 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { | 5104 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
5165 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); | 5105 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
5166 | 5106 |
(...skipping 2293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7460 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim); | 7400 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim); |
7461 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); | 7401 descriptors->SetNumberOfDescriptors(number_of_own_descriptors); |
7462 | 7402 |
7463 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); | 7403 if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors); |
7464 descriptors->Sort(); | 7404 descriptors->Sort(); |
7465 } | 7405 } |
7466 | 7406 |
7467 | 7407 |
7468 // Clear a possible back pointer in case the transition leads to a dead map. | 7408 // Clear a possible back pointer in case the transition leads to a dead map. |
7469 // Return true in case a back pointer has been cleared and false otherwise. | 7409 // Return true in case a back pointer has been cleared and false otherwise. |
7470 static bool ClearBackPointer(Heap* heap, | 7410 static bool ClearBackPointer(Heap* heap, Map* target) { |
7471 Map* target, | |
7472 DescriptorArray* descriptors, | |
7473 bool* descriptors_owner_died) { | |
7474 if (Marking::MarkBitFrom(target).Get()) return false; | 7411 if (Marking::MarkBitFrom(target).Get()) return false; |
7475 if (target->instance_descriptors() == descriptors) { | |
7476 *descriptors_owner_died = true; | |
7477 } | |
7478 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); | 7412 target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER); |
7479 return true; | 7413 return true; |
7480 } | 7414 } |
7481 | 7415 |
7482 | 7416 |
7483 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, | 7417 // TODO(mstarzinger): This method should be moved into MarkCompactCollector, |
7484 // because it cannot be called from outside the GC and we already have methods | 7418 // because it cannot be called from outside the GC and we already have methods |
7485 // depending on the transitions layout in the GC anyways. | 7419 // depending on the transitions layout in the GC anyways. |
7486 void Map::ClearNonLiveTransitions(Heap* heap) { | 7420 void Map::ClearNonLiveTransitions(Heap* heap) { |
7487 // If there are no transitions to be cleared, return. | 7421 // If there are no transitions to be cleared, return. |
7488 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7422 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7489 // properly cleared. | 7423 // properly cleared. |
7490 if (!HasTransitionArray()) return; | 7424 if (!HasTransitionArray()) return; |
7491 | 7425 |
7492 TransitionArray* t = transitions(); | 7426 TransitionArray* t = transitions(); |
7493 MarkCompactCollector* collector = heap->mark_compact_collector(); | 7427 MarkCompactCollector* collector = heap->mark_compact_collector(); |
7494 | 7428 |
7495 int transition_index = 0; | 7429 int transition_index = 0; |
7496 | 7430 |
7497 DescriptorArray* descriptors = t->descriptors(); | 7431 DescriptorArray* descriptors = instance_descriptors(); |
7498 bool descriptors_owner_died = false; | 7432 bool descriptors_owner_died = false; |
7499 | 7433 |
7500 // Compact all live descriptors to the left. | 7434 // Compact all live descriptors to the left. |
7501 for (int i = 0; i < t->number_of_transitions(); ++i) { | 7435 for (int i = 0; i < t->number_of_transitions(); ++i) { |
7502 Map* target = t->GetTarget(i); | 7436 Map* target = t->GetTarget(i); |
7503 if (!ClearBackPointer(heap, target, descriptors, &descriptors_owner_died)) { | 7437 if (ClearBackPointer(heap, target)) { |
| 7438 if (target->instance_descriptors() == descriptors) { |
| 7439 descriptors_owner_died = true; |
| 7440 descriptors_owner_died = true; |
| 7441 } |
| 7442 } else { |
7504 if (i != transition_index) { | 7443 if (i != transition_index) { |
7505 String* key = t->GetKey(i); | 7444 String* key = t->GetKey(i); |
7506 t->SetKey(transition_index, key); | 7445 t->SetKey(transition_index, key); |
7507 Object** key_slot = t->GetKeySlot(transition_index); | 7446 Object** key_slot = t->GetKeySlot(transition_index); |
7508 collector->RecordSlot(key_slot, key_slot, key); | 7447 collector->RecordSlot(key_slot, key_slot, key); |
7509 // Target slots do not need to be recorded since maps are not compacted. | 7448 // Target slots do not need to be recorded since maps are not compacted. |
7510 t->SetTarget(transition_index, t->GetTarget(i)); | 7449 t->SetTarget(transition_index, t->GetTarget(i)); |
7511 } | 7450 } |
7512 transition_index++; | 7451 transition_index++; |
7513 } | 7452 } |
7514 } | 7453 } |
7515 | 7454 |
7516 if (t->HasElementsTransition() && | 7455 if (t->HasElementsTransition() && |
7517 ClearBackPointer(heap, | 7456 ClearBackPointer(heap, t->elements_transition())) { |
7518 t->elements_transition(), | 7457 if (t->elements_transition()->instance_descriptors() == descriptors) { |
7519 descriptors, | 7458 descriptors_owner_died = true; |
7520 &descriptors_owner_died)) { | 7459 } |
7521 t->ClearElementsTransition(); | 7460 t->ClearElementsTransition(); |
7522 } else { | 7461 } else { |
7523 // If there are no transitions to be cleared, return. | 7462 // If there are no transitions to be cleared, return. |
7524 // TODO(verwaest) Should be an assert, otherwise back pointers are not | 7463 // TODO(verwaest) Should be an assert, otherwise back pointers are not |
7525 // properly cleared. | 7464 // properly cleared. |
7526 if (transition_index == t->number_of_transitions()) return; | 7465 if (transition_index == t->number_of_transitions()) return; |
7527 } | 7466 } |
7528 | 7467 |
7529 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 7468 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
7530 | 7469 |
7531 if (descriptors_owner_died) { | 7470 if (descriptors_owner_died) { |
7532 if (number_of_own_descriptors > 0) { | 7471 if (number_of_own_descriptors > 0) { |
7533 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); | 7472 TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors); |
7534 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); | 7473 ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors); |
7535 } else { | 7474 } else { |
7536 t->set_descriptors(heap->empty_descriptor_array()); | 7475 ASSERT(descriptors == GetHeap()->empty_descriptor_array()); |
7537 } | 7476 } |
7538 } | 7477 } |
7539 | 7478 |
7540 int trim = t->number_of_transitions() - transition_index; | 7479 int trim = t->number_of_transitions() - transition_index; |
7541 if (trim > 0) { | 7480 if (trim > 0) { |
7542 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() | 7481 RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition() |
7543 ? trim : trim * TransitionArray::kTransitionSize); | 7482 ? trim : trim * TransitionArray::kTransitionSize); |
7544 } | 7483 } |
7545 } | 7484 } |
7546 | 7485 |
(...skipping 5461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13008 descriptors->Set(enumeration_index - 1, &d, witness); | 12947 descriptors->Set(enumeration_index - 1, &d, witness); |
13009 } else { | 12948 } else { |
13010 UNREACHABLE(); | 12949 UNREACHABLE(); |
13011 } | 12950 } |
13012 } | 12951 } |
13013 } | 12952 } |
13014 ASSERT(current_offset == number_of_fields); | 12953 ASSERT(current_offset == number_of_fields); |
13015 | 12954 |
13016 descriptors->Sort(); | 12955 descriptors->Sort(); |
13017 | 12956 |
13018 MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors); | 12957 new_map->InitializeDescriptors(descriptors); |
13019 if (maybe_failure->IsFailure()) return maybe_failure; | |
13020 new_map->set_unused_property_fields(unused_property_fields); | 12958 new_map->set_unused_property_fields(unused_property_fields); |
13021 | 12959 |
13022 // Transform the object. | 12960 // Transform the object. |
13023 obj->set_map(new_map); | 12961 obj->set_map(new_map); |
13024 | 12962 |
13025 obj->set_properties(fields); | 12963 obj->set_properties(fields); |
13026 ASSERT(obj->IsJSObject()); | 12964 ASSERT(obj->IsJSObject()); |
13027 | 12965 |
13028 // Check that it really works. | 12966 // Check that it really works. |
13029 ASSERT(obj->HasFastProperties()); | 12967 ASSERT(obj->HasFastProperties()); |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13529 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13467 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13530 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13468 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13531 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13469 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13532 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13470 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13533 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13471 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13534 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13472 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13535 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13473 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13536 } | 13474 } |
13537 | 13475 |
13538 } } // namespace v8::internal | 13476 } } // namespace v8::internal |
OLD | NEW |