Commit 2de2d3dc authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[runtime] Amortize descriptor array growing for fast-mode prototypes

This avoids an O(n^2) algorithm that creates an equal amount of garbage.
Even though the actual final descriptor array might be a little bigger,
it reduces peak memory usage by allocating less.

Bug: b:148346655
Change-Id: I984159d36e9e0b37c19bc81afc90c94c9a9d168a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2135728
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67031}
parent 68c9e9f0
......@@ -440,8 +440,12 @@ void Map::MapVerify(Isolate* isolate) {
if (GetBackPointer().IsUndefined(isolate)) {
// Root maps must not have descriptors in the descriptor array that do not
// belong to the map.
CHECK_EQ(NumberOfOwnDescriptors(),
instance_descriptors().number_of_descriptors());
int nof = instance_descriptors().number_of_descriptors();
if (is_prototype_map()) {
CHECK(base::IsInRange(NumberOfOwnDescriptors(), 0, nof));
} else {
CHECK_EQ(NumberOfOwnDescriptors(), nof);
}
} else {
// If there is a parent map it must be non-stable.
Map parent = Map::cast(GetBackPointer());
......
......@@ -655,7 +655,7 @@ Map Map::FindRootMap(Isolate* isolate) const {
if (back.IsUndefined(isolate)) {
// Initial map must not contain descriptors in the descriptors array
// that do not belong to the map.
DCHECK_EQ(result.NumberOfOwnDescriptors(),
DCHECK_LE(result.NumberOfOwnDescriptors(),
result.instance_descriptors().number_of_descriptors());
return result;
}
......@@ -2374,16 +2374,40 @@ Handle<Map> Map::CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
return ShareDescriptor(isolate, map, descriptors, descriptor);
}
int nof = map->NumberOfOwnDescriptors();
Handle<DescriptorArray> new_descriptors =
DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
Handle<DescriptorArray> new_descriptors;
if (map->is_prototype_map()) {
if (descriptors->number_of_slack_descriptors() == 0) {
int old_size = descriptors->number_of_descriptors();
if (old_size == 0) {
new_descriptors = DescriptorArray::Allocate(isolate, 0, 1);
} else {
int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
EnsureDescriptorSlack(isolate, map, slack);
new_descriptors = handle(map->instance_descriptors(), isolate);
}
} else {
new_descriptors = descriptors;
}
} else {
int nof = map->NumberOfOwnDescriptors();
new_descriptors = DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
}
new_descriptors->Append(descriptor);
Handle<LayoutDescriptor> new_layout_descriptor =
FLAG_unbox_double_fields
? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
: handle(LayoutDescriptor::FastPointerLayout(), isolate);
Handle<LayoutDescriptor> new_layout_descriptor;
if (map->is_prototype_map()) {
new_layout_descriptor =
FLAG_unbox_double_fields
? LayoutDescriptor::ShareAppend(isolate, map,
descriptor->GetDetails())
: handle(LayoutDescriptor::FastPointerLayout(), isolate);
} else {
int nof = map->NumberOfOwnDescriptors();
new_layout_descriptor =
FLAG_unbox_double_fields
? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
: handle(LayoutDescriptor::FastPointerLayout(), isolate);
}
return CopyReplaceDescriptors(
isolate, map, new_descriptors, new_layout_descriptor, flag,
descriptor->GetKey(), "CopyAddDescriptor", SIMPLE_PROPERTY_TRANSITION);
......
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