Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: src/objects.cc

Issue 1411933005: Establish an invariant on initial maps: (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698