Skip to content

Commit

Permalink
Only pass the method context when tracking transitions. (dotnet#47238)
Browse files Browse the repository at this point in the history
* Only pass the method context when tracking transitions.

* Add another separate helper for exit. use a jitflag to signify when to track transitions

* Apply suggestions from code review

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

* Wire up R2R helpers.

* Revert "Wire up R2R helpers."

This reverts commit 80a4749.

* Update CorInfoHelpFunc to have the new entries. Don't handle the new helpers since they won't be used.

* Simplify if check since CORProfilerTrackTransitions is process-wide.

* Remove unneeded assignment.

* Fix formatting.

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
  • Loading branch information
jkoritzinsky and jkotas committed Jan 21, 2021
1 parent ef88908 commit 7225baf
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 32 deletions.
4 changes: 3 additions & 1 deletion src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,10 @@ enum CorInfoHelpFunc
CORINFO_HELP_JIT_PINVOKE_BEGIN, // Transition to preemptive mode before a P/Invoke, frame is the first argument
CORINFO_HELP_JIT_PINVOKE_END, // Transition to cooperative mode after a P/Invoke, frame is the first argument

CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS, // Transition to cooperative mode and track transitions in reverse P/Invoke prolog.
CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS, // Transition to preemptive mode and track transitions in reverse P/Invoke prolog.

CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/corjitflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class CORJIT_FLAGS
CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background
CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions
CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog
CORJIT_FLAG_UNUSED14 = 38,
CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the REVERSE_PINVOKE helper variants that track transitions.
CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible
CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//

constexpr GUID JITEEVersionIdentifier = { /* 768493d2-21cb-41e6-b06d-e62131fd0fc2 */
0x768493d2,
0x21cb,
0x41e6,
{0xb0, 0x6d, 0xe6, 0x21, 0x31, 0xfd, 0x0f, 0xc2}
constexpr GUID JITEEVersionIdentifier = { /* c7a0a71a-1510-42d2-9b55-12255e325b86 */
0xc7a0a71a,
0x1510,
0x42d2,
{0x9b, 0x55, 0x12, 0x25, 0x5e, 0x32, 0x5b, 0x86}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,10 @@
JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, JIT_PInvokeBegin, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, JIT_PInvokeEnd, CORINFO_HELP_SIG_REG_ONLY)

JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, JIT_ReversePInvokeEnter, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, JIT_ReversePInvokeExit, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, JIT_ReversePInvokeEnter, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS, JIT_ReversePInvokeEnterTrackTransitions, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, JIT_ReversePInvokeExit, CORINFO_HELP_SIG_REG_ONLY)
JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS, JIT_ReversePInvokeExitTrackTransitions, CORINFO_HELP_SIG_REG_ONLY)

JITHELPER(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2600,6 +2600,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_EnC));
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_DEBUG_INFO));
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_REVERSE_PINVOKE));
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_TRACK_TRANSITIONS));
}

opts.jitFlags = jitFlags;
Expand Down
44 changes: 31 additions & 13 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8687,25 +8687,38 @@ void Compiler::fgAddReversePInvokeEnterExit()

GenTree* pInvokeFrameVar = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));

GenTree* stubArgument;
GenTree* tree;

CorInfoHelpFunc reversePInvokeEnterHelper;

if (info.compPublishStubParam)
GenTreeCall::Use* args;

if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TRACK_TRANSITIONS))
{
// If we have a secret param for a Reverse P/Invoke, that means that we are in an IL stub.
// In this case, the method handle we pass down to the Reverse P/Invoke helper should be
// the target method, which is passed in the secret parameter.
stubArgument = gtNewLclvNode(lvaStubArgumentVar, TYP_I_IMPL);
reversePInvokeEnterHelper = CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS;

GenTree* stubArgument;
if (info.compPublishStubParam)
{
// If we have a secret param for a Reverse P/Invoke, that means that we are in an IL stub.
// In this case, the method handle we pass down to the Reverse P/Invoke helper should be
// the target method, which is passed in the secret parameter.
stubArgument = gtNewLclvNode(lvaStubArgumentVar, TYP_I_IMPL);
}
else
{
stubArgument = gtNewIconNode(0, TYP_I_IMPL);
}

args = gtNewCallArgs(pInvokeFrameVar, gtNewIconEmbMethHndNode(info.compMethodHnd), stubArgument);
}
else
{
stubArgument = gtNewIconNode(0, TYP_I_IMPL);
reversePInvokeEnterHelper = CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER;
args = gtNewCallArgs(pInvokeFrameVar);
}

GenTree* tree;

GenTreeCall::Use* args = gtNewCallArgs(pInvokeFrameVar, gtNewIconEmbMethHndNode(info.compMethodHnd), stubArgument);

tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, TYP_VOID, args);
tree = gtNewHelperCallNode(reversePInvokeEnterHelper, TYP_VOID, args);

fgEnsureFirstBBisScratch();

Expand All @@ -8725,7 +8738,11 @@ void Compiler::fgAddReversePInvokeEnterExit()

tree = gtNewOperNode(GT_ADDR, TYP_I_IMPL, gtNewLclvNode(lvaReversePInvokeFrameVar, TYP_BLK));

tree = gtNewHelperCallNode(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, TYP_VOID, gtNewCallArgs(tree));
CorInfoHelpFunc reversePInvokeExitHelper = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TRACK_TRANSITIONS)
? CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS
: CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT;

tree = gtNewHelperCallNode(reversePInvokeExitHelper, TYP_VOID, gtNewCallArgs(tree));

assert(genReturnBB != nullptr);

Expand Down Expand Up @@ -23655,6 +23672,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe
compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_EnC);
compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_DEBUG_INFO);
compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_REVERSE_PINVOKE);
compileFlagsForInlinee.Clear(JitFlags::JIT_FLAG_TRACK_TRANSITIONS);

compileFlagsForInlinee.Set(JitFlags::JIT_FLAG_SKIP_VERIFICATION);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/jitee.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class JitFlags
JIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background
JIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions
JIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog
JIT_FLAG_UNUSED14 = 38,
JIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions.
JIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible
JIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code

Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,10 @@ which is the right helper to use to allocate an object of a given type. */
CORINFO_HELP_JIT_PINVOKE_BEGIN, // Transition to preemptive mode before a P/Invoke, frame is the first argument
CORINFO_HELP_JIT_PINVOKE_END, // Transition to cooperative mode after a P/Invoke, frame is the first argument

CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS, // Transition to cooperative mode and track transitions in reverse P/Invoke prolog.
CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument
CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS, // Transition to preemptive mode and track transitions in reverse P/Invoke prolog.

CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ public enum CorJitFlag : uint
CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background
CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions
CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog
CORJIT_FLAG_UNUSED10 = 38,
CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions.
CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible
CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code
CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records
Expand Down
59 changes: 52 additions & 7 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5407,19 +5407,17 @@ NOINLINE static void JIT_ReversePInvokeEnterRare2(ReversePInvokeFrame* frame, vo
#endif // DEBUGGING_SUPPORTED
}

