From a26e2c670fc7a793794f4a499212a115c5d5a4b3 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Mon, 13 Feb 2017 11:05:02 -0800 Subject: Jit: fix for broken type equality optimization The jit relies on a particular tree remaining intact during importation to optimize type equality tests commonly found in generics. In #7909 the jit started aggressively spilling the evaluation stack before calls, which broke up the trees needed for the optimizations. In the special cases pertaining to type tests the trees can safely remain intact because we know the calls can't interact with the computations on the stack. Recognize these cases and selectively suppress spilling. Closes #9552. --- src/jit/importer.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 7a489332f5..1849a57848 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -7692,10 +7692,33 @@ DONE_CALL: call = gtNewLclvNode(calliSlot, type); } } + // For non-candidates we must also spill, since we // might have locals live on the eval stack that this // call can modify. - impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call")); + // + // Suppress this for certain well-known call targets + // that we know won't modify locals, eg calls that are + // recognized in gtCanOptimizeTypeEquality. Otherwise + // we may break key fragile pattern matches later on. + bool spillStack = true; + if (call->IsCall()) + { + GenTreeCall* callNode = call->AsCall(); + if ((callNode->gtCallType == CT_HELPER) && gtIsTypeHandleToRuntimeTypeHelper(callNode)) + { + spillStack = false; + } + else if ((callNode->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) != 0) + { + spillStack = false; + } + } + + if (spillStack) + { + impSpillSideEffects(true, CHECK_SPILL_ALL DEBUGARG("non-inline candidate call")); + } } } @@ -12813,7 +12836,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper); #if 0 // DevDiv 410397 - This breaks too many obfuscated apps to do this in an in-place release - + // DevDiv 291703 - we need to check for accessibility between the caller of InitializeArray // and the field it is reading, thus it is now unverifiable to not immediately precede with // ldtoken , and we now check accessibility -- cgit v1.2.3