[compiler] Perform Map::bit_field_3 non-release/acquire if possible

We have to have special rules for bit_fields since we multiple accesors
touch the same field. I used:
 * If the accessor is set at map initalization time only and:
   * only the main thread accesses it: non-atomic write/read
   * bg accesses it too: non-atomic write, relaxed read (read has to be
     relaxed due to the whole bit_field being modified concurrently via
     other bit_field3 accessors)
 * If the accessor is set after map initialization:
   * but it is not necessary for synchronization: relaxed write/read
   * If the accessor is needed for synchronization: release/acquire

As a note, Map::NumberOfOwnDescriptors are the bits accessed by the
concurrent marker. For concurrent marker reasons it can be relaxed, but
we would like it to be release/acquire for the compiler since that's
where we synchronize Maps with adding descriptors to the descriptor
array.

Bug: v8:7790, chromium:1150811
Change-Id: I0ba7d2f8cb81d65a487970b4ea0bfa2a4cb3a975
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2773286
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73911}
This commit is contained in:
Santiago Aboy Solanes 2021-04-09 10:34:04 +01:00 committed by Commit Bot
parent e101c057af
commit f2b4272dae
4 changed files with 47 additions and 23 deletions

View File

@ -1340,7 +1340,8 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object,
// is set to false when it was already false).
bit_field_(object->relaxed_bit_field()),
bit_field2_(object->bit_field2()),
bit_field3_(object->bit_field3()),
// Similar to the bit_field comment above.
bit_field3_(object->relaxed_bit_field3()),
can_be_deprecated_(object->NumberOfOwnDescriptors() > 0
? object->CanBeDeprecated()
: false),

View File

