Skip to content

Commit a73eb7b

Browse files
[mono] Optimize and clean-up System.Reflection.Emit.ILGenerator. (#65251)
1 parent 688d2d0 commit a73eb7b

File tree

1 file changed

+37
-130
lines changed

1 file changed

+37
-130
lines changed

src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs

Lines changed: 37 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
//
3535

3636
#if MONO_FEATURE_SRE
37+
using System.Buffers.Binary;
3738
using System.Collections.Generic;
3839
using System.Diagnostics.CodeAnalysis;
3940
using System.Diagnostics.SymbolStore;
@@ -218,7 +219,7 @@ public LabelData(int addr, int maxStack)
218219
private int num_fixups;
219220
internal Module module;
220221
private int cur_block;
221-
private Stack? open_blocks;
222+
private Int32Stack? open_blocks;
222223
private ITokenGenerator token_gen;
223224

224225
private const int defaultFixupSize = 4;
@@ -235,6 +236,9 @@ internal ILGenerator(Module m, ITokenGenerator token_gen, int size)
235236
this.token_gen = token_gen;
236237
}
237238

239+
[MemberNotNullWhen(true, nameof(open_blocks))]
240+
private bool InExceptionBlock => open_blocks != null && open_blocks.Count > 0;
241+
238242
private void make_room(int nbytes)
239243
{
240244
if (code_len + nbytes < code.Length)
@@ -246,10 +250,8 @@ private void make_room(int nbytes)
246250

247251
private void emit_int(int val)
248252
{
249-
code[code_len++] = (byte)(val & 0xFF);
250-
code[code_len++] = (byte)((val >> 8) & 0xFF);
251-
code[code_len++] = (byte)((val >> 16) & 0xFF);
252-
code[code_len++] = (byte)((val >> 24) & 0xFF);
253+
BinaryPrimitives.WriteInt32LittleEndian(code.AsSpan(code_len), val);
254+
code_len += 4;
253255
}
254256

255257
/* change to pass by ref to avoid copy */
@@ -343,9 +345,7 @@ private void InternalEndClause()
343345

344346
public virtual void BeginCatchBlock(Type exceptionType)
345347
{
346-
open_blocks ??= new Stack(defaultExceptionStackSize);
347-
348-
if (open_blocks.Count <= 0)
348+
if (!InExceptionBlock)
349349
throw new NotSupportedException("Not in an exception block");
350350
if (exceptionType != null && exceptionType.IsUserType)
351351
throw new NotSupportedException("User defined subclasses of System.Type are not yet supported.");
@@ -371,10 +371,7 @@ public virtual void BeginCatchBlock(Type exceptionType)
371371

372372
public virtual void BeginExceptFilterBlock()
373373
{
374-
if (open_blocks == null)
375-
open_blocks = new Stack(defaultExceptionStackSize);
376-
377-
if (open_blocks.Count <= 0)
374+
if (!InExceptionBlock)
378375
throw new NotSupportedException("Not in an exception block");
379376
InternalEndClause();
380377

@@ -384,8 +381,7 @@ public virtual void BeginExceptFilterBlock()
384381
public virtual Label BeginExceptionBlock()
385382
{
386383
//System.Console.WriteLine ("Begin Block");
387-
if (open_blocks == null)
388-
open_blocks = new Stack(defaultExceptionStackSize);
384+
Int32Stack open_blocks = this.open_blocks ??= new Int32Stack(defaultExceptionStackSize);
389385

390386
if (ex_handlers != null)
391387
{
@@ -406,10 +402,7 @@ public virtual Label BeginExceptionBlock()
406402

407403
public virtual void BeginFaultBlock()
408404
{
409-
if (open_blocks == null)
410-
open_blocks = new Stack(defaultExceptionStackSize);
411-
412-
if (open_blocks.Count <= 0)
405+
if (!InExceptionBlock)
413406
throw new NotSupportedException("Not in an exception block");
414407

415408
if (ex_handlers![cur_block].LastClauseType() == ILExceptionBlock.FILTER_START)
@@ -425,10 +418,7 @@ public virtual void BeginFaultBlock()
425418

426419
public virtual void BeginFinallyBlock()
427420
{
428-
if (open_blocks == null)
429-
open_blocks = new Stack(defaultExceptionStackSize);
430-
431-
if (open_blocks.Count <= 0)
421+
if (!InExceptionBlock)
432422
throw new NotSupportedException("Not in an exception block");
433423

434424
InternalEndClause();
@@ -520,25 +510,10 @@ public virtual void Emit(OpCode opcode, ConstructorInfo con)
520510

521511
public virtual void Emit(OpCode opcode, double arg)
522512
{
523-
byte[] s = BitConverter.GetBytes(arg);
524513
make_room(10);
525514
ll_emit(opcode);
526-
if (BitConverter.IsLittleEndian)
527-
{
528-
Array.Copy(s, 0, code, code_len, 8);
529-
code_len += 8;
530-
}
531-
else
532-
{
533-
code[code_len++] = s[7];
534-
code[code_len++] = s[6];
535-
code[code_len++] = s[5];
536-
code[code_len++] = s[4];
537-
code[code_len++] = s[3];
538-
code[code_len++] = s[2];
539-
code[code_len++] = s[1];
540-
code[code_len++] = s[0];
541-
}
515+
BinaryPrimitives.WriteDoubleLittleEndian(code.AsSpan(code_len), arg);
516+
code_len += 8;
542517
}
543518

544519
public virtual void Emit(OpCode opcode, FieldInfo field)
@@ -553,8 +528,8 @@ public virtual void Emit(OpCode opcode, short arg)
553528
{
554529
make_room(4);
555530
ll_emit(opcode);
556-
code[code_len++] = (byte)(arg & 0xFF);
557-
code[code_len++] = (byte)((arg >> 8) & 0xFF);
531+
BinaryPrimitives.WriteInt16LittleEndian(code.AsSpan(code_len), arg);
532+
code_len += 2;
558533
}
559534

560535
public virtual void Emit(OpCode opcode, int arg)
@@ -568,14 +543,8 @@ public virtual void Emit(OpCode opcode, long arg)
568543
{
569544
make_room(10);
570545
ll_emit(opcode);
571-
code[code_len++] = (byte)(arg & 0xFF);
572-
code[code_len++] = (byte)((arg >> 8) & 0xFF);
573-
code[code_len++] = (byte)((arg >> 16) & 0xFF);
574-
code[code_len++] = (byte)((arg >> 24) & 0xFF);
575-
code[code_len++] = (byte)((arg >> 32) & 0xFF);
576-
code[code_len++] = (byte)((arg >> 40) & 0xFF);
577-
code[code_len++] = (byte)((arg >> 48) & 0xFF);
578-
code[code_len++] = (byte)((arg >> 56) & 0xFF);
546+
BinaryPrimitives.WriteInt64LittleEndian(code.AsSpan(code_len), arg);
547+
code_len += 8;
579548
}
580549

581550
public virtual void Emit(OpCode opcode, Label label)
@@ -792,21 +761,10 @@ public virtual void Emit(OpCode opcode, SignatureHelper signature)
792761

793762
public virtual void Emit(OpCode opcode, float arg)
794763
{
795-
byte[] s = BitConverter.GetBytes(arg);
796764
make_room(6);
797765
ll_emit(opcode);
798-
if (BitConverter.IsLittleEndian)
799-
{
800-
Array.Copy(s, 0, code, code_len, 4);
801-
code_len += 4;
802-
}
803-
else
804-
{
805-
code[code_len++] = s[3];
806-
code[code_len++] = s[2];
807-
code[code_len++] = s[1];
808-
code[code_len++] = s[0];
809-
}
766+
BinaryPrimitives.WriteSingleLittleEndian(code.AsSpan(code_len), arg);
767+
code_len += 4;
810768
}
811769

812770
public virtual void Emit(OpCode opcode, string str)
@@ -909,10 +867,7 @@ public virtual void EmitWriteLine(string value)
909867

910868
public virtual void EndExceptionBlock()
911869
{
912-
if (open_blocks == null)
913-
open_blocks = new Stack(defaultExceptionStackSize);
914-
915-
if (open_blocks.Count <= 0)
870+
if (!InExceptionBlock)
916871
throw new NotSupportedException("Not in an exception block");
917872

918873
if (ex_handlers![cur_block].LastClauseType() == ILExceptionBlock.FILTER_START)
@@ -923,7 +878,7 @@ public virtual void EndExceptionBlock()
923878
ex_handlers[cur_block].End(code_len);
924879
open_blocks.Pop();
925880
if (open_blocks.Count > 0)
926-
cur_block = (int)open_blocks.Peek()!;
881+
cur_block = open_blocks.Peek()!;
927882
}
928883

929884
public virtual void EndScope()
@@ -995,26 +950,15 @@ internal void SetCode(byte[]? code, int max_stack)
995950
internal unsafe void SetCode(byte* code, int code_size, int max_stack)
996951
{
997952
// Make a copy to avoid possible security problems
998-
this.code = new byte[code_size];
999-
for (int i = 0; i < code_size; ++i)
1000-
this.code[i] = code[i];
953+
this.code = new ReadOnlySpan<byte>(code, code_size).ToArray();
1001954
this.code_len = code_size;
1002955
this.max_stack = max_stack;
1003956
this.cur_stack = 0;
1004957
}
1005958

1006-
internal ITokenGenerator TokenGenerator
1007-
{
1008-
get
1009-
{
1010-
return token_gen;
1011-
}
1012-
}
959+
internal ITokenGenerator TokenGenerator => token_gen;
1013960

1014-
public virtual int ILOffset
1015-
{
1016-
get { return code_len; }
1017-
}
961+
public virtual int ILOffset => code_len;
1018962
}
1019963

1020964
internal struct SequencePoint
@@ -1026,70 +970,33 @@ internal struct SequencePoint
1026970
public int EndCol;
1027971
}
1028972

1029-
internal sealed class Stack
973+
internal sealed class Int32Stack : List<int>
1030974
{
1031-
private object?[] _array;
1032-
private int _size;
1033-
private int _version;
1034-
1035-
private const int _defaultCapacity = 10;
1036-
1037-
public Stack()
975+
public Int32Stack(int initialCapacity) : base(initialCapacity)
1038976
{
1039-
_array = new object[_defaultCapacity];
1040-
_size = 0;
1041-
_version = 0;
1042977
}
1043978

1044-
public Stack(int initialCapacity)
979+
public int Peek()
1045980
{
1046-
if (initialCapacity < 0)
1047-
throw new ArgumentOutOfRangeException(nameof(initialCapacity), SR.ArgumentOutOfRange_NeedNonNegNum);
1048-
1049-
if (initialCapacity < _defaultCapacity)
1050-
initialCapacity = _defaultCapacity;
1051-
_array = new object[initialCapacity];
1052-
_size = 0;
1053-
_version = 0;
1054-
}
1055-
1056-
public int Count
1057-
{
1058-
get
1059-
{
1060-
return _size;
1061-
}
1062-
}
1063-
1064-
public object? Peek()
1065-
{
1066-
if (_size == 0)
981+
if (Count == 0)
1067982
throw new InvalidOperationException();
1068983

1069-
return _array[_size - 1];
984+
return this[Count - 1];
1070985
}
1071986

1072-
public object? Pop()
987+
public int Pop()
1073988
{
1074-
if (_size == 0)
989+
if (Count == 0)
1075990
throw new InvalidOperationException();
1076991

1077-
_version++;
1078-
object? obj = _array[--_size];
1079-
_array[_size] = null;
1080-
return obj;
992+
int value = this[Count - 1];
993+
RemoveAt(Count - 1);
994+
return value;
1081995
}
1082996

1083-
public void Push(object obj)
997+
public void Push(int value)
1084998
{
1085-
if (_size == _array.Length)
1086-
{
1087-
object[] newArray = new object[2 * _array.Length];
1088-
Array.Copy(_array, 0, newArray, 0, _size);
1089-
_array = newArray;
1090-
}
1091-
_array[_size++] = obj;
1092-
_version++;
999+
Add(value);
10931000
}
10941001
}
10951002
}

0 commit comments

Comments
 (0)