Commit 11960b13 authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[runtime] Dehandlify some Map and Descriptor code

Avoiding handles in tight loops and setup code improves performance
and reduces code size.

This CL also makes more non-allocating mode more explicit by adding
more DisallowGarbageCollection scopes.

Change-Id: I95b5b1a29204c27a23c42ccd67fff150b3fa4a3e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3460740Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79142}
parent 6f8b501c
...@@ -688,8 +688,8 @@ bool Map::IsBooleanMap() const { ...@@ -688,8 +688,8 @@ bool Map::IsBooleanMap() const {
} }
bool Map::IsNullOrUndefinedMap() const { bool Map::IsNullOrUndefinedMap() const {
return *this == GetReadOnlyRoots().null_map() || auto roots = GetReadOnlyRoots();
*this == GetReadOnlyRoots().undefined_map(); return *this == roots.null_map() || *this == roots.undefined_map();
} }
bool Map::IsPrimitiveMap() const { bool Map::IsPrimitiveMap() const {
......
...@@ -924,6 +924,7 @@ Map Map::FindElementsKindTransitionedMap(Isolate* isolate, ...@@ -924,6 +924,7 @@ Map Map::FindElementsKindTransitionedMap(Isolate* isolate,
static Map FindClosestElementsTransition(Isolate* isolate, Map map, static Map FindClosestElementsTransition(Isolate* isolate, Map map,
ElementsKind to_kind, ElementsKind to_kind,
ConcurrencyMode cmode) { ConcurrencyMode cmode) {
DisallowGarbageCollection no_gc;
// Ensure we are requested to search elements kind transition "near the root". // Ensure we are requested to search elements kind transition "near the root".
DCHECK_EQ(map.FindRootMap(isolate).NumberOfOwnDescriptors(), DCHECK_EQ(map.FindRootMap(isolate).NumberOfOwnDescriptors(),
map.NumberOfOwnDescriptors()); map.NumberOfOwnDescriptors());
...@@ -1129,29 +1130,36 @@ bool Map::MayHaveReadOnlyElementsInPrototypeChain(Isolate* isolate) { ...@@ -1129,29 +1130,36 @@ bool Map::MayHaveReadOnlyElementsInPrototypeChain(Isolate* isolate) {
return false; return false;
} }
Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map, int instance_size, Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> src_handle,
int inobject_properties) { int instance_size, int inobject_properties) {
Handle<Map> result = isolate->factory()->NewMap( Handle<Map> result = isolate->factory()->NewMap(
map->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND, src_handle->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND,
inobject_properties); inobject_properties);
Handle<HeapObject> prototype(map->prototype(), isolate); Handle<HeapObject> prototype(src_handle->prototype(), isolate);
Map::SetPrototype(isolate, result, prototype); Map::SetPrototype(isolate, result, prototype);
result->set_constructor_or_back_pointer(map->GetConstructor()); {
result->set_bit_field(map->bit_field()); DisallowGarbageCollection no_gc;
result->set_bit_field2(map->bit_field2()); Map src = *src_handle;
int new_bit_field3 = map->bit_field3(); Map raw = *result;
raw.set_constructor_or_back_pointer(src.GetConstructor());
raw.set_bit_field(src.bit_field());
raw.set_bit_field2(src.bit_field2());
int new_bit_field3 = src.bit_field3();
new_bit_field3 = Bits3::OwnsDescriptorsBit::update(new_bit_field3, true); new_bit_field3 = Bits3::OwnsDescriptorsBit::update(new_bit_field3, true);
new_bit_field3 = Bits3::NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
new_bit_field3 = new_bit_field3 =
Bits3::EnumLengthBits::update(new_bit_field3, kInvalidEnumCacheSentinel); Bits3::NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
new_bit_field3 = Bits3::EnumLengthBits::update(new_bit_field3,
kInvalidEnumCacheSentinel);
new_bit_field3 = Bits3::IsDeprecatedBit::update(new_bit_field3, false); new_bit_field3 = Bits3::IsDeprecatedBit::update(new_bit_field3, false);
new_bit_field3 = Bits3::IsInRetainedMapListBit::update(new_bit_field3, false); new_bit_field3 =
if (!map->is_dictionary_map()) { Bits3::IsInRetainedMapListBit::update(new_bit_field3, false);
if (!src.is_dictionary_map()) {
new_bit_field3 = Bits3::IsUnstableBit::update(new_bit_field3, false); new_bit_field3 = Bits3::IsUnstableBit::update(new_bit_field3, false);
} }
// Same as bit_field comment above. // Same as bit_field comment above.
result->set_bit_field3(new_bit_field3); raw.set_bit_field3(new_bit_field3);
result->clear_padding(); raw.clear_padding();
}
return result; return result;
} }
...@@ -1242,13 +1250,17 @@ Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map, ...@@ -1242,13 +1250,17 @@ Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,
Handle<Map> result = RawCopy( Handle<Map> result = RawCopy(
isolate, map, new_instance_size, isolate, map, new_instance_size,
mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties()); mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
{
DisallowGarbageCollection no_gc;
Map raw = *result;
// Clear the unused_property_fields explicitly as this field should not // Clear the unused_property_fields explicitly as this field should not
// be accessed for normalized maps. // be accessed for normalized maps.
result->SetInObjectUnusedPropertyFields(0); raw.SetInObjectUnusedPropertyFields(0);
result->set_is_dictionary_map(true); raw.set_is_dictionary_map(true);
result->set_is_migration_target(false); raw.set_is_migration_target(false);
result->set_may_have_interesting_symbols(true); raw.set_may_have_interesting_symbols(true);
result->set_construction_counter(kNoSlackTracking); raw.set_construction_counter(kNoSlackTracking);
}
#ifdef VERIFY_HEAP #ifdef VERIFY_HEAP
if (FLAG_verify_heap) result->DictionaryMapVerify(isolate); if (FLAG_verify_heap) result->DictionaryMapVerify(isolate);
...@@ -1635,9 +1647,11 @@ Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map, const char* reason) { ...@@ -1635,9 +1647,11 @@ Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map, const char* reason) {
} }
Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
Handle<Map> copy = Handle<Map> copy_handle =
Copy(isolate, handle(isolate->object_function()->initial_map(), isolate), Copy(isolate, handle(isolate->object_function()->initial_map(), isolate),
"MapCreate"); "MapCreate");
DisallowGarbageCollection no_gc;
Map copy = *copy_handle;
// Check that we do not overflow the instance size when adding the extra // Check that we do not overflow the instance size when adding the extra
// inobject properties. If the instance size overflows, we allocate as many // inobject properties. If the instance size overflows, we allocate as many
...@@ -1650,12 +1664,13 @@ Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) { ...@@ -1650,12 +1664,13 @@ Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
JSObject::kHeaderSize + kTaggedSize * inobject_properties; JSObject::kHeaderSize + kTaggedSize * inobject_properties;
// Adjust the map with the extra inobject properties. // Adjust the map with the extra inobject properties.
copy->set_instance_size(new_instance_size); copy.set_instance_size(new_instance_size);
copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kTaggedSize); copy.SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kTaggedSize);
DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties); DCHECK_EQ(copy.GetInObjectProperties(), inobject_properties);
copy->SetInObjectUnusedPropertyFields(inobject_properties); copy.SetInObjectUnusedPropertyFields(inobject_properties);
copy->set_visitor_id(Map::GetVisitorId(*copy)); copy.set_visitor_id(Map::GetVisitorId(copy));
return copy;
return copy_handle;
} }
Handle<Map> Map::CopyForPreventExtensions( Handle<Map> Map::CopyForPreventExtensions(
......
...@@ -3816,22 +3816,25 @@ Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate, ...@@ -3816,22 +3816,25 @@ Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
} }
Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index, Isolate* isolate, Handle<DescriptorArray> source_handle,
PropertyAttributes attributes, int slack) { int enumeration_index, PropertyAttributes attributes, int slack) {
if (enumeration_index + slack == 0) { if (enumeration_index + slack == 0) {
return isolate->factory()->empty_descriptor_array(); return isolate->factory()->empty_descriptor_array();
} }
int size = enumeration_index; int size = enumeration_index;
Handle<DescriptorArray> copy_handle =
Handle<DescriptorArray> descriptors =
DescriptorArray::Allocate(isolate, size, slack); DescriptorArray::Allocate(isolate, size, slack);
DisallowGarbageCollection no_gc;
auto source = *source_handle;
auto copy = *copy_handle;
if (attributes != NONE) { if (attributes != NONE) {
for (InternalIndex i : InternalIndex::Range(size)) { for (InternalIndex i : InternalIndex::Range(size)) {
MaybeObject value_or_field_type = desc->GetValue(i); MaybeObject value_or_field_type = source.GetValue(i);
Name key = desc->GetKey(i); Name key = source.GetKey(i);
PropertyDetails details = desc->GetDetails(i); PropertyDetails details = source.GetDetails(i);
// Bulk attribute changes never affect private properties. // Bulk attribute changes never affect private properties.
if (!key.IsPrivate()) { if (!key.IsPrivate()) {
int mask = DONT_DELETE | DONT_ENUM; int mask = DONT_DELETE | DONT_ENUM;
...@@ -3845,35 +3848,39 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( ...@@ -3845,35 +3848,39 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
details = details.CopyAddAttributes( details = details.CopyAddAttributes(
static_cast<PropertyAttributes>(attributes & mask)); static_cast<PropertyAttributes>(attributes & mask));
} }
descriptors->Set(i, key, value_or_field_type, details); copy.Set(i, key, value_or_field_type, details);
} }
} else { } else {
for (InternalIndex i : InternalIndex::Range(size)) { for (InternalIndex i : InternalIndex::Range(size)) {
descriptors->CopyFrom(i, *desc); copy.CopyFrom(i, source);
} }
} }
if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort(); if (source.number_of_descriptors() != enumeration_index) copy.Sort();
return descriptors; return copy_handle;
} }
// Create a new descriptor array with only enumerable, configurable, writeable // Create a new descriptor array with only enumerable, configurable, writeable
// data properties, but identical field locations. // data properties, but identical field locations.
Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone( Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
Isolate* isolate, Handle<DescriptorArray> src, int enumeration_index, Isolate* isolate, Handle<DescriptorArray> src_handle, int enumeration_index,
int slack) { int slack) {
if (enumeration_index + slack == 0) { if (enumeration_index + slack == 0) {
return isolate->factory()->empty_descriptor_array(); return isolate->factory()->empty_descriptor_array();
} }
int size = enumeration_index; int size = enumeration_index;
Handle<DescriptorArray> descriptors = Handle<DescriptorArray> descriptors_handle =
DescriptorArray::Allocate(isolate, size, slack); DescriptorArray::Allocate(isolate, size, slack);
DisallowGarbageCollection no_gc;
auto src = *src_handle;
auto descriptors = *descriptors_handle;
for (InternalIndex i : InternalIndex::Range(size)) { for (InternalIndex i : InternalIndex::Range(size)) {
Name key = src->GetKey(i); Name key = src.GetKey(i);
PropertyDetails details = src->GetDetails(i); PropertyDetails details = src.GetDetails(i);
Representation new_representation = details.representation(); Representation new_representation = details.representation();
DCHECK(!key.IsPrivateName()); DCHECK(!key.IsPrivateName());
...@@ -3882,7 +3889,7 @@ Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone( ...@@ -3882,7 +3889,7 @@ Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
// If the new representation is an in-place changeable field, make it // If the new representation is an in-place changeable field, make it
// generic as possible (under in-place changes) to avoid type confusion if // generic as possible (under in-place changes) to avoid type confusion if
// the source representation changes after this feedback has been collected. // the source representation changes after this feedback has been collected.
MaybeObject type = src->GetValue(i); MaybeObject type = src.GetValue(i);
if (details.location() == PropertyLocation::kField) { if (details.location() == PropertyLocation::kField) {
type = MaybeObject::FromObject(FieldType::Any()); type = MaybeObject::FromObject(FieldType::Any());
// TODO(bmeurer,ishell): Igor suggested to use some kind of dynamic // TODO(bmeurer,ishell): Igor suggested to use some kind of dynamic
...@@ -3899,12 +3906,12 @@ Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone( ...@@ -3899,12 +3906,12 @@ Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
details.constness(), new_representation, details.constness(), new_representation,
details.field_index()); details.field_index());
descriptors->Set(i, key, type, new_details); descriptors.Set(i, key, type, new_details);
} }
descriptors->Sort(); descriptors.Sort();
return descriptors; return descriptors_handle;
} }
bool DescriptorArray::IsEqualUpTo(DescriptorArray desc, int nof_descriptors) { bool DescriptorArray::IsEqualUpTo(DescriptorArray desc, int nof_descriptors) {
......
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