Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes on optimizer about CATCH, ENDFINALLY and PUSHA #966

Merged
merged 13 commits into from
Feb 28, 2024
3 changes: 2 additions & 1 deletion src/Neo.Compiler.CSharp/CompilationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Neo.Compiler.Optimizer;
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.Json;
Expand Down Expand Up @@ -134,7 +135,7 @@ internal void Compile()
instructions.RebuildOffsets();
if (Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
{
Optimizer.CompressJumps(instructions);
BasicOptimizer.CompressJumps(instructions);
}
instructions.RebuildOperands();
}
Expand Down
3 changes: 2 additions & 1 deletion src/Neo.Compiler.CSharp/MethodConvert/MethodConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Neo.Compiler.Optimizer;
using Neo.Cryptography.ECC;
using Neo.IO;
using Neo.SmartContract;
Expand Down Expand Up @@ -238,7 +239,7 @@ public void Convert(SemanticModel model)
AddInstruction(OpCode.RET);
}
if (_context.Options.Optimize.HasFlag(CompilationOptions.OptimizationType.Basic))
Optimizer.RemoveNops(_instructions);
BasicOptimizer.RemoveNops(_instructions);
_startTarget.Instruction = _instructions[0];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
using Neo.VM;
using System.Collections.Generic;

namespace Neo.Compiler
namespace Neo.Compiler.Optimizer
{
static class Optimizer
static class BasicOptimizer
{
public static void RemoveNops(List<Instruction> instructions)
{
Expand Down Expand Up @@ -57,8 +57,8 @@ public static void CompressJumps(IReadOnlyList<Instruction> instructions)
}
if (instruction.OpCode == OpCode.TRY_L)
{
int offset1 = (instruction.Target.Instruction?.Offset - instruction.Offset) ?? 0;
int offset2 = (instruction.Target2!.Instruction?.Offset - instruction.Offset) ?? 0;
int offset1 = instruction.Target.Instruction?.Offset - instruction.Offset ?? 0;
int offset2 = instruction.Target2!.Instruction?.Offset - instruction.Offset ?? 0;
if (offset1 >= sbyte.MinValue && offset1 <= sbyte.MaxValue && offset2 >= sbyte.MinValue && offset2 <= sbyte.MaxValue)
{
compressed = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.Compiler.CSharp/Optimizer/DumpNef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace Neo.Optimizer
{
public static class DumpNef
static class DumpNef
{
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.
private static readonly Regex DocumentRegex = new(@"\[(\d+)\](\d+)\:(\d+)\-(\d+)\:(\d+)", RegexOptions.Compiled);
Expand Down
58 changes: 40 additions & 18 deletions src/Neo.Compiler.CSharp/Optimizer/JumpTarget.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
using Neo.SmartContract;
using Neo.VM;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Neo.Optimizer.OpCodeTypes;
using static Neo.VM.OpCode;

namespace Neo.Optimizer
{
public static class JumpTarget
static class JumpTarget
{
public static bool SingleJumpInOperand(Instruction instruction) => SingleJumpInOperand(instruction.OpCode);
public static bool SingleJumpInOperand(OpCode opcode)
Expand Down Expand Up @@ -56,36 +54,60 @@ public static (int catchTarget, int finallyTarget) ComputeTryTarget(int addr, In
};
}

public static (ConcurrentDictionary<Instruction, Instruction>,
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
public static (Dictionary<Instruction, Instruction>,
Dictionary<Instruction, (Instruction, Instruction)>,
Dictionary<Instruction, HashSet<Instruction>>)
FindAllJumpAndTrySourceToTargets(NefFile nef)
{
Script script = nef.Script;
return FindAllJumpAndTrySourceToTargets(script);
}
public static (ConcurrentDictionary<Instruction, Instruction>,
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
public static (Dictionary<Instruction, Instruction>,
Dictionary<Instruction, (Instruction, Instruction)>,
Dictionary<Instruction, HashSet<Instruction>>)
FindAllJumpAndTrySourceToTargets(Script script) => FindAllJumpAndTrySourceToTargets(script.EnumerateInstructions().ToList());
public static (ConcurrentDictionary<Instruction, Instruction>,
ConcurrentDictionary<Instruction, (Instruction, Instruction)>)
public static (
Dictionary<Instruction, Instruction>, // jump source to target
Dictionary<Instruction, (Instruction, Instruction)>, // try source to targets
Dictionary<Instruction, HashSet<Instruction>> // target to source
)
FindAllJumpAndTrySourceToTargets(List<(int, Instruction)> addressAndInstructionsList)
{
Dictionary<int, Instruction> addressToInstruction = new();
foreach ((int a, Instruction i) in addressAndInstructionsList)
addressToInstruction.Add(a, i);
ConcurrentDictionary<Instruction, Instruction> jumpSourceToTargets = new();
ConcurrentDictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new();
Parallel.ForEach(addressAndInstructionsList, item =>
Dictionary<Instruction, Instruction> jumpSourceToTargets = new();
Dictionary<Instruction, (Instruction, Instruction)> trySourceToTargets = new();
Dictionary<Instruction, HashSet<Instruction>> targetToSources = new();
foreach ((int a, Instruction i) in addressAndInstructionsList)
{
(int a, Instruction i) = (item.Item1, item.Item2);
if (SingleJumpInOperand(i))
jumpSourceToTargets.TryAdd(i, addressToInstruction[ComputeJumpTarget(a, i)]);
{
Instruction target = addressToInstruction[ComputeJumpTarget(a, i)];
jumpSourceToTargets.TryAdd(i, target);
if (!targetToSources.TryGetValue(target, out HashSet<Instruction>? sources)) sources = new();
sources.Add(i);
}
if (i.OpCode == TRY)
trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1]));
{
(Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI8], addressToInstruction[a + i.TokenI8_1]);
trySourceToTargets.TryAdd(i, (t1, t2));
if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new();
sources1.Add(i);
if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new();
sources2.Add(i);
}
if (i.OpCode == TRY_L)
trySourceToTargets.TryAdd(i, (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1]));
});
return (jumpSourceToTargets, trySourceToTargets);
{
(Instruction t1, Instruction t2) = (addressToInstruction[a + i.TokenI32], addressToInstruction[a + i.TokenI32_1]);
trySourceToTargets.TryAdd(i, (t1, t2));
if (!targetToSources.TryGetValue(t1, out HashSet<Instruction>? sources1)) sources1 = new();
sources1.Add(i);
if (!targetToSources.TryGetValue(t2, out HashSet<Instruction>? sources2)) sources2 = new();
sources2.Add(i);
}
}
return (jumpSourceToTargets, trySourceToTargets, targetToSources);
}
}
}
2 changes: 1 addition & 1 deletion src/Neo.Compiler.CSharp/Optimizer/OpCodeTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Neo.Optimizer
{
public static class OpCodeTypes
static class OpCodeTypes
{
public static readonly HashSet<OpCode> push = new();

Expand Down
2 changes: 1 addition & 1 deletion src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Neo.Optimizer
{
public class Optimizer
class Optimizer
{
public static readonly int[] OperandSizePrefixTable = new int[256];
public static readonly int[] OperandSizeTable = new int[256];
Expand Down
Loading
Loading