From bd9d4e0a4776fa8eb8320e1665b0a05b1a1ad3ea Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Thu, 15 Jul 2021 07:51:44 -0700 Subject: [PATCH] JIT: enable GDV when static class deduction fails. (#55660) Update the early bailout in impDevirtualizeCall that gives up if the object class cannot not be determined to check if we can do GDV (guarded devirtualization) based on profile data. Fixes one of the cases noted in #55079. --- src/coreclr/jit/importer.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index b3857cdec583..5d6c0d7354f5 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -20935,6 +20935,13 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, return; } + // Fetch information about the class that introduced the virtual method. + CORINFO_CLASS_HANDLE baseClass = info.compCompHnd->getMethodClass(baseMethod); + const DWORD baseClassAttribs = info.compCompHnd->getClassAttribs(baseClass); + + // Is the call an interface call? + const bool isInterface = (baseClassAttribs & CORINFO_FLG_INTERFACE) != 0; + // See what we know about the type of 'this' in the call. GenTree* thisObj = call->gtCallThisArg->GetNode()->gtEffectiveVal(false); bool isExact = false; @@ -20942,18 +20949,23 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, CORINFO_CLASS_HANDLE objClass = gtGetClassHandle(thisObj, &isExact, &objIsNonNull); // Bail if we know nothing. - if (objClass == nullptr) + if (objClass == NO_CLASS_HANDLE) { JITDUMP("\nimpDevirtualizeCall: no type available (op=%s)\n", GenTree::OpName(thisObj->OperGet())); - return; - } - // Fetch information about the class that introduced the virtual method. - CORINFO_CLASS_HANDLE baseClass = info.compCompHnd->getMethodClass(baseMethod); - const DWORD baseClassAttribs = info.compCompHnd->getClassAttribs(baseClass); + // Don't try guarded devirtualiztion when we're doing late devirtualization. + // + if (isLateDevirtualization) + { + JITDUMP("No guarded devirt during late devirtualization\n"); + return; + } - // Is the call an interface call? - const bool isInterface = (baseClassAttribs & CORINFO_FLG_INTERFACE) != 0; + considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, + pContextHandle DEBUGARG(objClass) DEBUGARG("unknown")); + + return; + } // If the objClass is sealed (final), then we may be able to devirtualize. const DWORD objClassAttribs = info.compCompHnd->getClassAttribs(objClass);