[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:
committed by
Commit Queue
parent
56ccf437e6
commit
7a44485843
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user