Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement portable tailcall helpers #341

Merged
merged 42 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cc45a0e
Implement portable tailcall helpers
jakobbotsch Nov 27, 2019
62a0134
Fix build
jakobbotsch Nov 27, 2019
b6af537
Update design doc for helper-based tailcalls
jakobbotsch Feb 5, 2020
de7608a
Address some feedback
jakobbotsch Mar 3, 2020
c121e9e
Merge remote-tracking branch 'upstream/master' into portable-tailcall…
jakobbotsch Mar 3, 2020
442f186
Fix some bad merges
jakobbotsch Mar 3, 2020
f21b9c6
Address some more feedback
jakobbotsch Mar 3, 2020
2671b74
Undo unnecessary change
jakobbotsch Mar 3, 2020
0406cbb
Regenerate CorInfoBase.cs
jakobbotsch Mar 3, 2020
08a44e4
Address feedback
jakobbotsch Mar 5, 2020
0b7e464
Fix uses of TARGET macros.
erozenfeld Mar 6, 2020
46a869b
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 7, 2020
f43b6a2
Merge branch 'master' of github.com:dotnet/runtime into portable-tail…
jakobbotsch Mar 8, 2020
710f7a2
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 10, 2020
6af504a
Reexclude implicit tailcalls test on x86
jakobbotsch Mar 10, 2020
ad93d07
Add test exclusions for arm64 windows.
erozenfeld Mar 10, 2020
565833f
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 11, 2020
13c9e22
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 11, 2020
2209664
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 13, 2020
6081e53
Fix build break after merge.
erozenfeld Mar 14, 2020
a508947
Fix formatting.
erozenfeld Mar 14, 2020
4801b25
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 16, 2020
29f2832
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Mar 21, 2020
03256b6
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 21, 2020
bd4fe1b
Fix build break after merge.
erozenfeld Mar 21, 2020
cc36784
Merge branch 'master' into portable-tailcall-helpers
erozenfeld Mar 21, 2020
84bd83e
Add comments and clean up getRuntimeLookupTree.
erozenfeld Mar 19, 2020
bcd44da
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Mar 31, 2020
b1d2b41
Expand only required intrinsics in methods that call NextCallReturnAd…
erozenfeld Mar 31, 2020
bd8415b
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 13, 2020
4219e96
Change lowering of GT_LABEL on arm.
erozenfeld Apr 13, 2020
564b089
Add COMPlus_FastTailCalls environment variable.
erozenfeld Apr 13, 2020
f3d9f09
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 13, 2020
28878a8
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 21, 2020
8b641b1
Fix the type of IL_STUB_StoreTailCallArgs `this` parameter.
erozenfeld Apr 21, 2020
47030d2
Fix handling of calls whose signature has `CORINFO_CALLCONV_EXPLICITT…
erozenfeld Apr 21, 2020
8fc501c
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 22, 2020
fb3d883
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 22, 2020
3ac5187
Merge branch 'master' of https://github.com/dotnet/runtime
erozenfeld Apr 24, 2020
20138ab
Address code review feedback.
erozenfeld Apr 24, 2020
be718ba
Address feedback
jakobbotsch Apr 25, 2020
f1e5638
Address some more feedback
jakobbotsch Apr 25, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
674 changes: 242 additions & 432 deletions docs/design/features/tailcalls-with-helpers.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,16 @@ public static IntPtr AllocateTypeAssociatedMemory(Type type, int size)

[DllImport(RuntimeHelpers.QCall)]
private static extern IntPtr AllocateTypeAssociatedMemoryInternal(QCallTypeHandle type, uint size);
}

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern IntPtr AllocTailCallArgBuffer(int size, IntPtr gcDesc);

[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void FreeTailCallArgBuffer();

[MethodImpl(MethodImplOptions.InternalCall)]
private static unsafe extern TailCallTls* GetTailCallInfo(IntPtr retAddrSlot, IntPtr* retAddr);
}
// Helper class to assist with unsafe pinning of arbitrary objects.
// It's used by VM code.
internal class RawData
Expand Down Expand Up @@ -421,4 +429,24 @@ public int MultiDimensionalArrayRank
}
}
}

// Helper structs used for tail calls via helper.
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct PortableTailCallFrame
{
public PortableTailCallFrame* Prev;
public IntPtr TailCallAwareReturnAddress;
public IntPtr NextCall;
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct TailCallTls
{
public PortableTailCallFrame* Frame;
public IntPtr ArgBuffer;
private IntPtr _argBufferSize;
private IntPtr _argBufferGCDesc;
private fixed byte _argBufferInline[64];
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1878,5 +1878,8 @@ internal static void CheckStringLength(uint length)
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void MulticastDebuggerTraceHelper(object o, int count);
#endif

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern IntPtr NextCallReturnAddress();
} // class StubHelpers
}
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,12 @@ void MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd);
// return a thunk that will copy the arguments for the given signature.
void* getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags);

bool getTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult);

bool convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert);

// get a block of memory for the code, readonly data, and read-write data
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ LWM(GetSharedCCtorHelper, DWORDLONG, DWORD)
LWM(GetStringConfigValue, DWORD, DWORD)
LWM(GetSystemVAmd64PassStructInRegisterDescriptor, DWORDLONG, Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor)
LWM(GetTailCallCopyArgsThunk, Agnostic_GetTailCallCopyArgsThunk, DWORDLONG)
LWM(GetTailCallHelpers, Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS)
LWM(GetThreadTLSIndex, DWORD, DLD)
LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG)
LWM(GetTypeForBox, DWORDLONG, DWORDLONG)
Expand Down
74 changes: 74 additions & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5956,12 +5956,14 @@ void MethodContext::recGetTailCallCopyArgsThunk(CORINFO_SIG_INFO*
GetTailCallCopyArgsThunk->Add(key, (DWORDLONG)result);
DEBUG_REC(dmpGetTailCallCopyArgsThunk(key, (DWORDLONG)result));
}

void MethodContext::dmpGetTailCallCopyArgsThunk(const Agnostic_GetTailCallCopyArgsThunk& key, DWORDLONG value)
{
printf("GetTailCallCopyArgsThunk key sig%s flg-%08X",
SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(key.Sig).c_str(), key.flags);
printf(", value res-%016llX", value);
}

void* MethodContext::repGetTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags)
{
AssertCodeMsg(GetTailCallCopyArgsThunk != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for ...");
Expand All @@ -5980,6 +5982,78 @@ void* MethodContext::repGetTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfo
return result;
}

void MethodContext::recGetTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
if (GetTailCallHelpers == nullptr)
GetTailCallHelpers = new LightWeightMap<Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS>();

Agnostic_GetTailCallHelpers key;
ZeroMemory(&key, sizeof(Agnostic_GetTailCallHelpers));

key.callToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(callToken, GetTailCallHelpers);
key.sig = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(*sig, GetTailCallHelpers);
key.flags = (DWORD)flags;

Agnostic_CORINFO_TAILCALL_HELPERS value;
ZeroMemory(&value, sizeof(Agnostic_CORINFO_TAILCALL_HELPERS));

value.result = pResult != nullptr;
if (pResult != nullptr)
{
value.flags = (DWORD)pResult->flags;
value.hStoreArgs = (DWORDLONG)pResult->hStoreArgs;
value.hCallTarget = (DWORDLONG)pResult->hCallTarget;
value.hDispatcher = (DWORDLONG)pResult->hDispatcher;
}
GetTailCallHelpers->Add(key, value);
DEBUG_REC(dmpGetTailCallHelpers(key, value));
}

void MethodContext::dmpGetTailCallHelpers(const Agnostic_GetTailCallHelpers& key, const Agnostic_CORINFO_TAILCALL_HELPERS& value)
jakobbotsch marked this conversation as resolved.
Show resolved Hide resolved
{
printf("GetTailCallHelpers key callToken-%s sig-%s flg-%08X",
SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.callToken).c_str(),
SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(key.sig).c_str(),
key.flags);
printf(", value result-%s flg-%08X hStoreArgs-%016llX hCallTarget-%016llX hDispatcher-%016llX",
value.result ? "true" : "false",
value.flags,
value.hStoreArgs,
value.hCallTarget,
value.hDispatcher);
}
jakobbotsch marked this conversation as resolved.
Show resolved Hide resolved

bool MethodContext::repGetTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
AssertCodeMsg(GetTailCallHelpers != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for ...");

Agnostic_GetTailCallHelpers key;
ZeroMemory(&key, sizeof(Agnostic_GetTailCallHelpers));
key.callToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(callToken, GetTailCallHelpers);
key.sig = SpmiRecordsHelper::RestoreAgnostic_CORINFO_SIG_INFO(*sig, GetTailCallHelpers);
key.flags = (DWORD)flags;

AssertCodeMsg(GetTailCallHelpers->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Could not find matching tail call helper call");
Agnostic_CORINFO_TAILCALL_HELPERS value = GetTailCallHelpers->Get(key);
if (!value.result)
return false;

pResult->flags = (CORINFO_TAILCALL_HELPERS_FLAGS)value.flags;
pResult->hStoreArgs = (CORINFO_METHOD_HANDLE)value.hStoreArgs;
pResult->hCallTarget = (CORINFO_METHOD_HANDLE)value.hCallTarget;
pResult->hDispatcher = (CORINFO_METHOD_HANDLE)value.hDispatcher;
DEBUG_REP(dmpGetTailCallHelpers(key, value));
return true;
}

void MethodContext::recGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod, mdMethodDef result)
{
if (GetMethodDefFromMethod == nullptr)
Expand Down
29 changes: 28 additions & 1 deletion src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,20 @@ class MethodContext
Agnostic_CORINFO_SIG_INFO Sig;
DWORD flags;
};
struct Agnostic_GetTailCallHelpers
{
Agnostic_CORINFO_RESOLVED_TOKEN callToken;
Agnostic_CORINFO_SIG_INFO sig;
DWORD flags;
};
struct Agnostic_CORINFO_TAILCALL_HELPERS
{
bool result;
DWORD flags;
DWORDLONG hStoreArgs;
DWORDLONG hCallTarget;
DWORDLONG hDispatcher;
};
struct Agnostic_GetArgClass_Value
{
DWORDLONG result;
Expand Down Expand Up @@ -1259,6 +1273,18 @@ class MethodContext
void dmpGetTailCallCopyArgsThunk(const Agnostic_GetTailCallCopyArgsThunk& key, DWORDLONG value);
void* repGetTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags);

void recGetTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult);
void dmpGetTailCallHelpers(const Agnostic_GetTailCallHelpers& key, const Agnostic_CORINFO_TAILCALL_HELPERS& value);
bool repGetTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult);

void recGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod, mdMethodDef result);
void dmpGetMethodDefFromMethod(DWORDLONG key, DWORD value);
mdMethodDef repGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod);
Expand Down Expand Up @@ -1320,7 +1346,7 @@ class MethodContext
};

// ********************* Please keep this up-to-date to ease adding more ***************
// Highest packet number: 177
// Highest packet number: 178
// *************************************************************************************
enum mcPackets
{
Expand Down Expand Up @@ -1439,6 +1465,7 @@ enum mcPackets
Packet_GetSecurityPrologHelper = 85, // Retired 2/18/2020
Packet_GetSharedCCtorHelper = 86,
Packet_GetTailCallCopyArgsThunk = 87,
Packet_GetTailCallHelpers = 178, // Added 3/18/2020
Packet_GetThreadTLSIndex = 88,
Packet_GetTokenTypeAsHandle = 89,
Packet_GetTypeForBox = 90,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,21 @@ void* interceptor_ICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfo
return result;
}

bool interceptor_ICJI::getTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
mc->cr->AddCall("getTailCallHelpers");
bool result = original_ICorJitInfo->getTailCallHelpers(callToken, sig, flags, pResult);
if (result)
mc->recGetTailCallHelpers(callToken, sig, flags, pResult);
else
mc->recGetTailCallHelpers(callToken, sig, flags, nullptr);
return result;
}

// Stuff directly on ICorJitInfo

// Returns extended flags for a particular compilation instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,16 @@ void* interceptor_ICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfo
return original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
}

bool interceptor_ICJI::getTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
mcs->AddCall("getTailCallHelpers");
return original_ICorJitInfo->getTailCallHelpers(callToken, sig, flags, pResult);
}

// Stuff directly on ICorJitInfo

// Returns extended flags for a particular compilation instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,15 @@ void* interceptor_ICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfo
return original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
}

bool interceptor_ICJI::getTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
return original_ICorJitInfo->getTailCallHelpers(callToken, sig, flags, pResult);
}

// Stuff directly on ICorJitInfo

// Returns extended flags for a particular compilation instance.
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,16 @@ void* MyICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTail
return jitInstance->mc->repGetTailCallCopyArgsThunk(pSig, flags);
}

bool MyICJI::getTailCallHelpers(
CORINFO_RESOLVED_TOKEN* callToken,
CORINFO_SIG_INFO* sig,
CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
CORINFO_TAILCALL_HELPERS* pResult)
{
jitInstance->mc->cr->AddCall("getTailCallHelpers");
return jitInstance->mc->repGetTailCallHelpers(callToken, sig, flags, pResult);
}

bool MyICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert)
{
jitInstance->mc->cr->AddCall("convertPInvokeCalliToCall");
Expand Down
Loading