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

Side by Side Diff: src/objects.cc

Issue 1520613006: During property reconfiguring ensure that the first map that gets new descriptors is the one that o… (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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 | « src/objects.h ('k') | src/objects-inl.h » ('j') | 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 2897 matching lines...) Expand 10 before | Expand all | Expand 10 after
2908 } 2908 }
2909 2909
2910 2910
2911 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) { 2911 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
2912 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds. 2912 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds.
2913 // TODO(ishell): compare AccessorPairs. 2913 // TODO(ishell): compare AccessorPairs.
2914 return false; 2914 return false;
2915 } 2915 }
2916 2916
2917 2917
2918 // Invalidates a transition target at |key|, and installs |new_descriptors| over 2918 // Installs |new_descriptors| over the current instance_descriptors to ensure
2919 // the current instance_descriptors to ensure proper sharing of descriptor 2919 // proper sharing of descriptor arrays.
2920 // arrays. 2920 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
2921 // Returns true if the transition target at given key was deprecated. 2921 LayoutDescriptor* new_layout_descriptor) {
2922 bool Map::DeprecateTarget(PropertyKind kind, Name* key,
2923 PropertyAttributes attributes,
2924 DescriptorArray* new_descriptors,
2925 LayoutDescriptor* new_layout_descriptor) {
2926 bool transition_target_deprecated = false;
2927 Map* maybe_transition =
2928 TransitionArray::SearchTransition(this, kind, key, attributes);
2929 if (maybe_transition != NULL) {
2930 maybe_transition->DeprecateTransitionTree();
2931 transition_target_deprecated = true;
2932 }
2933
2934 // Don't overwrite the empty descriptor array or initial map's descriptors. 2922 // Don't overwrite the empty descriptor array or initial map's descriptors.
2935 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) { 2923 if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) {
2936 return transition_target_deprecated; 2924 return;
2937 } 2925 }
2938 2926
2939 DescriptorArray* to_replace = instance_descriptors(); 2927 DescriptorArray* to_replace = instance_descriptors();
2940 GetHeap()->incremental_marking()->RecordWrites(to_replace); 2928 GetHeap()->incremental_marking()->RecordWrites(to_replace);
2941 Map* current = this; 2929 Map* current = this;
2942 while (current->instance_descriptors() == to_replace) { 2930 while (current->instance_descriptors() == to_replace) {
2943 Object* next = current->GetBackPointer(); 2931 Object* next = current->GetBackPointer();
2944 if (next->IsUndefined()) break; // Stop overwriting at initial map. 2932 if (next->IsUndefined()) break; // Stop overwriting at initial map.
2945 current->SetEnumLength(kInvalidEnumCacheSentinel); 2933 current->SetEnumLength(kInvalidEnumCacheSentinel);
2946 current->UpdateDescriptors(new_descriptors, new_layout_descriptor); 2934 current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
2947 current = Map::cast(next); 2935 current = Map::cast(next);
2948 } 2936 }
2949 set_owns_descriptors(false); 2937 set_owns_descriptors(false);
2950 return transition_target_deprecated;
2951 } 2938 }
2952 2939
2953 2940
2954 Map* Map::FindRootMap() { 2941 Map* Map::FindRootMap() {
2955 Map* result = this; 2942 Map* result = this;
2956 while (true) { 2943 while (true) {
2957 Object* back = result->GetBackPointer(); 2944 Object* back = result->GetBackPointer();
2958 if (back->IsUndefined()) { 2945 if (back->IsUndefined()) {
2959 // Initial map always owns descriptors and doesn't have unused entries 2946 // Initial map always owns descriptors and doesn't have unused entries
2960 // in the descriptor array. 2947 // in the descriptor array.
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 new_descriptors->Sort(); 3593 new_descriptors->Sort();
3607 3594
3608 DCHECK(store_mode != FORCE_FIELD || 3595 DCHECK(store_mode != FORCE_FIELD ||
3609 new_descriptors->GetDetails(modify_index).location() == kField); 3596 new_descriptors->GetDetails(modify_index).location() == kField);
3610 3597
3611 Handle<Map> split_map(root_map->FindLastMatchMap( 3598 Handle<Map> split_map(root_map->FindLastMatchMap(
3612 root_nof, old_nof, *new_descriptors), isolate); 3599 root_nof, old_nof, *new_descriptors), isolate);
3613 int split_nof = split_map->NumberOfOwnDescriptors(); 3600 int split_nof = split_map->NumberOfOwnDescriptors();
3614 DCHECK_NE(old_nof, split_nof); 3601 DCHECK_NE(old_nof, split_nof);
3615 3602
3616 Handle<LayoutDescriptor> new_layout_descriptor =
3617 LayoutDescriptor::New(split_map, new_descriptors, old_nof);
3618
3619 PropertyKind split_kind; 3603 PropertyKind split_kind;
3620 PropertyAttributes split_attributes; 3604 PropertyAttributes split_attributes;
3621 if (modify_index == split_nof) { 3605 if (modify_index == split_nof) {
3622 split_kind = new_kind; 3606 split_kind = new_kind;
3623 split_attributes = new_attributes; 3607 split_attributes = new_attributes;
3624 } else { 3608 } else {
3625 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); 3609 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
3626 split_kind = split_prop_details.kind(); 3610 split_kind = split_prop_details.kind();
3627 split_attributes = split_prop_details.attributes(); 3611 split_attributes = split_prop_details.attributes();
3628 } 3612 }
3629 bool transition_target_deprecated = split_map->DeprecateTarget(
3630 split_kind, old_descriptors->GetKey(split_nof), split_attributes,
3631 *new_descriptors, *new_layout_descriptor);
3632 3613
3633 // If |transition_target_deprecated| is true then the transition array 3614 // Invalidate a transition target at |key|.
3634 // already contains entry for given descriptor. This means that the transition 3615 Map* maybe_transition = TransitionArray::SearchTransition(
3616 *split_map, split_kind, old_descriptors->GetKey(split_nof),
3617 split_attributes);
3618 if (maybe_transition != NULL) {
3619 maybe_transition->DeprecateTransitionTree();
3620 }
3621
3622 // If |maybe_transition| is not NULL then the transition array already
3623 // contains entry for given descriptor. This means that the transition
3635 // could be inserted regardless of whether transitions array is full or not. 3624 // could be inserted regardless of whether transitions array is full or not.
3636 if (!transition_target_deprecated && 3625 if (maybe_transition == NULL &&
3637 !TransitionArray::CanHaveMoreTransitions(split_map)) { 3626 !TransitionArray::CanHaveMoreTransitions(split_map)) {
3638 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, 3627 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
3639 new_kind, new_attributes, 3628 new_kind, new_attributes,
3640 "GenAll_CantHaveMoreTransitions"); 3629 "GenAll_CantHaveMoreTransitions");
3641 } 3630 }
3642 3631
3643 old_map->NotifyLeafMapLayoutChange(); 3632 old_map->NotifyLeafMapLayoutChange();
3644 3633
3645 if (FLAG_trace_generalization && modify_index >= 0) { 3634 if (FLAG_trace_generalization && modify_index >= 0) {
3646 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); 3635 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
(...skipping 10 matching lines...) Expand all
3657 : HeapType::Constant( 3646 : HeapType::Constant(
3658 handle(new_descriptors->GetValue(modify_index), isolate), 3647 handle(new_descriptors->GetValue(modify_index), isolate),
3659 isolate); 3648 isolate);
3660 old_map->PrintGeneralization( 3649 old_map->PrintGeneralization(
3661 stdout, "", modify_index, split_nof, old_nof, 3650 stdout, "", modify_index, split_nof, old_nof,
3662 old_details.location() == kDescriptor && store_mode == FORCE_FIELD, 3651 old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
3663 old_details.representation(), new_details.representation(), 3652 old_details.representation(), new_details.representation(),
3664 *old_field_type, *new_field_type); 3653 *old_field_type, *new_field_type);
3665 } 3654 }
3666 3655
3667 // Add missing transitions. 3656 Handle<LayoutDescriptor> new_layout_descriptor =
3668 Handle<Map> new_map = split_map; 3657 LayoutDescriptor::New(split_map, new_descriptors, old_nof);
3669 for (int i = split_nof; i < old_nof; ++i) { 3658
3670 new_map = CopyInstallDescriptors(new_map, i, new_descriptors, 3659 Handle<Map> new_map =
3671 new_layout_descriptor); 3660 AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
3672 } 3661
3673 new_map->set_owns_descriptors(true); 3662 // Deprecated part of the transition tree is no longer reachable, so replace
3663 // current instance descriptors in the "survived" part of the tree with
3664 // the new descriptors to maintain descriptors sharing invariant.
3665 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
3674 return new_map; 3666 return new_map;
3675 } 3667 }
3676 3668
3677 3669
3678 // Generalize the representation of all DATA descriptors. 3670 // Generalize the representation of all DATA descriptors.
3679 Handle<Map> Map::GeneralizeAllFieldRepresentations( 3671 Handle<Map> Map::GeneralizeAllFieldRepresentations(
3680 Handle<Map> map) { 3672 Handle<Map> map) {
3681 Handle<DescriptorArray> descriptors(map->instance_descriptors()); 3673 Handle<DescriptorArray> descriptors(map->instance_descriptors());
3682 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { 3674 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
3683 PropertyDetails details = descriptors->GetDetails(i); 3675 PropertyDetails details = descriptors->GetDetails(i);
(...skipping 5484 matching lines...) Expand 10 before | Expand all | Expand 10 after
9168 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n", 9160 PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
9169 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result), 9161 reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
9170 reason); 9162 reason);
9171 } 9163 }
9172 #endif 9164 #endif
9173 9165
9174 return result; 9166 return result;
9175 } 9167 }
9176 9168
9177 9169
9170 // Creates transition tree starting from |split_map| and adding all descriptors
9171 // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
9172 // The way how it is done is tricky because of GC and special descriptors
9173 // marking logic.
9174 Handle<Map> Map::AddMissingTransitions(
9175 Handle<Map> split_map, Handle<DescriptorArray> descriptors,
9176 Handle<LayoutDescriptor> full_layout_descriptor) {
9177 DCHECK(descriptors->IsSortedNoDuplicates());
9178 int split_nof = split_map->NumberOfOwnDescriptors();
9179 int nof_descriptors = descriptors->number_of_descriptors();
9180 DCHECK_LT(split_nof, nof_descriptors);
9181
9182 // Start with creating last map which will own full descriptors array.
9183 // This is necessary to guarantee that GC will mark the whole descriptor
9184 // array if any of the allocations happening below fail.
9185 // Number of unused properties is temporarily incorrect and the layout
9186 // descriptor could unnecessarily be in slow mode but we will fix after
9187 // all the other intermediate maps are created.
9188 Handle<Map> last_map = CopyDropDescriptors(split_map);
9189 last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
9190 last_map->set_unused_property_fields(0);
9191
9192 // During creation of intermediate maps we violate descriptors sharing
9193 // invariant since the last map is not yet connected to the transition tree
9194 // we create here. But it is safe because GC never trims map's descriptors
9195 // if there are no dead transitions from that map and this is exactly the
9196 // case for all the intermediate maps we create here.
9197 Handle<Map> map = split_map;
9198 for (int i = split_nof; i < nof_descriptors - 1; ++i) {
9199 Handle<Map> new_map = CopyDropDescriptors(map);
9200 InstallDescriptors(map, new_map, i, descriptors, full_layout_descriptor);
9201 map = new_map;
9202 }
9203 InstallDescriptors(map, last_map, nof_descriptors - 1, descriptors,
9204 full_layout_descriptor);
9205 return last_map;
9206 }
9207
9208
9178 // Since this method is used to rewrite an existing transition tree, it can 9209 // Since this method is used to rewrite an existing transition tree, it can
9179 // always insert transitions without checking. 9210 // always insert transitions without checking.
9180 Handle<Map> Map::CopyInstallDescriptors( 9211 void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
9181 Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors, 9212 int new_descriptor,
9182 Handle<LayoutDescriptor> full_layout_descriptor) { 9213 Handle<DescriptorArray> descriptors,
9214 Handle<LayoutDescriptor> full_layout_descriptor) {
9183 DCHECK(descriptors->IsSortedNoDuplicates()); 9215 DCHECK(descriptors->IsSortedNoDuplicates());
9184 9216
9185 Handle<Map> result = CopyDropDescriptors(map); 9217 child->set_instance_descriptors(*descriptors);
9218 child->SetNumberOfOwnDescriptors(new_descriptor + 1);
9186 9219
9187 result->set_instance_descriptors(*descriptors); 9220 int unused_property_fields = parent->unused_property_fields();
9188 result->SetNumberOfOwnDescriptors(new_descriptor + 1);
9189
9190 int unused_property_fields = map->unused_property_fields();
9191 PropertyDetails details = descriptors->GetDetails(new_descriptor); 9221 PropertyDetails details = descriptors->GetDetails(new_descriptor);
9192 if (details.location() == kField) { 9222 if (details.location() == kField) {
9193 unused_property_fields = map->unused_property_fields() - 1; 9223 unused_property_fields = parent->unused_property_fields() - 1;
9194 if (unused_property_fields < 0) { 9224 if (unused_property_fields < 0) {
9195 unused_property_fields += JSObject::kFieldsAdded; 9225 unused_property_fields += JSObject::kFieldsAdded;
9196 } 9226 }
9197 } 9227 }
9198 result->set_unused_property_fields(unused_property_fields); 9228 child->set_unused_property_fields(unused_property_fields);
9199 9229
9200 if (FLAG_unbox_double_fields) { 9230 if (FLAG_unbox_double_fields) {
9201 Handle<LayoutDescriptor> layout_descriptor = 9231 Handle<LayoutDescriptor> layout_descriptor =
9202 LayoutDescriptor::AppendIfFastOrUseFull(map, details, 9232 LayoutDescriptor::AppendIfFastOrUseFull(parent, details,
9203 full_layout_descriptor); 9233 full_layout_descriptor);
9204 result->set_layout_descriptor(*layout_descriptor); 9234 child->set_layout_descriptor(*layout_descriptor);
9205 #ifdef VERIFY_HEAP 9235 #ifdef VERIFY_HEAP
9206 // TODO(ishell): remove these checks from VERIFY_HEAP mode. 9236 // TODO(ishell): remove these checks from VERIFY_HEAP mode.
9207 if (FLAG_verify_heap) { 9237 if (FLAG_verify_heap) {
9208 CHECK(result->layout_descriptor()->IsConsistentWithMap(*result)); 9238 CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9209 } 9239 }
9210 #else 9240 #else
9211 SLOW_DCHECK(result->layout_descriptor()->IsConsistentWithMap(*result)); 9241 SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
9212 #endif 9242 #endif
9213 result->set_visitor_id(Heap::GetStaticVisitorIdForMap(*result)); 9243 child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child));
9214 } 9244 }
9215 9245
9216 Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); 9246 Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
9217 ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); 9247 ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
9218
9219 return result;
9220 } 9248 }
9221 9249
9222 9250
9223 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, 9251 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
9224 TransitionFlag flag) { 9252 TransitionFlag flag) {
9225 Map* maybe_elements_transition_map = NULL; 9253 Map* maybe_elements_transition_map = NULL;
9226 if (flag == INSERT_TRANSITION) { 9254 if (flag == INSERT_TRANSITION) {
9227 maybe_elements_transition_map = map->ElementsTransitionMap(); 9255 maybe_elements_transition_map = map->ElementsTransitionMap();
9228 DCHECK(maybe_elements_transition_map == NULL || 9256 DCHECK(maybe_elements_transition_map == NULL ||
9229 (maybe_elements_transition_map->elements_kind() == 9257 (maybe_elements_transition_map->elements_kind() ==
(...skipping 9933 matching lines...) Expand 10 before | Expand all | Expand 10 after
19163 if (cell->value() != *new_value) { 19191 if (cell->value() != *new_value) {
19164 cell->set_value(*new_value); 19192 cell->set_value(*new_value);
19165 Isolate* isolate = cell->GetIsolate(); 19193 Isolate* isolate = cell->GetIsolate();
19166 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19194 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19167 isolate, DependentCode::kPropertyCellChangedGroup); 19195 isolate, DependentCode::kPropertyCellChangedGroup);
19168 } 19196 }
19169 } 19197 }
19170 19198
19171 } // namespace internal 19199 } // namespace internal
19172 } // namespace v8 19200 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698