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
56 changes: 39 additions & 17 deletions src/Neo.Compiler.CSharp/Optimizer/JumpTarget.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
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;

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);
}
}
}
Loading
Loading