Skip to content

Commit f042822

Browse files
alexmarkovCommit Queue
authored and
Commit Queue
committed
[vm] Possible fix for data race during TypeRef canonicalization
AbstractType::flags_ is changed to atomic with relaxed memory order in order to allow accesses to a mutable type state outside of the type canonicalization mutex and program lock. TEST=iso-stress bot Fixes #50065 Change-Id: Iaebd4ea809e7f1bb0b9afe29308e0e6a2bd3d6ec Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262503 Reviewed-by: Ryan Macnak <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 15be61e commit f042822

File tree

4 files changed

+27
-22
lines changed

4 files changed

+27
-22
lines changed

runtime/vm/app_snapshot.cc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4124,7 +4124,7 @@ class TypeSerializationCluster
41244124
}
41254125
#endif
41264126
WriteFromTo(type);
4127-
s->WriteUnsigned(type->untag()->flags_);
4127+
s->WriteUnsigned(type->untag()->flags());
41284128
}
41294129
};
41304130
#endif // !DART_PRECOMPILED_RUNTIME
@@ -4153,7 +4153,7 @@ class TypeDeserializationCluster
41534153
Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
41544154
mark_canonical);
41554155
d.ReadFromTo(type);
4156-
type->untag()->flags_ = d.ReadUnsigned();
4156+
type->untag()->set_flags(d.ReadUnsigned());
41574157
}
41584158
}
41594159

@@ -4235,8 +4235,8 @@ class FunctionTypeSerializationCluster
42354235
void WriteFunctionType(Serializer* s, FunctionTypePtr type) {
42364236
AutoTraceObject(type);
42374237
WriteFromTo(type);
4238-
ASSERT(Utils::IsUint(8, type->untag()->flags_));
4239-
s->Write<uint8_t>(type->untag()->flags_);
4238+
ASSERT(Utils::IsUint(8, type->untag()->flags()));
4239+
s->Write<uint8_t>(type->untag()->flags());
42404240
s->Write<uint32_t>(type->untag()->packed_parameter_counts_);
42414241
s->Write<uint16_t>(type->untag()->packed_type_parameter_counts_);
42424242
}
@@ -4267,7 +4267,7 @@ class FunctionTypeDeserializationCluster
42674267
Deserializer::InitializeHeader(
42684268
type, kFunctionTypeCid, FunctionType::InstanceSize(), mark_canonical);
42694269
d.ReadFromTo(type);
4270-
type->untag()->flags_ = d.Read<uint8_t>();
4270+
type->untag()->set_flags(d.Read<uint8_t>());
42714271
type->untag()->packed_parameter_counts_ = d.Read<uint32_t>();
42724272
type->untag()->packed_type_parameter_counts_ = d.Read<uint16_t>();
42734273
}
@@ -4351,8 +4351,8 @@ class RecordTypeSerializationCluster
43514351
void WriteRecordType(Serializer* s, RecordTypePtr type) {
43524352
AutoTraceObject(type);
43534353
WriteFromTo(type);
4354-
ASSERT(Utils::IsUint(8, type->untag()->flags_));
4355-
s->Write<uint8_t>(type->untag()->flags_);
4354+
ASSERT(Utils::IsUint(8, type->untag()->flags()));
4355+
s->Write<uint8_t>(type->untag()->flags());
43564356
}
43574357
};
43584358
#endif // !DART_PRECOMPILED_RUNTIME
@@ -4380,7 +4380,7 @@ class RecordTypeDeserializationCluster
43804380
Deserializer::InitializeHeader(
43814381
type, kRecordTypeCid, RecordType::InstanceSize(), mark_canonical);
43824382
d.ReadFromTo(type);
4383-
type->untag()->flags_ = d.Read<uint8_t>();
4383+
type->untag()->set_flags(d.Read<uint8_t>());
43844384
}
43854385
}
43864386

@@ -4556,8 +4556,8 @@ class TypeParameterSerializationCluster
45564556
s->Write<int32_t>(type->untag()->parameterized_class_id_);
45574557
s->Write<uint8_t>(type->untag()->base_);
45584558
s->Write<uint8_t>(type->untag()->index_);
4559-
ASSERT(Utils::IsUint(8, type->untag()->flags_));
4560-
s->Write<uint8_t>(type->untag()->flags_);
4559+
ASSERT(Utils::IsUint(8, type->untag()->flags()));
4560+
s->Write<uint8_t>(type->untag()->flags());
45614561
}
45624562
};
45634563
#endif // !DART_PRECOMPILED_RUNTIME
@@ -4590,7 +4590,7 @@ class TypeParameterDeserializationCluster
45904590
type->untag()->parameterized_class_id_ = d.Read<int32_t>();
45914591
type->untag()->base_ = d.Read<uint8_t>();
45924592
type->untag()->index_ = d.Read<uint8_t>();
4593-
type->untag()->flags_ = d.Read<uint8_t>();
4593+
type->untag()->set_flags(d.Read<uint8_t>());
45944594
}
45954595
}
45964596

runtime/vm/object.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20336,19 +20336,19 @@ void AbstractType::SetIsBeingFinalized() const {
2033620336
}
2033720337

