diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2017-08-08 01:26:23 +0300 |
---|---|---|
committer | dotnet-bot <dotnet-bot@microsoft.com> | 2017-08-08 01:26:23 +0300 |
commit | 1bc2b144bd978d441c6afff399e33081edf41f18 (patch) | |
tree | 1d5dbd674d725956edfb7843e54c279991001925 /src/Native/Runtime/RuntimeInstance.cpp | |
parent | 980f02121ea435fd5610deafd6248376f32bd246 (diff) |
ProjectX: Loop Hijack for GC poll
This change enables hijacking loops for GC poll. A loop needs a GC poll if it's not proved to have other GC hijack points, such as function calls.
Unlike the current table-based approach adopted in ProjectN, a piece of hijack code is injected to the loop to lead the control flow to the runtime for GC. For example, a loop usually has a conditional or unconditional branch at each of its back edge.
$LN10:
// loop body
test eax, eax
jne $LN10,
With this change the branch code will be changed to
cmp LoopHijackFlag, 0
jne $LNStub
$LNsource:
test eax, eax
jne $LN10
LNStub: (at the end of function)
call RhpLoopHijackX
jmp $LNsource;
A compare-and-jump is injected directly to the loop body while the hijacking code is placed at the end of the function since it's considered "cold code" assuming GC does not happened very often.
The global variable LoopHijackFlag is per module since we don't want to occupy or trash a register for it inside the loop.
The runtime helper RhpLoopHijackX is designed the preserve every register including callee-save registers and scratch registers so that no register used in the loop is trashed.
The transform happens very late in UTC in order not to affect the register allocation and to catch lower-introduced loops.
The change only works for Od mode for now. In Ox mode, a liveness analysis of up-exposed CC flag register use is needed so that the LoopHijackFlag check doesn't trash the CC register.
Testing:
The Nutc\BugFixes\BusyWait.proj test which is specifically designed to test this feature passed
No regression to other ToF tests
[tfs-changeset: 1669432]
Diffstat (limited to 'src/Native/Runtime/RuntimeInstance.cpp')
-rw-r--r-- | src/Native/Runtime/RuntimeInstance.cpp | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/src/Native/Runtime/RuntimeInstance.cpp b/src/Native/Runtime/RuntimeInstance.cpp index 982676f43..30dfc9328 100644 --- a/src/Native/Runtime/RuntimeInstance.cpp +++ b/src/Native/Runtime/RuntimeInstance.cpp @@ -258,6 +258,14 @@ void RuntimeInstance::EnumAllStaticGCRefs(void * pfnCallback, void * pvCallbackD EnumThreadStaticGCRefDescs(pfnCallback, pvCallbackData); } +void RuntimeInstance::SetLoopHijackFlags(UInt32 flag) +{ + for (TypeManagerList::Iterator iter = m_TypeManagerList.Begin(); iter != m_TypeManagerList.End(); iter++) + { + iter->m_pTypeManager->SetLoopHijackFlag(flag); + } +} + RuntimeInstance::OsModuleList* RuntimeInstance::GetOsModuleList() { return dac_cast<DPTR(OsModuleList)>(dac_cast<TADDR>(this) + offsetof(RuntimeInstance, m_OsModuleList)); |