From ce1b6dcae9bf07ee3d10c5c8202df4f9380d1c1a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sat, 25 Feb 2017 06:33:11 -0800 Subject: [PATCH] Revert "Simplified MinOpts GC ref tracking." Commit migrated from https://github.com/dotnet/coreclr/commit/a77dae93c1708663e864e77159b16bdaee7c9635 --- src/coreclr/src/jit/codegenarm.cpp | 6 +- src/coreclr/src/jit/codegenarm64.cpp | 7 +- src/coreclr/src/jit/codegenlegacy.cpp | 6 +- src/coreclr/src/jit/codegenxarch.cpp | 6 +- src/coreclr/src/jit/gcencode.cpp | 98 +++++++--------------- src/coreclr/src/jit/jitconfigvalues.h | 9 -- src/coreclr/src/jit/jitgcinfo.h | 6 +- src/coreclr/src/jit/lclvars.cpp | 4 - src/coreclr/src/vm/gcinfodecoder.cpp | 55 +++++------- src/coreclr/tests/src/GC/API/GC/KeepAlive.cs | 11 +-- .../tests/src/GC/Scenarios/LeakGen/leakgen.cs | 10 ++- src/coreclr/tests/src/GC/Scenarios/Samples/gc.cs | 13 +-- .../src/GC/Scenarios/WeakReference/weakreffinal.cs | 10 +-- .../tests/src/JIT/Methodical/Arrays/misc/arrres.cs | 27 +++--- 14 files changed, 91 insertions(+), 177 deletions(-) diff --git a/src/coreclr/src/jit/codegenarm.cpp b/src/coreclr/src/jit/codegenarm.cpp index 27d188f..ca6ae01 100644 --- a/src/coreclr/src/jit/codegenarm.cpp +++ b/src/coreclr/src/jit/codegenarm.cpp @@ -1918,14 +1918,12 @@ void CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32). gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize); - // We keep the call count for the second call to gcMakeRegPtrTable() below. - unsigned callCnt = 0; // First we figure out the encoder ID's for the stack slots and registers. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS); // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them). gcInfoEncoder->FinalizeSlotIds(); // Now we can actually use those slot ID's to declare live ranges. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); gcInfoEncoder->Build(); diff --git a/src/coreclr/src/jit/codegenarm64.cpp b/src/coreclr/src/jit/codegenarm64.cpp index 62ebc48..5c31a09 100644 --- a/src/coreclr/src/jit/codegenarm64.cpp +++ b/src/coreclr/src/jit/codegenarm64.cpp @@ -6061,17 +6061,14 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32). gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize); - // We keep the call count for the second call to gcMakeRegPtrTable() below. - unsigned callCnt = 0; - // First we figure out the encoder ID's for the stack slots and registers. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS); // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them). gcInfoEncoder->FinalizeSlotIds(); // Now we can actually use those slot ID's to declare live ranges. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); if (compiler->opts.compDbgEnC) { diff --git a/src/coreclr/src/jit/codegenlegacy.cpp b/src/coreclr/src/jit/codegenlegacy.cpp index 922a9b1..7fd2956 100644 --- a/src/coreclr/src/jit/codegenlegacy.cpp +++ b/src/coreclr/src/jit/codegenlegacy.cpp @@ -20164,14 +20164,12 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32). gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize); - // We keep the call count for the second call to gcMakeRegPtrTable() below. - unsigned callCnt = 0; // First we figure out the encoder ID's for the stack slots and registers. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS); // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them). gcInfoEncoder->FinalizeSlotIds(); // Now we can actually use those slot ID's to declare live ranges. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); gcInfoEncoder->Build(); diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp index acf7a0d..66ae5ff 100644 --- a/src/coreclr/src/jit/codegenxarch.cpp +++ b/src/coreclr/src/jit/codegenxarch.cpp @@ -8361,14 +8361,12 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32). gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize); - // We keep the call count for the second call to gcMakeRegPtrTable() below. - unsigned callCnt = 0; // First we figure out the encoder ID's for the stack slots and registers. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS); // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them). gcInfoEncoder->FinalizeSlotIds(); // Now we can actually use those slot ID's to declare live ranges. - gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt); + gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK); if (compiler->opts.compDbgEnC) { diff --git a/src/coreclr/src/jit/gcencode.cpp b/src/coreclr/src/jit/gcencode.cpp index 2b9fe37..dcca19e 100644 --- a/src/coreclr/src/jit/gcencode.cpp +++ b/src/coreclr/src/jit/gcencode.cpp @@ -3844,15 +3844,13 @@ struct InterruptibleRangeReporter } }; -void GCInfo::gcMakeRegPtrTable( - GcInfoEncoder* gcInfoEncoder, unsigned codeSize, unsigned prologSize, MakeRegPtrMode mode, unsigned* callCntRef) +void GCInfo::gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder, + unsigned codeSize, + unsigned prologSize, + MakeRegPtrMode mode) { GCENCODER_WITH_LOGGING(gcInfoEncoderWithLog, gcInfoEncoder); - const bool noTrackedGCSlots = - (compiler->opts.MinOpts() && !compiler->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && - !JitConfig.JitMinOptsTrackGCrefs()); - if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS) { m_regSlotMap = new (compiler->getAllocator()) RegSlotMap(compiler->getAllocator()); @@ -3963,25 +3961,14 @@ void GCInfo::gcMakeRegPtrTable( { stackSlotBase = GC_FRAMEREG_REL; } - if (noTrackedGCSlots) + StackSlotIdKey sskey(varDsc->lvStkOffs, (stackSlotBase == GC_FRAMEREG_REL), flags); + GcSlotId varSlotId; + if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS) { - // No need to hash/lookup untracked GC refs; just grab a new Slot Id. - if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS) - { - gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase); - } - } - else - { - StackSlotIdKey sskey(varDsc->lvStkOffs, (stackSlotBase == GC_FRAMEREG_REL), flags); - GcSlotId varSlotId; - if (mode == MAKE_REG_PTR_MODE_ASSIGN_SLOTS) + if (!m_stackSlotMap->Lookup(sskey, &varSlotId)) { - if (!m_stackSlotMap->Lookup(sskey, &varSlotId)) - { - varSlotId = gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase); - m_stackSlotMap->Set(sskey, varSlotId); - } + varSlotId = gcInfoEncoderWithLog->GetStackSlotId(varDsc->lvStkOffs, flags, stackSlotBase); + m_stackSlotMap->Set(sskey, varSlotId); } } } @@ -4217,24 +4204,9 @@ void GCInfo::gcMakeRegPtrTable( { if (gcCallDescList != nullptr) { - if (noTrackedGCSlots) + for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext) { - // We have the call count from the previous run. - numCallSites = *callCntRef; - - // If there are no calls, tell the world and bail. - if (numCallSites == 0) - { - gcInfoEncoderWithLog->DefineCallSites(nullptr, nullptr, 0); - return; - } - } - else - { - for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext) - { - numCallSites++; - } + numCallSites++; } pCallSites = new (compiler, CMK_GC) unsigned[numCallSites]; pCallSiteSizes = new (compiler, CMK_GC) BYTE[numCallSites]; @@ -4244,8 +4216,17 @@ void GCInfo::gcMakeRegPtrTable( // Now consider every call. for (CallDsc* call = gcCallDescList; call != nullptr; call = call->cdNext) { + if (mode == MAKE_REG_PTR_MODE_DO_WORK) + { + pCallSites[callSiteNum] = call->cdOffs - call->cdCallInstrSize; + pCallSiteSizes[callSiteNum] = call->cdCallInstrSize; + callSiteNum++; + } + + unsigned nextOffset; + // Figure out the code offset of this entry. - unsigned nextOffset = call->cdOffs; + nextOffset = call->cdOffs; // As far as I (DLD, 2010) can determine by asking around, the "call->u1.cdArgMask" // and "cdArgCnt" cases are to handle x86 situations in which a call expression is nested as an @@ -4270,36 +4251,13 @@ void GCInfo::gcMakeRegPtrTable( assert(call->cdOffs >= call->cdCallInstrSize); // call->cdOffs is actually the offset of the instruction *following* the call, so subtract // the call instruction size to get the offset of the actual call instruction... - unsigned callOffset = nextOffset - call->cdCallInstrSize; - - if (noTrackedGCSlots && regMask == 0) - { - // No live GC refs in regs at the call -> don't record the call. - } - else - { - // Append an entry for the call if doing the real thing. - if (mode == MAKE_REG_PTR_MODE_DO_WORK) - { - pCallSites[callSiteNum] = callOffset; - pCallSiteSizes[callSiteNum] = call->cdCallInstrSize; - } - callSiteNum++; - - // Record that these registers are live before the call... - gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, callOffset, regMask, GC_SLOT_LIVE, byrefRegMask, - nullptr); - // ...and dead after. - gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, nextOffset, regMask, GC_SLOT_DEAD, byrefRegMask, - nullptr); - } + unsigned callOffset = call->cdOffs - call->cdCallInstrSize; + // Record that these registers are live before the call... + gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, callOffset, regMask, GC_SLOT_LIVE, byrefRegMask, nullptr); + // ...and dead after. + gcInfoRecordGCRegStateChange(gcInfoEncoder, mode, call->cdOffs, regMask, GC_SLOT_DEAD, byrefRegMask, + nullptr); } - - // Make sure we've recorded the expected number of calls - assert(mode != MAKE_REG_PTR_MODE_DO_WORK || numCallSites == callSiteNum); - // Return the actual recorded call count to the caller - *callCntRef = callSiteNum; - // OK, define the call sites. if (mode == MAKE_REG_PTR_MODE_DO_WORK) { diff --git a/src/coreclr/src/jit/jitconfigvalues.h b/src/coreclr/src/jit/jitconfigvalues.h index 264b661..a3e30de 100644 --- a/src/coreclr/src/jit/jitconfigvalues.h +++ b/src/coreclr/src/jit/jitconfigvalues.h @@ -214,15 +214,6 @@ CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 0) CONFIG_INTEGER(JitEnableNoWayAssert, W("JitEnableNoWayAssert"), 1) #endif // !defined(DEBUG) && !defined(_DEBUG) -#if !defined(JIT32_GCENCODER) -#if defined(_TARGET_AMD64_) && defined(FEATURE_CORECLR) -#define JitMinOptsTrackGCrefs_Default 0 // Not tracking GC refs in MinOpts is new behavior -#else -#define JitMinOptsTrackGCrefs_Default 1 -#endif -CONFIG_INTEGER(JitMinOptsTrackGCrefs, W("JitMinOptsTrackGCrefs"), JitMinOptsTrackGCrefs_Default) // Track GC roots -#endif // !defined(JIT32_GCENCODER) - // The following should be wrapped inside "#if MEASURE_MEM_ALLOC / #endif", but // some files include this one without bringing in the definitions from "jit.h" // so we don't always know what the "true" value of that flag should be. For now diff --git a/src/coreclr/src/jit/jitgcinfo.h b/src/coreclr/src/jit/jitgcinfo.h index 7b17b84..3f8d8af 100644 --- a/src/coreclr/src/jit/jitgcinfo.h +++ b/src/coreclr/src/jit/jitgcinfo.h @@ -295,11 +295,7 @@ public: // references, building up mappings from tuples of to the corresponding // slot id (in the two member fields declared above). In the "do work" mode, we use these slot ids to // actually declare live ranges to the encoder. - void gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder, - unsigned codeSize, - unsigned prologSize, - MakeRegPtrMode mode, - unsigned* callCntRef); + void gcMakeRegPtrTable(GcInfoEncoder* gcInfoEncoder, unsigned codeSize, unsigned prologSize, MakeRegPtrMode mode); #endif #ifdef JIT32_GCENCODER diff --git a/src/coreclr/src/jit/lclvars.cpp b/src/coreclr/src/jit/lclvars.cpp index 3edff3b..6e5ab9e 100644 --- a/src/coreclr/src/jit/lclvars.cpp +++ b/src/coreclr/src/jit/lclvars.cpp @@ -3023,10 +3023,6 @@ void Compiler::lvaSortByRefCount() lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_PinningRef)); #endif } - else if (opts.MinOpts() && !JitConfig.JitMinOptsTrackGCrefs() && varTypeIsGC(varDsc->TypeGet())) - { - varDsc->lvTracked = 0; - } // Are we not optimizing and we have exception handlers? // if so mark all args and locals "do not enregister". diff --git a/src/coreclr/src/vm/gcinfodecoder.cpp b/src/coreclr/src/vm/gcinfodecoder.cpp index 5dd52b9..89f4704 100644 --- a/src/coreclr/src/vm/gcinfodecoder.cpp +++ b/src/coreclr/src/vm/gcinfodecoder.cpp @@ -628,8 +628,6 @@ bool GcInfoDecoder::EnumerateLiveSlots( #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - bool noTrackedRefs = false; - if(m_SafePointIndex < m_NumSafePoints && !executionAborted) { // Skip interruptibility information @@ -650,40 +648,33 @@ bool GcInfoDecoder::EnumerateLiveSlots( // if(!executionAborted) { - if(m_NumInterruptibleRanges == 0) - { - // No ranges and no explicit safepoint - must be MinOpts with untracked refs. - noTrackedRefs = true; - } + _ASSERTE(m_NumInterruptibleRanges); } - if(m_NumInterruptibleRanges != 0) + int countIntersections = 0; + UINT32 lastNormStop = 0; + for(UINT32 i=0; i= normStart && normBreakOffset < normStop) - { - _ASSERTE(pseudoBreakOffset == 0); - countIntersections++; - pseudoBreakOffset = numInterruptibleLength + normBreakOffset - normStart; - } - numInterruptibleLength += normStopDelta; - lastNormStop = normStop; - } - _ASSERTE(countIntersections <= 1); - if(countIntersections == 0) + UINT32 normStart = lastNormStop + normStartDelta; + UINT32 normStop = normStart + normStopDelta; + if(normBreakOffset >= normStart && normBreakOffset < normStop) { - _ASSERTE(executionAborted); - LOG((LF_GCROOTS, LL_INFO100000, "Not reporting this frame because it is aborted and not fully interruptible.\n")); - goto ExitSuccess; + _ASSERTE(pseudoBreakOffset == 0); + countIntersections++; + pseudoBreakOffset = numInterruptibleLength + normBreakOffset - normStart; } + numInterruptibleLength += normStopDelta; + lastNormStop = normStop; + } + _ASSERTE(countIntersections <= 1); + if(countIntersections == 0) + { + _ASSERTE(executionAborted); + LOG((LF_GCROOTS, LL_INFO100000, "Not reporting this frame because it is aborted and not fully interruptible.\n")); + goto ExitSuccess; } } #else // !PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -727,7 +718,7 @@ bool GcInfoDecoder::EnumerateLiveSlots( if(executionAborted) { - // Skip over safepoint info (if any is present). + _ASSERTE(m_NumSafePoints == 0); m_Reader.Skip(m_NumSafePoints * numSlots); } else if( m_SafePointIndex != m_NumSafePoints ) @@ -796,8 +787,6 @@ bool GcInfoDecoder::EnumerateLiveSlots( else { m_Reader.Skip(m_NumSafePoints * numSlots); - if(noTrackedRefs) - goto ReportUntracked; } #endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED diff --git a/src/coreclr/tests/src/GC/API/GC/KeepAlive.cs b/src/coreclr/tests/src/GC/API/GC/KeepAlive.cs index 3174f89..df3d9d2 100644 --- a/src/coreclr/tests/src/GC/API/GC/KeepAlive.cs +++ b/src/coreclr/tests/src/GC/API/GC/KeepAlive.cs @@ -47,23 +47,16 @@ public class Test } - public static void RunTest2() - { - Dummy2 obj2 = new Dummy2(); - obj2 = null; - } - - public static void RunTest() { Dummy obj = new Dummy(); - - RunTest2(); + Dummy2 obj2 = new Dummy2(); // *uncomment the for loop to make test fail with complus_jitminops set // by design as per briansul //for (int i=0; i<5; i++) { + obj2 = null; GC.Collect(); GC.WaitForPendingFinalizers(); //} diff --git a/src/coreclr/tests/src/GC/Scenarios/LeakGen/leakgen.cs b/src/coreclr/tests/src/GC/Scenarios/LeakGen/leakgen.cs index 8ec6531..9235256 100644 --- a/src/coreclr/tests/src/GC/Scenarios/LeakGen/leakgen.cs +++ b/src/coreclr/tests/src/GC/Scenarios/LeakGen/leakgen.cs @@ -62,10 +62,6 @@ namespace LGen { MakeLeak(iObj); } - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - Console.WriteLine("~LeakObject() was called {0} times.", LeakObject.icFinal); return (LeakObject.icFinal == iObj*iRep); } @@ -84,6 +80,12 @@ namespace LGen { mem[mem.Length-1] = 1; } + Mv_Obj = null; + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } diff --git a/src/coreclr/tests/src/GC/Scenarios/Samples/gc.cs b/src/coreclr/tests/src/GC/Scenarios/Samples/gc.cs index 7ed11bc..a6c1cfe 100644 --- a/src/coreclr/tests/src/GC/Scenarios/Samples/gc.cs +++ b/src/coreclr/tests/src/GC/Scenarios/Samples/gc.cs @@ -273,21 +273,16 @@ class Application { static public ResurrectObj ResObjHolder; // Defaults to null - // These methods demonstrate how the GC supports resurrection. + // This method demonstrates how the GC supports resurrection. // NOTE: Resurrection is discouraged. - private static void ResurrectionInit() { + private static void ResurrectionDemo() { + Display(0, "\n\nDemo start: Object Resurrection.", +1); + // Create a ResurrectionObj ResurrectObj obj = new ResurrectObj("Resurrection"); // Destroy all strong references to the new ResurrectionObj obj = null; - } - - private static void ResurrectionDemo() { - Display(0, "\n\nDemo start: Object Resurrection.", +1); - - // Create a ResurrectionObj and drop it on the floor. - ResurrectionInit(); // Force the GC to determine that the object is unreachable. Collect(); diff --git a/src/coreclr/tests/src/GC/Scenarios/WeakReference/weakreffinal.cs b/src/coreclr/tests/src/GC/Scenarios/WeakReference/weakreffinal.cs index 754e88d..a356cec 100644 --- a/src/coreclr/tests/src/GC/Scenarios/WeakReference/weakreffinal.cs +++ b/src/coreclr/tests/src/GC/Scenarios/WeakReference/weakreffinal.cs @@ -22,11 +22,6 @@ namespace DefaultNamespace { public bool RunTest(int iObj,int iSwitch) { DeleteObj(iObj,iSwitch); - - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - bool result = CheckResult(iObj,iSwitch); return result; } @@ -53,6 +48,11 @@ namespace DefaultNamespace { { rgNode[i] = null; } + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + } public bool CheckResult(int iObj,int iSwitch) diff --git a/src/coreclr/tests/src/JIT/Methodical/Arrays/misc/arrres.cs b/src/coreclr/tests/src/JIT/Methodical/Arrays/misc/arrres.cs index e021a59..7956cc6 100644 --- a/src/coreclr/tests/src/JIT/Methodical/Arrays/misc/arrres.cs +++ b/src/coreclr/tests/src/JIT/Methodical/Arrays/misc/arrres.cs @@ -45,18 +45,13 @@ namespace GCTest return 100; } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - private static void CollectAndFinalize() - { - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - } - [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test1() { for (int i = 0; i < 50; i++) s_arr[i] = new Test(i); - CollectAndFinalize(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test2() @@ -67,44 +62,52 @@ namespace GCTest s_arr[i].CheckValid(); s_arr[i] = null; } + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test3() { - CollectAndFinalize(); for (int i = 0; i < 50; i++) { if (s_arr[i] == null) throw new Exception(); s_arr[i].CheckValid(); s_arr[i] = null; } + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test4() { - CollectAndFinalize(); for (int i = 0; i < 50; i++) { if (s_arr[i] == null) throw new Exception(); s_arr[i].CheckValid(); s_arr[i] = null; } + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test5() { - CollectAndFinalize(); for (int i = 0; i < 50; i++) { if (s_arr[i] == null) throw new Exception(); s_arr[i].CheckValid(); s_arr[i] = null; } + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); } [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static void Test6() { - CollectAndFinalize(); for (int i = 0; i < 50; i++) { if (s_arr[i] == null) throw new Exception(); -- 2.7.4