Skip to content

Commit 841c440

Browse files
Hecate2shargon
andauthored
fixes on optimizer about CATCH, ENDFINALLY and PUSHA (#966)
* fixes on CATCH and ENDFINALLY * fix methodEnd * comments on Abort & Assert tests * TryGetValue for performance * set PUSHA target to itself * correct branch return type * correct branch return type * Move basic optimizer * clean changes * Update tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Abort.cs * Change visibility --------- Co-authored-by: Fernando Diaz Toledano <shargon@gmail.com>
1 parent 277c952 commit 841c440

File tree

11 files changed

+177
-84
lines changed

11 files changed

+177
-84
lines changed

src/Neo.Compiler.CSharp/CompilationContext.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using Microsoft.CodeAnalysis.CSharp;
1515
using Microsoft.CodeAnalysis.CSharp.Syntax;
1616
using Microsoft.CodeAnalysis.Text;
17+
using Neo.Compiler.Optimizer;
1718
using Neo.Cryptography.ECC;
1819
using Neo.IO;
1920
using Neo.Json;
@@ -134,7 +135,7 @@ internal void Compile()
134135
instructions.RebuildOffsets();
135136
if (Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
136137
{
137-
Optimizer.CompressJumps(instructions);
138+
BasicOptimizer.CompressJumps(instructions);
138139
}
139140
instructions.RebuildOperands();
140141
}

src/Neo.Compiler.CSharp/MethodConvert/MethodConvert.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Microsoft.CodeAnalysis;
1414
using Microsoft.CodeAnalysis.CSharp;
1515
using Microsoft.CodeAnalysis.CSharp.Syntax;
16+
using Neo.Compiler.Optimizer;
1617
using Neo.Cryptography.ECC;
1718
using Neo.IO;
1819
using Neo.SmartContract;
@@ -238,7 +239,7 @@ public void Convert(SemanticModel model)
238239
AddInstruction(OpCode.RET);
239240
}
240241
if (_context.Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
241-
Optimizer.RemoveNops(_instructions);
242+
BasicOptimizer.RemoveNops(_instructions);
242243
_startTarget.Instruction = _instructions[0];
243244
}
244245

src/Neo.Compiler.CSharp/Optimizer.cs src/Neo.Compiler.CSharp/Optimizer/BasicOptimizer.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
using Neo.VM;
1212
using System.Collections.Generic;
1313

