Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2017-08-08 01:26:23 +0300
committerdotnet-bot <dotnet-bot@microsoft.com>2017-08-08 01:26:23 +0300
commit1bc2b144bd978d441c6afff399e33081edf41f18 (patch)
tree1d5dbd674d725956edfb7843e54c279991001925 /src/Native/Runtime/threadstore.cpp
parent980f02121ea435fd5610deafd6248376f32bd246 (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/threadstore.cpp')
-rw-r--r--src/Native/Runtime/threadstore.cpp7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/Native/Runtime/threadstore.cpp b/src/Native/Runtime/threadstore.cpp
index 3bbd16b89..3342b7e42 100644
--- a/src/Native/Runtime/threadstore.cpp
+++ b/src/Native/Runtime/threadstore.cpp
@@ -229,6 +229,9 @@ void ThreadStore::SuspendAllThreads(CLREventStatic* pCompletionEvent)
// set the global trap for pinvoke leave and return
RhpTrapThreads |= (UInt32)TrapThreadsFlags::TrapThreads;
+ // Set each module's loop hijack flag
+ GetRuntimeInstance()->SetLoopHijackFlags(RhpTrapThreads);
+
// Our lock-free algorithm depends on flushing write buffers of all processors running RH code. The
// reason for this is that we essentially implement Dekker's algorithm, which requires write ordering.
PalFlushProcessWriteBuffers();
@@ -292,6 +295,10 @@ void ThreadStore::ResumeAllThreads(CLREventStatic* pCompletionEvent)
END_FOREACH_THREAD
RhpTrapThreads &= ~(UInt32)TrapThreadsFlags::TrapThreads;
+
+ // Reset module's hijackLoops flag
+ GetRuntimeInstance()->SetLoopHijackFlags(0);
+
RhpSuspendingThread = NULL;
pCompletionEvent->Set();
UnlockThreadStore();