From 77a5f9cef77c34db739bb3c13bfd091c693a12d4 Mon Sep 17 00:00:00 2001 From: Benjamin Bartels Date: Mon, 15 Apr 2019 23:09:10 +0100 Subject: [PATCH] Improved performance of System.Reflection.Emit API (#23833) * Improved performance of System.Reflection.Emit API * Moved heap allocation to stack * Eliminating conditional branch by casting sbyte to byte * Reduced heap allocation of ScopeTree * Removed redundant `unsafe` from function signature --- .../Reflection/Emit/CustomAttributeBuilder.cs | 19 +- .../System/Reflection/Emit/DynamicILGenerator.cs | 6 +- .../src/System/Reflection/Emit/ILGenerator.cs | 387 +++++++-------------- .../src/System/Reflection/Emit/SignatureHelper.cs | 19 +- 4 files changed, 150 insertions(+), 281 deletions(-) diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs index c3da6cc..ff3ccd6 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs @@ -14,12 +14,9 @@ ===========================================================*/ -using System; -using System.Reflection; +using System.Buffers.Binary; using System.IO; using System.Text; -using System.Runtime.InteropServices; -using System.Globalization; using System.Diagnostics; namespace System.Reflection.Emit @@ -305,7 +302,7 @@ namespace System.Reflection.Emit } } - private void EmitType(BinaryWriter writer, Type type) + private static void EmitType(BinaryWriter writer, Type type) { if (type.IsPrimitive) { @@ -377,7 +374,7 @@ namespace System.Reflection.Emit } } - private void EmitString(BinaryWriter writer, string str) + private static void EmitString(BinaryWriter writer, string str) { // Strings are emitted with a length prefix in a compressed format (1, 2 or 4 bytes) as used internally by metadata. byte[] utf8Str = Encoding.UTF8.GetBytes(str); @@ -388,20 +385,16 @@ namespace System.Reflection.Emit } else if (length <= 0x3fff) { - writer.Write((byte)((length >> 8) | 0x80)); - writer.Write((byte)(length & 0xff)); + writer.Write(BinaryPrimitives.ReverseEndianness((short)(length | 0x80_00))); } else { - writer.Write((byte)((length >> 24) | 0xc0)); - writer.Write((byte)((length >> 16) & 0xff)); - writer.Write((byte)((length >> 8) & 0xff)); - writer.Write((byte)(length & 0xff)); + writer.Write(BinaryPrimitives.ReverseEndianness(length | 0xC0_00_00_00)); } writer.Write(utf8Str); } - private void EmitValue(BinaryWriter writer, Type type, object value) + private static void EmitValue(BinaryWriter writer, Type type, object value) { if (type.IsEnum) { diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index aee47df..fb763a5 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -7,6 +7,7 @@ namespace System.Reflection.Emit { using System; + using System.Buffers.Binary; using System.Globalization; using System.Diagnostics.SymbolStore; using System.Runtime.InteropServices; @@ -723,10 +724,7 @@ namespace System.Reflection.Emit if ((header & 0x40) != 0) // Fat { - byte[] size = new byte[4]; - for (int q = 0; q < 3; q++) - size[q] = m_exceptionHeader[q + 1]; - EHCount = (BitConverter.ToInt32(size, 0) - 4) / 24; + EHCount = (BinaryPrimitives.ReadInt32LittleEndian(m_exceptionHeader.AsSpan(1)) - 4) / 24; } else EHCount = (m_exceptionHeader[1] - 2) / 12; diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index 6de54f3..47c20c9 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -4,20 +4,18 @@ // -using System; +using System.Buffers.Binary; +using System.Diagnostics; using System.Diagnostics.SymbolStore; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Reflection; -using System.Globalization; -using System.Diagnostics; -using System.Diagnostics.Contracts; namespace System.Reflection.Emit { public class ILGenerator { #region Const Members - private const int defaultSize = 16; + private const int DefaultSize = 16; private const int DefaultFixupArraySize = 8; private const int DefaultLabelArraySize = 4; private const int DefaultExceptionArraySize = 2; @@ -38,19 +36,6 @@ namespace System.Reflection.Emit return temp; } - private static byte[] EnlargeArray(byte[] incoming) - { - return EnlargeArray(incoming, incoming.Length * 2); - } - - private static byte[] EnlargeArray(byte[] incoming, int requiredSize) - { - Debug.Assert(incoming != null); - - byte[] temp = new byte[requiredSize]; - Buffer.BlockCopy(incoming, 0, temp, 0, incoming.Length); - return temp; - } #endregion #region Internal Data Members @@ -84,15 +69,10 @@ namespace System.Reflection.Emit private int m_maxMidStack = 0; // Maximum stack size for a given basic block. private int m_maxMidStackCur = 0; // Running count of the maximum stack size for the current basic block. - internal int CurrExcStackCount - { - get { return m_currExcStackCount; } - } + internal int CurrExcStackCount => m_currExcStackCount; + + internal __ExceptionInfo[] CurrExcStack => m_currExcStack; - internal __ExceptionInfo[] CurrExcStack - { - get { return m_currExcStack; } - } #endregion #region Constructor @@ -107,14 +87,7 @@ namespace System.Reflection.Emit Debug.Assert(methodBuilder != null); Debug.Assert(methodBuilder is MethodBuilder || methodBuilder is DynamicMethod); - if (size < defaultSize) - { - m_ILStream = new byte[defaultSize]; - } - else - { - m_ILStream = new byte[size]; - } + m_ILStream = new byte[Math.Max(size, DefaultSize)]; m_length = 0; @@ -140,10 +113,7 @@ namespace System.Reflection.Emit // initialize local signature m_localCount = 0; MethodBuilder mb = m_methodBuilder as MethodBuilder; - if (mb == null) - m_localSignature = SignatureHelper.GetLocalVarSigHelper(null); - else - m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb.GetTypeBuilder().Module); + m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb?.GetTypeBuilder().Module); } #endregion @@ -161,16 +131,21 @@ namespace System.Reflection.Emit internal void InternalEmit(OpCode opcode) { + short opcodeValue = opcode.Value; if (opcode.Size != 1) { - m_ILStream[m_length++] = (byte)(opcode.Value >> 8); + BinaryPrimitives.WriteInt16BigEndian(m_ILStream.AsSpan(m_length), opcodeValue); + m_length += 2; + } + else + { + m_ILStream[m_length++] = (byte)opcodeValue; } - - m_ILStream[m_length++] = (byte)opcode.Value; UpdateStackSize(opcode, opcode.StackChange()); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void UpdateStackSize(OpCode opcode, int stackchange) { // Updates internal variables for keeping track of the stack size @@ -223,57 +198,45 @@ namespace System.Reflection.Emit // BakeByteArray is an internal function designed to be called by MethodBuilder to do // all of the fixups and return a new byte array representing the byte stream with labels resolved, etc. - int newSize; - int updateAddr; - byte[] newBytes; - if (m_currExcStackCount != 0) { throw new ArgumentException(SR.Argument_UnclosedExceptionBlock); } + if (m_length == 0) return null; - //Calculate the size of the new array. - newSize = m_length; - //Allocate space for the new array. - newBytes = new byte[newSize]; + byte[] newBytes = new byte[m_length]; //Copy the data from the old array - Buffer.BlockCopy(m_ILStream, 0, newBytes, 0, newSize); + Array.Copy(m_ILStream, 0, newBytes, 0, m_length); //Do the fixups. //This involves iterating over all of the labels and //replacing them with their proper values. for (int i = 0; i < m_fixupCount; i++) { - updateAddr = GetLabelPos(m_fixupData[i].m_fixupLabel) - (m_fixupData[i].m_fixupPos + m_fixupData[i].m_fixupInstSize); + __FixupData fixupData = m_fixupData[i]; + int updateAddr = GetLabelPos(fixupData.m_fixupLabel) - (fixupData.m_fixupPos + fixupData.m_fixupInstSize); //Handle single byte instructions //Throw an exception if they're trying to store a jump in a single byte instruction that doesn't fit. - if (m_fixupData[i].m_fixupInstSize == 1) + if (fixupData.m_fixupInstSize == 1) { //Verify that our one-byte arg will fit into a Signed Byte. if (updateAddr < sbyte.MinValue || updateAddr > sbyte.MaxValue) { - throw new NotSupportedException(SR.Format(SR.NotSupported_IllegalOneByteBranch, m_fixupData[i].m_fixupPos, updateAddr)); + throw new NotSupportedException(SR.Format(SR.NotSupported_IllegalOneByteBranch, fixupData.m_fixupPos, updateAddr)); } //Place the one-byte arg - if (updateAddr < 0) - { - newBytes[m_fixupData[i].m_fixupPos] = (byte)(256 + updateAddr); - } - else - { - newBytes[m_fixupData[i].m_fixupPos] = (byte)updateAddr; - } + newBytes[fixupData.m_fixupPos] = (byte)updateAddr; } else { //Place the four-byte arg - PutInteger4InArray(updateAddr, m_fixupData[i].m_fixupPos, newBytes); + BinaryPrimitives.WriteInt32LittleEndian(newBytes.AsSpan(fixupData.m_fixupPos), updateAddr); } } return newBytes; @@ -281,7 +244,6 @@ namespace System.Reflection.Emit internal __ExceptionInfo[] GetExceptions() { - __ExceptionInfo[] temp; if (m_currExcStackCount != 0) { throw new NotSupportedException(SR.Argument_UnclosedExceptionBlock); @@ -292,7 +254,7 @@ namespace System.Reflection.Emit return null; } - temp = new __ExceptionInfo[m_exceptionCount]; + var temp = new __ExceptionInfo[m_exceptionCount]; Array.Copy(m_exceptions, 0, temp, 0, m_exceptionCount); SortExceptions(temp); return temp; @@ -303,31 +265,22 @@ namespace System.Reflection.Emit // Guarantees an array capable of holding at least size elements. if (m_length + size >= m_ILStream.Length) { - if (m_length + size >= 2 * m_ILStream.Length) - { - m_ILStream = EnlargeArray(m_ILStream, m_length + size); - } - else - { - m_ILStream = EnlargeArray(m_ILStream); - } + IncreaseCapacity(size); } } - internal void PutInteger4(int value) + private void IncreaseCapacity(int size) { - m_length = PutInteger4InArray(value, m_length, m_ILStream); + byte[] temp = new byte[Math.Max(m_ILStream.Length * 2, m_length + size)]; + Array.Copy(m_ILStream, 0, temp, 0, m_ILStream.Length); + m_ILStream = temp; } - private static int PutInteger4InArray(int value, int startPos, byte[] array) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void PutInteger4(int value) { - // Puts an Int32 onto the stream. This is an internal routine, so it does not do any error checking. - - array[startPos++] = (byte)value; - array[startPos++] = (byte)(value >> 8); - array[startPos++] = (byte)(value >> 16); - array[startPos++] = (byte)(value >> 24); - return startPos; + BinaryPrimitives.WriteInt32LittleEndian(m_ILStream.AsSpan(m_length), value); + m_length += 4; } private int GetLabelPos(Label lbl) @@ -360,11 +313,12 @@ namespace System.Reflection.Emit m_fixupData = EnlargeArray(m_fixupData); } - m_fixupData[m_fixupCount].m_fixupPos = pos; - m_fixupData[m_fixupCount].m_fixupLabel = lbl; - m_fixupData[m_fixupCount].m_fixupInstSize = instSize; - - m_fixupCount++; + m_fixupData[m_fixupCount++] = new __FixupData + { + m_fixupPos = pos, + m_fixupLabel = lbl, + m_fixupInstSize = instSize + }; } internal int GetMaxStackSize() @@ -428,17 +382,9 @@ namespace System.Reflection.Emit public void Emit(OpCode opcode, sbyte arg) { // Puts opcode onto the stream of instructions followed by arg - EnsureCapacity(4); InternalEmit(opcode); - if (arg < 0) - { - m_ILStream[m_length++] = (byte)(256 + arg); - } - else - { - m_ILStream[m_length++] = (byte)arg; - } + m_ILStream[m_length++] = (byte)arg; } public virtual void Emit(OpCode opcode, short arg) @@ -446,8 +392,8 @@ namespace System.Reflection.Emit // Puts opcode onto the stream of instructions followed by arg EnsureCapacity(5); InternalEmit(opcode); - m_ILStream[m_length++] = (byte)arg; - m_ILStream[m_length++] = (byte)(arg >> 8); + BinaryPrimitives.WriteInt16LittleEndian(m_ILStream.AsSpan(m_length), arg); + m_length += 2; } public virtual void Emit(OpCode opcode, int arg) @@ -469,8 +415,6 @@ namespace System.Reflection.Emit } else { - int stackchange = 0; - // Reflection doesn't distinguish between these two concepts: // 1. A generic method definition: Foo`1 // 2. A generic method definition instantiated over its own generic arguments: Foo`1 @@ -481,18 +425,16 @@ namespace System.Reflection.Emit EnsureCapacity(7); InternalEmit(opcode); - UpdateStackSize(opcode, stackchange); + UpdateStackSize(opcode, 0); RecordTokenFixup(); PutInteger4(tk); } } - public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) { int stackchange = 0; - SignatureHelper sig; if (optionalParameterTypes != null) { if ((callingConvention & CallingConventions.VarArgs) == 0) @@ -503,10 +445,10 @@ namespace System.Reflection.Emit } ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; - sig = GetMemberRefSignature(callingConvention, - returnType, - parameterTypes, - optionalParameterTypes); + SignatureHelper sig = GetMemberRefSignature(callingConvention, + returnType, + parameterTypes, + optionalParameterTypes); EnsureCapacity(7); Emit(OpCodes.Calli); @@ -535,8 +477,6 @@ namespace System.Reflection.Emit { int stackchange = 0; int cParams = 0; - int i; - SignatureHelper sig; ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; @@ -545,14 +485,14 @@ namespace System.Reflection.Emit cParams = parameterTypes.Length; } - sig = SignatureHelper.GetMethodSigHelper( + SignatureHelper sig = SignatureHelper.GetMethodSigHelper( modBuilder, unmanagedCallConv, returnType); if (parameterTypes != null) { - for (i = 0; i < cParams; i++) + for (int i = 0; i < cParams; i++) { sig.AddArgument(parameterTypes[i]); } @@ -693,7 +633,7 @@ namespace System.Reflection.Emit // by cls. The location of cls is recorded so that the token can be // patched if necessary when persisting the module to a PE. - int tempVal = 0; + int tempVal; ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; if (opcode == OpCodes.Ldtoken && cls != null && cls.IsGenericTypeDefinition) { @@ -717,40 +657,24 @@ namespace System.Reflection.Emit { EnsureCapacity(11); InternalEmit(opcode); - m_ILStream[m_length++] = (byte)arg; - m_ILStream[m_length++] = (byte)(arg >> 8); - m_ILStream[m_length++] = (byte)(arg >> 16); - m_ILStream[m_length++] = (byte)(arg >> 24); - m_ILStream[m_length++] = (byte)(arg >> 32); - m_ILStream[m_length++] = (byte)(arg >> 40); - m_ILStream[m_length++] = (byte)(arg >> 48); - m_ILStream[m_length++] = (byte)(arg >> 56); + BinaryPrimitives.WriteInt64LittleEndian(m_ILStream.AsSpan(m_length), arg); + m_length += 8; } - public unsafe virtual void Emit(OpCode opcode, float arg) + public virtual void Emit(OpCode opcode, float arg) { EnsureCapacity(7); InternalEmit(opcode); - uint tempVal = *(uint*)&arg; - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); - m_ILStream[m_length++] = (byte)(tempVal >> 16); - m_ILStream[m_length++] = (byte)(tempVal >> 24); + BinaryPrimitives.WriteInt32LittleEndian(m_ILStream.AsSpan(m_length), BitConverter.SingleToInt32Bits(arg)); + m_length += 4; } - public unsafe virtual void Emit(OpCode opcode, double arg) + public virtual void Emit(OpCode opcode, double arg) { EnsureCapacity(11); InternalEmit(opcode); - ulong tempVal = *(ulong*)&arg; - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); - m_ILStream[m_length++] = (byte)(tempVal >> 16); - m_ILStream[m_length++] = (byte)(tempVal >> 24); - m_ILStream[m_length++] = (byte)(tempVal >> 32); - m_ILStream[m_length++] = (byte)(tempVal >> 40); - m_ILStream[m_length++] = (byte)(tempVal >> 48); - m_ILStream[m_length++] = (byte)(tempVal >> 56); + BinaryPrimitives.WriteInt64LittleEndian(m_ILStream.AsSpan(m_length), BitConverter.DoubleToInt64Bits(arg)); + m_length += 8; } public virtual void Emit(OpCode opcode, Label label) @@ -765,15 +689,13 @@ namespace System.Reflection.Emit // verify this). Since branches are relative instructions, label will be replaced with the // correct offset to branch during the fixup process. - int tempVal = label.GetLabelValue(); EnsureCapacity(7); InternalEmit(opcode); if (OpCodes.TakesSingleByteArgument(opcode)) { - AddFixup(label, m_length, 1); - m_length++; + AddFixup(label, m_length++, 1); } else { @@ -897,10 +819,11 @@ namespace System.Reflection.Emit if (opcode.OperandType == OperandType.InlineNone) return; - else if (!OpCodes.TakesSingleByteArgument(opcode)) + + if (!OpCodes.TakesSingleByteArgument(opcode)) { - m_ILStream[m_length++] = (byte)tempVal; - m_ILStream[m_length++] = (byte)(tempVal >> 8); + BinaryPrimitives.WriteInt16LittleEndian(m_ILStream.AsSpan(m_length), (short)tempVal); + m_length += 2; } else { @@ -970,8 +893,7 @@ namespace System.Reflection.Emit // Pop the current exception block __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; - m_currExcStack[m_currExcStackCount - 1] = null; - m_currExcStackCount--; + m_currExcStack[--m_currExcStackCount] = null; Label endLabel = current.GetEndLabel(); int state = current.GetCurrentState(); @@ -984,23 +906,21 @@ namespace System.Reflection.Emit if (state == __ExceptionInfo.State_Catch) { - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, endLabel); } else if (state == __ExceptionInfo.State_Finally || state == __ExceptionInfo.State_Fault) { - this.Emit(OpCodes.Endfinally); + Emit(OpCodes.Endfinally); } //Check if we've already set this label. //The only reason why we might have set this is if we have a finally block. - if (m_labelList[endLabel.GetLabelValue()] == -1) - { - MarkLabel(endLabel); - } - else - { - MarkLabel(current.GetFinallyEndLabel()); - } + + Label label = m_labelList[endLabel.GetLabelValue()] != -1 + ? current.m_finallyEndLabel + : endLabel; + + MarkLabel(label); current.Done(m_length); } @@ -1014,8 +934,7 @@ namespace System.Reflection.Emit __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFilterAddr(m_length); } @@ -1037,7 +956,7 @@ namespace System.Reflection.Emit throw new ArgumentException(SR.Argument_ShouldNotSpecifyExceptionType); } - this.Emit(OpCodes.Endfilter); + Emit(OpCodes.Endfilter); } else { @@ -1047,8 +966,7 @@ namespace System.Reflection.Emit throw new ArgumentNullException(nameof(exceptionType)); } - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); } current.MarkCatchAddr(m_length, exceptionType); @@ -1063,8 +981,7 @@ namespace System.Reflection.Emit __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1]; // emit the leave for the clause before this one. - Label endLabel = current.GetEndLabel(); - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFaultAddr(m_length); } @@ -1082,18 +999,18 @@ namespace System.Reflection.Emit if (state != __ExceptionInfo.State_Try) { // generate leave for any preceeding catch clause - this.Emit(OpCodes.Leave, endLabel); + Emit(OpCodes.Leave, endLabel); catchEndAddr = m_length; } MarkLabel(endLabel); - Label finallyEndLabel = this.DefineLabel(); + Label finallyEndLabel = DefineLabel(); current.SetFinallyEndLabel(finallyEndLabel); // generate leave for try clause - this.Emit(OpCodes.Leave, finallyEndLabel); + Emit(OpCodes.Leave, finallyEndLabel); if (catchEndAddr == 0) catchEndAddr = m_length; current.MarkFinallyAddr(m_length, catchEndAddr); @@ -1164,8 +1081,8 @@ namespace System.Reflection.Emit { throw new ArgumentException(SR.Argument_MissingDefaultConstructor); } - this.Emit(OpCodes.Newobj, con); - this.Emit(OpCodes.Throw); + Emit(OpCodes.Newobj, con); + Emit(OpCodes.Throw); } private static Type GetConsoleType() @@ -1191,7 +1108,6 @@ namespace System.Reflection.Emit // one of the types for which Console.WriteLine implements overloads. (e.g. // we do *not* call ToString on the locals. - object cls; if (m_methodBuilder == null) { throw new ArgumentException(SR.InvalidOperation_BadILGeneratorUsage); @@ -1201,7 +1117,7 @@ namespace System.Reflection.Emit Emit(OpCodes.Call, prop); Emit(OpCodes.Ldloc, localBuilder); Type[] parameterTypes = new Type[1]; - cls = localBuilder.LocalType; + object cls = localBuilder.LocalType; if (cls is TypeBuilder || cls is EnumBuilder) { throw new ArgumentException(SR.NotSupported_OutputStreamUsingTypeBuilder); @@ -1223,8 +1139,6 @@ namespace System.Reflection.Emit // one of the types for which Console.WriteLine implements overloads. (e.g. // we do *not* call ToString on the fields. - object cls; - if (fld == null) { throw new ArgumentNullException(nameof(fld)); @@ -1243,7 +1157,7 @@ namespace System.Reflection.Emit Emit(OpCodes.Ldfld, fld); } Type[] parameterTypes = new Type[1]; - cls = fld.FieldType; + object cls = fld.FieldType; if (cls is TypeBuilder || cls is EnumBuilder) { throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); @@ -1270,8 +1184,6 @@ namespace System.Reflection.Emit // Declare a local of type "local". The current active lexical scope // will be the scope that local will live. - LocalBuilder localBuilder; - MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) throw new NotSupportedException(); @@ -1295,9 +1207,7 @@ namespace System.Reflection.Emit // add the localType to local signature m_localSignature.AddArgument(localType, pinned); - localBuilder = new LocalBuilder(m_localCount, localType, methodBuilder, pinned); - m_localCount++; - return localBuilder; + return new LocalBuilder(m_localCount++, localType, methodBuilder, pinned); } public virtual void UsingNamespace(string usingNamespace) @@ -1311,12 +1221,11 @@ namespace System.Reflection.Emit if (usingNamespace.Length == 0) throw new ArgumentException(SR.Argument_EmptyName, nameof(usingNamespace)); - int index; MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) throw new NotSupportedException(); - index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex(); + int index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex(); if (index == -1) { methodBuilder.m_localSymInfo.AddUsingNamespace(usingNamespace); @@ -1351,13 +1260,7 @@ namespace System.Reflection.Emit m_ScopeTree.AddScopeInfo(ScopeAction.Close, m_length); } - public virtual int ILOffset - { - get - { - return m_length; - } - } + public virtual int ILOffset => m_length; #endregion @@ -1422,7 +1325,8 @@ namespace System.Reflection.Emit Type catchClass, // catch exception type int type) // kind of clause { - if (m_currentCatch >= m_catchAddr.Length) + int currentCatch = m_currentCatch; + if (currentCatch >= m_catchAddr.Length) { m_filterAddr = ILGenerator.EnlargeArray(m_filterAddr); m_catchAddr = ILGenerator.EnlargeArray(m_catchAddr); @@ -1432,33 +1336,33 @@ namespace System.Reflection.Emit } if (type == Filter) { - m_type[m_currentCatch] = type; - m_filterAddr[m_currentCatch] = catchorfilterAddr; - m_catchAddr[m_currentCatch] = -1; - if (m_currentCatch > 0) + m_type[currentCatch ] = type; + m_filterAddr[currentCatch ] = catchorfilterAddr; + m_catchAddr[currentCatch ] = -1; + if (currentCatch > 0) { - Debug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); - m_catchEndAddr[m_currentCatch - 1] = catchorfilterAddr; + Debug.Assert(m_catchEndAddr[currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); + m_catchEndAddr[currentCatch - 1] = catchorfilterAddr; } } else { // catch or Fault clause - m_catchClass[m_currentCatch] = catchClass; - if (m_type[m_currentCatch] != Filter) + m_catchClass[currentCatch ] = catchClass; + if (m_type[currentCatch ] != Filter) { - m_type[m_currentCatch] = type; + m_type[currentCatch ] = type; } - m_catchAddr[m_currentCatch] = catchorfilterAddr; - if (m_currentCatch > 0) + m_catchAddr[currentCatch ] = catchorfilterAddr; + if (currentCatch > 0) { - if (m_type[m_currentCatch] != Filter) + if (m_type[currentCatch ] != Filter) { - Debug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); - m_catchEndAddr[m_currentCatch - 1] = catchEndAddr; + Debug.Assert(m_catchEndAddr[currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1"); + m_catchEndAddr[currentCatch - 1] = catchEndAddr; } } - m_catchEndAddr[m_currentCatch] = -1; + m_catchEndAddr[currentCatch ] = -1; m_currentCatch++; } @@ -1492,11 +1396,9 @@ namespace System.Reflection.Emit { throw new ArgumentException(SR.Argument_TooManyFinallyClause); } - else - { - m_currentState = State_Finally; - m_endFinally = finallyAddr; - } + + m_currentState = State_Finally; + m_endFinally = finallyAddr; MarkHelper(finallyAddr, endCatchAddr, null, Finally); } @@ -1588,14 +1490,13 @@ namespace System.Reflection.Emit if (exc.m_catchEndAddr[exclast] < m_catchEndAddr[last]) return true; - else if (exc.m_catchEndAddr[exclast] == m_catchEndAddr[last]) - { - Debug.Assert(exc.GetEndAddress() != GetEndAddress(), - "exc.GetEndAddress() != GetEndAddress()"); - if (exc.GetEndAddress() > GetEndAddress()) - return true; - } - return false; + + if (exc.m_catchEndAddr[exclast] != m_catchEndAddr[last]) + return false; + Debug.Assert(exc.GetEndAddress() != GetEndAddress(), + "exc.GetEndAddress() != GetEndAddress()"); + + return exc.GetEndAddress() > GetEndAddress(); } // 0 indicates in a try block @@ -1616,10 +1517,10 @@ namespace System.Reflection.Emit /// OpenScope or CloseScope. m_iOffset records the offset where the action /// takes place. /// - internal enum ScopeAction + internal enum ScopeAction : sbyte { - Open = 0x0, - Close = 0x1, + Open = -0x1, + Close = 0x1 } internal sealed class ScopeTree @@ -1638,21 +1539,16 @@ namespace System.Reflection.Emit /// internal int GetCurrentActiveScopeIndex() { - int cClose = 0; - int i = m_iCount - 1; - if (m_iCount == 0) { return -1; } - for (; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--) + + int i = m_iCount - 1; + + for (int cClose = 0; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--) { - if (m_ScopeActions[i] == ScopeAction.Open) - { - cClose--; - } - else - cClose++; + cClose += (sbyte)m_ScopeActions[i]; } return i; @@ -1699,12 +1595,8 @@ namespace System.Reflection.Emit m_iOffsets[m_iCount] = iOffset; m_localSymInfos[m_iCount] = null; checked { m_iCount++; } - if (sa == ScopeAction.Open) - { - m_iOpenScopeCount++; - } - else - m_iOpenScopeCount--; + + m_iOpenScopeCount += -(sbyte)sa; } /// @@ -1740,8 +1632,7 @@ namespace System.Reflection.Emit internal void EmitScopeTree(ISymbolWriter symWriter) { - int i; - for (i = 0; i < m_iCount; i++) + for (int i = 0; i < m_iCount; i++) { if (m_ScopeActions[i] == ScopeAction.Open) { @@ -1787,10 +1678,8 @@ namespace System.Reflection.Emit int iEndLine, int iEndColumn) { - int i; - // make sure that arrays are large enough to hold addition info - i = FindDocument(document); + int i = FindDocument(document); Debug.Assert(i < m_DocumentCount, "Bad document look up!"); m_Documents[i].AddLineNumberInfo(document, iOffset, iStartLine, iStartColumn, iEndLine, iEndColumn); @@ -1800,14 +1689,12 @@ namespace System.Reflection.Emit // the REDocument array. private int FindDocument(ISymbolDocumentWriter document) { - int i; - // This is an optimization. The chance that the previous line is coming from the same // document is very high. if (m_iLastFound < m_DocumentCount && m_Documents[m_iLastFound].m_document == document) return m_iLastFound; - for (i = 0; i < m_DocumentCount; i++) + for (int i = 0; i < m_DocumentCount; i++) { if (m_Documents[i].m_document == document) { @@ -1932,28 +1819,22 @@ namespace System.Reflection.Emit internal void EmitLineNumberInfo(ISymbolWriter symWriter) { - int[] iOffsetsTemp; - int[] iLinesTemp; - int[] iColumnsTemp; - int[] iEndLinesTemp; - int[] iEndColumnsTemp; - if (m_iLineNumberCount == 0) return; // reduce the array size to be exact - iOffsetsTemp = new int[m_iLineNumberCount]; + int[] iOffsetsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iOffsets, 0, iOffsetsTemp, 0, m_iLineNumberCount); - iLinesTemp = new int[m_iLineNumberCount]; + int[] iLinesTemp = new int[m_iLineNumberCount]; Array.Copy(m_iLines, 0, iLinesTemp, 0, m_iLineNumberCount); - iColumnsTemp = new int[m_iLineNumberCount]; + int[] iColumnsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iColumns, 0, iColumnsTemp, 0, m_iLineNumberCount); - iEndLinesTemp = new int[m_iLineNumberCount]; + int[] iEndLinesTemp = new int[m_iLineNumberCount]; Array.Copy(m_iEndLines, 0, iEndLinesTemp, 0, m_iLineNumberCount); - iEndColumnsTemp = new int[m_iLineNumberCount]; + int[] iEndColumnsTemp = new int[m_iLineNumberCount]; Array.Copy(m_iEndColumns, 0, iEndColumnsTemp, 0, m_iLineNumberCount); symWriter.DefineSequencePoints(m_document, iOffsetsTemp, iLinesTemp, iColumnsTemp, iEndLinesTemp, iEndColumnsTemp); diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs index b9eecdb..c7333eb 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs @@ -6,6 +6,7 @@ using System.Text; using System; +using System.Buffers.Binary; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; @@ -483,8 +484,6 @@ namespace System.Reflection.Emit private void AddData(int data) { - // A managed representation of CorSigCompressData; - if (m_currSig + 4 > m_signature.Length) { m_signature = ExpandArray(m_signature); @@ -492,19 +491,17 @@ namespace System.Reflection.Emit if (data <= 0x7F) { - m_signature[m_currSig++] = (byte)(data & 0xFF); + m_signature[m_currSig++] = (byte)data; } - else if (data <= 0x3FFF) + else if (data <= 0x3F_FF) { - m_signature[m_currSig++] = (byte)((data >> 8) | 0x80); - m_signature[m_currSig++] = (byte)(data & 0xFF); + BinaryPrimitives.WriteInt16BigEndian(m_signature.AsSpan(m_currSig), (short)(data | 0x80_00)); + m_currSig += 2; } - else if (data <= 0x1FFFFFFF) + else if (data <= 0x1F_FF_FF_FF) { - m_signature[m_currSig++] = (byte)((data >> 24) | 0xC0); - m_signature[m_currSig++] = (byte)((data >> 16) & 0xFF); - m_signature[m_currSig++] = (byte)((data >> 8) & 0xFF); - m_signature[m_currSig++] = (byte)((data) & 0xFF); + BinaryPrimitives.WriteInt32BigEndian(m_signature.AsSpan(m_currSig), (int)(data | 0xC0_00_00_00)); + m_currSig += 4; } else { -- 2.7.4