OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 2686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2697 DescriptorArray* new_descriptors, | 2697 DescriptorArray* new_descriptors, |
2698 LayoutDescriptor* new_layout_descriptor) { | 2698 LayoutDescriptor* new_layout_descriptor) { |
2699 bool transition_target_deprecated = false; | 2699 bool transition_target_deprecated = false; |
2700 Map* maybe_transition = | 2700 Map* maybe_transition = |
2701 TransitionArray::SearchTransition(this, kind, key, attributes); | 2701 TransitionArray::SearchTransition(this, kind, key, attributes); |
2702 if (maybe_transition != NULL) { | 2702 if (maybe_transition != NULL) { |
2703 maybe_transition->DeprecateTransitionTree(); | 2703 maybe_transition->DeprecateTransitionTree(); |
2704 transition_target_deprecated = true; | 2704 transition_target_deprecated = true; |
2705 } | 2705 } |
2706 | 2706 |
2707 // Don't overwrite the empty descriptor array. | 2707 // Don't overwrite the empty descriptor array or initial map's descriptors. |
2708 if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated; | 2708 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) { |
| 2709 return transition_target_deprecated; |
| 2710 } |
2709 | 2711 |
2710 DescriptorArray* to_replace = instance_descriptors(); | 2712 DescriptorArray* to_replace = instance_descriptors(); |
| 2713 GetHeap()->incremental_marking()->RecordWrites(to_replace); |
2711 Map* current = this; | 2714 Map* current = this; |
2712 GetHeap()->incremental_marking()->RecordWrites(to_replace); | |
2713 while (current->instance_descriptors() == to_replace) { | 2715 while (current->instance_descriptors() == to_replace) { |
| 2716 Object* next = current->GetBackPointer(); |
| 2717 if (next->IsUndefined()) break; // Stop overwriting at initial map. |
2714 current->SetEnumLength(kInvalidEnumCacheSentinel); | 2718 current->SetEnumLength(kInvalidEnumCacheSentinel); |
2715 current->UpdateDescriptors(new_descriptors, new_layout_descriptor); | 2719 current->UpdateDescriptors(new_descriptors, new_layout_descriptor); |
2716 Object* next = current->GetBackPointer(); | |
2717 if (next->IsUndefined()) break; | |
2718 current = Map::cast(next); | 2720 current = Map::cast(next); |
2719 } | 2721 } |
2720 | |
2721 set_owns_descriptors(false); | 2722 set_owns_descriptors(false); |
2722 return transition_target_deprecated; | 2723 return transition_target_deprecated; |
2723 } | 2724 } |
2724 | 2725 |
2725 | 2726 |
2726 Map* Map::FindRootMap() { | 2727 Map* Map::FindRootMap() { |
2727 Map* result = this; | 2728 Map* result = this; |
2728 while (true) { | 2729 while (true) { |
2729 Object* back = result->GetBackPointer(); | 2730 Object* back = result->GetBackPointer(); |
2730 if (back->IsUndefined()) return result; | 2731 if (back->IsUndefined()) { |
| 2732 // Initial map always owns descriptors and doesn't have unused entries |
| 2733 // in the descriptor array. |
| 2734 DCHECK(result->owns_descriptors()); |
| 2735 DCHECK_EQ(result->NumberOfOwnDescriptors(), |
| 2736 result->instance_descriptors()->number_of_descriptors()); |
| 2737 return result; |
| 2738 } |
2731 result = Map::cast(back); | 2739 result = Map::cast(back); |
2732 } | 2740 } |
2733 } | 2741 } |
2734 | 2742 |
2735 | 2743 |
2736 Map* Map::FindLastMatchMap(int verbatim, | 2744 Map* Map::FindLastMatchMap(int verbatim, |
2737 int length, | 2745 int length, |
2738 DescriptorArray* descriptors) { | 2746 DescriptorArray* descriptors) { |
2739 DisallowHeapAllocation no_allocation; | 2747 DisallowHeapAllocation no_allocation; |
2740 | 2748 |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4082 // on a cache always being available once it is set. If the map has more | 4090 // on a cache always being available once it is set. If the map has more |
4083 // enumerated descriptors than available in the original cache, the cache | 4091 // enumerated descriptors than available in the original cache, the cache |
4084 // will be lazily replaced by the extended cache when needed. | 4092 // will be lazily replaced by the extended cache when needed. |
4085 if (descriptors->HasEnumCache()) { | 4093 if (descriptors->HasEnumCache()) { |
4086 new_descriptors->CopyEnumCacheFrom(*descriptors); | 4094 new_descriptors->CopyEnumCacheFrom(*descriptors); |
4087 } | 4095 } |
4088 | 4096 |
4089 // Replace descriptors by new_descriptors in all maps that share it. | 4097 // Replace descriptors by new_descriptors in all maps that share it. |
4090 map->GetHeap()->incremental_marking()->RecordWrites(*descriptors); | 4098 map->GetHeap()->incremental_marking()->RecordWrites(*descriptors); |
4091 | 4099 |
4092 Map* walk_map; | 4100 Map* current = *map; |
4093 for (Object* current = map->GetBackPointer(); | 4101 while (current->instance_descriptors() == *descriptors) { |
4094 !current->IsUndefined(); | 4102 Object* next = current->GetBackPointer(); |
4095 current = walk_map->GetBackPointer()) { | 4103 if (next->IsUndefined()) break; // Stop overwriting at initial map. |
4096 walk_map = Map::cast(current); | 4104 current->UpdateDescriptors(*new_descriptors, layout_descriptor); |
4097 if (walk_map->instance_descriptors() != *descriptors) break; | 4105 current = Map::cast(next); |
4098 walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor); | |
4099 } | 4106 } |
4100 | |
4101 map->UpdateDescriptors(*new_descriptors, layout_descriptor); | 4107 map->UpdateDescriptors(*new_descriptors, layout_descriptor); |
4102 } | 4108 } |
4103 | 4109 |
4104 | 4110 |
4105 template<class T> | 4111 template<class T> |
4106 static int AppendUniqueCallbacks(NeanderArray* callbacks, | 4112 static int AppendUniqueCallbacks(NeanderArray* callbacks, |
4107 Handle<typename T::Array> array, | 4113 Handle<typename T::Array> array, |
4108 int valid_descriptors) { | 4114 int valid_descriptors) { |
4109 int nof_callbacks = callbacks->length(); | 4115 int nof_callbacks = callbacks->length(); |
4110 | 4116 |
(...skipping 4097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8208 | 8214 |
8209 | 8215 |
8210 Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size, | 8216 Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size, |
8211 int in_object_properties, | 8217 int in_object_properties, |
8212 int unused_property_fields) { | 8218 int unused_property_fields) { |
8213 #ifdef DEBUG | 8219 #ifdef DEBUG |
8214 Object* constructor = map->GetConstructor(); | 8220 Object* constructor = map->GetConstructor(); |
8215 DCHECK(constructor->IsJSFunction()); | 8221 DCHECK(constructor->IsJSFunction()); |
8216 DCHECK_EQ(*map, JSFunction::cast(constructor)->initial_map()); | 8222 DCHECK_EQ(*map, JSFunction::cast(constructor)->initial_map()); |
8217 #endif | 8223 #endif |
| 8224 // Initial maps must always own their descriptors and it's descriptor array |
| 8225 // does not contain descriptors that do not belong to the map. |
| 8226 DCHECK(map->owns_descriptors()); |
| 8227 DCHECK_EQ(map->NumberOfOwnDescriptors(), |
| 8228 map->instance_descriptors()->number_of_descriptors()); |
| 8229 |
8218 Handle<Map> result = RawCopy(map, instance_size); | 8230 Handle<Map> result = RawCopy(map, instance_size); |
8219 | 8231 |
8220 // Please note instance_type and instance_size are set when allocated. | 8232 // Please note instance_type and instance_size are set when allocated. |
8221 result->SetInObjectProperties(in_object_properties); | 8233 result->SetInObjectProperties(in_object_properties); |
8222 result->set_unused_property_fields(unused_property_fields); | 8234 result->set_unused_property_fields(unused_property_fields); |
8223 | 8235 |
8224 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 8236 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
8225 if (number_of_own_descriptors > 0) { | 8237 if (number_of_own_descriptors > 0) { |
8226 DCHECK(map->owns_descriptors()); | 8238 // The copy will use the same descriptors array. |
8227 // The copy will use the same descriptors array, but it's not the owner. | |
8228 result->UpdateDescriptors(map->instance_descriptors(), | 8239 result->UpdateDescriptors(map->instance_descriptors(), |
8229 map->layout_descriptor()); | 8240 map->layout_descriptor()); |
8230 result->set_owns_descriptors(false); | |
8231 result->SetNumberOfOwnDescriptors(number_of_own_descriptors); | 8241 result->SetNumberOfOwnDescriptors(number_of_own_descriptors); |
8232 | 8242 |
8233 DCHECK_EQ(result->NumberOfFields(), | 8243 DCHECK_EQ(result->NumberOfFields(), |
8234 in_object_properties - unused_property_fields); | 8244 in_object_properties - unused_property_fields); |
8235 } | 8245 } |
8236 | 8246 |
8237 return result; | 8247 return result; |
8238 } | 8248 } |
8239 | 8249 |
8240 | 8250 |
8241 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { | 8251 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { |
8242 Handle<Map> result = RawCopy(map, map->instance_size()); | 8252 Handle<Map> result = RawCopy(map, map->instance_size()); |
8243 | 8253 |
8244 // Please note instance_type and instance_size are set when allocated. | 8254 // Please note instance_type and instance_size are set when allocated. |
8245 result->SetInObjectProperties(map->GetInObjectProperties()); | 8255 result->SetInObjectProperties(map->GetInObjectProperties()); |
8246 result->set_unused_property_fields(map->unused_property_fields()); | 8256 result->set_unused_property_fields(map->unused_property_fields()); |
8247 | 8257 |
8248 result->ClearCodeCache(map->GetHeap()); | 8258 result->ClearCodeCache(map->GetHeap()); |
8249 map->NotifyLeafMapLayoutChange(); | 8259 map->NotifyLeafMapLayoutChange(); |
8250 return result; | 8260 return result; |
8251 } | 8261 } |
8252 | 8262 |
8253 | 8263 |
8254 Handle<Map> Map::ShareDescriptor(Handle<Map> map, | 8264 Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
8255 Handle<DescriptorArray> descriptors, | 8265 Handle<DescriptorArray> descriptors, |
8256 Descriptor* descriptor) { | 8266 Descriptor* descriptor) { |
8257 // Sanity check. This path is only to be taken if the map owns its descriptor | 8267 // Sanity check. This path is only to be taken if the map owns its descriptor |
8258 // array, implying that its NumberOfOwnDescriptors equals the number of | 8268 // array, implying that its NumberOfOwnDescriptors equals the number of |
8259 // descriptors in the descriptor array. | 8269 // descriptors in the descriptor array. |
8260 DCHECK(map->NumberOfOwnDescriptors() == | 8270 DCHECK_EQ(map->NumberOfOwnDescriptors(), |
8261 map->instance_descriptors()->number_of_descriptors()); | 8271 map->instance_descriptors()->number_of_descriptors()); |
8262 | 8272 |
8263 Handle<Map> result = CopyDropDescriptors(map); | 8273 Handle<Map> result = CopyDropDescriptors(map); |
8264 Handle<Name> name = descriptor->GetKey(); | 8274 Handle<Name> name = descriptor->GetKey(); |
8265 | 8275 |
8266 // Ensure there's space for the new descriptor in the shared descriptor array. | 8276 // Ensure there's space for the new descriptor in the shared descriptor array. |
8267 if (descriptors->NumberOfSlackDescriptors() == 0) { | 8277 if (descriptors->NumberOfSlackDescriptors() == 0) { |
8268 int old_size = descriptors->number_of_descriptors(); | 8278 int old_size = descriptors->number_of_descriptors(); |
8269 if (old_size == 0) { | 8279 if (old_size == 0) { |
8270 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); | 8280 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); |
8271 } else { | 8281 } else { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8316 Map::TraceTransition("Transition", map, target, key); | 8326 Map::TraceTransition("Transition", map, target, key); |
8317 Map::TraceAllTransitions(target); | 8327 Map::TraceAllTransitions(target); |
8318 } | 8328 } |
8319 } | 8329 } |
8320 | 8330 |
8321 #endif // TRACE_MAPS | 8331 #endif // TRACE_MAPS |
8322 | 8332 |
8323 | 8333 |
8324 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, | 8334 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
8325 Handle<Name> name, SimpleTransitionFlag flag) { | 8335 Handle<Name> name, SimpleTransitionFlag flag) { |
8326 parent->set_owns_descriptors(false); | 8336 if (!parent->GetBackPointer()->IsUndefined()) { |
| 8337 parent->set_owns_descriptors(false); |
| 8338 } else { |
| 8339 // |parent| is initial map and it must keep the ownership, there must be no |
| 8340 // descriptors in the descriptors array that do not belong to the map. |
| 8341 DCHECK(parent->owns_descriptors()); |
| 8342 DCHECK_EQ(parent->NumberOfOwnDescriptors(), |
| 8343 parent->instance_descriptors()->number_of_descriptors()); |
| 8344 } |
8327 if (parent->is_prototype_map()) { | 8345 if (parent->is_prototype_map()) { |
8328 DCHECK(child->is_prototype_map()); | 8346 DCHECK(child->is_prototype_map()); |
8329 #if TRACE_MAPS | 8347 #if TRACE_MAPS |
8330 Map::TraceTransition("NoTransition", *parent, *child, *name); | 8348 Map::TraceTransition("NoTransition", *parent, *child, *name); |
8331 #endif | 8349 #endif |
8332 } else { | 8350 } else { |
8333 TransitionArray::Insert(parent, name, child, flag); | 8351 TransitionArray::Insert(parent, name, child, flag); |
8334 #if TRACE_MAPS | 8352 #if TRACE_MAPS |
8335 Map::TraceTransition("Transition", *parent, *child, *name); | 8353 Map::TraceTransition("Transition", *parent, *child, *name); |
8336 #endif | 8354 #endif |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8814 | 8832 |
8815 | 8833 |
8816 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, | 8834 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
8817 Descriptor* descriptor, | 8835 Descriptor* descriptor, |
8818 TransitionFlag flag) { | 8836 TransitionFlag flag) { |
8819 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 8837 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
8820 | 8838 |
8821 // Ensure the key is unique. | 8839 // Ensure the key is unique. |
8822 descriptor->KeyToUniqueName(); | 8840 descriptor->KeyToUniqueName(); |
8823 | 8841 |
| 8842 // Share descriptors only if map owns descriptors and it not an initial map. |
8824 if (flag == INSERT_TRANSITION && map->owns_descriptors() && | 8843 if (flag == INSERT_TRANSITION && map->owns_descriptors() && |
| 8844 !map->GetBackPointer()->IsUndefined() && |
8825 TransitionArray::CanHaveMoreTransitions(map)) { | 8845 TransitionArray::CanHaveMoreTransitions(map)) { |
8826 return ShareDescriptor(map, descriptors, descriptor); | 8846 return ShareDescriptor(map, descriptors, descriptor); |
8827 } | 8847 } |
8828 | 8848 |
8829 int nof = map->NumberOfOwnDescriptors(); | 8849 int nof = map->NumberOfOwnDescriptors(); |
8830 Handle<DescriptorArray> new_descriptors = | 8850 Handle<DescriptorArray> new_descriptors = |
8831 DescriptorArray::CopyUpTo(descriptors, nof, 1); | 8851 DescriptorArray::CopyUpTo(descriptors, nof, 1); |
8832 new_descriptors->Append(descriptor); | 8852 new_descriptors->Append(descriptor); |
8833 | 8853 |
8834 Handle<LayoutDescriptor> new_layout_descriptor = | 8854 Handle<LayoutDescriptor> new_layout_descriptor = |
(...skipping 9198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18033 if (cell->value() != *new_value) { | 18053 if (cell->value() != *new_value) { |
18034 cell->set_value(*new_value); | 18054 cell->set_value(*new_value); |
18035 Isolate* isolate = cell->GetIsolate(); | 18055 Isolate* isolate = cell->GetIsolate(); |
18036 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18056 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18037 isolate, DependentCode::kPropertyCellChangedGroup); | 18057 isolate, DependentCode::kPropertyCellChangedGroup); |
18038 } | 18058 } |
18039 } | 18059 } |
18040 | 18060 |
18041 } // namespace internal | 18061 } // namespace internal |
18042 } // namespace v8 | 18062 } // namespace v8 |
OLD | NEW |