Commit f53c728f authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

Properly share descriptor arrays

... and remove too restrictive checks.

Bug: chromium:1025468, chromium:1027498
Change-Id: I1558d66ef88d1481530479969c0fb81fb6ff808c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1932373Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65153}
parent e8e3bbe8
...@@ -442,18 +442,30 @@ void Map::MapVerify(Isolate* isolate) { ...@@ -442,18 +442,30 @@ void Map::MapVerify(Isolate* isolate) {
CHECK(native_context().IsNativeContext()); CHECK(native_context().IsNativeContext());
} else { } else {
if (GetBackPointer().IsUndefined(isolate)) { if (GetBackPointer().IsUndefined(isolate)) {
// Root maps must keep the ownership and there must be no descriptors // Root maps must not have descriptors in the descriptor array that do not
// in the descriptors array that do not belong to the map. // belong to the map.
CHECK(owns_descriptors() || is_prototype_map());
CHECK_EQ(NumberOfOwnDescriptors(), CHECK_EQ(NumberOfOwnDescriptors(),
instance_descriptors().number_of_descriptors()); instance_descriptors().number_of_descriptors());
if (!is_prototype_map()) {
// There must be no slack in root maps' descriptors array.
CHECK_EQ(0, instance_descriptors().number_of_slack_descriptors());
}
} else { } else {
// If there is a parent map it must be non-stable. // If there is a parent map it must be non-stable.
CHECK(!Map::cast(GetBackPointer()).is_stable()); Map parent = Map::cast(GetBackPointer());
CHECK(!parent.is_stable());
DescriptorArray descriptors = instance_descriptors();
if (descriptors == parent.instance_descriptors()) {
if (NumberOfOwnDescriptors() == parent.NumberOfOwnDescriptors() + 1) {
// Descriptors sharing through property transitions takes over
// ownership from the parent map.
CHECK(!parent.owns_descriptors());
} else {
CHECK_EQ(NumberOfOwnDescriptors(), parent.NumberOfOwnDescriptors());
// Descriptors sharing through special transitions takes over
// ownership from the parent map unless it uses the canonical empty
// descriptor array.
CHECK_IMPLIES(
descriptors != ReadOnlyRoots(isolate).empty_descriptor_array(),
!parent.owns_descriptors());
}
}
} }
} }
SLOW_DCHECK(instance_descriptors().IsSortedNoDuplicates()); SLOW_DCHECK(instance_descriptors().IsSortedNoDuplicates());
......
...@@ -634,9 +634,8 @@ Map Map::FindRootMap(Isolate* isolate) const { ...@@ -634,9 +634,8 @@ Map Map::FindRootMap(Isolate* isolate) const {
while (true) { while (true) {
Object back = result.GetBackPointer(isolate); Object back = result.GetBackPointer(isolate);
if (back.IsUndefined(isolate)) { if (back.IsUndefined(isolate)) {
// Initial map always owns descriptors and doesn't have unused entries // Initial map must not contain descriptors in the descriptors array
// in the descriptor array. // that do not belong to the map.
DCHECK(result.owns_descriptors());
DCHECK_EQ(result.NumberOfOwnDescriptors(), DCHECK_EQ(result.NumberOfOwnDescriptors(),
result.instance_descriptors().number_of_descriptors()); result.instance_descriptors().number_of_descriptors());
return result; return result;
...@@ -1572,9 +1571,8 @@ void EnsureInitialMap(Isolate* isolate, Handle<Map> map) { ...@@ -1572,9 +1571,8 @@ void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
*map == *isolate->async_function_with_home_object_map() || *map == *isolate->async_function_with_home_object_map() ||
*map == *isolate->async_function_with_name_and_home_object_map()); *map == *isolate->async_function_with_name_and_home_object_map());
#endif #endif
// Initial maps must always own their descriptors and it's descriptor array // Initial maps must not contain descriptors in the descriptors array
// does not contain descriptors that do not belong to the map. // that do not belong to the map.
DCHECK(map->owns_descriptors());
DCHECK_EQ(map->NumberOfOwnDescriptors(), DCHECK_EQ(map->NumberOfOwnDescriptors(),
map->instance_descriptors().number_of_descriptors()); map->instance_descriptors().number_of_descriptors());
} }
...@@ -1592,6 +1590,11 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map, ...@@ -1592,6 +1590,11 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
int instance_size, int inobject_properties, int instance_size, int inobject_properties,
int unused_property_fields) { int unused_property_fields) {
EnsureInitialMap(isolate, map); EnsureInitialMap(isolate, map);
// Initial map must not contain descriptors in the descriptors array
// that do not belong to the map.
DCHECK_EQ(map->NumberOfOwnDescriptors(),
map->instance_descriptors().number_of_descriptors());
Handle<Map> result = Handle<Map> result =
RawCopy(isolate, map, instance_size, inobject_properties); RawCopy(isolate, map, instance_size, inobject_properties);
...@@ -1600,9 +1603,10 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map, ...@@ -1600,9 +1603,10 @@ Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
int number_of_own_descriptors = map->NumberOfOwnDescriptors(); int number_of_own_descriptors = map->NumberOfOwnDescriptors();
if (number_of_own_descriptors > 0) { if (number_of_own_descriptors > 0) {
// The copy will use the same descriptors array. // The copy will use the same descriptors array without ownership.
result->UpdateDescriptors(isolate, map->instance_descriptors(), DescriptorArray descriptors = map->instance_descriptors();
map->GetLayoutDescriptor(), result->set_owns_descriptors(false);
result->UpdateDescriptors(isolate, descriptors, map->GetLayoutDescriptor(),
number_of_own_descriptors); number_of_own_descriptors);
DCHECK_EQ(result->NumberOfFields(), DCHECK_EQ(result->NumberOfFields(),
...@@ -1682,9 +1686,8 @@ void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent, ...@@ -1682,9 +1686,8 @@ void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
if (!parent->GetBackPointer().IsUndefined(isolate)) { if (!parent->GetBackPointer().IsUndefined(isolate)) {
parent->set_owns_descriptors(false); parent->set_owns_descriptors(false);
} else { } else {
// |parent| is initial map and it must keep the ownership, there must be no // |parent| is initial map and it must not contain descriptors in the
// descriptors in the descriptors array that do not belong to the map. // descriptors array that do not belong to the map.
DCHECK(parent->owns_descriptors());
DCHECK_EQ(parent->NumberOfOwnDescriptors(), DCHECK_EQ(parent->NumberOfOwnDescriptors(),
parent->instance_descriptors().number_of_descriptors()); parent->instance_descriptors().number_of_descriptors());
} }
...@@ -1928,6 +1931,7 @@ Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) { ...@@ -1928,6 +1931,7 @@ Handle<Map> Map::CopyForElementsTransition(Isolate* isolate, Handle<Map> map) {
// In case the map owned its own descriptors, share the descriptors and // In case the map owned its own descriptors, share the descriptors and
// transfer ownership to the new map. // transfer ownership to the new map.
// The properties did not change, so reuse descriptors. // The properties did not change, so reuse descriptors.
map->set_owns_descriptors(false);
new_map->InitializeDescriptors(isolate, map->instance_descriptors(), new_map->InitializeDescriptors(isolate, map->instance_descriptors(),
map->GetLayoutDescriptor()); map->GetLayoutDescriptor());
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment