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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index ecd31f7f5b531a6cc05d041d247704a0429dcf22..da65e86189d38a511005ff79ee6963b151c2880c 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2704,20 +2704,21 @@ bool Map::DeprecateTarget(PropertyKind kind, Name* key,
transition_target_deprecated = true;
}
- // Don't overwrite the empty descriptor array.
- if (NumberOfOwnDescriptors() == 0) return transition_target_deprecated;
+ // Don't overwrite the empty descriptor array or initial map's descriptors.
+ if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined()) {
+ return transition_target_deprecated;
+ }
DescriptorArray* to_replace = instance_descriptors();
- Map* current = this;
GetHeap()->incremental_marking()->RecordWrites(to_replace);
+ Map* current = this;
while (current->instance_descriptors() == to_replace) {
+ Object* next = current->GetBackPointer();
+ if (next->IsUndefined()) break; // Stop overwriting at initial map.
current->SetEnumLength(kInvalidEnumCacheSentinel);
current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
- Object* next = current->GetBackPointer();
- if (next->IsUndefined()) break;
current = Map::cast(next);
}
-
set_owns_descriptors(false);
return transition_target_deprecated;
}
@@ -2727,7 +2728,14 @@ Map* Map::FindRootMap() {
Map* result = this;
while (true) {
Object* back = result->GetBackPointer();
- if (back->IsUndefined()) return result;
+ if (back->IsUndefined()) {
+ // Initial map always owns descriptors and doesn't have unused entries
+ // in the descriptor array.
+ DCHECK(result->owns_descriptors());
+ DCHECK_EQ(result->NumberOfOwnDescriptors(),
+ result->instance_descriptors()->number_of_descriptors());
+ return result;
+ }
result = Map::cast(back);
}
}
@@ -4089,15 +4097,13 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
// Replace descriptors by new_descriptors in all maps that share it.
map->GetHeap()->incremental_marking()->RecordWrites(*descriptors);
- Map* walk_map;
- for (Object* current = map->GetBackPointer();
- !current->IsUndefined();
- current = walk_map->GetBackPointer()) {
- walk_map = Map::cast(current);
- if (walk_map->instance_descriptors() != *descriptors) break;
- walk_map->UpdateDescriptors(*new_descriptors, layout_descriptor);
+ Map* current = *map;
+ while (current->instance_descriptors() == *descriptors) {
+ Object* next = current->GetBackPointer();
+ if (next->IsUndefined()) break; // Stop overwriting at initial map.
+ current->UpdateDescriptors(*new_descriptors, layout_descriptor);
+ current = Map::cast(next);
}
-
map->UpdateDescriptors(*new_descriptors, layout_descriptor);
}
@@ -8215,6 +8221,12 @@ Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
DCHECK(constructor->IsJSFunction());
DCHECK_EQ(*map, JSFunction::cast(constructor)->initial_map());
#endif
+ // Initial maps must always own their descriptors and it's descriptor array
+ // does not contain descriptors that do not belong to the map.
+ DCHECK(map->owns_descriptors());
+ DCHECK_EQ(map->NumberOfOwnDescriptors(),
+ map->instance_descriptors()->number_of_descriptors());
+
Handle<Map> result = RawCopy(map, instance_size);
// Please note instance_type and instance_size are set when allocated.
@@ -8223,11 +8235,9 @@ Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
if (number_of_own_descriptors > 0) {
- DCHECK(map->owns_descriptors());
- // The copy will use the same descriptors array, but it's not the owner.
+ // The copy will use the same descriptors array.
result->UpdateDescriptors(map->instance_descriptors(),
map->layout_descriptor());
- result->set_owns_descriptors(false);
result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
DCHECK_EQ(result->NumberOfFields(),
@@ -8257,8 +8267,8 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map,
// Sanity check. This path is only to be taken if the map owns its descriptor
// array, implying that its NumberOfOwnDescriptors equals the number of
// descriptors in the descriptor array.
- DCHECK(map->NumberOfOwnDescriptors() ==
- map->instance_descriptors()->number_of_descriptors());
+ DCHECK_EQ(map->NumberOfOwnDescriptors(),
+ map->instance_descriptors()->number_of_descriptors());
Handle<Map> result = CopyDropDescriptors(map);
Handle<Name> name = descriptor->GetKey();
@@ -8323,7 +8333,15 @@ void Map::TraceAllTransitions(Map* map) {
void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
Handle<Name> name, SimpleTransitionFlag flag) {
- parent->set_owns_descriptors(false);
+ if (!parent->GetBackPointer()->IsUndefined()) {
+ parent->set_owns_descriptors(false);
+ } else {
+ // |parent| is initial map and it must keep the ownership, there must be no
+ // descriptors in the descriptors array that do not belong to the map.
+ DCHECK(parent->owns_descriptors());
+ DCHECK_EQ(parent->NumberOfOwnDescriptors(),
+ parent->instance_descriptors()->number_of_descriptors());
+ }
if (parent->is_prototype_map()) {
DCHECK(child->is_prototype_map());
#if TRACE_MAPS
@@ -8821,7 +8839,9 @@ Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
// Ensure the key is unique.
descriptor->KeyToUniqueName();
+ // Share descriptors only if map owns descriptors and it not an initial map.
if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
+ !map->GetBackPointer()->IsUndefined() &&
TransitionArray::CanHaveMoreTransitions(map)) {
return ShareDescriptor(map, descriptors, descriptor);
}
« 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