// The following two methods are special.
// The following JIT_ReversePInvoke helpers are special.
// They handle setting up Reverse P/Invoke calls and transitioning back to unmanaged code.
// As a result, we may not have a thread in JIT_ReversePInvokeEnter and we will be in the wrong GC mode for the HCALL prolog.
// Additionally, we set up and tear down SEH handlers when we're on x86, so we can't use dynamic contracts anyway.
// As a result, we specially decorate this method to have the correct calling convention
// and argument ordering for an HCALL, but we don't use the HCALL macros and contracts
// since this method doesn't follow the contracts.
void F_CALL_CONV HCCALL3(JIT_ReversePInvokeEnter, ReversePInvokeFrame* frame, CORINFO_METHOD_HANDLE handle, void* secretArg)
void F_CALL_CONV HCCALL3(JIT_ReversePInvokeEnterTrackTransitions, ReversePInvokeFrame* frame, CORINFO_METHOD_HANDLE handle, void* secretArg)
{
_ASSERTE(frame != NULL && handle != NULL);

void* traceAddr = _ReturnAddress();

MethodDesc* pMD = GetMethod(handle);
if (pMD->IsILStub() && secretArg != NULL)
{
Expand Down Expand Up @@ -5447,12 +5445,12 @@ void F_CALL_CONV HCCALL3(JIT_ReversePInvokeEnter, ReversePInvokeFrame* frame, CO
thread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1);
if (g_TrapReturningThreads.LoadWithoutBarrier() != 0)
{
JIT_ReversePInvokeEnterRare2(frame, traceAddr);
JIT_ReversePInvokeEnterRare2(frame, _ReturnAddress());
}
}
else
{
JIT_ReversePInvokeEnterRare(frame, traceAddr);
JIT_ReversePInvokeEnterRare(frame, _ReturnAddress());
}

#ifndef FEATURE_EH_FUNCLETS
Expand All @@ -5462,7 +5460,39 @@ void F_CALL_CONV HCCALL3(JIT_ReversePInvokeEnter, ReversePInvokeFrame* frame, CO
#endif
}

void F_CALL_CONV HCCALL1(JIT_ReversePInvokeExit, ReversePInvokeFrame* frame)
void F_CALL_CONV HCCALL1(JIT_ReversePInvokeEnter, ReversePInvokeFrame* frame)
{
_ASSERTE(frame != NULL);

Thread* thread = GetThreadNULLOk();

// If a thread instance exists and is in the
// correct GC mode attempt a quick transition.
if (thread != NULL
&& !thread->PreemptiveGCDisabled())
{
frame->currentThread = thread;

// Manually inline the fast path in Thread::DisablePreemptiveGC().
thread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(1);
if (g_TrapReturningThreads.LoadWithoutBarrier() != 0)
{
JIT_ReversePInvokeEnterRare2(frame, _ReturnAddress());
}
}
else
{
JIT_ReversePInvokeEnterRare(frame, _ReturnAddress());
}

#ifndef FEATURE_EH_FUNCLETS
frame->record.m_pEntryFrame = frame->currentThread->GetFrame();
frame->record.m_ExReg.Handler = (PEXCEPTION_ROUTINE)FastNExportExceptHandler;
INSTALL_EXCEPTION_HANDLING_RECORD(&frame->record.m_ExReg);
#endif
}

void F_CALL_CONV HCCALL1(JIT_ReversePInvokeExitTrackTransitions, ReversePInvokeFrame* frame)
{
_ASSERTE(frame != NULL);
_ASSERTE(frame->currentThread == GetThread());
Expand All @@ -5484,6 +5514,21 @@ void F_CALL_CONV HCCALL1(JIT_ReversePInvokeExit, ReversePInvokeFrame* frame)
#endif
}

void F_CALL_CONV HCCALL1(JIT_ReversePInvokeExit, ReversePInvokeFrame* frame)
{
_ASSERTE(frame != NULL);
_ASSERTE(frame->currentThread == GetThread());

// Manually inline the fast path in Thread::EnablePreemptiveGC().
// This is a trade off with GC suspend performance. We are opting
// to make this exit faster.
frame->currentThread->m_fPreemptiveGCDisabled.StoreWithoutBarrier(0);

#ifndef FEATURE_EH_FUNCLETS
UNINSTALL_EXCEPTION_HANDLING_RECORD(&frame->record.m_ExReg);
#endif
}

//========================================================================
//
// JIT HELPERS INITIALIZATION
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12695,6 +12695,10 @@ CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr,
COMDelegate::ThrowIfInvalidUnmanagedCallersOnlyUsage(ftn);

flags.Set(CORJIT_FLAGS::CORJIT_FLAG_REVERSE_PINVOKE);
if (CORProfilerTrackTransitions())
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_TRACK_TRANSITIONS);
}
}

return flags;
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/readytoruninfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,11 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig
pConfig->SetProfilerRejectedPrecompiledCode();
goto done;
}
if (CORProfilerTrackTransitions() && pMD->HasUnmanagedCallersOnlyAttribute())
{
pConfig->SetProfilerRejectedPrecompiledCode();
goto done;
}
#endif // PROFILING_SUPPORTED
#endif // CROSSGEN_COMPILE

Expand Down

0 comments on commit 7225baf

Please sign in to comment.