@ -90,19 +90,21 @@ BIT_FIELD_ACCESSORS(Map, bit_field2, is_immutable_proto,
Map::Bits2::IsImmutablePrototypeBit)
// |bit_field3| fields.
BIT_FIELD_ACCESSORS(Map, bit_field3, owns_descriptors,
BIT_FIELD_ACCESSORS(Map, relaxed_bit_field3, owns_descriptors,
Map::Bits3::OwnsDescriptorsBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, is_deprecated, Map::Bits3::IsDeprecatedBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, is_in_retained_map_list,
BIT_FIELD_ACCESSORS(Map, release_acquire_bit_field3, is_deprecated,
Map::Bits3::IsDeprecatedBit)
BIT_FIELD_ACCESSORS(Map, relaxed_bit_field3, is_in_retained_map_list,
Map::Bits3::IsInRetainedMapListBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, is_prototype_map,
BIT_FIELD_ACCESSORS(Map, release_acquire_bit_field3, is_prototype_map,
Map::Bits3::IsPrototypeMapBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, is_migration_target,
BIT_FIELD_ACCESSORS(Map, relaxed_bit_field3, is_migration_target,
Map::Bits3::IsMigrationTargetBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, is_extensible, Map::Bits3::IsExtensibleBit)
BIT_FIELD_ACCESSORS(Map, relaxed_bit_field3, is_extensible,
Map::Bits3::IsExtensibleBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, may_have_interesting_symbols,
Map::Bits3::MayHaveInterestingSymbolsBit)
BIT_FIELD_ACCESSORS(Map, bit_field3, construction_counter,
BIT_FIELD_ACCESSORS(Map, relaxed_bit_field3, construction_counter,
Map::Bits3::ConstructionCounterBits)
DEF_GETTER(Map, GetNamedInterceptor, InterceptorInfo) {
@ -199,14 +201,15 @@ InternalIndex Map::LastAdded() const {
}
int Map::NumberOfOwnDescriptors() const {
return Bits3::NumberOfOwnDescriptorsBits::decode(bit_field3());
return Bits3::NumberOfOwnDescriptorsBits::decode(
release_acquire_bit_field3());
}
void Map::SetNumberOfOwnDescriptors(int number) {
DCHECK_LE(number, instance_descriptors().number_of_descriptors());
CHECK_LE(static_cast<unsigned>(number),
static_cast<unsigned>(kMaxNumberOfDescriptors));
set_bit_field3(
set_release_acquire_bit_field3(
Bits3::NumberOfOwnDescriptorsBits::update(bit_field3(), number));
}
@ -224,7 +227,7 @@ void Map::SetEnumLength(int length) {
CHECK_LE(static_cast<unsigned>(length),
static_cast<unsigned>(kMaxNumberOfDescriptors));
}
set_bit_field3(Bits3::EnumLengthBits::update(bit_field3(), length));
set_relaxed_bit_field3(Bits3::EnumLengthBits::update(bit_field3(), length));
}
FixedArrayBase Map::GetInitialElements() const {
@ -471,6 +474,30 @@ void Map::set_bit_field2(byte value) {
WriteField<byte>(kBitField2Offset, value);
}
uint32_t Map::bit_field3() const {
return ReadField<uint32_t>(kBitField3Offset);
}
void Map::set_bit_field3(uint32_t value) {
WriteField<uint32_t>(kBitField3Offset, value);
}
uint32_t Map::relaxed_bit_field3() const {
return RELAXED_READ_UINT32_FIELD(*this, kBitField3Offset);
}
void Map::set_relaxed_bit_field3(uint32_t value) {
RELAXED_WRITE_UINT32_FIELD(*this, kBitField3Offset, value);
}
uint32_t Map::release_acquire_bit_field3() const {
return ACQUIRE_READ_UINT32_FIELD(*this, kBitField3Offset);
}
void Map::set_release_acquire_bit_field3(uint32_t value) {
RELEASE_WRITE_UINT32_FIELD(*this, kBitField3Offset, value);
}
bool Map::is_abandoned_prototype_map() const {
return is_prototype_map() && !owns_descriptors();
}
@ -554,15 +581,16 @@ void Map::set_is_dictionary_map(bool value) {
}
bool Map::is_dictionary_map() const {
return Bits3::IsDictionaryMapBit::decode(bit_field3());
return Bits3::IsDictionaryMapBit::decode(relaxed_bit_field3());
}
void Map::mark_unstable() {
set_bit_field3(Bits3::IsUnstableBit::update(bit_field3(), true));
set_release_acquire_bit_field3(
Bits3::IsUnstableBit::update(bit_field3(), true));
}
bool Map::is_stable() const {
return !Bits3::IsUnstableBit::decode(bit_field3());
return !Bits3::IsUnstableBit::decode(release_acquire_bit_field3());
}
bool Map::CanBeDeprecated() const {
@ -619,14 +647,6 @@ void Map::InitializeDescriptors(Isolate* isolate, DescriptorArray descriptors) {
descriptors.number_of_descriptors());
}
void Map::set_bit_field3(uint32_t bits) {
RELEASE_WRITE_UINT32_FIELD(*this, kBitField3Offset, bits);
}
uint32_t Map::bit_field3() const {
return ACQUIRE_READ_UINT32_FIELD(*this, kBitField3Offset);
}
void Map::clear_padding() {
if (FIELD_SIZE(kOptionalPaddingOffset) == 0) return;
DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));

View File

@ -1224,7 +1224,8 @@ Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map, int instance_size,
if (!map->is_dictionary_map()) {
new_bit_field3 = Bits3::IsUnstableBit::update(new_bit_field3, false);
}
result->set_bit_field3(new_bit_field3);
// Same as bit_field comment above.
result->set_relaxed_bit_field3(new_bit_field3);
result->clear_padding();
return result;
}

View File

@ -267,6 +267,8 @@ class Map : public HeapObject {
// Bit field 3.
//
DECL_PRIMITIVE_ACCESSORS(bit_field3, uint32_t)
DECL_PRIMITIVE_ACCESSORS(relaxed_bit_field3, uint32_t)
DECL_PRIMITIVE_ACCESSORS(release_acquire_bit_field3, uint32_t)
// Clear uninitialized padding space. This ensures that the snapshot content
// is deterministic. Depending on the V8 build mode there could be no padding.