From c55282fef2de4c982aaada492e9be26d34d1f0f6 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Wed, 25 Jan 2023 23:29:46 +0100 Subject: [PATCH] Fix max chunk size limiting When the new stub heaps were implemented, the chunk size needed to be limited so that all precodes for a chunk fit into a single memory page. That was done in `MethodDescChunk::CreateChunk`. But it was discovered now that there is another place where it needs to be limited, the `MethodTableBuilder::AllocAndInitMethodDescChunk`. The JIT\opt\ObjectStackAllocation\ObjectStackAllocationTests started to fail in the outerloop due to too long chunk. The failure happens in crossgen2 as it is using a separate build of runtime in release and only that uncovers the problem. And only when DOTNET_TieredCompilation=0 and DOTNET_ProfApi_RejitOnAttach=0. This change fixes the problem. With this change applied to the dotnet runtime version used by the crossgen2 and patching it in place in the .dotnet/shared/.... directory, the issue doesn't occur. Close #81103 --- src/coreclr/vm/methodtablebuilder.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 245fcaf55bf2bb..3a941210b7a209 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -6871,9 +6871,15 @@ VOID MethodTableBuilder::AllocAndInitMethodDescs() SIZE_T sizeOfMethodDescs = 0; // current running size of methodDesc chunk int startIndex = 0; // start of the current chunk (index into bmtMethod array) + // Limit the maximum MethodDescs per chunk by the number of precodes that can fit to a single memory page, + // since we allocate consecutive temporary entry points for all MethodDescs in the whole chunk. + DWORD maxPrecodesPerPage = Precode::GetMaxTemporaryEntryPointsCount(); + DWORD methodDescCount = 0; + DeclaredMethodIterator it(*this); while (it.Next()) { + DWORD currentSlotMethodDescCount = 1; int tokenRange = GetTokenRange(it.Token()); // This code assumes that iterator returns tokens in ascending order. If this assumption does not hold, @@ -6896,6 +6902,7 @@ VOID MethodTableBuilder::AllocAndInitMethodDescs() // See comment in AllocAndInitMethodDescChunk if (NeedsTightlyBoundUnboxingStub(*it)) { + currentSlotMethodDescCount = 2; size *= 2; if (bmtGenerics->GetNumGenericArgs() == 0) { @@ -6907,7 +6914,8 @@ VOID MethodTableBuilder::AllocAndInitMethodDescs() } if (tokenRange != currentTokenRange || - sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs) + sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs || + methodDescCount + currentSlotMethodDescCount > maxPrecodesPerPage) { if (sizeOfMethodDescs != 0) { @@ -6917,9 +6925,11 @@ VOID MethodTableBuilder::AllocAndInitMethodDescs() currentTokenRange = tokenRange; sizeOfMethodDescs = 0; + methodDescCount = 0; } sizeOfMethodDescs += size; + methodDescCount += currentSlotMethodDescCount; } if (sizeOfMethodDescs != 0)