summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vm/appdomain.cpp2
-rw-r--r--src/vm/ceemain.cpp4
-rw-r--r--src/vm/tieredcompilation.cpp87
-rw-r--r--src/vm/tieredcompilation.h7
-rw-r--r--tests/runtest.cmd2
-rw-r--r--tests/src/CLRTest.Execute.Bash.targets6
-rw-r--r--tests/src/CLRTest.Execute.Batch.targets6
7 files changed, 83 insertions, 31 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 78ebe50c26..a569b90052 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -8103,7 +8103,7 @@ void AppDomain::Exit(BOOL fRunFinalizers, BOOL fAsyncExit)
// have exited the domain.
//
#ifdef FEATURE_TIERED_COMPILATION
- m_tieredCompilationManager.OnAppDomainShutdown();
+ m_tieredCompilationManager.Shutdown(FALSE);
#endif
//
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp
index 0bc7f4994a..a9cbc8f10e 100644
--- a/src/vm/ceemain.cpp
+++ b/src/vm/ceemain.cpp
@@ -1623,6 +1623,10 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
// Indicate the EE is the shut down phase.
g_fEEShutDown |= ShutDown_Start;
+#ifdef FEATURE_TIERED_COMPILATION
+ TieredCompilationManager::ShutdownAllDomains();
+#endif
+
fFinalizeOK = TRUE;
// Terminate the BBSweep thread
diff --git a/src/vm/tieredcompilation.cpp b/src/vm/tieredcompilation.cpp
index 8486bf2671..a4a8c90070 100644
--- a/src/vm/tieredcompilation.cpp
+++ b/src/vm/tieredcompilation.cpp
@@ -48,14 +48,16 @@
// # Important entrypoints in this code:
//
//
-// a) .ctor and Init(...) - called once during AppDomain initialization
-// b) OnMethodCalled(...) - called when a method is being invoked. When a method
-// has been called enough times this is currently the only
-// trigger that initiates re-compilation.
-// c) OnAppDomainShutdown() - called during AppDomain::Exit() to begin the process
-// of stopping tiered compilation. After this point no more
-// background optimization work will be initiated but in-progress
-// work still needs to complete.
+// a) .ctor and Init(...) - called once during AppDomain initialization
+// b) OnMethodCalled(...) - called when a method is being invoked. When a method
+// has been called enough times this is currently the only
+// trigger that initiates re-compilation.
+// c) Shutdown() - called during AppDomain::Exit() to begin the process
+// of stopping tiered compilation. After this point no more
+// background optimization work will be initiated but in-progress
+// work still needs to complete.
+// d) ShutdownAllDomains() - Called from EEShutdownHelper to block until all async work is
+// complete. We must do this before we shutdown the JIT.
//
// # Overall workflow
//
@@ -108,6 +110,8 @@ void TieredCompilationManager::Init(ADID appDomainId)
SpinLockHolder holder(&m_lock);
m_domainId = appDomainId;
+ m_pAsyncWorkDoneEvent = new CLREvent();
+ m_pAsyncWorkDoneEvent->CreateManualEvent(TRUE);
}
// Called each time code in this AppDomain has been run. This is our sole entrypoint to begin
@@ -190,7 +194,7 @@ void TieredCompilationManager::AsyncPromoteMethodToTier1(MethodDesc* pMethodDesc
{
// Our current policy throttles at 1 thread, but in the future we
// could experiment with more parallelism.
- m_countOptimizationThreadsRunning++;
+ IncrementWorkerThreadCount();
}
else
{
@@ -203,7 +207,7 @@ void TieredCompilationManager::AsyncPromoteMethodToTier1(MethodDesc* pMethodDesc
if (!ThreadpoolMgr::QueueUserWorkItem(StaticOptimizeMethodsCallback, this, QUEUE_ONLY, TRUE))
{
SpinLockHolder holder(&m_lock);
- m_countOptimizationThreadsRunning--;
+ DecrementWorkerThreadCount();
STRESS_LOG1(LF_TIEREDCOMPILATION, LL_WARNING, "TieredCompilationManager::OnMethodCalled: "
"ThreadpoolMgr::QueueUserWorkItem returned FALSE (no thread will run), method=%pM\n",
pMethodDesc);
@@ -212,7 +216,7 @@ void TieredCompilationManager::AsyncPromoteMethodToTier1(MethodDesc* pMethodDesc
EX_CATCH
{
SpinLockHolder holder(&m_lock);
- m_countOptimizationThreadsRunning--;
+ DecrementWorkerThreadCount();
STRESS_LOG2(LF_TIEREDCOMPILATION, LL_WARNING, "TieredCompilationManager::OnMethodCalled: "
"Exception queuing work item to threadpool, hr=0x%x, method=%pM\n",
GET_EXCEPTION()->GetHR(), pMethodDesc);
@@ -222,19 +226,35 @@ void TieredCompilationManager::AsyncPromoteMethodToTier1(MethodDesc* pMethodDesc
return;
}
-void TieredCompilationManager::OnAppDomainShutdown()
+// static
+// called from EEShutDownHelper
+void TieredCompilationManager::ShutdownAllDomains()
{
- CONTRACTL
+ STANDARD_VM_CONTRACT;
+
+ AppDomainIterator domain(TRUE);
+ while (domain.Next())
{
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- CAN_TAKE_LOCK;
+ AppDomain * pDomain = domain.GetDomain();
+ if (pDomain != NULL)
+ {
+ pDomain->GetTieredCompilationManager()->Shutdown(TRUE);
+ }
}
- CONTRACTL_END
+}
- SpinLockHolder holder(&m_lock);
- m_isAppDomainShuttingDown = TRUE;
+void TieredCompilationManager::Shutdown(BOOL fBlockUntilAsyncWorkIsComplete)
+{
+ STANDARD_VM_CONTRACT;
+
+ {
+ SpinLockHolder holder(&m_lock);
+ m_isAppDomainShuttingDown = TRUE;
+ }
+ if (fBlockUntilAsyncWorkIsComplete)
+ {
+ m_pAsyncWorkDoneEvent->Wait(INFINITE, FALSE);
+ }
}
// This is the initial entrypoint for the background thread, called by
@@ -268,7 +288,7 @@ void TieredCompilationManager::OptimizeMethodsCallback()
SpinLockHolder holder(&m_lock);
if (m_isAppDomainShuttingDown)
{
- m_countOptimizationThreadsRunning--;
+ DecrementWorkerThreadCount();
return;
}
}
@@ -289,7 +309,7 @@ void TieredCompilationManager::OptimizeMethodsCallback()
if (nativeCodeVersion.IsNull() ||
m_isAppDomainShuttingDown)
{
- m_countOptimizationThreadsRunning--;
+ DecrementWorkerThreadCount();
break;
}
@@ -305,7 +325,7 @@ void TieredCompilationManager::OptimizeMethodsCallback()
if (!ThreadpoolMgr::QueueUserWorkItem(StaticOptimizeMethodsCallback, this, QUEUE_ONLY, TRUE))
{
SpinLockHolder holder(&m_lock);
- m_countOptimizationThreadsRunning--;
+ DecrementWorkerThreadCount();
STRESS_LOG0(LF_TIEREDCOMPILATION, LL_WARNING, "TieredCompilationManager::OptimizeMethodsCallback: "
"ThreadpoolMgr::QueueUserWorkItem returned FALSE (no thread will run)\n");
}
@@ -421,6 +441,27 @@ NativeCodeVersion TieredCompilationManager::GetNextMethodToOptimize()
return NativeCodeVersion();
}
+void TieredCompilationManager::IncrementWorkerThreadCount()
+{
+ STANDARD_VM_CONTRACT;
+ //m_lock should be held
+
+ m_countOptimizationThreadsRunning++;
+ m_pAsyncWorkDoneEvent->Reset();
+}
+
+void TieredCompilationManager::DecrementWorkerThreadCount()
+{
+ STANDARD_VM_CONTRACT;
+ //m_lock should be held
+
+ m_countOptimizationThreadsRunning--;
+ if (m_countOptimizationThreadsRunning == 0)
+ {
+ m_pAsyncWorkDoneEvent->Set();
+ }
+}
+
//static
CORJIT_FLAGS TieredCompilationManager::GetJitFlags(NativeCodeVersion nativeCodeVersion)
{
diff --git a/src/vm/tieredcompilation.h b/src/vm/tieredcompilation.h
index 6e155fef14..1e28f388b7 100644
--- a/src/vm/tieredcompilation.h
+++ b/src/vm/tieredcompilation.h
@@ -27,7 +27,8 @@ public:
void Init(ADID appDomainId);
BOOL OnMethodCalled(MethodDesc* pMethodDesc, DWORD currentCallCount);
void AsyncPromoteMethodToTier1(MethodDesc* pMethodDesc);
- void OnAppDomainShutdown();
+ static void ShutdownAllDomains();
+ void Shutdown(BOOL fBlockUntilAsyncWorkIsComplete);
static CORJIT_FLAGS GetJitFlags(NativeCodeVersion nativeCodeVersion);
private:
@@ -39,6 +40,9 @@ private:
BOOL CompileCodeVersion(NativeCodeVersion nativeCodeVersion);
void ActivateCodeVersion(NativeCodeVersion nativeCodeVersion);
+ void IncrementWorkerThreadCount();
+ void DecrementWorkerThreadCount();
+
SpinLock m_lock;
SList<SListElem<NativeCodeVersion>> m_methodsToOptimize;
ADID m_domainId;
@@ -46,6 +50,7 @@ private:
DWORD m_countOptimizationThreadsRunning;
DWORD m_callCountOptimizationThreshhold;
DWORD m_optimizationQuantumMs;
+ CLREvent* m_pAsyncWorkDoneEvent;
};
#endif // FEATURE_TIERED_COMPILATION
diff --git a/tests/runtest.cmd b/tests/runtest.cmd
index 675f1f4cad..936383ea12 100644
--- a/tests/runtest.cmd
+++ b/tests/runtest.cmd
@@ -85,6 +85,7 @@ if /i "%1" == "GenerateLayoutOnly" (set __GenerateLayoutOnly=1&shift&goto Arg
if /i "%1" == "PerfTests" (set __PerfTests=true&shift&goto Arg_Loop)
if /i "%1" == "runcrossgentests" (set RunCrossGen=true&shift&goto Arg_Loop)
if /i "%1" == "link" (set DoLink=true&set ILLINK=%2&shift&shift&goto Arg_Loop)
+if /i "%1" == "tieredcompilation" (set COMPLUS_EXPERIMENTAL_TieredCompilation=1&shift&goto Arg_Loop)
REM change it to COMPlus_GCStress when we stop using xunit harness
if /i "%1" == "gcstresslevel" (set __GCSTRESSLEVEL=%2&set __TestTimeout=1800000&shift&shift&goto Arg_Loop)
@@ -464,6 +465,7 @@ echo 2: GC on transitions to preemptive GC
echo 4: GC on every allowable JITed instruction
echo 8: GC on every allowable NGEN instruction
echo 16: GC only on a unique stack trace
+echo tieredcompilation - Run the tests with COMPlus_EXPERIMENTAL_TieredCompilation=1
echo msbuildargs ^<args...^> - Pass all subsequent args directly to msbuild invocations.
echo ^<CORE_ROOT^> - Path to the runtime to test (if specified).
echo.
diff --git a/tests/src/CLRTest.Execute.Bash.targets b/tests/src/CLRTest.Execute.Bash.targets
index 10f4aa612d..73f70313b0 100644
--- a/tests/src/CLRTest.Execute.Bash.targets
+++ b/tests/src/CLRTest.Execute.Bash.targets
@@ -83,9 +83,9 @@ fi
]]></BashCLRTestEnvironmentCompatibilityCheck>
<BashCLRTestEnvironmentCompatibilityCheck Condition="'$(JitOptimizationSensitive)' == 'true'"><![CDATA[
$(BashCLRTestEnvironmentCompatibilityCheck)
-if [[ ( ! -z "$COMPlus_JitStress" ) || ( ! -z "$COMPlus_JitStressRegs" ) || ( ! -z "$COMPlus_JITMinOpts" ) || ( ! -z "$COMPlus_TailcallStress" ) ]]
+if [[ ( ! -z "$COMPlus_JitStress" ) || ( ! -z "$COMPlus_JitStressRegs" ) || ( ! -z "$COMPlus_JITMinOpts" ) || ( ! -z "$COMPlus_TailcallStress" ) || ( ! -z "$COMPlus_EXPERIMENTAL_TieredCompilation" ) ]]
then
- echo "SKIPPING EXECUTION BECAUSE ONE OR MORE OF (COMPlus_JitStress, COMPlus_JitStressRegs, COMPlus_JITMinOpts, COMPlus_TailcallStress) IS SET"
+ echo "SKIPPING EXECUTION BECAUSE ONE OR MORE OF (COMPlus_JitStress, COMPlus_JitStressRegs, COMPlus_JITMinOpts, COMPlus_TailcallStress, COMPlus_EXPERIMENTAL_TieredCompilation) IS SET"
exit $(GCBashScriptExitCode)
fi
]]></BashCLRTestEnvironmentCompatibilityCheck>
@@ -396,4 +396,4 @@ $(BashCLRTestExitCodeCheck)
Overwrite="true" />
</Target>
-</Project> \ No newline at end of file
+</Project>
diff --git a/tests/src/CLRTest.Execute.Batch.targets b/tests/src/CLRTest.Execute.Batch.targets
index dfd87bad5f..7abf16a731 100644
--- a/tests/src/CLRTest.Execute.Batch.targets
+++ b/tests/src/CLRTest.Execute.Batch.targets
@@ -78,8 +78,8 @@ IF NOT "%COMPlus_GCStress%"=="" (
]]></BatchCLRTestEnvironmentCompatibilityCheck>
<BatchCLRTestEnvironmentCompatibilityCheck Condition="'$(JitOptimizationSensitive)' == 'true'"><![CDATA[
$(BatchCLRTestEnvironmentCompatibilityCheck)
-IF "%COMPlus_JitStress%"=="" IF "%COMPlus_JitStressRegs%"=="" IF "%COMPlus_JITMinOpts%"=="" IF "%COMPlus_TailcallStress%"=="" goto :Compatible1
- ECHO SKIPPING EXECUTION BECAUSE ONE OR MORE OF (COMPlus_JitStress, COMPlus_JitStressRegs, COMPlus_JITMinOpts, COMPlus_TailcallStress) IS SET
+IF "%COMPlus_JitStress%"=="" IF "%COMPlus_JitStressRegs%"=="" IF "%COMPlus_JITMinOpts%"=="" IF "%COMPlus_TailcallStress%"=="" IF "%COMPlus_EXPERIMENTAL_TieredCompilation%"=="" goto :Compatible1
+ ECHO SKIPPING EXECUTION BECAUSE ONE OR MORE OF (COMPlus_JitStress, COMPlus_JitStressRegs, COMPlus_JITMinOpts, COMPlus_TailcallStress, COMPlus_EXPERIMENTAL_TieredCompilation) IS SET
popd
Exit /b 0
:Compatible1
@@ -391,4 +391,4 @@ $(BatchCLRTestExitCodeCheck)
Overwrite="true" />
</Target>
-</Project> \ No newline at end of file
+</Project>