From a5087edc95a1c40ded5f439e95eb366962b71b5e Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Wed, 31 Jan 2024 22:12:03 +0200 Subject: [PATCH 1/6] Spanify ILReader * Make ILReader ref struct, only holding IL body bytes and a offset * Use BinaryPrimitives instead of manual bit-shifting * Remove unused ILStreamReader.cs * Make ReadMIbcGroup return List instead of using enumerator --- .../tools/Common/TypeSystem/IL/ILReader.cs | 69 +++---- .../Compiler/Dataflow/MethodBodyScanner.cs | 3 +- .../Compiler/ILStreamReader.cs | 181 ------------------ .../ILCompiler.Compiler.csproj | 1 - .../IBC/MIbcProfileParser.cs | 8 +- 5 files changed, 36 insertions(+), 226 deletions(-) delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILStreamReader.cs diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILReader.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILReader.cs index d0022a5bad78be..3e2b5cd7aa0251 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILReader.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILReader.cs @@ -1,42 +1,27 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Buffers.Binary; + using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; namespace Internal.IL { - internal struct ILReader + internal ref struct ILReader { private int _currentOffset; - private readonly byte[] _ilBytes; + private readonly ReadOnlySpan _ilBytes; - public int Offset - { - get - { - return _currentOffset; - } - } + public readonly int Offset => _currentOffset; - public int Size - { - get - { - return _ilBytes.Length; - } - } + public readonly int Size => _ilBytes.Length; - public bool HasNext - { - get - { - return _currentOffset < _ilBytes.Length; - } - } + public readonly bool HasNext => _currentOffset < _ilBytes.Length; - public ILReader(byte[] ilBytes, int currentOffset = 0) + public ILReader(ReadOnlySpan ilBytes, int currentOffset = 0) { _ilBytes = ilBytes; _currentOffset = currentOffset; @@ -56,22 +41,20 @@ public byte ReadILByte() public ushort ReadILUInt16() { - if (_currentOffset + 2 > _ilBytes.Length) + if (!BinaryPrimitives.TryReadUInt16LittleEndian(_ilBytes.Slice(_currentOffset), out ushort value)) ThrowHelper.ThrowInvalidProgramException(); - ushort val = (ushort)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8)); - _currentOffset += 2; - return val; + _currentOffset += sizeof(ushort); + return value; } public uint ReadILUInt32() { - if (_currentOffset + 4 > _ilBytes.Length) + if (!BinaryPrimitives.TryReadUInt32LittleEndian(_ilBytes.Slice(_currentOffset), out uint value)) ThrowHelper.ThrowInvalidProgramException(); - uint val = (uint)(_ilBytes[_currentOffset] + (_ilBytes[_currentOffset + 1] << 8) + (_ilBytes[_currentOffset + 2] << 16) + (_ilBytes[_currentOffset + 3] << 24)); - _currentOffset += 4; - return val; + _currentOffset += sizeof(uint); + return value; } public int ReadILToken() @@ -81,21 +64,29 @@ public int ReadILToken() public ulong ReadILUInt64() { - ulong value = ReadILUInt32(); - value |= (((ulong)ReadILUInt32()) << 32); + if (!BinaryPrimitives.TryReadUInt64LittleEndian(_ilBytes.Slice(_currentOffset), out ulong value)) + ThrowHelper.ThrowInvalidProgramException(); + + _currentOffset += sizeof(ulong); return value; } - public unsafe float ReadILFloat() + public float ReadILFloat() { - uint value = ReadILUInt32(); - return *(float*)(&value); + if (!BinaryPrimitives.TryReadSingleLittleEndian(_ilBytes.Slice(_currentOffset), out float value)) + ThrowHelper.ThrowInvalidProgramException(); + + _currentOffset += sizeof(float); + return value; } public unsafe double ReadILDouble() { - ulong value = ReadILUInt64(); - return *(double*)(&value); + if (!BinaryPrimitives.TryReadDoubleLittleEndian(_ilBytes.Slice(_currentOffset), out double value)) + ThrowHelper.ThrowInvalidProgramException(); + + _currentOffset += sizeof(double); + return value; } public ILOpcode ReadILOpcode() diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs index 13a55993c829ea..87764b54a3d738 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodBodyScanner.cs @@ -188,8 +188,7 @@ public int MoveNext(int offset) _foundEndOfPrevBlock = false; } - var reader = new ILReader(_methodBody.GetILBytes()); - reader.Seek(offset); + var reader = new ILReader(_methodBody.GetILBytes(), offset); ILOpcode opcode = reader.ReadILOpcode(); if (opcode.IsControlFlowInstruction()) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILStreamReader.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILStreamReader.cs deleted file mode 100644 index 8238d72a3f8a33..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILStreamReader.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; - -using Internal.TypeSystem; -using Internal.IL; - -namespace Internal.Compiler -{ - /// - /// IL Opcode reader in external reader style where the reading is done by trying to read - /// various opcodes, and the reader can indicate success or failure of reading a particular opcode - /// - /// Used by logic which is designed to encode information in il structure, but not used - /// to support general compilation of IL. - /// - public struct ILStreamReader - { - private ILReader _reader; - private readonly MethodIL _methodIL; - - public ILStreamReader(MethodIL methodIL) - { - _methodIL = methodIL; - _reader = new ILReader(methodIL.GetILBytes()); - } - - public bool HasNextInstruction - { - get - { - return _reader.HasNext; - } - } - - public bool TryReadLdtoken(out int token) - { - if (_reader.PeekILOpcode() != ILOpcode.ldtoken) - { - token = 0; - return false; - } - - _reader.ReadILOpcode(); - token = _reader.ReadILToken(); - return true; - } - - public int ReadLdtoken() - { - int result; - if (!TryReadLdtoken(out result)) - throw new BadImageFormatException(); - - return result; - } - - public bool TryReadLdtokenAsTypeSystemEntity(out TypeSystemEntity entity) - { - int token; - bool tokenResolved; - try - { - tokenResolved = TryReadLdtoken(out token); - entity = tokenResolved ? (TypeSystemEntity)_methodIL.GetObject(token) : null; - } - catch (TypeSystemException) - { - tokenResolved = false; - entity = null; - } - - return tokenResolved; - } - - public TypeSystemEntity ReadLdtokenAsTypeSystemEntity() - { - TypeSystemEntity result; - if (!TryReadLdtokenAsTypeSystemEntity(out result)) - throw new BadImageFormatException(); - - return result; - } - - public bool TryReadLdcI4(out int value) - { - ILOpcode opcode = _reader.PeekILOpcode(); - - if (opcode == ILOpcode.ldc_i4) // ldc.i4 - { - _reader.ReadILOpcode(); - value = unchecked((int)_reader.ReadILUInt32()); - return true; - } - - if ((opcode >= ILOpcode.ldc_i4_m1) && (opcode <= ILOpcode.ldc_i4_8)) // ldc.m1 to ldc.i4.8 - { - _reader.ReadILOpcode(); - value = -1 + ((int)opcode) - 0x15; - return true; - } - - if (opcode == ILOpcode.ldc_i4_s) // ldc.i4.s - { - _reader.ReadILOpcode(); - - value = (int)unchecked((sbyte)_reader.ReadILByte()); - return true; - } - value = 0; - return false; - } - - public int ReadLdcI4() - { - int result; - if (!TryReadLdcI4(out result)) - throw new BadImageFormatException(); - - return result; - } - - public bool TryReadRet() - { - ILOpcode opcode = _reader.PeekILOpcode(); - if (opcode == ILOpcode.ret) - { - _reader.ReadILOpcode(); - return true; - } - return false; - } - - public void ReadRet() - { - if (!TryReadRet()) - throw new BadImageFormatException(); - } - - public bool TryReadPop() - { - ILOpcode opcode = _reader.PeekILOpcode(); - if (opcode == ILOpcode.pop) - { - _reader.ReadILOpcode(); - return true; - } - return false; - } - - public void ReadPop() - { - if (!TryReadPop()) - throw new BadImageFormatException(); - } - - public bool TryReadLdstr(out string ldstrString) - { - if (_reader.PeekILOpcode() != ILOpcode.ldstr) - { - ldstrString = null; - return false; - } - - _reader.ReadILOpcode(); - int token = _reader.ReadILToken(); - ldstrString = (string)_methodIL.GetObject(token); - return true; - } - - public string ReadLdstr() - { - string result; - if (!TryReadLdstr(out result)) - throw new BadImageFormatException(); - - return result; - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 52a6e15a013178..ebf936fd2eab2a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -478,7 +478,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs index 28b327ace002eb..dca94d90a3fe52 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs @@ -353,7 +353,7 @@ private enum MibcGroupParseState /// /// This format is designed to be extensible to hold more data as we add new per method profile data without breaking existing parsers. /// - private static IEnumerable ReadMIbcGroup(EcmaMethod method) + private static List ReadMIbcGroup(EcmaMethod method) { EcmaMethodIL ilBody = EcmaMethodIL.Create(method); MetadataLoaderForPgoData metadataLoader = new MetadataLoaderForPgoData(ilBody); @@ -369,6 +369,7 @@ private static IEnumerable ReadMIbcGroup(EcmaMethod method) Dictionary weights = null; List instrumentationDataLongs = null; PgoSchemaElem[] pgoSchemaData = null; + var methodProfileData = new List(); while (ilReader.HasNext) { @@ -552,8 +553,7 @@ private static IEnumerable ReadMIbcGroup(EcmaMethod method) if (methodInProgress != null) { // If the method being loaded didn't have meaningful input, skip - MethodProfileData mibcData = new MethodProfileData((MethodDesc)methodInProgress, MethodProfilingDataFlags.ReadMethodCode, exclusiveWeight, weights, 0xFFFFFFFF, pgoSchemaData); - yield return mibcData; + methodProfileData.Add(new MethodProfileData((MethodDesc)methodInProgress, MethodProfilingDataFlags.ReadMethodCode, exclusiveWeight, weights, 0xFFFFFFFF, pgoSchemaData)); } state = MibcGroupParseState.LookingForNextMethod; exclusiveWeight = 0; @@ -608,6 +608,8 @@ private static IEnumerable ReadMIbcGroup(EcmaMethod method) } } } + + return methodProfileData; } /// From 19ed77becfbd69bf47fd39341cb59eaca375d6dc Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Wed, 31 Jan 2024 23:12:23 +0200 Subject: [PATCH 2/6] Spanify ILStackHelper --- .../Common/TypeSystem/IL/ILStackHelper.cs | 56 ++++++------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs index 1204f1b6655f34..81786d1dee090a 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs @@ -25,16 +25,16 @@ public static void CheckStackBalance(this MethodIL methodIL) public static int ComputeMaxStack(this MethodIL methodIL) { const int StackHeightNotSet = int.MinValue; + const int StackAllocThreshold = 256 / sizeof(int); - byte[] ilbytes = methodIL.GetILBytes(); - int currentOffset = 0; + var ilReader = new ILReader(methodIL.GetILBytes()); int stackHeight = 0; int maxStack = 0; - // TODO: Use Span for this and stackalloc the array if reasonably sized - int[] stackHeights = new int[ilbytes.Length]; - for (int i = 0; i < stackHeights.Length; i++) - stackHeights[i] = StackHeightNotSet; + Span stackHeights = ilReader.Size <= StackAllocThreshold ? + stackalloc int[StackAllocThreshold].Slice(0, ilReader.Size) : new int[ilReader.Size]; + + stackHeights.Fill(StackHeightNotSet); // Catch and filter clauses have a known non-zero stack height. foreach (ILExceptionRegion region in methodIL.GetExceptionRegions()) @@ -50,11 +50,10 @@ public static int ComputeMaxStack(this MethodIL methodIL) } } - while (currentOffset < ilbytes.Length) + while (ilReader.HasNext) { - ILOpcode opcode = (ILOpcode)ilbytes[currentOffset]; - if (opcode == ILOpcode.prefix1) - opcode = 0x100 + (ILOpcode)ilbytes[currentOffset + 1]; + int currentOffset = ilReader.Offset; + ILOpcode opcode = ilReader.ReadILOpcode(); // The stack height could be unknown if the previous instruction // was an unconditional control transfer. @@ -73,7 +72,6 @@ public static int ComputeMaxStack(this MethodIL methodIL) || stackHeights[currentOffset] == stackHeight); stackHeights[currentOffset] = stackHeight; - bool isVariableSize = false; switch (opcode) { case ILOpcode.arglist: @@ -168,6 +166,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.stloc_2: case ILOpcode.stloc_3: case ILOpcode.stloc_s: + case ILOpcode.switch_: Debug.Assert(stackHeight > 0); stackHeight -= 1; break; @@ -192,7 +191,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.blt_un: case ILOpcode.bne_un: { - int target = currentOffset + ReadInt32(ilbytes, currentOffset + 1) + 5; + int target = currentOffset + (int)ilReader.ReadILUInt32() + 5; int adjustment; bool isConditional; @@ -243,7 +242,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.blt_un_s: case ILOpcode.bne_un_s: { - int target = currentOffset + (sbyte)ilbytes[currentOffset + 1] + 2; + int target = currentOffset + (sbyte)ilReader.ReadILByte() + 2; int adjustment; bool isConditional; @@ -284,11 +283,9 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.callvirt: case ILOpcode.newobj: { - int token = ReadILToken(ilbytes, currentOffset + 1); - object obj = methodIL.GetObject(token); - MethodSignature sig = obj is MethodSignature ? - (MethodSignature)obj : - ((MethodDesc)obj).Signature; + object obj = methodIL.GetObject(ilReader.ReadILToken()); + MethodSignature sig = obj is MethodSignature methodSignature ? + methodSignature : ((MethodDesc)obj).Signature; int adjustment = sig.Length; if (opcode == ILOpcode.newobj) { @@ -436,38 +433,17 @@ public static int ComputeMaxStack(this MethodIL methodIL) Debug.Assert(stackHeight > 0); break; - case ILOpcode.switch_: - Debug.Assert(stackHeight > 0); - isVariableSize = true; - stackHeight -= 1; - currentOffset += 1 + (ReadInt32(ilbytes, currentOffset + 1) * 4) + 4; - break; - default: Debug.Fail("Unknown instruction"); break; } - if (!isVariableSize) - currentOffset += opcode.GetSize(); + ilReader.Skip(opcode); maxStack = Math.Max(maxStack, stackHeight); } return maxStack; } - - private static int ReadInt32(byte[] ilBytes, int offset) - { - return ilBytes[offset] - + (ilBytes[offset + 1] << 8) - + (ilBytes[offset + 2] << 16) - + (ilBytes[offset + 3] << 24); - } - - private static int ReadILToken(byte[] ilBytes, int offset) - { - return ReadInt32(ilBytes, offset); - } } } From 04138758339b51606b875aab682f7c59ba3f0514 Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Thu, 1 Feb 2024 00:30:19 +0200 Subject: [PATCH 3/6] Use built-in Read7BitEncodedInt * Remove ReaderExtensions.cs from ILCompiler.Ryujit --- .../IBC/IBCDataReader.cs | 6 +-- .../IBC/ReaderExtensions.cs | 48 ------------------- .../ILCompiler.RyuJit.csproj | 1 - 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCDataReader.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCDataReader.cs index fffa41f08168ec..1893a39680c6e1 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCDataReader.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCDataReader.cs @@ -39,7 +39,7 @@ uint ReadTokenWithMemory(ref uint lastToken) return reader.ReadUInt32(); } - uint current = reader.Read7BitEncodedUInt(); + uint current = (uint)reader.Read7BitEncodedInt(); byte highByte = (byte)(current >> 24); uint result; @@ -116,7 +116,7 @@ private int ReadSmallInt() private uint ReadSmallUInt() { - return minified ? reader.Read7BitEncodedUInt() : reader.ReadUInt32(); + return minified ? (uint)reader.Read7BitEncodedInt() : reader.ReadUInt32(); } #endregion @@ -327,7 +327,7 @@ IBC.MethodData ReadMethod() if (minified) { - uint firstBlockHitCount = reader.Read7BitEncodedUInt(); + uint firstBlockHitCount = (uint)reader.Read7BitEncodedInt(); result.BasicBlocks.Add(new IBC.BasicBlockData { ILOffset = 0, ExecutionCount = firstBlockHitCount }); } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/ReaderExtensions.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/ReaderExtensions.cs index 711fbf9906a2c8..86639b89e72d40 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/ReaderExtensions.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/ReaderExtensions.cs @@ -39,36 +39,6 @@ public static string ReadEncodedString(this BinaryReader reader, int length) return new string(characters, 0, length - 1); } - - // BinaryReader.Read7BitEncodedInt is protected internal, so its - // implementation is duplicated here. - public static int Read7BitEncodedInt(this BinaryReader reader) - { - int result = 0; - int shift = 0; - byte current; - do - { - current = reader.ReadByte(); - - result |= (current & 0x7f) << shift; - - shift += 7; - } - while ((shift <= 28) && ((current & 0x80) != 0)); - - if ((current & 0x80) != 0) - { - throw new InvalidDataException("Improperly encoded integer"); - } - - return result; - } - - public static uint Read7BitEncodedUInt(this BinaryReader reader) - { - return (uint)reader.Read7BitEncodedInt(); - } } public static class WriterExtensions @@ -92,23 +62,5 @@ public static void WriteEncodedString(this BinaryWriter writer, string s) writer.Write((short)'\0'); } - - // BinaryWriter.Write7BitEncodedInt is protected internal, so its - // implementation is duplicated here. - public static void Write7BitEncodedInt(this BinaryWriter writer, uint i) - { - while (i > 0x7f) - { - writer.Write((byte)(i | 0x80)); - i >>= 7; - } - - writer.Write((byte)i); - } - - public static void Write7BitEncodedInt(this BinaryWriter writer, int i) - { - writer.Write7BitEncodedInt((uint)i); - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj index 4e1c8859136abe..d7d809d2d9efdb 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj @@ -97,7 +97,6 @@ - From 80b6d4b90aabdd40eefd87dbc9b21b9c1c2a7183 Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Thu, 1 Feb 2024 02:49:23 +0200 Subject: [PATCH 4/6] Fix ILStackHelper regression * Use ILReader.ReadBranchDestination to merge two switch branches --- .../Common/TypeSystem/IL/ILStackHelper.cs | 50 ++++--------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs index 81786d1dee090a..19d5ccb0b5aad8 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs @@ -72,6 +72,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) || stackHeights[currentOffset] == stackHeight); stackHeights[currentOffset] = stackHeight; + bool hasReadOperand = false; switch (opcode) { case ILOpcode.arglist: @@ -190,43 +191,6 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.blt: case ILOpcode.blt_un: case ILOpcode.bne_un: - { - int target = currentOffset + (int)ilReader.ReadILUInt32() + 5; - - int adjustment; - bool isConditional; - if (opcode == ILOpcode.br || opcode == ILOpcode.leave) - { - isConditional = false; - adjustment = 0; - } - else if (opcode == ILOpcode.brfalse || opcode == ILOpcode.brtrue) - { - isConditional = true; - adjustment = 1; - } - else - { - isConditional = true; - adjustment = 2; - } - - Debug.Assert(stackHeight >= adjustment); - stackHeight -= adjustment; - - Debug.Assert(stackHeights[target] == StackHeightNotSet - || stackHeights[target] == stackHeight); - - // Forward branch carries information about stack height at a future - // offset. We need to remember it. - if (target > currentOffset) - stackHeights[target] = stackHeight; - - if (!isConditional) - stackHeight = StackHeightNotSet; - } - break; - case ILOpcode.br_s: case ILOpcode.leave_s: case ILOpcode.brfalse_s: @@ -242,16 +206,17 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.blt_un_s: case ILOpcode.bne_un_s: { - int target = currentOffset + (sbyte)ilReader.ReadILByte() + 2; + int target = ilReader.ReadBranchDestination(opcode); + hasReadOperand = true; int adjustment; bool isConditional; - if (opcode == ILOpcode.br_s || opcode == ILOpcode.leave_s) + if (opcode is ILOpcode.br or ILOpcode.br_s or ILOpcode.leave or ILOpcode.leave_s) { isConditional = false; adjustment = 0; } - else if (opcode == ILOpcode.brfalse_s || opcode == ILOpcode.brtrue_s) + else if (opcode is ILOpcode.brfalse or ILOpcode.brfalse_s or ILOpcode.brtrue_s or ILOpcode.brtrue) { isConditional = true; adjustment = 1; @@ -284,6 +249,8 @@ public static int ComputeMaxStack(this MethodIL methodIL) case ILOpcode.newobj: { object obj = methodIL.GetObject(ilReader.ReadILToken()); + hasReadOperand = true; + MethodSignature sig = obj is MethodSignature methodSignature ? methodSignature : ((MethodDesc)obj).Signature; int adjustment = sig.Length; @@ -438,7 +405,8 @@ public static int ComputeMaxStack(this MethodIL methodIL) break; } - ilReader.Skip(opcode); + if (!hasReadOperand) + ilReader.Skip(opcode); maxStack = Math.Max(maxStack, stackHeight); } From f40fcacfb2acdcaa880ad4988fc12c0f0ae21429 Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Thu, 1 Feb 2024 16:50:03 +0200 Subject: [PATCH 5/6] Use short to represent the stack height --- .../tools/Common/TypeSystem/IL/ILStackHelper.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs index 19d5ccb0b5aad8..367fe8e30a797f 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs @@ -24,15 +24,15 @@ public static void CheckStackBalance(this MethodIL methodIL) /// public static int ComputeMaxStack(this MethodIL methodIL) { - const int StackHeightNotSet = int.MinValue; - const int StackAllocThreshold = 256 / sizeof(int); + const short StackHeightNotSet = short.MinValue; + const int StackallocThreshold = 256 / sizeof(short); var ilReader = new ILReader(methodIL.GetILBytes()); - int stackHeight = 0; - int maxStack = 0; + short stackHeight = 0; + short maxStack = 0; - Span stackHeights = ilReader.Size <= StackAllocThreshold ? - stackalloc int[StackAllocThreshold].Slice(0, ilReader.Size) : new int[ilReader.Size]; + Span stackHeights = ilReader.Size <= StackallocThreshold ? + stackalloc short[StackallocThreshold].Slice(0, ilReader.Size) : new short[ilReader.Size]; stackHeights.Fill(StackHeightNotSet); @@ -209,7 +209,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) int target = ilReader.ReadBranchDestination(opcode); hasReadOperand = true; - int adjustment; + short adjustment; bool isConditional; if (opcode is ILOpcode.br or ILOpcode.br_s or ILOpcode.leave or ILOpcode.leave_s) { @@ -253,7 +253,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) MethodSignature sig = obj is MethodSignature methodSignature ? methodSignature : ((MethodDesc)obj).Signature; - int adjustment = sig.Length; + short adjustment = (short)sig.Length; if (opcode == ILOpcode.newobj) { adjustment--; From d6b2b334eb09f44f2e44e76b4157c1b003b9d98a Mon Sep 17 00:00:00 2001 From: PaulusParssinen Date: Thu, 1 Feb 2024 17:19:55 +0200 Subject: [PATCH 6/6] Revert "Use short to represent the stack height" This reverts commit f40fcacfb2acdcaa880ad4988fc12c0f0ae21429. --- .../tools/Common/TypeSystem/IL/ILStackHelper.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs index 367fe8e30a797f..19d5ccb0b5aad8 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/ILStackHelper.cs @@ -24,15 +24,15 @@ public static void CheckStackBalance(this MethodIL methodIL) /// public static int ComputeMaxStack(this MethodIL methodIL) { - const short StackHeightNotSet = short.MinValue; - const int StackallocThreshold = 256 / sizeof(short); + const int StackHeightNotSet = int.MinValue; + const int StackAllocThreshold = 256 / sizeof(int); var ilReader = new ILReader(methodIL.GetILBytes()); - short stackHeight = 0; - short maxStack = 0; + int stackHeight = 0; + int maxStack = 0; - Span stackHeights = ilReader.Size <= StackallocThreshold ? - stackalloc short[StackallocThreshold].Slice(0, ilReader.Size) : new short[ilReader.Size]; + Span stackHeights = ilReader.Size <= StackAllocThreshold ? + stackalloc int[StackAllocThreshold].Slice(0, ilReader.Size) : new int[ilReader.Size]; stackHeights.Fill(StackHeightNotSet); @@ -209,7 +209,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) int target = ilReader.ReadBranchDestination(opcode); hasReadOperand = true; - short adjustment; + int adjustment; bool isConditional; if (opcode is ILOpcode.br or ILOpcode.br_s or ILOpcode.leave or ILOpcode.leave_s) { @@ -253,7 +253,7 @@ public static int ComputeMaxStack(this MethodIL methodIL) MethodSignature sig = obj is MethodSignature methodSignature ? methodSignature : ((MethodDesc)obj).Signature; - short adjustment = (short)sig.Length; + int adjustment = sig.Length; if (opcode == ILOpcode.newobj) { adjustment--;