2033820338
void AbstractType::set_flags(uint32_t value) const {
20339-
StoreNonPointer(&untag()->flags_, value);
20339+
untag()->set_flags(value);
2034020340
}
2034120341

2034220342
void AbstractType::set_type_state(UntaggedAbstractType::TypeState value) const {
2034320343
ASSERT(!IsCanonical());
2034420344
set_flags(
20345-
UntaggedAbstractType::TypeStateBits::update(value, untag()->flags_));
20345+
UntaggedAbstractType::TypeStateBits::update(value, untag()->flags()));
2034620346
}
2034720347

2034820348
void AbstractType::set_nullability(Nullability value) const {
2034920349
ASSERT(!IsCanonical());
2035020350
set_flags(UntaggedAbstractType::NullabilityBits::update(
20351-
static_cast<uint8_t>(value), untag()->flags_));
20351+
static_cast<uint8_t>(value), untag()->flags()));
2035220352
}
2035320353

2035420354
bool AbstractType::IsEquivalent(const Instance& other,

runtime/vm/object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8197,7 +8197,7 @@ class AbstractType : public Instance {
81978197

81988198
Nullability nullability() const {
81998199
return static_cast<Nullability>(
8200-
UntaggedAbstractType::NullabilityBits::decode(untag()->flags_));
8200+
UntaggedAbstractType::NullabilityBits::decode(untag()->flags()));
82018201
}
82028202
// Returns true if type has '?' nullability suffix, or it is a
82038203
// built-in type which is always nullable (Null, dynamic or void).
@@ -8493,7 +8493,7 @@ class AbstractType : public Instance {
84938493

84948494
UntaggedAbstractType::TypeState type_state() const {
84958495
return static_cast<UntaggedAbstractType::TypeState>(
8496-
UntaggedAbstractType::TypeStateBits::decode(untag()->flags_));
8496+
UntaggedAbstractType::TypeStateBits::decode(untag()->flags()));
84978497
}
84988498
void set_flags(uint32_t value) const;
84998499
void set_type_state(UntaggedAbstractType::TypeState value) const;

runtime/vm/raw_object.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2613,10 +2613,15 @@ class UntaggedAbstractType : public UntaggedInstance {
26132613
// Accessed from generated code.
26142614
std::atomic<uword> type_test_stub_entry_point_;
26152615
// Accessed from generated code.
2616-
uint32_t flags_;
2616+
std::atomic<uint32_t> flags_;
26172617
COMPRESSED_POINTER_FIELD(CodePtr, type_test_stub)
26182618
VISIT_FROM(type_test_stub)
26192619

2620+
uint32_t flags() const { return flags_.load(std::memory_order_relaxed); }
2621+
void set_flags(uint32_t value) {
2622+
flags_.store(value, std::memory_order_relaxed);
2623+
}
2624+
26202625
public:
26212626
enum TypeState {
26222627
kAllocated, // Initial state.
@@ -2625,13 +2630,13 @@ class UntaggedAbstractType : public UntaggedInstance {
26252630
kFinalizedUninstantiated, // Uninstantiated type ready for use.
26262631
};
26272632

2628-
using NullabilityBits = BitField<decltype(flags_), uint8_t, 0, 2>;
2633+
using NullabilityBits = BitField<uint32_t, uint8_t, 0, 2>;
26292634
static constexpr intptr_t kNullabilityMask = NullabilityBits::mask();
26302635

26312636
static constexpr intptr_t kTypeStateShift = NullabilityBits::kNextBit;
26322637
static constexpr intptr_t kTypeStateBits = 2;
26332638
using TypeStateBits =
2634-
BitField<decltype(flags_), uint8_t, kTypeStateShift, kTypeStateBits>;
2639+
BitField<uint32_t, uint8_t, kTypeStateShift, kTypeStateBits>;
26352640

26362641
private:
26372642
RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractType);
@@ -2643,7 +2648,7 @@ class UntaggedAbstractType : public UntaggedInstance {
26432648
class UntaggedType : public UntaggedAbstractType {
26442649
public:
26452650
static constexpr intptr_t kTypeClassIdShift = TypeStateBits::kNextBit;
2646-
using TypeClassIdBits = BitField<decltype(flags_),
2651+
using TypeClassIdBits = BitField<uint32_t,
26472652
ClassIdTagType,
26482653
kTypeClassIdShift,
26492654
sizeof(ClassIdTagType) * kBitsPerByte>;
@@ -2658,10 +2663,10 @@ class UntaggedType : public UntaggedAbstractType {
26582663
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
26592664

26602665
ClassIdTagType type_class_id() const {
2661-
return TypeClassIdBits::decode(flags_);
2666+
return TypeClassIdBits::decode(flags());
26622667
}
26632668
void set_type_class_id(ClassIdTagType value) {
2664-
flags_ = TypeClassIdBits::update(value, flags_);
2669+
set_flags(TypeClassIdBits::update(value, flags()));
26652670
}
26662671

26672672
friend class compiler::target::UntaggedType;

0 commit comments

Comments
 (0)