mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:18:13 +00:00
[vm] Update Megamorphic::filled_entry_count_ under the megamorphic lock.
Otherwise the background compiler may see 0 when the mutator grows the megamorphic cache. Bug: https://github.com/dart-lang/sdk/issues/37257 Change-Id: I64a31937391ad6c0f086f8f175501ca4ef06c305 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105969 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
0f91731f98
commit
112dbabc10
|
@ -776,7 +776,7 @@ void Cids::CreateHelper(Zone* zone,
|
||||||
if (ic_data.is_megamorphic()) {
|
if (ic_data.is_megamorphic()) {
|
||||||
const MegamorphicCache& cache =
|
const MegamorphicCache& cache =
|
||||||
MegamorphicCache::Handle(zone, ic_data.AsMegamorphicCache());
|
MegamorphicCache::Handle(zone, ic_data.AsMegamorphicCache());
|
||||||
SafepointMutexLocker ml(Isolate::Current()->megamorphic_lookup_mutex());
|
SafepointMutexLocker ml(Isolate::Current()->megamorphic_mutex());
|
||||||
MegamorphicCacheEntries entries(Array::Handle(zone, cache.buckets()));
|
MegamorphicCacheEntries entries(Array::Handle(zone, cache.buckets()));
|
||||||
for (intptr_t i = 0; i < entries.Length(); i++) {
|
for (intptr_t i = 0; i < entries.Length(); i++) {
|
||||||
const intptr_t id =
|
const intptr_t id =
|
||||||
|
@ -787,8 +787,10 @@ void Cids::CreateHelper(Zone* zone,
|
||||||
if (include_targets) {
|
if (include_targets) {
|
||||||
Function& function = Function::ZoneHandle(zone);
|
Function& function = Function::ZoneHandle(zone);
|
||||||
function ^= entries[i].Get<MegamorphicCache::kTargetFunctionIndex>();
|
function ^= entries[i].Get<MegamorphicCache::kTargetFunctionIndex>();
|
||||||
|
const intptr_t filled_entry_count = cache.filled_entry_count();
|
||||||
|
ASSERT(filled_entry_count > 0);
|
||||||
cid_ranges_.Add(new (zone) TargetInfo(
|
cid_ranges_.Add(new (zone) TargetInfo(
|
||||||
id, id, &function, Usage(function) / cache.filled_entry_count(),
|
id, id, &function, Usage(function) / filled_entry_count,
|
||||||
StaticTypeExactnessState::NotTracking()));
|
StaticTypeExactnessState::NotTracking()));
|
||||||
} else {
|
} else {
|
||||||
cid_ranges_.Add(new (zone) CidRange(id, id));
|
cid_ranges_.Add(new (zone) CidRange(id, id));
|
||||||
|
|
|
@ -892,8 +892,7 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags)
|
||||||
NOT_IN_PRODUCT("Isolate::type_canonicalization_mutex_")),
|
NOT_IN_PRODUCT("Isolate::type_canonicalization_mutex_")),
|
||||||
constant_canonicalization_mutex_(
|
constant_canonicalization_mutex_(
|
||||||
NOT_IN_PRODUCT("Isolate::constant_canonicalization_mutex_")),
|
NOT_IN_PRODUCT("Isolate::constant_canonicalization_mutex_")),
|
||||||
megamorphic_lookup_mutex_(
|
megamorphic_mutex_(NOT_IN_PRODUCT("Isolate::megamorphic_mutex_")),
|
||||||
NOT_IN_PRODUCT("Isolate::megamorphic_lookup_mutex_")),
|
|
||||||
kernel_data_lib_cache_mutex_(
|
kernel_data_lib_cache_mutex_(
|
||||||
NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_")),
|
NOT_IN_PRODUCT("Isolate::kernel_data_lib_cache_mutex_")),
|
||||||
kernel_data_class_cache_mutex_(
|
kernel_data_class_cache_mutex_(
|
||||||
|
|
|
@ -355,7 +355,7 @@ class Isolate : public BaseIsolate {
|
||||||
Mutex* constant_canonicalization_mutex() {
|
Mutex* constant_canonicalization_mutex() {
|
||||||
return &constant_canonicalization_mutex_;
|
return &constant_canonicalization_mutex_;
|
||||||
}
|
}
|
||||||
Mutex* megamorphic_lookup_mutex() { return &megamorphic_lookup_mutex_; }
|
Mutex* megamorphic_mutex() { return &megamorphic_mutex_; }
|
||||||
|
|
||||||
Mutex* kernel_data_lib_cache_mutex() { return &kernel_data_lib_cache_mutex_; }
|
Mutex* kernel_data_lib_cache_mutex() { return &kernel_data_lib_cache_mutex_; }
|
||||||
Mutex* kernel_data_class_cache_mutex() {
|
Mutex* kernel_data_class_cache_mutex() {
|
||||||
|
@ -1027,7 +1027,8 @@ class Isolate : public BaseIsolate {
|
||||||
Mutex symbols_mutex_; // Protects concurrent access to the symbol table.
|
Mutex symbols_mutex_; // Protects concurrent access to the symbol table.
|
||||||
Mutex type_canonicalization_mutex_; // Protects type canonicalization.
|
Mutex type_canonicalization_mutex_; // Protects type canonicalization.
|
||||||
Mutex constant_canonicalization_mutex_; // Protects const canonicalization.
|
Mutex constant_canonicalization_mutex_; // Protects const canonicalization.
|
||||||
Mutex megamorphic_lookup_mutex_; // Protects megamorphic table lookup.
|
Mutex megamorphic_mutex_; // Protects the table of megamorphic caches and
|
||||||
|
// their entries.
|
||||||
Mutex kernel_data_lib_cache_mutex_;
|
Mutex kernel_data_lib_cache_mutex_;
|
||||||
Mutex kernel_data_class_cache_mutex_;
|
Mutex kernel_data_class_cache_mutex_;
|
||||||
Mutex kernel_constants_mutex_;
|
Mutex kernel_constants_mutex_;
|
||||||
|
|
|
@ -16,7 +16,7 @@ RawMegamorphicCache* MegamorphicCacheTable::Lookup(Isolate* isolate,
|
||||||
const String& name,
|
const String& name,
|
||||||
const Array& descriptor) {
|
const Array& descriptor) {
|
||||||
// Multiple compilation threads could access this lookup.
|
// Multiple compilation threads could access this lookup.
|
||||||
SafepointMutexLocker ml(isolate->megamorphic_lookup_mutex());
|
SafepointMutexLocker ml(isolate->megamorphic_mutex());
|
||||||
ASSERT(name.IsSymbol());
|
ASSERT(name.IsSymbol());
|
||||||
// TODO(rmacnak): ASSERT(descriptor.IsCanonical());
|
// TODO(rmacnak): ASSERT(descriptor.IsCanonical());
|
||||||
|
|
||||||
|
|
|
@ -14175,7 +14175,7 @@ bool ICData::HasOneTarget() const {
|
||||||
if (is_megamorphic()) {
|
if (is_megamorphic()) {
|
||||||
const MegamorphicCache& cache =
|
const MegamorphicCache& cache =
|
||||||
MegamorphicCache::Handle(AsMegamorphicCache());
|
MegamorphicCache::Handle(AsMegamorphicCache());
|
||||||
SafepointMutexLocker ml(Isolate::Current()->megamorphic_lookup_mutex());
|
SafepointMutexLocker ml(Isolate::Current()->megamorphic_mutex());
|
||||||
MegamorphicCacheEntries entries(Array::Handle(cache.buckets()));
|
MegamorphicCacheEntries entries(Array::Handle(cache.buckets()));
|
||||||
for (intptr_t i = 0; i < entries.Length(); i++) {
|
for (intptr_t i = 0; i < entries.Length(); i++) {
|
||||||
const intptr_t id =
|
const intptr_t id =
|
||||||
|
@ -15672,7 +15672,14 @@ RawMegamorphicCache* MegamorphicCache::New(const String& target_name,
|
||||||
return result.raw();
|
return result.raw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MegamorphicCache::EnsureCapacity() const {
|
void MegamorphicCache::Insert(const Smi& class_id, const Object& target) const {
|
||||||
|
SafepointMutexLocker ml(Isolate::Current()->megamorphic_mutex());
|
||||||
|
EnsureCapacityLocked();
|
||||||
|
InsertLocked(class_id, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MegamorphicCache::EnsureCapacityLocked() const {
|
||||||
|
ASSERT(Isolate::Current()->megamorphic_mutex()->IsOwnedByCurrentThread());
|
||||||
intptr_t old_capacity = mask() + 1;
|
intptr_t old_capacity = mask() + 1;
|
||||||
double load_limit = kLoadFactor * static_cast<double>(old_capacity);
|
double load_limit = kLoadFactor * static_cast<double>(old_capacity);
|
||||||
if (static_cast<double>(filled_entry_count() + 1) > load_limit) {
|
if (static_cast<double>(filled_entry_count() + 1) > load_limit) {
|
||||||
|
@ -15696,16 +15703,18 @@ void MegamorphicCache::EnsureCapacity() const {
|
||||||
class_id ^= GetClassId(old_buckets, i);
|
class_id ^= GetClassId(old_buckets, i);
|
||||||
if (class_id.Value() != kIllegalCid) {
|
if (class_id.Value() != kIllegalCid) {
|
||||||
target = GetTargetFunction(old_buckets, i);
|
target = GetTargetFunction(old_buckets, i);
|
||||||
Insert(class_id, target);
|
InsertLocked(class_id, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MegamorphicCache::Insert(const Smi& class_id, const Object& target) const {
|
void MegamorphicCache::InsertLocked(const Smi& class_id,
|
||||||
|
const Object& target) const {
|
||||||
|
ASSERT(Isolate::Current()->megamorphic_mutex()->IsOwnedByCurrentThread());
|
||||||
|
ASSERT(Thread::Current()->IsMutatorThread());
|
||||||
ASSERT(static_cast<double>(filled_entry_count() + 1) <=
|
ASSERT(static_cast<double>(filled_entry_count() + 1) <=
|
||||||
(kLoadFactor * static_cast<double>(mask() + 1)));
|
(kLoadFactor * static_cast<double>(mask() + 1)));
|
||||||
SafepointMutexLocker ml(Isolate::Current()->megamorphic_lookup_mutex());
|
|
||||||
const Array& backing_array = Array::Handle(buckets());
|
const Array& backing_array = Array::Handle(buckets());
|
||||||
intptr_t id_mask = mask();
|
intptr_t id_mask = mask();
|
||||||
intptr_t index = (class_id.Value() * kSpreadFactor) & id_mask;
|
intptr_t index = (class_id.Value() * kSpreadFactor) & id_mask;
|
||||||
|
|
|
@ -5836,8 +5836,6 @@ class MegamorphicCache : public Object {
|
||||||
static RawMegamorphicCache* New(const String& target_name,
|
static RawMegamorphicCache* New(const String& target_name,
|
||||||
const Array& arguments_descriptor);
|
const Array& arguments_descriptor);
|
||||||
|
|
||||||
void EnsureCapacity() const;
|
|
||||||
|
|
||||||
void Insert(const Smi& class_id, const Object& target) const;
|
void Insert(const Smi& class_id, const Object& target) const;
|
||||||
|
|
||||||
void SwitchToBareInstructions();
|
void SwitchToBareInstructions();
|
||||||
|
@ -5856,6 +5854,10 @@ class MegamorphicCache : public Object {
|
||||||
void set_target_name(const String& value) const;
|
void set_target_name(const String& value) const;
|
||||||
void set_arguments_descriptor(const Array& value) const;
|
void set_arguments_descriptor(const Array& value) const;
|
||||||
|
|
||||||
|
// The caller must hold Isolate::megamorphic_mutex().
|
||||||
|
void EnsureCapacityLocked() const;
|
||||||
|
void InsertLocked(const Smi& class_id, const Object& target) const;
|
||||||
|
|
||||||
static inline void SetEntry(const Array& array,
|
static inline void SetEntry(const Array& array,
|
||||||
intptr_t index,
|
intptr_t index,
|
||||||
const Smi& class_id,
|
const Smi& class_id,
|
||||||
|
|
|
@ -1786,7 +1786,6 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
|
||||||
} else {
|
} else {
|
||||||
const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache);
|
const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache);
|
||||||
// Insert function found into cache and return it.
|
// Insert function found into cache and return it.
|
||||||
cache.EnsureCapacity();
|
|
||||||
const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id()));
|
const Smi& class_id = Smi::Handle(zone, Smi::New(cls.id()));
|
||||||
cache.Insert(class_id, target_function);
|
cache.Insert(class_id, target_function);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue