diff options
author | Brian Sullivan <briansul@microsoft.com> | 2019-01-10 18:50:35 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-10 18:50:35 -0800 |
commit | df88b1f6f858a558306e0e012c16d9de9c62ec15 (patch) | |
tree | 2cb161b64731b031f0aa5354e9cddf6f36075d66 /src | |
parent | 689035630bd8191da725cd3a9caf28c71142071f (diff) | |
parent | b4cbfba170ccdf277a5080bf24460fde4c41bbf3 (diff) | |
download | coreclr-df88b1f6f858a558306e0e012c16d9de9c62ec15.tar.gz coreclr-df88b1f6f858a558306e0e012c16d9de9c62ec15.tar.bz2 coreclr-df88b1f6f858a558306e0e012c16d9de9c62ec15.zip |
Merge pull request #21804 from briansull/fix-unbox-opt
Fix issue with devirtualization and tailcalls
Diffstat (limited to 'src')
-rw-r--r-- | src/jit/compiler.h | 3 | ||||
-rw-r--r-- | src/jit/flowgraph.cpp | 4 | ||||
-rw-r--r-- | src/jit/importer.cpp | 29 | ||||
-rw-r--r-- | src/jit/indirectcalltransformer.cpp | 6 |
4 files changed, 34 insertions, 8 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 21a426e3f1..6c93434dea 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -3329,7 +3329,8 @@ public: unsigned* methodFlags, CORINFO_CONTEXT_HANDLE* contextHandle, CORINFO_CONTEXT_HANDLE* exactContextHandle, - bool isLateDevirtualization); + bool isLateDevirtualization, + bool isExplicitTailCall); //========================================================================= // PROTECTED diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index eedb1aa58f..86f18ca404 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -22552,7 +22552,9 @@ Compiler::fgWalkResult Compiler::fgLateDevirtualization(GenTree** pTree, fgWalkD unsigned methodFlags = 0; CORINFO_CONTEXT_HANDLE context = nullptr; const bool isLateDevirtualization = true; - comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr, isLateDevirtualization); + bool explicitTailCall = (call->gtCall.gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; + comp->impDevirtualizeCall(call, &method, &methodFlags, &context, nullptr, isLateDevirtualization, + explicitTailCall); } } else if (tree->OperGet() == GT_ASG) diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 47ed202e1b..27ea06abaf 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -5276,7 +5276,7 @@ BOOL Compiler::verIsSDArray(typeInfo ti) typeInfo Compiler::verGetArrayElemType(typeInfo arrayObjectType) { - assert(!arrayObjectType.IsNullObjRef()); // you need to check for null explictly since that is a success case + assert(!arrayObjectType.IsNullObjRef()); // you need to check for null explicitly since that is a success case if (!verIsSDArray(arrayObjectType)) { @@ -8590,9 +8590,11 @@ var_types Compiler::impImportCall(OPCODE opcode, assert(obj->gtType == TYP_REF); // See if we can devirtualize. + + bool explicitTailCall = (tailCall & PREFIX_TAILCALL_EXPLICIT) != 0; const bool isLateDevirtualization = false; impDevirtualizeCall(call->AsCall(), &callInfo->hMethod, &callInfo->methodFlags, &callInfo->contextHandle, - &exactContextHnd, isLateDevirtualization); + &exactContextHnd, isLateDevirtualization, explicitTailCall); } if (impIsThis(obj)) @@ -8742,7 +8744,6 @@ DONE: if (info.compCompHnd->canTailCall(info.compMethodHnd, methHnd, exactCalleeHnd, explicitTailCall)) { - canTailCall = true; if (explicitTailCall) { // In case of explicit tail calls, mark it so that it is not considered @@ -20174,6 +20175,7 @@ bool Compiler::IsMathIntrinsic(GenTree* tree) // contextHandle -- [IN/OUT] context handle for the call. Updated iff call devirtualized. // exactContextHnd -- [OUT] updated context handle iff call devirtualized // isLateDevirtualization -- if devirtualization is happening after importation +// isExplicitTailCalll -- [IN] true if we plan on using an explicit tail call // // Notes: // Virtual calls in IL will always "invoke" the base class method. @@ -20207,7 +20209,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, unsigned* methodFlags, CORINFO_CONTEXT_HANDLE* contextHandle, CORINFO_CONTEXT_HANDLE* exactContextHandle, - bool isLateDevirtualization) + bool isLateDevirtualization, + bool isExplicitTailCall) { assert(call != nullptr); assert(method != nullptr); @@ -20558,6 +20561,12 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, { JITDUMP("Now have direct call to boxed entry point, looking for unboxed entry point\n"); + if (isExplicitTailCall) + { + JITDUMP("Call is an explicit tail call, we cannot perform an unbox\n"); + return; + } + // Note for some shared methods the unboxed entry point requires an extra parameter. bool requiresInstMethodTableArg = false; CORINFO_METHOD_HANDLE unboxedEntryMethod = @@ -20640,6 +20649,18 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, call->gtCallMethHnd = unboxedEntryMethod; call->gtCallMoreFlags |= GTF_CALL_M_UNBOXED; derivedMethod = unboxedEntryMethod; + +#if FEATURE_TAILCALL_OPT + if (call->IsImplicitTailCall()) + { + JITDUMP("Clearing the implicit tail call flag\n"); + + // If set, we clear the implicit tail call flag + // as we just introduced a new address taken local variable + // + call->gtCallMoreFlags &= ~GTF_CALL_M_IMPLICIT_TAILCALL; + } +#endif // FEATURE_TAILCALL_OPT } else { diff --git a/src/jit/indirectcalltransformer.cpp b/src/jit/indirectcalltransformer.cpp index 85d6d227cb..e0782b5b73 100644 --- a/src/jit/indirectcalltransformer.cpp +++ b/src/jit/indirectcalltransformer.cpp @@ -676,14 +676,16 @@ private: JITDUMP("Direct call [%06u] in block BB%02u\n", compiler->dspTreeID(call), thenBlock->bbNum); - // Then invoke impDevirtualizeCall do actually + // Then invoke impDevirtualizeCall to actually // transform the call for us. It should succeed.... as we have // now provided an exact typed this. CORINFO_METHOD_HANDLE methodHnd = inlineInfo->methInfo.ftn; unsigned methodFlags = inlineInfo->methAttr; CORINFO_CONTEXT_HANDLE context = inlineInfo->exactContextHnd; const bool isLateDevirtualization = true; - compiler->impDevirtualizeCall(call, &methodHnd, &methodFlags, &context, nullptr, isLateDevirtualization); + bool explicitTailCall = (call->gtCall.gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; + compiler->impDevirtualizeCall(call, &methodHnd, &methodFlags, &context, nullptr, isLateDevirtualization, + explicitTailCall); // Presumably devirt might fail? If so we should try and avoid // making this a guarded devirt candidate instead of ending |