14-
namespace Neo.Compiler
14+
namespace Neo.Compiler.Optimizer
1515
{
16-
static class Optimizer
16+
static class BasicOptimizer
1717
{
1818
public static void RemoveNops(List<Instruction> instructions)
1919
{
@@ -57,8 +57,8 @@ public static void CompressJumps(IReadOnlyList<Instruction> instructions)
5757
}
5858
if (instruction.OpCode == OpCode.TRY_L)
5959
{
60-
int offset1 = (instruction.Target.Instruction?.Offset - instruction.Offset) ?? 0;
61-
int offset2 = (instruction.Target2!.Instruction?.Offset - instruction.Offset) ?? 0;
60+
int offset1 = instruction.Target.Instruction?.Offset - instruction.Offset ?? 0;
61+
int offset2 = instruction.Target2!.Instruction?.Offset - instruction.Offset ?? 0;
6262
if (offset1 >= sbyte.MinValue && offset1 <= sbyte.MaxValue && offset2 >= sbyte.MinValue && offset2 <= sbyte.MaxValue)
6363
{
6464
compressed = true;

src/Neo.Compiler.CSharp/Optimizer/DumpNef.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace Neo.Optimizer
1414
{
15-
public static class DumpNef
15+
static class DumpNef
1616
{
1717
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.
1818
private static readonly Regex DocumentRegex = new(@"\[(\d+)\](\d+)\:(\d+)\-(\d+)\:(\d+)", RegexOptions.Compiled);

src/Neo.Compiler.CSharp/Optimizer/JumpTarget.cs

+40-18
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
using Neo.SmartContract;
22
using Neo.VM;
33
using System;
4-
using System.Collections.Concurrent;
54
using System.Collections.Generic;
65
using System.Linq;
7-
using System.Threading.Tasks;
86
using static Neo.Optimizer.OpCodeTypes;
97
using static Neo.VM.OpCode;
108

119
namespace Neo.Optimizer
1210
{
13-
public static class JumpTarget
11+
static class JumpTarget
1412
{
1513
public static bool SingleJumpInOperand(Instruction instruction) => SingleJumpInOperand(instruction.OpCode);
1614
public static bool SingleJumpInOperand(OpCode opcode)
@@ -56,36 +54,60 @@ public static (int catchTarget, int finallyTarget) ComputeTryTarget(int addr, In
5654
};
5755
}
5856

59-
public static (ConcurrentDictionary<Instruction, Instruction>,
60-
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
57+
public static (Dictionary<Instruction, Instruction>,
58+
Dictionary<Instruction, (Instruction, Instruction)>,
59+
Dictionary<Instruction, HashSet<Instruction>>)
6160
FindAllJumpAndTrySourceToTargets(NefFile nef)
6261
{
6362
Script script = nef.Script;
6463
return FindAllJumpAndTrySourceToTargets(script);
6564
}
66-
public static (ConcurrentDictionary<Instruction, Instruction>,
67-
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
65+
public static (Dictionary<Instruction, Instruction>,
66+
Dictionary<Instruction, (Instruction, Instruction)>,
67+
Dictionary<Instruction, HashSet<Instruction>>)
6868
FindAllJumpAndTrySourceToTargets(Script script) => FindAllJumpAndTrySourceToTargets(script.EnumerateInstructions().ToList());
69-
public static (ConcurrentDictionary<Instruction, Instruction>,
70-
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
69+
public static (
70+
Dictionary<Instruction, Instruction>, // jump source to target
71+
Dictionary<Instruction, (Instruction, Instruction)>, // try source to targets
72+
Dictionary<Instruction, HashSet<Instruction>> // target to source
73+
)
7174
FindAllJumpAndTrySourceToTargets(List<(int, Instruction)> addressAndInstructionsList)
7275
{
7376
Dictionary<int, Instruction> addressToInstruction = new();
7477
foreach ((int a, Instruction i) in addressAndInstructionsList)
7578
addressToInstruction.Add(a, i);
76-
ConcurrentDictionary<Instruction, Instruction> jumpSourceToTargets = new();
77-
ConcurrentDictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new();
78-
Parallel.ForEach(addressAndInstructionsList, item =>
79+
Dictionary<Instruction, Instruction> jumpSourceToTargets = new();
80+
Dictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new();
81+
Dictionary<Instruction, HashSet<Instruction>> targetToSources = new();
82+
foreach ((int a, Instruction i) in addressAndInstructionsList)
7983
{
80-
(int a, Instruction i) = (item.Item1, item.Item2);
8184
if (SingleJumpInOperand(i))
82-
jumpSourceToTargets.TryAdd(i, addressToInstruction[ComputeJumpTarget(a, i)]);
85+
{
86+
Instruction target = addressToInstruction[ComputeJumpTarget(a, i)];
87+
jumpSourceToTargets.TryAdd(i, target);
88+
if (!targetToSources.TryGetValue(target, out HashSet<Instruction>? sources)) sources = new();
89+
sources.Add(i);
90+
}
8391
if (i.OpCode == TRY)
84-
trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1]));
92+
{
93+
(Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1]);
94+
trySourceToTargets.TryAdd(i, (t1, t2));
95+
if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new();
96+
sources1.Add(i);
97+
if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new();
98+
sources2.Add(i);
99+
}
85100
if (i.OpCode == TRY_L)
86-
trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1]));
87-
});
88-
return (jumpSourceToTargets, trySourceToTargets);
101+
{
102+
(Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1]);
103+
trySourceToTargets.TryAdd(i, (t1, t2));
104+
if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new();
105+
sources1.Add(i);
106+
if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new();
107+
sources2.Add(i);
108+
}
109+
}
110+
return (jumpSourceToTargets, trySourceToTargets, targetToSources);
89111
}
90112
}
91113
}

src/Neo.Compiler.CSharp/Optimizer/OpCodeTypes.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Neo.Optimizer
66
{
7-
public static class OpCodeTypes
7+
static class OpCodeTypes
88
{
99
public static readonly HashSet<OpCode> push = new();
1010

src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace Neo.Optimizer
1010
{
11-
public class Optimizer
11+
class Optimizer
1212
{
1313
public static readonly int[] OperandSizePrefixTable = new int[256];
1414
public static readonly int[] OperandSizeTable = new int[256];

0 commit comments

Comments
 (0)