[vm] Move catch_entry_cache, handler_info_cache to IsolateGroup.

This should help speeding up new isolate creation (or running dart code on mutator thread when it is supported).

TEST=ci

Change-Id: I88b5deeb33e72694cb3e2727cf5668ce15fd8c6b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/420361
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
Alexander Aprelev
2025-04-08 09:13:39 -07:00
committed by Commit Queue
parent 56ccf437e6
commit 7a44485843
6 changed files with 87 additions and 88 deletions
+3 -30
View File
@@ -137,7 +137,6 @@ class ExceptionHandlerFinder : public StackResource {
uword temp_handler_pc = kUwordMax;
bool is_optimized = false;
code_ = nullptr;
catch_entry_moves_cache_ = thread_->isolate()->catch_entry_moves_cache();
while (!frame->IsEntryFrame()) {
if (frame->IsDartFrame()) {
@@ -154,14 +153,6 @@ class ExceptionHandlerFinder : public StackResource {
StubCode::AsyncExceptionHandler().EntryPoint())) {
pc_ = frame->pc();
code_ = &Code::Handle(frame->LookupDartCode());
CatchEntryMovesRefPtr* cached_catch_entry_moves =
catch_entry_moves_cache_->Lookup(pc_);
if (cached_catch_entry_moves != nullptr) {
cached_catch_entry_moves_ = *cached_catch_entry_moves;
}
if (cached_catch_entry_moves_.IsEmpty()) {
ReadCompressedCatchEntryMoves();
}
}
}
if (needs_stacktrace || is_catch_all) {
@@ -190,15 +181,9 @@ class ExceptionHandlerFinder : public StackResource {
if (code_ == nullptr || !code_->is_optimized()) {
return;
}
if (cached_catch_entry_moves_.IsEmpty()) {
catch_entry_moves_cache_->Insert(
pc_, CatchEntryMovesRefPtr(catch_entry_moves_));
} else {
catch_entry_moves_ = &cached_catch_entry_moves_.moves();
}
ExecuteCatchEntryMoves(*catch_entry_moves_);
thread_->isolate_group()->RunWithCachedCatchEntryMoves(
*code_, pc_,
[&](const CatchEntryMoves& moves) { ExecuteCatchEntryMoves(moves); });
}
void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) {
@@ -295,14 +280,6 @@ class ExceptionHandlerFinder : public StackResource {
}
}
void ReadCompressedCatchEntryMoves() {
const intptr_t pc_offset = pc_ - code_->PayloadStart();
const auto& td = TypedData::Handle(code_->catch_entry_moves_maps());
CatchEntryMovesMapReader reader(td);
catch_entry_moves_ = reader.ReadMovesForPcOffset(pc_offset);
}
bool needs_stacktrace;
uword handler_pc;
uword handler_sp;
@@ -325,10 +302,6 @@ class ExceptionHandlerFinder : public StackResource {
Code* code_;
bool handler_pc_set_;
intptr_t pc_; // Current pc in the handler frame.
const CatchEntryMoves* catch_entry_moves_ = nullptr;
CatchEntryMovesCache* catch_entry_moves_cache_ = nullptr;
CatchEntryMovesRefPtr cached_catch_entry_moves_;
};
CatchEntryMove CatchEntryMove::ReadFrom(ReadStream* stream) {
+2 -2
View File
@@ -329,9 +329,9 @@ class CatchEntryMovesRefPtr {
return *this;
}
bool IsEmpty() { return ref_count_ == nullptr; }
bool IsEmpty() const { return ref_count_ == nullptr; }
const CatchEntryMoves& moves() { return *moves_; }
const CatchEntryMoves& moves() const { return *moves_; }
private:
void Destroy() {
+2 -6
View File
@@ -545,12 +545,8 @@ void Heap::CollectOldSpaceGarbage(Thread* thread,
#endif
// Some Code objects may have been collected so invalidate handler cache.
thread->isolate_group()->ForEachIsolate(
[&](Isolate* isolate) {
isolate->handler_info_cache()->Clear();
isolate->catch_entry_moves_cache()->Clear();
},
/*at_safepoint=*/true);
thread->isolate_group()->handler_info_cache()->Clear();
thread->isolate_group()->ClearCatchEntryMovesCache();
assume_scavenge_will_fail_ = false;
}
}
+29 -6
View File
@@ -372,12 +372,13 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
boxed_field_list_(GrowableObjectArray::null()),
program_lock_(new SafepointRwLock(SafepointLevel::kGCAndDeopt)),
active_mutators_monitor_(new Monitor()),
max_active_mutators_(Scavenger::MaxMutatorThreadCount())
max_active_mutators_(Scavenger::MaxMutatorThreadCount()),
#if !defined(PRODUCT)
,
debugger_(new GroupDebugger(this))
debugger_(new GroupDebugger(this)),
#endif
{
cache_mutex_(),
handler_info_cache_(),
catch_entry_moves_cache_() {
FlagsCopyFrom(api_flags);
if (!is_vm_isolate) {
intptr_t max_worker_threads;
@@ -927,6 +928,30 @@ void IsolateGroup::ExitTemporaryIsolate() {
Dart::ShutdownIsolate(thread);
}
void IsolateGroup::RunWithCachedCatchEntryMoves(
const Code& code,
intptr_t pc,
std::function<void(const CatchEntryMoves&)> action) {
SafepointMutexLocker ml(&cache_mutex_);
const CatchEntryMovesRefPtr* ref = catch_entry_moves_cache_.Lookup(pc);
if (ref != nullptr) {
action(ref->moves());
} else {
const intptr_t pc_offset = pc - code.PayloadStart();
const auto& td = TypedData::Handle(code.catch_entry_moves_maps());
CatchEntryMovesMapReader reader(td);
const CatchEntryMoves* moves = reader.ReadMovesForPcOffset(pc_offset);
catch_entry_moves_cache_.Insert(pc, CatchEntryMovesRefPtr(moves));
action(*moves);
}
}
void IsolateGroup::ClearCatchEntryMovesCache() {
SafepointMutexLocker ml(&cache_mutex_);
catch_entry_moves_cache_.Clear();
}
void IsolateGroup::RehashConstants(Become* become) {
// Even though no individual constant contains a cycle, there can be "cycles"
// between the canonical tables if some const instances of A have fields that
@@ -1816,8 +1841,6 @@ Isolate::Isolate(IsolateGroup* isolate_group,
tag_table_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
spawn_count_monitor_(),
handler_info_cache_(),
catch_entry_moves_cache_(),
wake_pause_event_handler_count_(0),
loaded_prefixes_set_storage_(nullptr) {
FlagsCopyFrom(api_flags);
+13 -9
View File
@@ -776,11 +776,20 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
Isolate* EnterTemporaryIsolate();
static void ExitTemporaryIsolate();
void RunWithCachedCatchEntryMoves(
const Code& code,
intptr_t pc,
std::function<void(const CatchEntryMoves&)> action);
void ClearCatchEntryMovesCache();
void SetNativeAssetsCallbacks(NativeAssetsApi* native_assets_api) {
native_assets_api_ = *native_assets_api;
}
NativeAssetsApi* native_assets_api() { return &native_assets_api_; }
Mutex* cache_mutex() { return &cache_mutex_; }
HandlerInfoCache* handler_info_cache() { return &handler_info_cache_; }
private:
friend class Dart; // For `object_store_ = ` in Dart::Init
friend class Heap;
@@ -931,6 +940,10 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
NOT_IN_PRODUCT(GroupDebugger* debugger_ = nullptr);
NativeAssetsApi native_assets_api_;
Mutex cache_mutex_;
HandlerInfoCache handler_info_cache_;
CatchEntryMovesCache catch_entry_moves_cache_;
};
// When an isolate sends-and-exits this class represent things that it passed
@@ -1447,12 +1460,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
}
static bool IsVMInternalIsolate(const Isolate* isolate);
HandlerInfoCache* handler_info_cache() { return &handler_info_cache_; }
CatchEntryMovesCache* catch_entry_moves_cache() {
return &catch_entry_moves_cache_;
}
// The weak table used in the snapshot writer for the purpose of fast message
// sending.
WeakTable* forward_table_new() { return forward_table_new_.get(); }
@@ -1697,9 +1704,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
Monitor spawn_count_monitor_;
intptr_t spawn_count_ = 0;
HandlerInfoCache handler_info_cache_;
CatchEntryMovesCache catch_entry_moves_cache_;
// Used during message sending of messages between isolates.
std::unique_ptr<WeakTable> forward_table_new_;
std::unique_ptr<WeakTable> forward_table_old_;
+38 -35
View File
@@ -469,47 +469,50 @@ bool StackFrame::FindExceptionHandler(Thread* thread,
descriptors = code.pc_descriptors();
*is_optimized = code.is_optimized();
}
HandlerInfoCache* cache = thread->isolate()->handler_info_cache();
ExceptionHandlerInfo* info = cache->Lookup(pc());
if (info != nullptr) {
*handler_pc = start + info->handler_pc_offset;
*needs_stacktrace = (info->needs_stacktrace != 0);
*has_catch_all = (info->has_catch_all != 0);
return true;
}
{
SafepointMutexLocker ml(thread->isolate_group()->cache_mutex());
HandlerInfoCache* cache = thread->isolate_group()->handler_info_cache();
ExceptionHandlerInfo* info = cache->Lookup(pc());
if (info != nullptr) {
*handler_pc = start + info->handler_pc_offset;
*needs_stacktrace = (info->needs_stacktrace != 0);
*has_catch_all = (info->has_catch_all != 0);
return true;
}
intptr_t try_index = -1;
if (handlers.num_entries() != 0) {
if (is_interpreted()) {
try_index = bytecode.GetTryIndexAtPc(pc());
} else {
uword pc_offset = pc() - code.PayloadStart();
PcDescriptors::Iterator iter(descriptors,
UntaggedPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
const intptr_t current_try_index = iter.TryIndex();
if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
try_index = current_try_index;
break;
intptr_t try_index = -1;
if (handlers.num_entries() != 0) {
if (is_interpreted()) {
try_index = bytecode.GetTryIndexAtPc(pc());
} else {
uword pc_offset = pc() - code.PayloadStart();
PcDescriptors::Iterator iter(descriptors,
UntaggedPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
const intptr_t current_try_index = iter.TryIndex();
if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
try_index = current_try_index;
break;
}
}
}
}
}
if (try_index == -1) {
if (handlers.has_async_handler()) {
*handler_pc = StubCode::AsyncExceptionHandler().EntryPoint();
*needs_stacktrace = true;
*has_catch_all = true;
return true;
if (try_index == -1) {
if (handlers.has_async_handler()) {
*handler_pc = StubCode::AsyncExceptionHandler().EntryPoint();
*needs_stacktrace = true;
*has_catch_all = true;
return true;
}
return false;
}
return false;
ExceptionHandlerInfo handler_info;
handlers.GetHandlerInfo(try_index, &handler_info);
*handler_pc = start + handler_info.handler_pc_offset;
*needs_stacktrace = (handler_info.needs_stacktrace != 0);
*has_catch_all = (handler_info.has_catch_all != 0);
cache->Insert(pc(), handler_info);
}
ExceptionHandlerInfo handler_info;
handlers.GetHandlerInfo(try_index, &handler_info);
*handler_pc = start + handler_info.handler_pc_offset;
*needs_stacktrace = (handler_info.needs_stacktrace != 0);
*has_catch_all = (handler_info.has_catch_all != 0);
cache->Insert(pc(), handler_info);
return true;
}