From 8d9b3eff90ff7376ca25abff99efb64dc946d2d7 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 23 Jul 2022 18:12:56 +0200 Subject: [PATCH 01/27] NativeAOT: Implement a fake EH filter for generic exceptions --- src/coreclr/jit/compiler.h | 1 + src/coreclr/jit/jiteh.cpp | 80 +++++++++++++++++++ .../IL/ILImporter.Scanner.cs | 10 +-- .../JitInterface/CorInfoImpl.RyuJit.cs | 7 -- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index f397d4bcd9e883..a76f03a5993fdf 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2217,6 +2217,7 @@ class Compiler bool fgNormalizeEHCase1(); bool fgNormalizeEHCase2(); bool fgNormalizeEHCase3(); + bool fgNormalizeEHCase_NativeAot(); void fgCheckForLoopsInHandlers(); diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index f0877dabf76eb2..2b3172cdcffd38 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2127,6 +2127,12 @@ void Compiler::fgNormalizeEH() #endif // 0 + // For NativeAOT we need to create a fake exception filter for generic handlers + if (IsTargetAbi(CORINFO_NATIVEAOT_ABI) && fgNormalizeEHCase_NativeAot()) + { + modified = true; + } + INDEBUG(fgNormalizeEHDone = true;) if (modified) @@ -2506,6 +2512,80 @@ bool Compiler::fgNormalizeEHCase2() return modified; } +//------------------------------------------------------------------------ +// fgNormalizeEHCase_NativeAot: +// For Exception types which require runtime lookup it creates a "fake" single-block +// EH filter that performs "catchArg isinst T!!" and in case of success forwards to the +// original EH handler. +// +// Return Value: +// true if basic block layout was changed +// + +bool Compiler::fgNormalizeEHCase_NativeAot() +{ + assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI)); + + bool modified = false; + for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) + { + EHblkDsc* eh = ehGetDsc(XTnum); + if ((eh->ebdHandlerType == EH_HANDLER_CATCH) && !eh->HasFilter()) + { + CORINFO_RESOLVED_TOKEN resolvedToken; + resolvedToken.tokenContext = impTokenLookupContextHandle; + resolvedToken.tokenScope = info.compScopeHnd; + resolvedToken.token = eh->ebdTyp; + resolvedToken.tokenType = CORINFO_TOKENKIND_Casting; + info.compCompHnd->resolveToken(&resolvedToken); + + bool runtimeLookupNeeded = false; + GenTree* runtimeLookup = impTokenToHandle(&resolvedToken, &runtimeLookupNeeded, false); + if (!runtimeLookupNeeded) + { + // Exception type does not need runtime lookup + continue; + } + + // Create a new bb for the fake filter + BasicBlock* handlerBb = eh->ebdHndBeg; + BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); + filterBb->bbCatchTyp = BBCT_FILTER; + filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler + filterBb->bbHndIndex = handlerBb->bbHndIndex; + filterBb->bbJumpDest = handlerBb; + filterBb->bbSetRunRarely(); + filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE; + + // Now we need to spill CATCH_ARG (it should be the first thing evaluated) + GenTree* arg = new (this, GT_CATCH_ARG) GenTree(GT_CATCH_ARG, TYP_REF); + arg->gtFlags |= GTF_ORDER_SIDEEFF; + unsigned tempNum = lvaGrabTemp(false DEBUGARG("SpillCatchArg")); + lvaTable[tempNum].lvType = TYP_REF; + GenTree* argAsg = gtNewTempAssign(tempNum, arg); + arg = gtNewLclvNode(tempNum, TYP_REF); + filterBb->bbStkTempsIn = tempNum; + fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg)); + + // Create "catchArg is TException" tree + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); + GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); + GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); + + // Insert it right before the handler (and make it a pred of the handler) + fgInsertBBbefore(handlerBb, filterBb); + fgAddRefPred(handlerBb, filterBb); + fgNewStmtAtEnd(filterBb, retFilt); + + handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER; + eh->ebdHandlerType = EH_HANDLER_FILTER; + eh->ebdFilter = filterBb; + modified = true; + } + } + return modified; +} + bool Compiler::fgNormalizeEHCase3() { bool modified = false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 3f561a850444fd..0229dec1c45dcf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -196,15 +196,15 @@ private void StartImportingBasicBlock(BasicBlock basicBlock) if (region.Kind == ILExceptionRegionKind.Filter) MarkBasicBlock(_basicBlocks[region.FilterOffset]); - // Once https://github.com/dotnet/corert/issues/3460 is done, this should be deleted. - // Throwing InvalidProgram is not great, but we want to do *something* if this happens - // because doing nothing means problems at runtime. This is not worth piping a - // a new exception with a fancy message for. if (region.Kind == ILExceptionRegionKind.Catch) { TypeDesc catchType = (TypeDesc)_methodIL.GetObject(region.ClassToken); if (catchType.IsRuntimeDeterminedSubtype) - ThrowHelper.ThrowInvalidProgramException(); + { + // For runtime determined Exception types we're going to emit a fake EH filter with isinst for this + // type inside with a runtime lookup + _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandleForCasting, catchType), "EH filter"); + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 2458aef8adb5e5..8250be95b36441 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -906,13 +906,6 @@ private ObjectNode.ObjectData EncodeEHInfo() var methodIL = (MethodIL)HandleToObject((IntPtr)_methodScope); var type = (TypeDesc)methodIL.GetObject((int)clause.ClassTokenOrOffset); - // Once https://github.com/dotnet/corert/issues/3460 is done, this should be an assert. - // Throwing InvalidProgram is not great, but we want to do *something* if this happens - // because doing nothing means problems at runtime. This is not worth piping a - // a new exception with a fancy message for. - if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) - ThrowHelper.ThrowInvalidProgramException(); - var typeSymbol = _compilation.NecessaryTypeSymbolIfPossible(type); RelocType rel = (_compilation.NodeFactory.Target.IsWindows) ? From 7d4bcbdcb5632e68e8bf6b0b1269b716e8f0670c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 23 Jul 2022 18:40:48 +0200 Subject: [PATCH 02/27] Add smoke test --- src/coreclr/jit/jiteh.cpp | 1 + .../SmokeTests/Exceptions/Exceptions.cs | 4 + .../SmokeTests/Exceptions/Exceptions.csproj | 1 + .../Exceptions/GenericExceptions.cs | 116 ++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 2b3172cdcffd38..98d6deddc1b421 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2553,6 +2553,7 @@ bool Compiler::fgNormalizeEHCase_NativeAot() filterBb->bbCatchTyp = BBCT_FILTER; filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler filterBb->bbHndIndex = handlerBb->bbHndIndex; + filterBb->bbTryIndex = handlerBb->bbTryIndex; filterBb->bbJumpDest = handlerBb; filterBb->bbSetRunRarely(); filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE; diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs index 76440c785363bd..77116cd3a9ca65 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs @@ -5,6 +5,8 @@ using System.Diagnostics; using System.Text; + + public class BringUpTest { const int Pass = 100; @@ -30,6 +32,8 @@ public static int Main() new BringUpTest().ToString(); } + GenericExceptions.RunTests(); + int counter = 0; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionEventHandler; diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj index 0b1a23bf56a1c8..34109d429a8a41 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj @@ -7,5 +7,6 @@ + diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs new file mode 100644 index 00000000000000..944791adea3af3 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; + +public class GenericExceptions +{ + public static void RunTests() + { + AssertEqual(GenericExceptions_Case1(1, 0, null), 44); + AssertExpects(() => GenericExceptions_Case1(1, 0, null)); + GenericExceptions_Case1(1, 0, "not null"); + AssertExpects(() => GenericExceptions_Case1(1, 10, null)); + AssertExpects(() => GenericExceptions_Case1(1, 0, "not null")); + + AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 111); + AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 222); + AssertEqual(GenericExceptions_Case2(() => throw new MyException>()), 42); + AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 42); + AssertEqual(GenericExceptions_Case2(() => throw new InvalidOperationException()), 42); + AssertEqual(_counter, 24); + } + + public static void AssertEqual(int a, int b) + { + if (a != b) + throw new InvalidOperationException($"{a} != {b}"); + } + + public static void AssertExpects(Action action) where T : Exception + { + try + { + action(); + } + catch (T) + { + return; + } + throw new InvalidOperationException($"{typeof(T)} was expected to be thrown"); + } + + public class MyException : Exception { } + + private static int _counter = 0; + + public static int GenericExceptions_Case1(int a, int b, object o) + where T1 : Exception + where T2 : Exception + { + try + { + _counter++; + return a / b; + } + catch (T1) + { + _counter++; + return 44; + } + finally + { + try + { + _counter++; + Console.WriteLine(o.ToString()); + } + catch (T2 t) + { + _counter++; + Console.WriteLine(t.GetType().Name); + } + } + } + + public static int GenericExceptions_Case2(Action action) + { + try + { + action?.Invoke(); + return 1; + } + catch (MyException e1) + { + _counter++; + int hc = 100; + if (e1.GetHashCode() > 1000) // just some BBs in the catch handler + hc += 100; + return 111; + } + catch (MyException e2) + { + _counter++; + int hc = 100; + if (e2.GetHashCode() > 1000) // just some BBs in the catch handler + hc += 100; + return 222; + } + catch (MyException e2) + { + _counter++; + Console.WriteLine("re-throw"); + throw; + } + catch + { + _counter++; + return 42; + } + finally + { + _counter++; + } + } +} From 39752c73a7a3121bd4354933f37db3491ca4384c Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 23 Jul 2022 19:24:46 +0200 Subject: [PATCH 03/27] Update GenericExceptions.cs --- src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs index 944791adea3af3..8a35b683964fed 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs @@ -17,7 +17,7 @@ public static void RunTests() AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 111); AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 222); AssertEqual(GenericExceptions_Case2(() => throw new MyException>()), 42); - AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 42); + AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 42); AssertEqual(GenericExceptions_Case2(() => throw new InvalidOperationException()), 42); AssertEqual(_counter, 24); } From 3a045da50f82e4e988b5dc97d9ff3b993de09d0c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 23 Jul 2022 20:16:54 +0200 Subject: [PATCH 04/27] CI test --- src/coreclr/jit/jiteh.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 98d6deddc1b421..32d76840edff99 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2128,7 +2128,7 @@ void Compiler::fgNormalizeEH() #endif // 0 // For NativeAOT we need to create a fake exception filter for generic handlers - if (IsTargetAbi(CORINFO_NATIVEAOT_ABI) && fgNormalizeEHCase_NativeAot()) + if (/*IsTargetAbi(CORINFO_NATIVEAOT_ABI) &&*/ fgNormalizeEHCase_NativeAot()) { modified = true; } @@ -2524,7 +2524,8 @@ bool Compiler::fgNormalizeEHCase2() bool Compiler::fgNormalizeEHCase_NativeAot() { - assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI)); + // CI test, let's run the logic for JIT + //assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI)); bool modified = false; for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) From f24208a47ab86d87d5cac9e4854432cfd3395c42 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 23 Jul 2022 23:10:03 +0200 Subject: [PATCH 05/27] Address feedback & fix AVE --- src/coreclr/jit/compiler.h | 3 +- src/coreclr/jit/jiteh.cpp | 23 +++---- .../tools/Common/JitInterface/CorInfoImpl.cs | 18 ------ src/coreclr/vm/codeman.cpp | 61 ------------------- src/coreclr/vm/jitinterface.cpp | 42 ------------- 5 files changed, 12 insertions(+), 135 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a76f03a5993fdf..db438e96e4c84f 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2217,7 +2217,8 @@ class Compiler bool fgNormalizeEHCase1(); bool fgNormalizeEHCase2(); bool fgNormalizeEHCase3(); - bool fgNormalizeEHCase_NativeAot(); + + bool fgCreateFiltersForGenericExceptions(); void fgCheckForLoopsInHandlers(); diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 32d76840edff99..779d1a24c7e4cb 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2127,8 +2127,7 @@ void Compiler::fgNormalizeEH() #endif // 0 - // For NativeAOT we need to create a fake exception filter for generic handlers - if (/*IsTargetAbi(CORINFO_NATIVEAOT_ABI) &&*/ fgNormalizeEHCase_NativeAot()) + if (fgCreateFiltersForGenericExceptions()) { modified = true; } @@ -2513,7 +2512,7 @@ bool Compiler::fgNormalizeEHCase2() } //------------------------------------------------------------------------ -// fgNormalizeEHCase_NativeAot: +// fgCreateFiltersForGenericExceptions: // For Exception types which require runtime lookup it creates a "fake" single-block // EH filter that performs "catchArg isinst T!!" and in case of success forwards to the // original EH handler. @@ -2522,11 +2521,8 @@ bool Compiler::fgNormalizeEHCase2() // true if basic block layout was changed // -bool Compiler::fgNormalizeEHCase_NativeAot() +bool Compiler::fgCreateFiltersForGenericExceptions() { - // CI test, let's run the logic for JIT - //assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI)); - bool modified = false; for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) { @@ -2540,9 +2536,9 @@ bool Compiler::fgNormalizeEHCase_NativeAot() resolvedToken.tokenType = CORINFO_TOKENKIND_Casting; info.compCompHnd->resolveToken(&resolvedToken); - bool runtimeLookupNeeded = false; - GenTree* runtimeLookup = impTokenToHandle(&resolvedToken, &runtimeLookupNeeded, false); - if (!runtimeLookupNeeded) + CORINFO_GENERICHANDLE_RESULT embedInfo; + info.compCompHnd->embedGenericHandle(&resolvedToken, true, &embedInfo); + if (!embedInfo.lookup.lookupKind.needsRuntimeLookup) { // Exception type does not need runtime lookup continue; @@ -2570,9 +2566,10 @@ bool Compiler::fgNormalizeEHCase_NativeAot() fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg)); // Create "catchArg is TException" tree - GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); - GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); - GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); + GenTree* runtimeLookup = getTokenHandleTree(&resolvedToken, true); + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); + GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); + GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); // Insert it right before the handler (and make it a pred of the handler) fgInsertBBbefore(handlerBb, filterBb); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index cdcb74e5a6b0e6..953f58be0b359a 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -737,24 +737,6 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args, methodIL); Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals); -#if READYTORUN - if ((methodInfo->options & CorInfoOptions.CORINFO_GENERICS_CTXT_MASK) != 0) - { - foreach (var region in exceptionRegions) - { - if (region.Kind == ILExceptionRegionKind.Catch) - { - TypeDesc catchType = (TypeDesc)methodIL.GetObject(region.ClassToken); - if (catchType.IsCanonicalSubtype(CanonicalFormKind.Any)) - { - methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_KEEP_ALIVE; - break; - } - } - } - } -#endif - return true; } diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 8609563446d1cd..7d7a351d608ebd 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -3476,36 +3476,6 @@ TypeHandle EEJitManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClause, PREFIX_ASSUME(pModule != NULL); SigTypeContext typeContext(pMD); - VarKind k = hasNoVars; - - // In the vast majority of cases the code under the "if" below - // will not be executed. - // - // First grab the representative instantiations. For code - // shared by multiple generic instantiations these are the - // canonical (representative) instantiation. - if (TypeFromToken(typeTok) == mdtTypeSpec) - { - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(pModule->GetMDImport()->GetTypeSpecFromToken(typeTok, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - k = psig.IsPolyType(&typeContext); - - // Grab the active class and method instantiation. This exact instantiation is only - // needed in the corner case of "generic" exception catching in shared - // generic code. We don't need the exact instantiation if the token - // doesn't contain E_T_VAR or E_T_MVAR. - if ((k & hasSharableVarsMask) != 0) - { - Instantiation classInst; - Instantiation methodInst; - pCf->GetExactGenericInstantiations(&classInst, &methodInst); - SigTypeContext::InitTypeContext(pMD,classInst, methodInst,&typeContext); - } - } - return ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, typeTok, &typeContext, ClassLoader::ReturnNullIfNotFound); } @@ -6001,38 +5971,7 @@ TypeHandle ReadyToRunJitManager::ResolveEHClause(EE_ILEXCEPTION_CLAUSE* pEHClaus PREFIX_ASSUME(pModule != NULL); SigTypeContext typeContext(pMD); - VarKind k = hasNoVars; - mdToken typeTok = pEHClause->ClassToken; - - // In the vast majority of cases the code un der the "if" below - // will not be executed. - // - // First grab the representative instantiations. For code - // shared by multiple generic instantiations these are the - // canonical (representative) instantiation. - if (TypeFromToken(typeTok) == mdtTypeSpec) - { - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(pModule->GetMDImport()->GetTypeSpecFromToken(typeTok, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - k = psig.IsPolyType(&typeContext); - - // Grab the active class and method instantiation. This exact instantiation is only - // needed in the corner case of "generic" exception catching in shared - // generic code. We don't need the exact instantiation if the token - // doesn't contain E_T_VAR or E_T_MVAR. - if ((k & hasSharableVarsMask) != 0) - { - Instantiation classInst; - Instantiation methodInst; - pCf->GetExactGenericInstantiations(&classInst,&methodInst); - SigTypeContext::InitTypeContext(pMD,classInst, methodInst,&typeContext); - } - } - return ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, typeTok, &typeContext, ClassLoader::ReturnNullIfNotFound); } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index a6bd0d8ea26c33..ead8ffc34e9164 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7514,49 +7514,7 @@ getMethodInfoHelper( { methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE); } - else #endif // defined(PROFILING_SUPPORTED) - { - // Check all the exception clauses - - if (ftn->IsDynamicMethod()) - { - // @TODO: how do we detect the need to mark this flag? - } - else - { - COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause; - - for (unsigned i = 0; i < methInfo->EHcount; i++) - { - const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo = - (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)header->EH->EHClause(i, &ehClause); - - // Is it a typed catch clause? - if (ehInfo->GetFlags() != COR_ILEXCEPTION_CLAUSE_NONE) - continue; - - // Check if we catch "C" ? - - DWORD catchTypeToken = ehInfo->GetClassToken(); - if (TypeFromToken(catchTypeToken) != mdtTypeSpec) - continue; - - PCCOR_SIGNATURE pSig; - ULONG cSig; - IfFailThrow(ftn->GetMDImport()->GetTypeSpecFromToken(catchTypeToken, &pSig, &cSig)); - - SigPointer psig(pSig, cSig); - - SigTypeContext sigTypeContext(ftn); - if (psig.IsPolyType(&sigTypeContext) & hasSharableVarsMask) - { - methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE); - break; - } - } - } - } } PCCOR_SIGNATURE pSig = NULL; From f7c55a7ce35c65163d490d443a2dd0b7838923fd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 23 Jul 2022 23:21:26 +0200 Subject: [PATCH 06/27] Clean up --- src/coreclr/jit/jiteh.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 779d1a24c7e4cb..4dbe33e85f07f5 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2524,10 +2524,10 @@ bool Compiler::fgNormalizeEHCase2() bool Compiler::fgCreateFiltersForGenericExceptions() { bool modified = false; - for (unsigned XTnum = 0; XTnum < compHndBBtabCount; XTnum++) + for (unsigned ehNum = 0; ehNum < compHndBBtabCount; ehNum++) { - EHblkDsc* eh = ehGetDsc(XTnum); - if ((eh->ebdHandlerType == EH_HANDLER_CATCH) && !eh->HasFilter()) + EHblkDsc* eh = ehGetDsc(ehNum); + if (eh->ebdHandlerType == EH_HANDLER_CATCH) { CORINFO_RESOLVED_TOKEN resolvedToken; resolvedToken.tokenContext = impTokenLookupContextHandle; From 861c6c3072829284c18c77d58cb0797a518e1ffd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 01:13:21 +0200 Subject: [PATCH 07/27] Fix runtime lookup for NativeAOT & Crossgen --- src/coreclr/jit/jiteh.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 4dbe33e85f07f5..36aae00f87dbce 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2566,7 +2566,19 @@ bool Compiler::fgCreateFiltersForGenericExceptions() fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg)); // Create "catchArg is TException" tree - GenTree* runtimeLookup = getTokenHandleTree(&resolvedToken, true); + GenTree* lookupTree; + GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); + if (opts.IsReadyToRun()) + { + lookupTree = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); + } + else + { + lookupTree = gtNewRuntimeLookupHelperCallNode(&embedInfo.lookup.runtimeLookup, ctxTree, + embedInfo.compileTimeHandle); + } + GenTree* runtimeLookup = gtNewRuntimeLookup(embedInfo.compileTimeHandle, embedInfo.handleType, lookupTree); GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); From 8a72927517fd3062eebf6e850bdc62e8f4bf69de Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 01:37:37 +0200 Subject: [PATCH 08/27] Another attempt to fix runtime lookup (now should be working) --- src/coreclr/jit/jiteh.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 36aae00f87dbce..ba14a9aaeccb17 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2566,22 +2566,21 @@ bool Compiler::fgCreateFiltersForGenericExceptions() fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg)); // Create "catchArg is TException" tree - GenTree* lookupTree; - GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); + GenTree* runtimeLookup; if (opts.IsReadyToRun()) { - lookupTree = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, - TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); + GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); + GenTree* lookupTree = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); + runtimeLookup = gtNewRuntimeLookup(embedInfo.compileTimeHandle, embedInfo.handleType, lookupTree); } else { - lookupTree = gtNewRuntimeLookupHelperCallNode(&embedInfo.lookup.runtimeLookup, ctxTree, - embedInfo.compileTimeHandle); + runtimeLookup = getTokenHandleTree(&resolvedToken, true); } - GenTree* runtimeLookup = gtNewRuntimeLookup(embedInfo.compileTimeHandle, embedInfo.handleType, lookupTree); - GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); - GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); - GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); + GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); + GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); // Insert it right before the handler (and make it a pred of the handler) fgInsertBBbefore(handlerBb, filterBb); From 58d3b77dc86d909ab0d94df30490977bfa0f1990 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 11:11:36 +0200 Subject: [PATCH 09/27] Remove tests from issues.targets --- src/coreclr/jit/jiteh.cpp | 22 +++++++++++----------- src/tests/issues.targets | 18 ------------------ 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index ba14a9aaeccb17..c74a1c2b261206 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2547,13 +2547,6 @@ bool Compiler::fgCreateFiltersForGenericExceptions() // Create a new bb for the fake filter BasicBlock* handlerBb = eh->ebdHndBeg; BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); - filterBb->bbCatchTyp = BBCT_FILTER; - filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler - filterBb->bbHndIndex = handlerBb->bbHndIndex; - filterBb->bbTryIndex = handlerBb->bbTryIndex; - filterBb->bbJumpDest = handlerBb; - filterBb->bbSetRunRarely(); - filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE; // Now we need to spill CATCH_ARG (it should be the first thing evaluated) GenTree* arg = new (this, GT_CATCH_ARG) GenTree(GT_CATCH_ARG, TYP_REF); @@ -2569,15 +2562,14 @@ bool Compiler::fgCreateFiltersForGenericExceptions() GenTree* runtimeLookup; if (opts.IsReadyToRun()) { - GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); - GenTree* lookupTree = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, - TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); - runtimeLookup = gtNewRuntimeLookup(embedInfo.compileTimeHandle, embedInfo.handleType, lookupTree); + compCurBB = filterBb; + runtimeLookup = impRuntimeLookupToTree(&resolvedToken, &embedInfo.lookup, embedInfo.compileTimeHandle); } else { runtimeLookup = getTokenHandleTree(&resolvedToken, true); } + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); @@ -2587,6 +2579,14 @@ bool Compiler::fgCreateFiltersForGenericExceptions() fgAddRefPred(handlerBb, filterBb); fgNewStmtAtEnd(filterBb, retFilt); + filterBb->bbCatchTyp = BBCT_FILTER; + filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler + filterBb->bbHndIndex = handlerBb->bbHndIndex; + filterBb->bbTryIndex = handlerBb->bbTryIndex; + filterBb->bbJumpDest = handlerBb; + filterBb->bbSetRunRarely(); + filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE; + handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER; eh->ebdHandlerType = EH_HANDLER_FILTER; eh->ebdFilter = filterBb; diff --git a/src/tests/issues.targets b/src/tests/issues.targets index d826d3f3cb4dd8..d194dd8cc4af3f 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1372,24 +1372,6 @@ - - - - - - - - - - - - - - - - - - From 54763a7fedb63381947d37a750766c4429b1ea86 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 18:39:59 +0200 Subject: [PATCH 10/27] Move fgCreateFiltersForGenericExceptions to fgAddInternal --- src/coreclr/jit/flowgraph.cpp | 4 ++++ src/coreclr/jit/jiteh.cpp | 8 ++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 5f8b6213a967d3..0b6ffd588a2328 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -2590,6 +2590,10 @@ void Compiler::fgAddInternal() { noway_assert(!compIsForInlining()); + // For runtime determined Exception types we're going to emit a fake EH filter with isinst for this + // type with a runtime lookup + fgCreateFiltersForGenericExceptions(); + // The backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is // required. Similarly, we need a scratch BB for poisoning. Create it here. if (compMethodRequiresPInvokeFrame() || compShouldPoisonFrame()) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index c74a1c2b261206..086ef0446f56e9 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2127,10 +2127,6 @@ void Compiler::fgNormalizeEH() #endif // 0 - if (fgCreateFiltersForGenericExceptions()) - { - modified = true; - } INDEBUG(fgNormalizeEHDone = true;) @@ -2545,8 +2541,7 @@ bool Compiler::fgCreateFiltersForGenericExceptions() } // Create a new bb for the fake filter - BasicBlock* handlerBb = eh->ebdHndBeg; - BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); + BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); // Now we need to spill CATCH_ARG (it should be the first thing evaluated) GenTree* arg = new (this, GT_CATCH_ARG) GenTree(GT_CATCH_ARG, TYP_REF); @@ -2575,6 +2570,7 @@ bool Compiler::fgCreateFiltersForGenericExceptions() GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); // Insert it right before the handler (and make it a pred of the handler) + BasicBlock* handlerBb = eh->ebdHndBeg; fgInsertBBbefore(handlerBb, filterBb); fgAddRefPred(handlerBb, filterBb); fgNewStmtAtEnd(filterBb, retFilt); From a32b92ad89310cc80ce7710fb818d7e0314f1cd2 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 21:40:04 +0200 Subject: [PATCH 11/27] simplify runtime lookup --- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/jiteh.cpp | 25 +++++++++---------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index db438e96e4c84f..e41241c450decc 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -2218,7 +2218,7 @@ class Compiler bool fgNormalizeEHCase2(); bool fgNormalizeEHCase3(); - bool fgCreateFiltersForGenericExceptions(); + void fgCreateFiltersForGenericExceptions(); void fgCheckForLoopsInHandlers(); diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 086ef0446f56e9..9c7ef39bd08905 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2127,7 +2127,6 @@ void Compiler::fgNormalizeEH() #endif // 0 - INDEBUG(fgNormalizeEHDone = true;) if (modified) @@ -2513,13 +2512,9 @@ bool Compiler::fgNormalizeEHCase2() // EH filter that performs "catchArg isinst T!!" and in case of success forwards to the // original EH handler. // -// Return Value: -// true if basic block layout was changed -// -bool Compiler::fgCreateFiltersForGenericExceptions() +void Compiler::fgCreateFiltersForGenericExceptions() { - bool modified = false; for (unsigned ehNum = 0; ehNum < compHndBBtabCount; ehNum++) { EHblkDsc* eh = ehGetDsc(ehNum); @@ -2541,7 +2536,8 @@ bool Compiler::fgCreateFiltersForGenericExceptions() } // Create a new bb for the fake filter - BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); + BasicBlock* filterBb = bbNewBasicBlock(BBJ_EHFILTERRET); + BasicBlock* handlerBb = eh->ebdHndBeg; // Now we need to spill CATCH_ARG (it should be the first thing evaluated) GenTree* arg = new (this, GT_CATCH_ARG) GenTree(GT_CATCH_ARG, TYP_REF); @@ -2551,29 +2547,28 @@ bool Compiler::fgCreateFiltersForGenericExceptions() GenTree* argAsg = gtNewTempAssign(tempNum, arg); arg = gtNewLclvNode(tempNum, TYP_REF); filterBb->bbStkTempsIn = tempNum; - fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg)); + fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg, handlerBb->firstStmt()->GetDebugInfo())); // Create "catchArg is TException" tree GenTree* runtimeLookup; - if (opts.IsReadyToRun()) + if (embedInfo.lookup.runtimeLookup.indirections == CORINFO_USEHELPER) { - compCurBB = filterBb; - runtimeLookup = impRuntimeLookupToTree(&resolvedToken, &embedInfo.lookup, embedInfo.compileTimeHandle); + GenTree* ctxTree = getRuntimeContextTree(embedInfo.lookup.lookupKind.runtimeLookupKind); + runtimeLookup = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + TYP_I_IMPL, &embedInfo.lookup.lookupKind, ctxTree); } else { runtimeLookup = getTokenHandleTree(&resolvedToken, true); } - GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); // Insert it right before the handler (and make it a pred of the handler) - BasicBlock* handlerBb = eh->ebdHndBeg; fgInsertBBbefore(handlerBb, filterBb); fgAddRefPred(handlerBb, filterBb); - fgNewStmtAtEnd(filterBb, retFilt); + fgNewStmtAtEnd(filterBb, retFilt, handlerBb->firstStmt()->GetDebugInfo()); filterBb->bbCatchTyp = BBCT_FILTER; filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler @@ -2586,10 +2581,8 @@ bool Compiler::fgCreateFiltersForGenericExceptions() handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER; eh->ebdHandlerType = EH_HANDLER_FILTER; eh->ebdFilter = filterBb; - modified = true; } } - return modified; } bool Compiler::fgNormalizeEHCase3() From 3668e25a70f9f2c984a3e51450f567139fa1a68e Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 24 Jul 2022 23:06:28 +0200 Subject: [PATCH 12/27] Address feedback --- src/coreclr/jit/jiteh.cpp | 12 +- .../SmokeTests/Exceptions/Exceptions.cs | 60 ++++++--- .../SmokeTests/Exceptions/Exceptions.csproj | 1 - .../Exceptions/GenericExceptions.cs | 116 ------------------ 4 files changed, 55 insertions(+), 134 deletions(-) delete mode 100644 src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 9c7ef39bd08905..b87dfcfe0f95aa 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2520,6 +2520,7 @@ void Compiler::fgCreateFiltersForGenericExceptions() EHblkDsc* eh = ehGetDsc(ehNum); if (eh->ebdHandlerType == EH_HANDLER_CATCH) { + // Resolve Exception type and check if it needs a runtime lookup CORINFO_RESOLVED_TOKEN resolvedToken; resolvedToken.tokenContext = impTokenLookupContextHandle; resolvedToken.tokenScope = info.compScopeHnd; @@ -2571,7 +2572,7 @@ void Compiler::fgCreateFiltersForGenericExceptions() fgNewStmtAtEnd(filterBb, retFilt, handlerBb->firstStmt()->GetDebugInfo()); filterBb->bbCatchTyp = BBCT_FILTER; - filterBb->bbCodeOffs = handlerBb->bbCodeOffs; // Technically, we're in the handler + filterBb->bbCodeOffs = handlerBb->bbCodeOffs; filterBb->bbHndIndex = handlerBb->bbHndIndex; filterBb->bbTryIndex = handlerBb->bbTryIndex; filterBb->bbJumpDest = handlerBb; @@ -2581,6 +2582,15 @@ void Compiler::fgCreateFiltersForGenericExceptions() handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER; eh->ebdHandlerType = EH_HANDLER_FILTER; eh->ebdFilter = filterBb; + +#ifdef DEBUG + if (verbose) + { + JITDUMP("EH%d: Adding EH filter block " FMT_BB " in front of generic handler " FMT_BB ":\n", ehNum, + filterBb->bbNum, handlerBb->bbNum); + fgDumpBlock(filterBb); + } +#endif // DEBUG } } } diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs index 77116cd3a9ca65..3bc01acb80df99 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs @@ -5,8 +5,6 @@ using System.Diagnostics; using System.Text; - - public class BringUpTest { const int Pass = 100; @@ -32,7 +30,7 @@ public static int Main() new BringUpTest().ToString(); } - GenericExceptions.RunTests(); + TestGenericExceptions(); int counter = 0; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionEventHandler; @@ -54,8 +52,8 @@ public static int Main() Console.WriteLine("Exception caught!"); if (e.Message != "My exception") { - Console.WriteLine("Unexpected exception message!"); - return Fail; + Console.WriteLine("Unexpected exception message!"); + return Fail; } string stackTrace = e.StackTrace; @@ -69,7 +67,7 @@ public static int Main() try { - g.myObjectField = new Object(); + g.myObjectField = new Object(); } catch (NullReferenceException) { @@ -79,14 +77,14 @@ public static int Main() try { - try - { - g.myField++; - } - finally - { - counter++; - } + try + { + g.myField++; + } + finally + { + counter++; + } } catch (NullReferenceException) { @@ -103,8 +101,8 @@ public static int Main() Console.WriteLine("Exception caught via filter!"); if (e.Message != "Testing filter") { - Console.WriteLine("Unexpected exception message!"); - return Fail; + Console.WriteLine("Unexpected exception message!"); + return Fail; } counter++; } @@ -213,6 +211,36 @@ static void ThrowExcThroughMethodsWithFinalizers2(string caller) } } + static void TestGenericExceptions() + { + if (CatchGenericException(100, 0) != 42) + { + Environment.Exit(Fail); + } + + try + { + CatchGenericException(100, 0); + } + catch (DivideByZeroException) + { + return; + } + Environment.Exit(Fail); + } + + static int CatchGenericException(int a, int b) where T : Exception + { + try + { + return a / b; + } + catch (T) + { + return 42; + } + } + static bool FilterWithStackTrace(Exception e) { var stackTrace = new StackTrace(0, true); diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj index 34109d429a8a41..0b1a23bf56a1c8 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj @@ -7,6 +7,5 @@ - diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs deleted file mode 100644 index 8a35b683964fed..00000000000000 --- a/src/tests/nativeaot/SmokeTests/Exceptions/GenericExceptions.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; - -public class GenericExceptions -{ - public static void RunTests() - { - AssertEqual(GenericExceptions_Case1(1, 0, null), 44); - AssertExpects(() => GenericExceptions_Case1(1, 0, null)); - GenericExceptions_Case1(1, 0, "not null"); - AssertExpects(() => GenericExceptions_Case1(1, 10, null)); - AssertExpects(() => GenericExceptions_Case1(1, 0, "not null")); - - AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 111); - AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 222); - AssertEqual(GenericExceptions_Case2(() => throw new MyException>()), 42); - AssertEqual(GenericExceptions_Case2(() => throw new MyException()), 42); - AssertEqual(GenericExceptions_Case2(() => throw new InvalidOperationException()), 42); - AssertEqual(_counter, 24); - } - - public static void AssertEqual(int a, int b) - { - if (a != b) - throw new InvalidOperationException($"{a} != {b}"); - } - - public static void AssertExpects(Action action) where T : Exception - { - try - { - action(); - } - catch (T) - { - return; - } - throw new InvalidOperationException($"{typeof(T)} was expected to be thrown"); - } - - public class MyException : Exception { } - - private static int _counter = 0; - - public static int GenericExceptions_Case1(int a, int b, object o) - where T1 : Exception - where T2 : Exception - { - try - { - _counter++; - return a / b; - } - catch (T1) - { - _counter++; - return 44; - } - finally - { - try - { - _counter++; - Console.WriteLine(o.ToString()); - } - catch (T2 t) - { - _counter++; - Console.WriteLine(t.GetType().Name); - } - } - } - - public static int GenericExceptions_Case2(Action action) - { - try - { - action?.Invoke(); - return 1; - } - catch (MyException e1) - { - _counter++; - int hc = 100; - if (e1.GetHashCode() > 1000) // just some BBs in the catch handler - hc += 100; - return 111; - } - catch (MyException e2) - { - _counter++; - int hc = 100; - if (e2.GetHashCode() > 1000) // just some BBs in the catch handler - hc += 100; - return 222; - } - catch (MyException e2) - { - _counter++; - Console.WriteLine("re-throw"); - throw; - } - catch - { - _counter++; - return 42; - } - finally - { - _counter++; - } - } -} From 49635ebc6ed23e686ad825befca8b880c266897a Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 17:20:58 +0200 Subject: [PATCH 13/27] Implement HELPER_SimpleIsInstanceOf --- docs/design/coreclr/botr/readytorun-format.md | 1 + .../Runtime/CompilerServices/CastHelpers.cs | 22 +++++++++++++++++++ src/coreclr/inc/corinfo.h | 2 ++ src/coreclr/inc/jiteeversionguid.h | 10 ++++----- src/coreclr/inc/jithelpers.h | 1 + src/coreclr/inc/readytorun.h | 3 ++- src/coreclr/inc/readytorunhelpers.h | 1 + src/coreclr/jit/jiteh.cpp | 5 ++--- .../src/System/Runtime/TypeCast.cs | 20 +++++++++++++++++ .../nativeaot/Runtime/inc/ModuleHeaders.h | 2 +- .../src/System/Runtime/RuntimeImports.cs | 4 ++++ .../Common/Internal/Runtime/ModuleHeaders.cs | 2 +- .../Internal/Runtime/ReadyToRunConstants.cs | 1 + .../Common/JitInterface/CorInfoHelpFunc.cs | 2 ++ .../ILCompiler.Compiler/Compiler/JitHelper.cs | 3 +++ .../JitInterface/CorInfoImpl.ReadyToRun.cs | 3 +++ .../ReadyToRunSignature.cs | 4 ++++ .../JitInterface/CorInfoImpl.RyuJit.cs | 6 +++++ src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/ecall.cpp | 4 ++++ src/coreclr/vm/jitinterface.cpp | 1 + src/coreclr/vm/metasig.h | 1 + 22 files changed, 88 insertions(+), 11 deletions(-) diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index d4b1e57a983591..4d1acf18b65da2 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -797,6 +797,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, + READYTORUN_HELPER_SimpleIsInstanceOf = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index a49ffaf9378b36..9aede3c466424c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -628,5 +628,27 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el throw new ArrayTypeMismatchException(); } + + [DebuggerHidden] + [StackTraceHidden] + [DebuggerStepThrough] + private static bool SimpleIsInstanceOf(void* typeHnd, object? obj) + { + if (obj == null) + return false; + + MethodTable* mt = RuntimeHelpers.GetMethodTable(obj); + + if (typeHnd == mt) + return true; + + while (mt != null) + { + mt = mt->ParentMethodTable; + if (mt == typeHnd) + return true; + } + return false; + } } } diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 84169d3c0a7e42..0a24f1b1a00db8 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -438,6 +438,8 @@ enum CorInfoHelpFunc CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check + CORINFO_HELP_SIMPLEISINSTANCEOF, + CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable CORINFO_HELP_UNBOX, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 2a9fc7d7b044b0..dedd71fc3ea134 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 0d853657-7a01-421f-b1b0-d22a8e691441 */ - 0x0d853657, - 0x7a01, - 0x421f, - {0xb1, 0xb0, 0xd2, 0x2a, 0x8e, 0x69, 0x14, 0x41} +constexpr GUID JITEEVersionIdentifier = { /* 4efa8fe2-8489-4b61-aac9-b4df74af15b7 */ + 0x4efa8fe2, + 0x8489, + 0x4b61, + {0xaa, 0xc9, 0xb4, 0xdf, 0x74, 0xaf, 0x15, 0xb7} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index a500c298978b67..4f5cb5335188e1 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -98,6 +98,7 @@ DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_SIMPLEISINSTANCEOF, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index ba36f7c555a332..e187792b2e1b0c 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -16,7 +16,7 @@ // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs #define READYTORUN_MAJOR_VERSION 0x0007 -#define READYTORUN_MINOR_VERSION 0x0000 +#define READYTORUN_MINOR_VERSION 0x0001 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 @@ -329,6 +329,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, + READYTORUN_HELPER_SimpleIsInstanceOf = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index 66e2d4a3b164e3..0ec94cb93cc4b0 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -54,6 +54,7 @@ HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GETGENERICS_GCT HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,) HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, ) +HELPER(READYTORUN_HELPER_SimpleIsInstanceOf, CORINFO_HELP_SIMPLEISINSTANCEOF, ) HELPER(READYTORUN_HELPER_LMul, CORINFO_HELP_LMUL, ) HELPER(READYTORUN_HELPER_LMulOfv, CORINFO_HELP_LMUL_OVF, ) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index b87dfcfe0f95aa..d23dd24740aa39 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2562,9 +2562,8 @@ void Compiler::fgCreateFiltersForGenericExceptions() { runtimeLookup = getTokenHandleTree(&resolvedToken, true); } - GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOFANY, TYP_REF, runtimeLookup, arg); - GenTree* cmp = gtNewOperNode(GT_NE, TYP_INT, isInstOfT, gtNewNull()); - GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, cmp); + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_SIMPLEISINSTANCEOF, TYP_INT, runtimeLookup, arg); + GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, isInstOfT); // Insert it right before the handler (and make it a pred of the handler) fgInsertBBbefore(handlerBb, filterBb); diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 7cd42c6ef6bd80..dbf0def37e6324 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -908,6 +908,26 @@ public static unsafe object IsInstanceOf(MethodTable* pTargetType, object obj) return IsInstanceOfClass(pTargetType, obj); } + [RuntimeExport("RhTypeCast_IsSimpleInstanceOf")] + public static unsafe bool IsSimpleInstanceOf(MethodTable* typeHnd, object obj) + { + if (obj == null) + return false; + + MethodTable* mt = obj.GetMethodTable(); + + if (typeHnd == mt) + return true; + + while (mt != null) + { + mt = mt->RawBaseType; + if (mt == typeHnd) + return true; + } + return false; + } + [RuntimeExport("RhTypeCast_CheckCast")] public static unsafe object CheckCast(MethodTable* pTargetType, object obj) { diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 8600b4c5913c1e..57aac4fc8d00d7 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -11,7 +11,7 @@ struct ReadyToRunHeaderConstants static const uint32_t Signature = 0x00525452; // 'RTR' static const uint32_t CurrentMajorVersion = 7; - static const uint32_t CurrentMinorVersion = 0; + static const uint32_t CurrentMinorVersion = 1; }; struct ReadyToRunHeader diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 287e80b34de9ac..9c373a0f922fb6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -327,6 +327,10 @@ internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj) [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfInterface")] internal static extern unsafe object IsInstanceOfInterface(MethodTable* pTargetType, object obj); + [MethodImpl(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsSimpleInstanceOf")] + internal static extern unsafe bool IsSimpleInstanceOf(MethodTable* pTargetType, object obj); + internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, object obj) => IsInstanceOfInterface(pTargetType.ToPointer(), obj); diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index ea705d1f6f34af..c73467fab3b0fc 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 7; - public const ushort CurrentMinorVersion = 0; + public const ushort CurrentMinorVersion = 1; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 2e63e5baf40d32..f07b53de299d4b 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -255,6 +255,7 @@ public enum ReadyToRunHelper GenericGcTlsBase = 0x66, GenericNonGcTlsBase = 0x67, VirtualFuncPtr = 0x68, + SimpleIsInstanceOf = 0x69, // Long mul/div/shift ops LMul = 0xC0, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index fd178769a1883d..d39bb529bbcf15 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -84,6 +84,8 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check + CORINFO_HELP_SIMPLEISINSTANCEOF, + CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable CORINFO_HELP_UNBOX, diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index a4ae4c40a66877..76197cfa7c71a0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -248,6 +248,9 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.CheckInstanceAny: mangledName = "RhTypeCast_IsInstanceOf"; break; + case ReadyToRunHelper.SimpleIsInstanceOf: + mangledName = "RhTypeCast_SimpleIsInstanceOf"; + break; case ReadyToRunHelper.CheckCastInterface: mangledName = "RhTypeCast_CheckCastInterface"; break; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 1904805336fd18..42564deeda9b93 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -775,6 +775,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.GetRuntimeTypeHandle; break; + case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: + id = ReadyToRunHelper.SimpleIsInstanceOf; + break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; break; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index daf9c194e517c5..d0aba98a9b9fb3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -1782,6 +1782,10 @@ private void ParseHelper(StringBuilder builder) builder.Append("CHECK_INSTANCE_ANY"); break; + case ReadyToRunHelper.SimpleIsInstanceOf: + builder.Append("SIMPLE_ISINSTANCE_OF"); + break; + case ReadyToRunHelper.GenericGcStaticBase: builder.Append("GENERIC_GC_STATIC_BASE"); break; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 8250be95b36441..6f6414b2f92a5c 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -543,6 +543,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.AreTypesEquivalent; break; + case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: + id = ReadyToRunHelper.SimpleIsInstanceOf; + break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; break; @@ -698,6 +701,9 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) // TODO: separate helper for the _SPECIAL case id = ReadyToRunHelper.CheckCastClass; break; + // case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: + // id = ReadyToRunHelper.SimpleIsInstanceOf; + // break; case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFCLASS: id = ReadyToRunHelper.CheckInstanceClass; break; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 3537c57d8cf05b..c83fd019351cd9 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1232,6 +1232,7 @@ DEFINE_METHOD(CASTHELPERS, CHKCASTANY, ChkCastAny, SM_Ptr DEFINE_METHOD(CASTHELPERS, CHKCASTINTERFACE, ChkCastInterface, SM_PtrVoid_Obj_RetObj) DEFINE_METHOD(CASTHELPERS, CHKCASTCLASS, ChkCastClass, SM_PtrVoid_Obj_RetObj) DEFINE_METHOD(CASTHELPERS, CHKCASTCLASSSPECIAL, ChkCastClassSpecial, SM_PtrVoid_Obj_RetObj) +DEFINE_METHOD(CASTHELPERS, SIMPLEISINSTANCEOF, SimpleIsInstanceOf, SM_PtrVoid_Obj_RetBool) DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_PtrVoid_Obj_RetRefByte) DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_Array_IntPtr_Obj_RetVoid) DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_Array_IntPtr_PtrVoid_RetRefObj) diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index 982690c28776bb..bc94a83343374b 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -133,6 +133,10 @@ void ECall::PopulateManagedCastHelpers() pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_CHKCASTCLASS_SPECIAL, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__SIMPLEISINSTANCEOF)); + pDest = pMD->GetMultiCallableAddrOfCode(); + SetJitHelperFunction(CORINFO_HELP_SIMPLEISINSTANCEOF, pDest); + pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__UNBOX)); pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_UNBOX, pDest); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index ead8ffc34e9164..c32ae7a1f587fc 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10661,6 +10661,7 @@ void* CEEJitInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTINTERFACE || dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTCLASS || dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTCLASS_SPECIAL || + dynamicFtnNum == DYNAMIC_CORINFO_HELP_SIMPLEISINSTANCEOF || dynamicFtnNum == DYNAMIC_CORINFO_HELP_UNBOX) { Precode* pPrecode = Precode::GetPrecodeFromEntryPoint((PCODE)hlpDynamicFuncTable[dynamicFtnNum].pfnHelper); diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index f567d34be2f7da..b6aced2a231f3d 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -243,6 +243,7 @@ DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Int_IntPtr_RetVoid, I I i i I, v)) DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_Obj_RetVoid, I r(j) I j, v)) DEFINE_METASIG(SM(Obj_Int_RetVoid, j i,v)) DEFINE_METASIG(SM(PtrVoid_Obj_RetObj, P(v) j, j)) +DEFINE_METASIG(SM(PtrVoid_Obj_RetBool, P(v) j, F)) DEFINE_METASIG(SM(PtrVoid_Obj_RetRefByte, P(v) j, r(b))) DEFINE_METASIG(SM(Flt_RetFlt, f, f)) From 2a47ff9b871868f607462a7286ac81086fcf8327 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 17:23:12 +0200 Subject: [PATCH 14/27] Clean up --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 32e9159237afc9..54a5bb3a89ec66 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -701,9 +701,6 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) // TODO: separate helper for the _SPECIAL case id = ReadyToRunHelper.CheckCastClass; break; - // case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: - // id = ReadyToRunHelper.SimpleIsInstanceOf; - // break; case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOFCLASS: id = ReadyToRunHelper.CheckInstanceClass; break; From bee1fb3295c1e1e0ad6d06c19a307d318462a412 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 22:05:07 +0200 Subject: [PATCH 15/27] Add Jan's IL test --- .../GenericCatchInterfaceProgram.cs | 151 ++++++++++++++++++ .../GenericCatchInterfaceProgram.csproj | 9 ++ 2 files changed, 160 insertions(+) create mode 100644 src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs create mode 100644 src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs new file mode 100644 index 00000000000000..d39c4cc1ddfb5b --- /dev/null +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime {} +.assembly extern System.Console {} +.assembly GenericCatchInterface {} + +// IL in this file is based on this C# program with a few IL modifications: + +// static class Program +// { +// private static int retCode = 0; +// static int Main() +// { +// try +// { +// try +// { +// throw new MyException(); +// } +// catch (MyException) // IL edit: Change to catch (IMyException) +// { +// Console.WriteLine("FAIL"); +// retCode++; +// } +// } +// catch +// { +// Console.WriteLine("PASS"); +// retCode += 50; +// } +// +// GenericCatch(); // IL edit: Change to GenericCatch() +// +// return retCode; +// } +// +// [MethodImpl(MethodImplOptions.NoInlining)] +// static void GenericCatch() where T : Exception // IL edit: Remove constraint +// { +// try +// { +// try +// { +// throw new MyException(); +// } +// catch (T) +// { +// Console.WriteLine("FAIL"); +// retCode++; +// } +// } +// catch +// { +// Console.WriteLine("PASS"); +// retCode += 50; +// } +// } +// } +// interface IMyInterface {} +// class MyException : Exception, IMyInterface {} + + +.class private abstract auto ansi sealed beforefieldinit GenericCatchInterfaceProgram + extends [System.Runtime]System.Object +{ + // + .field private static int32 retCode + + .method private hidebysig static int32 Main() cil managed + { + .entrypoint + .maxstack 2 + IL_0000: newobj instance void MyException::.ctor() + IL_0005: throw + + IL_0006: pop + IL_0007: ldstr "FAIL" + IL_000c: call void [System.Console]System.Console::WriteLine(string) + IL_0011: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0016: ldc.i4.1 + IL_0017: add + IL_0018: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_001d: leave.s IL_001f + + IL_001f: leave.s IL_003b + + IL_0021: pop + IL_0022: ldstr "PASS" + IL_0027: call void [System.Console]System.Console::WriteLine(string) + IL_002c: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0031: ldc.i4.s 50 + IL_0033: add + IL_0034: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_0039: leave.s IL_003b + + IL_003b: call void GenericCatchInterfaceProgram::GenericCatch() + IL_0040: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0045: ret + IL_0046: + .try IL_0000 to IL_0006 catch IMyInterface handler IL_0006 to IL_001f + .try IL_0000 to IL_0021 catch [System.Runtime]System.Object handler IL_0021 to IL_003b + } + + .method private hidebysig static void GenericCatch<([System.Runtime]System.Object) T>() cil managed noinlining + { + .maxstack 2 + IL_0000: newobj instance void MyException::.ctor() + IL_0005: throw + + IL_0006: pop + IL_0007: ldstr "FAIL" + IL_000c: call void [System.Console]System.Console::WriteLine(string) + IL_0011: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0016: ldc.i4.1 + IL_0017: add + IL_0018: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_001d: leave.s IL_001f + + IL_001f: leave.s IL_003b + + IL_0021: pop + IL_0022: ldstr "PASS" + IL_0027: call void [System.Console]System.Console::WriteLine(string) + IL_002c: ldsfld int32 GenericCatchInterfaceProgram::retCode + IL_0031: ldc.i4.s 50 + IL_0033: add + IL_0034: stsfld int32 GenericCatchInterfaceProgram::retCode + IL_0039: leave.s IL_003b + + IL_003b: ret + IL_003c: + .try IL_0000 to IL_0006 catch !!T handler IL_0006 to IL_001f + .try IL_0000 to IL_0021 catch [System.Runtime]System.Object handler IL_0021 to IL_003b + } +} + +.class interface private abstract auto ansi IMyInterface {} + +.class private auto ansi beforefieldinit MyException + extends [System.Runtime]System.Exception + implements IMyInterface +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [System.Runtime]System.Exception::.ctor() + IL_0006: ret + } +} \ No newline at end of file diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj new file mode 100644 index 00000000000000..f492aeac9d056b --- /dev/null +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file From 10ca9698f1261f30a8700e9ffc49eade95644285 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 22:48:30 +0200 Subject: [PATCH 16/27] Address feedback (NativeAOT's part is not finished yet) --- docs/design/coreclr/botr/readytorun-format.md | 2 +- .../System/Runtime/CompilerServices/CastHelpers.cs | 2 +- src/coreclr/inc/corinfo.h | 2 +- src/coreclr/inc/jithelpers.h | 3 ++- src/coreclr/inc/readytorun.h | 2 +- src/coreclr/inc/readytorunhelpers.h | 2 +- src/coreclr/jit/jiteh.cpp | 2 +- .../Common/Internal/Runtime/ReadyToRunConstants.cs | 2 +- .../tools/Common/JitInterface/CorInfoHelpFunc.cs | 2 +- .../aot/ILCompiler.Compiler/Compiler/JitHelper.cs | 4 ++-- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 4 ++-- .../ReadyToRunSignature.cs | 2 +- .../JitInterface/CorInfoImpl.RyuJit.cs | 4 ++-- src/coreclr/vm/corelib.h | 1 - src/coreclr/vm/ecall.cpp | 4 ---- src/coreclr/vm/jithelpers.cpp | 11 ++++++++++- src/coreclr/vm/jitinterface.cpp | 1 - src/coreclr/vm/metasig.h | 1 - 18 files changed, 27 insertions(+), 24 deletions(-) diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index 54282081f6dafd..fa6bb18b114c9d 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -797,7 +797,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, - READYTORUN_HELPER_SimpleIsInstanceOf = 0x69, + READYTORUN_HELPER_IsInstanceOfException = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 9aede3c466424c..ee9e544a39efb7 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -632,7 +632,7 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el [DebuggerHidden] [StackTraceHidden] [DebuggerStepThrough] - private static bool SimpleIsInstanceOf(void* typeHnd, object? obj) + private static bool IsInstanceOfException(void* typeHnd, object? obj) { if (obj == null) return false; diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index efac72ac9007a0..80ef9c127733df 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -438,7 +438,7 @@ enum CorInfoHelpFunc CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check - CORINFO_HELP_SIMPLEISINSTANCEOF, + CORINFO_HELP_ISINSTANCEOF_EXCEPTION, CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 4f5cb5335188e1..e897d592322e69 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -98,7 +98,8 @@ DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY) - DYNAMICJITHELPER(CORINFO_HELP_SIMPLEISINSTANCEOF, NULL, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_ISINSTANCEOF_EXCEPTION, JIT_IsInstanceOfException, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 8fa19aa44c4c79..0934f2ea627481 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -329,7 +329,7 @@ enum ReadyToRunHelper READYTORUN_HELPER_GenericGcTlsBase = 0x66, READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, READYTORUN_HELPER_VirtualFuncPtr = 0x68, - READYTORUN_HELPER_SimpleIsInstanceOf = 0x69, + READYTORUN_HELPER_IsInstanceOfException = 0x69, // Long mul/div/shift ops READYTORUN_HELPER_LMul = 0xC0, diff --git a/src/coreclr/inc/readytorunhelpers.h b/src/coreclr/inc/readytorunhelpers.h index 0ec94cb93cc4b0..b9d904b9c41935 100644 --- a/src/coreclr/inc/readytorunhelpers.h +++ b/src/coreclr/inc/readytorunhelpers.h @@ -54,7 +54,7 @@ HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GETGENERICS_GCT HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,) HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, ) -HELPER(READYTORUN_HELPER_SimpleIsInstanceOf, CORINFO_HELP_SIMPLEISINSTANCEOF, ) +HELPER(READYTORUN_HELPER_IsInstanceOfException, CORINFO_HELP_ISINSTANCEOF_EXCEPTION, ) HELPER(READYTORUN_HELPER_LMul, CORINFO_HELP_LMUL, ) HELPER(READYTORUN_HELPER_LMulOfv, CORINFO_HELP_LMUL_OVF, ) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 506824721ac170..690b9b0e9f85e2 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2562,7 +2562,7 @@ void Compiler::fgCreateFiltersForGenericExceptions() { runtimeLookup = getTokenHandleTree(&resolvedToken, true); } - GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_SIMPLEISINSTANCEOF, TYP_INT, runtimeLookup, arg); + GenTree* isInstOfT = gtNewHelperCallNode(CORINFO_HELP_ISINSTANCEOF_EXCEPTION, TYP_INT, runtimeLookup, arg); GenTree* retFilt = gtNewOperNode(GT_RETFILT, TYP_INT, isInstOfT); // Insert it right before the handler (and make it a pred of the handler) diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs index 9786031d21a7f7..193b0f3814a483 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs @@ -255,7 +255,7 @@ public enum ReadyToRunHelper GenericGcTlsBase = 0x66, GenericNonGcTlsBase = 0x67, VirtualFuncPtr = 0x68, - SimpleIsInstanceOf = 0x69, + IsInstanceOfException = 0x69, // Long mul/div/shift ops LMul = 0xC0, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index d39bb529bbcf15..b0a53c8232e566 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -84,7 +84,7 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check - CORINFO_HELP_SIMPLEISINSTANCEOF, + CORINFO_HELP_ISINSTANCEOF_EXCEPTION, CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs index 76197cfa7c71a0..3cbd44db0b3892 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs @@ -248,8 +248,8 @@ public static void GetEntryPoint(TypeSystemContext context, ReadyToRunHelper id, case ReadyToRunHelper.CheckInstanceAny: mangledName = "RhTypeCast_IsInstanceOf"; break; - case ReadyToRunHelper.SimpleIsInstanceOf: - mangledName = "RhTypeCast_SimpleIsInstanceOf"; + case ReadyToRunHelper.IsInstanceOfException: + mangledName = "RhTypeCast_IsInstanceOfException"; break; case ReadyToRunHelper.CheckCastInterface: mangledName = "RhTypeCast_CheckCastInterface"; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 1ca44fad824849..dce751e370c76b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -775,8 +775,8 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.GetRuntimeTypeHandle; break; - case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: - id = ReadyToRunHelper.SimpleIsInstanceOf; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOF_EXCEPTION: + id = ReadyToRunHelper.IsInstanceOfException; break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs index 568c58dc51b4da..ab88c0ce03e607 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs @@ -1782,7 +1782,7 @@ private void ParseHelper(StringBuilder builder) builder.Append("CHECK_INSTANCE_ANY"); break; - case ReadyToRunHelper.SimpleIsInstanceOf: + case ReadyToRunHelper.IsInstanceOfException: builder.Append("SIMPLE_ISINSTANCE_OF"); break; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 54a5bb3a89ec66..e54366f91906f8 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -543,8 +543,8 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum) id = ReadyToRunHelper.AreTypesEquivalent; break; - case CorInfoHelpFunc.CORINFO_HELP_SIMPLEISINSTANCEOF: - id = ReadyToRunHelper.SimpleIsInstanceOf; + case CorInfoHelpFunc.CORINFO_HELP_ISINSTANCEOF_EXCEPTION: + id = ReadyToRunHelper.IsInstanceOfException; break; case CorInfoHelpFunc.CORINFO_HELP_BOX: id = ReadyToRunHelper.Box; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index c83fd019351cd9..3537c57d8cf05b 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1232,7 +1232,6 @@ DEFINE_METHOD(CASTHELPERS, CHKCASTANY, ChkCastAny, SM_Ptr DEFINE_METHOD(CASTHELPERS, CHKCASTINTERFACE, ChkCastInterface, SM_PtrVoid_Obj_RetObj) DEFINE_METHOD(CASTHELPERS, CHKCASTCLASS, ChkCastClass, SM_PtrVoid_Obj_RetObj) DEFINE_METHOD(CASTHELPERS, CHKCASTCLASSSPECIAL, ChkCastClassSpecial, SM_PtrVoid_Obj_RetObj) -DEFINE_METHOD(CASTHELPERS, SIMPLEISINSTANCEOF, SimpleIsInstanceOf, SM_PtrVoid_Obj_RetBool) DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_PtrVoid_Obj_RetRefByte) DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_Array_IntPtr_Obj_RetVoid) DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_Array_IntPtr_PtrVoid_RetRefObj) diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index bc94a83343374b..982690c28776bb 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -133,10 +133,6 @@ void ECall::PopulateManagedCastHelpers() pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_CHKCASTCLASS_SPECIAL, pDest); - pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__SIMPLEISINSTANCEOF)); - pDest = pMD->GetMultiCallableAddrOfCode(); - SetJitHelperFunction(CORINFO_HELP_SIMPLEISINSTANCEOF, pDest); - pMD = CoreLibBinder::GetMethod((BinderMethodID)(METHOD__CASTHELPERS__UNBOX)); pDest = pMD->GetMultiCallableAddrOfCode(); SetJitHelperFunction(CORINFO_HELP_UNBOX, pDest); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 9a7be8a9e70863..2daef63c2ad586 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -2832,7 +2832,6 @@ HCIMPL2_IV(LPVOID, JIT_GetRefAny, CORINFO_CLASS_HANDLE type, TypedByRef typedByR FCALL_CONTRACT; TypeHandle clsHnd(type); - // @TODO right now we check for precisely the correct type. // do we want to allow inheritance? (watch out since value // classes inherit from object but do not normal object layout). @@ -2845,6 +2844,16 @@ HCIMPL2_IV(LPVOID, JIT_GetRefAny, CORINFO_CLASS_HANDLE type, TypedByRef typedByR HCIMPLEND +/*************************************************************/ +HCIMPL2(BOOL, JIT_IsInstanceOfException, CORINFO_CLASS_HANDLE type, Object* obj) +{ + FCALL_CONTRACT; + TypeHandle clsHnd(type); + return ExceptionIsOfRightType(clsHnd, obj->GetTypeHandle()); +} +HCIMPLEND + + //======================================================================== // // GENERICS HELPERS diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index b7fab906acba5e..87161faf38304c 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10661,7 +10661,6 @@ void* CEEJitInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTINTERFACE || dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTCLASS || dynamicFtnNum == DYNAMIC_CORINFO_HELP_CHKCASTCLASS_SPECIAL || - dynamicFtnNum == DYNAMIC_CORINFO_HELP_SIMPLEISINSTANCEOF || dynamicFtnNum == DYNAMIC_CORINFO_HELP_UNBOX) { Precode* pPrecode = Precode::GetPrecodeFromEntryPoint((PCODE)hlpDynamicFuncTable[dynamicFtnNum].pfnHelper); diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index b6aced2a231f3d..f567d34be2f7da 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -243,7 +243,6 @@ DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Int_IntPtr_RetVoid, I I i i I, v)) DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_Obj_RetVoid, I r(j) I j, v)) DEFINE_METASIG(SM(Obj_Int_RetVoid, j i,v)) DEFINE_METASIG(SM(PtrVoid_Obj_RetObj, P(v) j, j)) -DEFINE_METASIG(SM(PtrVoid_Obj_RetBool, P(v) j, F)) DEFINE_METASIG(SM(PtrVoid_Obj_RetRefByte, P(v) j, r(b))) DEFINE_METASIG(SM(Flt_RetFlt, f, f)) From 79e87b80b1d797b882865c963320be55534fd0f2 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 22:59:48 +0200 Subject: [PATCH 17/27] remove dead code --- .../Runtime/CompilerServices/CastHelpers.cs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index ee9e544a39efb7..a49ffaf9378b36 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -628,27 +628,5 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el throw new ArrayTypeMismatchException(); } - - [DebuggerHidden] - [StackTraceHidden] - [DebuggerStepThrough] - private static bool IsInstanceOfException(void* typeHnd, object? obj) - { - if (obj == null) - return false; - - MethodTable* mt = RuntimeHelpers.GetMethodTable(obj); - - if (typeHnd == mt) - return true; - - while (mt != null) - { - mt = mt->ParentMethodTable; - if (mt == typeHnd) - return true; - } - return false; - } } } From 5420035acba18d7bb43c8eb4ffbd67ea6ca5def7 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 25 Jul 2022 23:39:56 +0200 Subject: [PATCH 18/27] Update src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs index d39c4cc1ddfb5b..33aa5426827e95 100644 --- a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs @@ -18,7 +18,7 @@ .assembly GenericCatchInterface {} // { // throw new MyException(); // } -// catch (MyException) // IL edit: Change to catch (IMyException) +// catch (MyException) // IL edit: Change to catch (IMyInterface) // { // Console.WriteLine("FAIL"); // retCode++; @@ -30,7 +30,7 @@ .assembly GenericCatchInterface {} // retCode += 50; // } // -// GenericCatch(); // IL edit: Change to GenericCatch() +// GenericCatch(); // IL edit: Change to GenericCatch() // // return retCode; // } From 9cf10d2fb722617792f2c2c6d5ed98f6643879f5 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 23:40:54 +0200 Subject: [PATCH 19/27] Fix test --- .../Generics/Exceptions/GenericCatchInterfaceProgram.csproj | 4 ++-- ...tchInterfaceProgram.cs => GenericCatchInterfaceProgram.il} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/tests/JIT/Generics/Exceptions/{GenericCatchInterfaceProgram.cs => GenericCatchInterfaceProgram.il} (100%) diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj index f492aeac9d056b..1f01486f84882d 100644 --- a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj +++ b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj @@ -1,9 +1,9 @@ - + Exe True - + \ No newline at end of file diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.il similarity index 100% rename from src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.cs rename to src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.il From fd3130e10514d5cb3d292477124e4bbdef06a559 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 25 Jul 2022 23:54:14 +0200 Subject: [PATCH 20/27] NativeAOT fix --- .../src/System/Runtime/ExceptionHandling.cs | 2 +- .../src/System/Runtime/TypeCast.cs | 34 ++++++++++++++----- .../src/System/Runtime/RuntimeImports.cs | 4 +-- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 4483386fd9f27c..9e576853a44cb1 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -847,7 +847,7 @@ private static bool ShouldTypedClauseCatchThisException(object exception, Method AssertNotRuntimeObject(pClauseType); #endif - return TypeCast.IsInstanceOfClass(pClauseType, exception) != null; + return TypeCast.IsInstanceOfException(pClauseType, exception); } private static void InvokeSecondPass(ref ExInfo exInfo, uint idxStart) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index be983f8e0bf4d6..5c7c6bbb0827ad 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -908,24 +908,42 @@ public static unsafe object IsInstanceOf(MethodTable* pTargetType, object obj) return IsInstanceOfClass(pTargetType, obj); } - [RuntimeExport("RhTypeCast_IsSimpleInstanceOf")] - public static unsafe bool IsSimpleInstanceOf(MethodTable* typeHnd, object obj) + [RuntimeExport("RhTypeCast_IsInstanceOfException")] + public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object? obj) { + // Based on IsInstanceOfClass_Helper + if (obj == null) return false; - MethodTable* mt = obj.GetMethodTable(); + MethodTable* pObjType = obj.GetMethodTable(); + if (pTargetType->IsCloned) + pTargetType = pTargetType->CanonicalEEType; + + if (pObjType->IsCloned) + pObjType = pObjType->CanonicalEEType; - if (typeHnd == mt) + if (pObjType == pTargetType) return true; - while (mt != null) + if (pTargetType->HasGenericVariance && pObjType->HasGenericVariance) + return CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource, null); + + if (pObjType->IsArray) + return false; + + while (true) { - mt = mt->RawBaseType; - if (mt == typeHnd) + pObjType = pObjType->NonClonedNonArrayBaseType; + if (pObjType == null) + return false; + + if (pObjType->IsCloned) + pObjType = pObjType->CanonicalEEType; + + if (pObjType == pTargetType) return true; } - return false; } [RuntimeExport("RhTypeCast_CheckCast")] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 9c373a0f922fb6..505adaee16808c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -328,8 +328,8 @@ internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj) internal static extern unsafe object IsInstanceOfInterface(MethodTable* pTargetType, object obj); [MethodImpl(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsSimpleInstanceOf")] - internal static extern unsafe bool IsSimpleInstanceOf(MethodTable* pTargetType, object obj); + [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfException")] + internal static extern unsafe bool IsInstanceOfException(MethodTable* pTargetType, object obj); internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, object obj) => IsInstanceOfInterface(pTargetType.ToPointer(), obj); From 22f2520bfe9f789916352feb0215c801f3023036 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 26 Jul 2022 00:00:37 +0200 Subject: [PATCH 21/27] remove "variance" block --- .../nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 5c7c6bbb0827ad..e9f129dfb14b3b 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -926,9 +926,6 @@ public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object if (pObjType == pTargetType) return true; - if (pTargetType->HasGenericVariance && pObjType->HasGenericVariance) - return CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource, null); - if (pObjType->IsArray) return false; From 9110e5ffa891502223250d061dc1456383ad944f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 26 Jul 2022 00:07:48 +0200 Subject: [PATCH 22/27] Address feedback --- .../nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index e9f129dfb14b3b..83c4f141a3d633 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -917,6 +917,7 @@ public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object return false; MethodTable* pObjType = obj.GetMethodTable(); + if (pTargetType->IsCloned) pTargetType = pTargetType->CanonicalEEType; @@ -926,8 +927,9 @@ public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object if (pObjType == pTargetType) return true; + // arrays can be cast to System.Object and System.Array if (pObjType->IsArray) - return false; + return WellKnownEETypes.IsSystemObject(pTargetType) || WellKnownEETypes.IsSystemArray(pTargetType); while (true) { From d3c01cb9e53754063d8ef263b578a49b7d12ccc4 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 26 Jul 2022 00:25:37 +0200 Subject: [PATCH 23/27] Remove IsPolyType --- src/coreclr/vm/siginfo.cpp | 115 ------------------------------------- src/coreclr/vm/siginfo.hpp | 28 --------- 2 files changed, 143 deletions(-) diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index 68b0ec711f8590..c35e9148fec355 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -1869,121 +1869,6 @@ TypeHandle SigPointer::GetTypeVariable(CorElementType et, #ifndef DACCESS_COMPILE -// Does this type contain class or method type parameters whose instantiation cannot -// be determined at JIT-compile time from the instantiations in the method context? -// Return a combination of hasClassVar and hasMethodVar flags. -// See header file for more info. -VarKind SigPointer::IsPolyType(const SigTypeContext *pTypeContext) const -{ - CONTRACTL - { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END - - SigPointer psig = *this; - CorElementType typ; - - if (FAILED(psig.GetElemType(&typ))) - return hasNoVars; - - switch(typ) { - case ELEMENT_TYPE_VAR: - case ELEMENT_TYPE_MVAR: - { - VarKind res = (typ == ELEMENT_TYPE_VAR ? hasClassVar : hasMethodVar); - if (pTypeContext != NULL) - { - TypeHandle ty = psig.GetTypeVariable(typ, pTypeContext); - if (ty.IsCanonicalSubtype()) - res = (VarKind) (res | (typ == ELEMENT_TYPE_VAR ? hasSharableClassVar : hasSharableMethodVar)); - } - return (res); - } - - case ELEMENT_TYPE_U: - case ELEMENT_TYPE_I: - case ELEMENT_TYPE_STRING: - case ELEMENT_TYPE_OBJECT: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R4: - case ELEMENT_TYPE_R8: - case ELEMENT_TYPE_VOID: - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_VALUETYPE: - case ELEMENT_TYPE_TYPEDBYREF: - return(hasNoVars); - - case ELEMENT_TYPE_GENERICINST: - { - VarKind k = psig.IsPolyType(pTypeContext); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - - uint32_t ntypars; - if(FAILED(psig.GetData(&ntypars))) - return hasNoVars; - - for (uint32_t i = 0; i < ntypars; i++) - { - k = (VarKind) (psig.IsPolyType(pTypeContext) | k); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - } - return(k); - } - - case ELEMENT_TYPE_ARRAY: - case ELEMENT_TYPE_SZARRAY: - case ELEMENT_TYPE_PINNED: - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_PTR: - { - return(psig.IsPolyType(pTypeContext)); - } - - case ELEMENT_TYPE_FNPTR: - { - if (FAILED(psig.GetData(NULL))) - return hasNoVars; - - // Get arg count; - uint32_t cArgs; - if (FAILED(psig.GetData(&cArgs))) - return hasNoVars; - - VarKind k = psig.IsPolyType(pTypeContext); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - - for (unsigned i = 0; i < cArgs; i++) - { - k = (VarKind) (psig.IsPolyType(pTypeContext) | k); - if (FAILED(psig.SkipExactlyOne())) - return hasNoVars; - } - - return(k); - } - - default: - BAD_FORMAT_NOTHROW_ASSERT(!"Bad type"); - } - return(hasNoVars); -} - BOOL SigPointer::IsStringType(Module* pModule, const SigTypeContext *pTypeContext) const { WRAPPER_NO_CONTRACT; diff --git a/src/coreclr/vm/siginfo.hpp b/src/coreclr/vm/siginfo.hpp index 29f811e627a74b..585fdb2071ef19 100644 --- a/src/coreclr/vm/siginfo.hpp +++ b/src/coreclr/vm/siginfo.hpp @@ -52,19 +52,6 @@ class ArgDestination; typedef const struct HardCodedMetaSig *LPHARDCODEDMETASIG; -//@GENERICS: flags returned from IsPolyType indicating the presence or absence of class and -// method type parameters in a type whose instantiation cannot be determined at JIT-compile time -enum VarKind -{ - hasNoVars = 0x0000, - hasClassVar = 0x0001, - hasMethodVar = 0x0002, - hasSharableClassVar = 0x0004, - hasSharableMethodVar = 0x0008, - hasAnyVarsMask = 0x0003, - hasSharableVarsMask = 0x000c -}; - //--------------------------------------------------------------------------------------- struct ScanContext; @@ -256,21 +243,6 @@ class SigPointer : public SigParser MethodTable *pMTInterfaceMapOwner = NULL) const; public: - //------------------------------------------------------------------------ - // Does this type contain class or method type parameters whose instantiation cannot - // be determined at JIT-compile time from the instantiations in the method context? - // Return a combination of hasClassVar and hasMethodVar flags. - // - // Example: class C containing instance method m - // Suppose that the method context is C::m - // Then the type Dict is considered to have *no* "polymorphic" type parameters because - // !0 is known to be float and !!0 is known to be double - // But Dict has polymorphic class *and* method type parameters because both - // !1=string and !!1=object are reference types and so code using these can be shared with - // other reference instantiations. - //------------------------------------------------------------------------ - VarKind IsPolyType(const SigTypeContext *pTypeContext) const; - //------------------------------------------------------------------------ // Tests if the element type is a System.String. Accepts // either ELEMENT_TYPE_STRING or ELEMENT_TYPE_CLASS encoding. From aaa075e32b7260c2c9e9df961839ac20336e873f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 26 Jul 2022 01:01:42 +0200 Subject: [PATCH 24/27] rename csproj to ilproj --- ...nterfaceProgram.csproj => GenericCatchInterfaceProgram.ilproj} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tests/JIT/Generics/Exceptions/{GenericCatchInterfaceProgram.csproj => GenericCatchInterfaceProgram.ilproj} (100%) diff --git a/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj b/src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.ilproj similarity index 100% rename from src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.csproj rename to src/tests/JIT/Generics/Exceptions/GenericCatchInterfaceProgram.ilproj From 98ce0063b8d975c60b2c3bf1f66130bb1abaaf80 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Tue, 26 Jul 2022 05:04:57 +0200 Subject: [PATCH 25/27] Update src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs Co-authored-by: Jan Kotas --- .../tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 0229dec1c45dcf..9f9c877fbed5db 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -202,7 +202,7 @@ private void StartImportingBasicBlock(BasicBlock basicBlock) if (catchType.IsRuntimeDeterminedSubtype) { // For runtime determined Exception types we're going to emit a fake EH filter with isinst for this - // type inside with a runtime lookup + // type with a runtime lookup _dependencies.Add(GetGenericLookupHelper(ReadyToRunHelperId.TypeHandleForCasting, catchType), "EH filter"); } } From 5c7c1579afecfa53b18f2fe1df80fef0bc807144 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Tue, 26 Jul 2022 06:19:21 +0200 Subject: [PATCH 26/27] Disable test on mono --- src/tests/issues.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 8c21256fe0936a..484345dac4841c 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1439,6 +1439,9 @@ + + https://github.com/dotnet/runtime/issues/72827 + https://github.com/dotnet/runtime/issues/71656 From d13147daf4eb118a6292d2dc38ab948ecce76574 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 28 Jul 2022 22:43:26 +0200 Subject: [PATCH 27/27] Update src/coreclr/jit/jiteh.cpp Co-authored-by: Andy Ayers --- src/coreclr/jit/jiteh.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index 690b9b0e9f85e2..278723442c3161 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -2547,7 +2547,6 @@ void Compiler::fgCreateFiltersForGenericExceptions() lvaTable[tempNum].lvType = TYP_REF; GenTree* argAsg = gtNewTempAssign(tempNum, arg); arg = gtNewLclvNode(tempNum, TYP_REF); - filterBb->bbStkTempsIn = tempNum; fgInsertStmtAtBeg(filterBb, gtNewStmt(argAsg, handlerBb->firstStmt()->GetDebugInfo())); // Create "catchArg is TException" tree