From 62cb7dc94f57408edae3606df6e47aca02ba5500 Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Mon, 14 Apr 2025 08:40:35 -0700 Subject: [PATCH] Optimized GetParallelMethodDesc --- src/coreclr/vm/methodtable.cpp | 30 ++++++++++++++------------- src/coreclr/vm/methodtablebuilder.cpp | 3 ++- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 7bd2dc24da4..733d883dba1 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -7810,23 +7810,25 @@ MethodDesc* MethodTable::GetParallelMethodDesc(MethodDesc* pDefMD, AsyncVariantL } else { - // Slow path for finding the Async variant (or not-Async variant, if we start from Async one) - // This could be optimized with some trickery around slot numbers, but doing so is ... confusing, so I'm not implementing this yet - mdMethodDef tkMethod = pDefMD->GetMemberDef(); - Module* mod = pDefMD->GetModule(); - bool isAsyncVariantMethod = pDefMD->IsAsyncVariantMethod(); + WORD slot = pDefMD->GetSlot(); - MethodTable::IntroducedMethodIterator it(this); - for (; it.IsValid(); it.Next()) + // Async variants are laid out one after another + // - fist the task-returning entry and then async2 variant. + // Thus what we look for is at +1 or -1 from the definition we are given. + // + // TODO: if we search within the same MT and the current chunk has space, + // we may just increment/decrement pDefMD by the size of current desc. + // (it would be even faster than through slot tables) + if (pDefMD->IsTaskReturningMethod()) { - MethodDesc* pMD = it.GetMethodDesc(); - if (pMD->GetMemberDef() == tkMethod - && pMD->GetModule() == mod - && pMD->IsAsyncVariantMethod() != isAsyncVariantMethod) - { - return pMD; - } + return GetMethodDescForSlot_NoThrow(slot + 1); } + else if (pDefMD->IsAsyncVariantMethod()) + { + return GetMethodDescForSlot_NoThrow(slot - 1); + } + + // the definition is not a variant from a pair. (TODO: this is likely unreachable) return NULL; } } diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 822e25fc180..14cf024e856 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -5631,7 +5631,8 @@ MethodTableBuilder::PlaceNonVirtualMethods() #endif // _DEBUG if (!fCanHaveNonVtableSlots || - it->GetMethodType() == mcInstantiated) + it->GetMethodType() == mcInstantiated || + it->GetAsyncMethodKind() != AsyncMethodKind::NotAsync) { // We use slot during remoting and to map methods between generic instantiations // (see MethodTable::GetParallelMethodDesc). The current implementation