Commit 12bb6c21 authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[compiler] Mark Map's bit_field set/get as non-atomic or relaxed

Most of Map's bit_field (as in not 2 or 3) accessors are not set after
construction e.g. is_callable. They are also not used as a
synchronization point. From the compiler's point of view, they can be
set as non-atomic. There are two accessors (`prototype_slot` and
`non_instance_prototype`) that have to be atomic for concurrent marker
reasons (relaxed is fine for them).

Bug: v8:7790, chromium:1150811
Change-Id: Ic3c81a59e7895ee9c35a128bb10656040b19dd42
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2752154Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73432}
parent b9ccf865
...@@ -704,7 +704,6 @@ Handle<JSFunction> ApiNatives::CreateApiFunction( ...@@ -704,7 +704,6 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
Handle<Map> map = isolate->factory()->NewMap(type, instance_size, Handle<Map> map = isolate->factory()->NewMap(type, instance_size,
TERMINAL_FAST_ELEMENTS_KIND); TERMINAL_FAST_ELEMENTS_KIND);
JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
// Mark as undetectable if needed. // Mark as undetectable if needed.
if (obj->undetectable()) { if (obj->undetectable()) {
...@@ -740,6 +739,7 @@ Handle<JSFunction> ApiNatives::CreateApiFunction( ...@@ -740,6 +739,7 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
if (immutable_proto) map->set_is_immutable_proto(true); if (immutable_proto) map->set_is_immutable_proto(true);
JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
return result; return result;
} }
......
...@@ -62,21 +62,26 @@ ACCESSORS_CHECKED(Map, prototype_info, Object, ...@@ -62,21 +62,26 @@ ACCESSORS_CHECKED(Map, prototype_info, Object,
// is explicitly allowlisted here. The former is never modified after the map // is explicitly allowlisted here. The former is never modified after the map
// is setup but it's being read by concurrent marker when pointer compression // is setup but it's being read by concurrent marker when pointer compression
// is enabled. The latter bit can be modified on a live objects. // is enabled. The latter bit can be modified on a live objects.
BIT_FIELD_ACCESSORS(Map, bit_field, has_non_instance_prototype, BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_non_instance_prototype,
Map::Bits1::HasNonInstancePrototypeBit) Map::Bits1::HasNonInstancePrototypeBit)
BIT_FIELD_ACCESSORS(Map, bit_field, is_callable, Map::Bits1::IsCallableBit) BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_prototype_slot,
BIT_FIELD_ACCESSORS(Map, bit_field, has_named_interceptor, Map::Bits1::HasPrototypeSlotBit)
// These are fine to be written as non-atomic since we don't have data races.
// However, they have to be read atomically from the background since the
// |bit_field| as a whole can mutate when using the above setters.
BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, is_callable,
Map::Bits1::IsCallableBit)
BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, has_named_interceptor,
Map::Bits1::HasNamedInterceptorBit) Map::Bits1::HasNamedInterceptorBit)
BIT_FIELD_ACCESSORS(Map, bit_field, has_indexed_interceptor, BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, has_indexed_interceptor,
Map::Bits1::HasIndexedInterceptorBit) Map::Bits1::HasIndexedInterceptorBit)
BIT_FIELD_ACCESSORS(Map, bit_field, is_undetectable, BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, is_undetectable,
Map::Bits1::IsUndetectableBit) Map::Bits1::IsUndetectableBit)
BIT_FIELD_ACCESSORS(Map, bit_field, is_access_check_needed, BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, is_access_check_needed,
Map::Bits1::IsAccessCheckNeededBit) Map::Bits1::IsAccessCheckNeededBit)
BIT_FIELD_ACCESSORS(Map, bit_field, is_constructor, BIT_FIELD_ACCESSORS2(Map, relaxed_bit_field, bit_field, is_constructor,
Map::Bits1::IsConstructorBit) Map::Bits1::IsConstructorBit)
BIT_FIELD_ACCESSORS(Map, bit_field, has_prototype_slot,
Map::Bits1::HasPrototypeSlotBit)
// |bit_field2| fields. // |bit_field2| fields.
BIT_FIELD_ACCESSORS(Map, bit_field2, new_target_is_base, BIT_FIELD_ACCESSORS(Map, bit_field2, new_target_is_base,
...@@ -437,12 +442,18 @@ void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) { ...@@ -437,12 +442,18 @@ void Map::AccountAddedOutOfObjectPropertyField(int unused_in_property_array) {
DCHECK_EQ(unused_in_property_array, UnusedPropertyFields()); DCHECK_EQ(unused_in_property_array, UnusedPropertyFields());
} }
byte Map::bit_field() const { byte Map::bit_field() const { return ReadField<byte>(kBitFieldOffset); }
return ACQUIRE_READ_BYTE_FIELD(*this, kBitFieldOffset);
}
void Map::set_bit_field(byte value) { void Map::set_bit_field(byte value) {
RELEASE_WRITE_BYTE_FIELD(*this, kBitFieldOffset, value); WriteField<byte>(kBitFieldOffset, value);
}
byte Map::relaxed_bit_field() const {
return RELAXED_READ_BYTE_FIELD(*this, kBitFieldOffset);
}
void Map::set_relaxed_bit_field(byte value) {
RELAXED_WRITE_BYTE_FIELD(*this, kBitFieldOffset, value);
} }
byte Map::bit_field2() const { byte Map::bit_field2() const {
......
...@@ -245,6 +245,8 @@ class Map : public HeapObject { ...@@ -245,6 +245,8 @@ class Map : public HeapObject {
// Bit field. // Bit field.
// //
DECL_PRIMITIVE_ACCESSORS(bit_field, byte) DECL_PRIMITIVE_ACCESSORS(bit_field, byte)
// Atomic accessors, used for allowlisting legitimate concurrent accesses.
DECL_PRIMITIVE_ACCESSORS(relaxed_bit_field, byte)
// Bit positions for |bit_field|. // Bit positions for |bit_field|.
struct Bits1 { struct Bits1 {
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#undef OBJECT_CONSTRUCTORS_IMPL_CHECK_SUPER #undef OBJECT_CONSTRUCTORS_IMPL_CHECK_SUPER
#undef NEVER_READ_ONLY_SPACE #undef NEVER_READ_ONLY_SPACE
#undef NEVER_READ_ONLY_SPACE_IMPL #undef NEVER_READ_ONLY_SPACE_IMPL
#undef DECL_PRIMITIVE_GETTER
#undef DECL_PRIMITIVE_SETTER
#undef DECL_PRIMITIVE_ACCESSORS #undef DECL_PRIMITIVE_ACCESSORS
#undef DECL_SYNCHRONIZED_PRIMITIVE_ACCESSORS #undef DECL_SYNCHRONIZED_PRIMITIVE_ACCESSORS
#undef DECL_BOOLEAN_ACCESSORS #undef DECL_BOOLEAN_ACCESSORS
...@@ -32,6 +34,7 @@ ...@@ -32,6 +34,7 @@
#undef DECL_ACQUIRE_GETTER #undef DECL_ACQUIRE_GETTER
#undef DECL_RELEASE_SETTER #undef DECL_RELEASE_SETTER
#undef DECL_RELEASE_ACQUIRE_ACCESSORS #undef DECL_RELEASE_ACQUIRE_ACCESSORS
#undef DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS
#undef DECL_CAST #undef DECL_CAST
#undef CAST_ACCESSOR #undef CAST_ACCESSOR
#undef INT_ACCESSORS #undef INT_ACCESSORS
...@@ -53,15 +56,18 @@ ...@@ -53,15 +56,18 @@
#undef WEAK_ACCESSORS_CHECKED2 #undef WEAK_ACCESSORS_CHECKED2
#undef WEAK_ACCESSORS_CHECKED #undef WEAK_ACCESSORS_CHECKED
#undef WEAK_ACCESSORS #undef WEAK_ACCESSORS
#undef SYNCHRONIZED_WEAK_ACCESSORS_CHECKED2 #undef RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED2
#undef SYNCHRONIZED_WEAK_ACCESSORS_CHECKED #undef RELEASE_ACQUIRE_WEAK_ACCESSORS_CHECKED
#undef SYNCHRONIZED_WEAK_ACCESSORS #undef RELEASE_ACQUIRE_WEAK_ACCESSORS
#undef SMI_ACCESSORS_CHECKED #undef SMI_ACCESSORS_CHECKED
#undef SMI_ACCESSORS #undef SMI_ACCESSORS
#undef SYNCHRONIZED_SMI_ACCESSORS #undef SYNCHRONIZED_SMI_ACCESSORS
#undef RELAXED_SMI_ACCESSORS #undef RELAXED_SMI_ACCESSORS
#undef BOOL_GETTER #undef BOOL_GETTER
#undef BOOL_ACCESSORS #undef BOOL_ACCESSORS
#undef DECL_RELAXED_BOOL_ACCESSORS
#undef RELAXED_BOOL_ACCESSORS
#undef BIT_FIELD_ACCESSORS2
#undef BIT_FIELD_ACCESSORS #undef BIT_FIELD_ACCESSORS
#undef INSTANCE_TYPE_CHECKER #undef INSTANCE_TYPE_CHECKER
#undef TYPE_CHECKER #undef TYPE_CHECKER
...@@ -83,6 +89,8 @@ ...@@ -83,6 +89,8 @@
#undef ACQUIRE_READ_INT32_FIELD #undef ACQUIRE_READ_INT32_FIELD
#undef RELAXED_WRITE_INT8_FIELD #undef RELAXED_WRITE_INT8_FIELD
#undef RELAXED_READ_INT8_FIELD #undef RELAXED_READ_INT8_FIELD
#undef RELAXED_READ_UINT16_FIELD
#undef RELAXED_WRITE_UINT16_FIELD
#undef RELAXED_READ_INT16_FIELD #undef RELAXED_READ_INT16_FIELD
#undef RELAXED_WRITE_INT16_FIELD #undef RELAXED_WRITE_INT16_FIELD
#undef RELAXED_READ_UINT32_FIELD #undef RELAXED_READ_UINT32_FIELD
...@@ -92,6 +100,10 @@ ...@@ -92,6 +100,10 @@
#undef RELAXED_READ_INT32_FIELD #undef RELAXED_READ_INT32_FIELD
#undef RELEASE_WRITE_INT32_FIELD #undef RELEASE_WRITE_INT32_FIELD
#undef RELAXED_WRITE_INT32_FIELD #undef RELAXED_WRITE_INT32_FIELD
#undef RELAXED_READ_INT_FIELD
#undef RELAXED_WRITE_INT_FIELD
#undef RELAXED_READ_UINT_FIELD
#undef RELAXED_WRITE_UINT_FIELD
#undef RELAXED_READ_BYTE_FIELD #undef RELAXED_READ_BYTE_FIELD
#undef ACQUIRE_READ_BYTE_FIELD #undef ACQUIRE_READ_BYTE_FIELD
#undef RELAXED_WRITE_BYTE_FIELD #undef RELAXED_WRITE_BYTE_FIELD
......
...@@ -364,14 +364,17 @@ ...@@ -364,14 +364,17 @@
kRelaxedStore); \ kRelaxedStore); \
} }
#define BIT_FIELD_ACCESSORS(holder, field, name, BitField) \ #define BIT_FIELD_ACCESSORS2(holder, get_field, set_field, name, BitField) \
typename BitField::FieldType holder::name() const { \ typename BitField::FieldType holder::name() const { \
return BitField::decode(field()); \ return BitField::decode(get_field()); \
} \ } \
void holder::set_##name(typename BitField::FieldType value) { \ void holder::set_##name(typename BitField::FieldType value) { \
set_##field(BitField::update(field(), value)); \ set_##set_field(BitField::update(set_field(), value)); \
} }
#define BIT_FIELD_ACCESSORS(holder, field, name, BitField) \
BIT_FIELD_ACCESSORS2(holder, field, field, name, BitField)
#define INSTANCE_TYPE_CHECKER(type, forinstancetype) \ #define INSTANCE_TYPE_CHECKER(type, forinstancetype) \
V8_INLINE bool Is##type(InstanceType instance_type) { \ V8_INLINE bool Is##type(InstanceType instance_type) { \
return instance_type == forinstancetype; \ return instance_type == forinstancetype; \
......
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