| 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 |