Skip to content

Commit

Permalink
Reduce notifications (#888)
Browse files Browse the repository at this point in the history
* Reduce notifications

* Add summary
  • Loading branch information
shargon authored Feb 9, 2024
1 parent 4985ad7 commit 71582f7
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 98 deletions.
6 changes: 4 additions & 2 deletions src/Neo.Compiler.CSharp/CompilationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,10 @@ public static CompilationContext Compile(IEnumerable<string> sourceFiles, IEnume

public static CompilationContext CompileSources(string[] sourceFiles, Options options)
{
List<MetadataReference> references = new(commonReferences);
references.Add(MetadataReference.CreateFromFile(typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.Location));
List<MetadataReference> references = new(commonReferences)
{
MetadataReference.CreateFromFile(typeof(scfx.Neo.SmartContract.Framework.SmartContract).Assembly.Location)
};
return Compile(sourceFiles, references, options);
}

Expand Down
11 changes: 6 additions & 5 deletions src/Neo.Compiler.CSharp/MethodConvert/MethodConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,8 @@ public void ConvertForward(SemanticModel model, MethodConvert target)
{
INamedTypeSymbol type = Symbol.ContainingType;
CreateObject(model, type, null);
IMethodSymbol? constructor = type.InstanceConstructors.FirstOrDefault(p => p.Parameters.Length == 0);
if (constructor is null)
throw new CompilationException(type, DiagnosticId.NoParameterlessConstructor, "The contract class requires a parameterless constructor.");
IMethodSymbol? constructor = type.InstanceConstructors.FirstOrDefault(p => p.Parameters.Length == 0)
?? throw new CompilationException(type, DiagnosticId.NoParameterlessConstructor, "The contract class requires a parameterless constructor.");
Call(model, constructor, true, Array.Empty<ArgumentSyntax>());
_returnTarget.Instruction = Jump(OpCode.JMP_L, target._startTarget);
_startTarget.Instruction = _instructions[0];
Expand Down Expand Up @@ -1825,8 +1824,10 @@ private bool TryProcessSystemMethods(SemanticModel model, IMethodSymbol symbol,
case "System.Numerics.BigInteger.GreatestCommonDivisor(System.Numerics.BigInteger, System.Numerics.BigInteger)":
if (arguments is not null)
PrepareArgumentsForMethod(model, symbol, arguments, CallingConvention.StdCall);
JumpTarget gcdTarget = new();
gcdTarget.Instruction = AddInstruction(OpCode.DUP);
JumpTarget gcdTarget = new()
{
Instruction = AddInstruction(OpCode.DUP)
};
AddInstruction(OpCode.REVERSE3);
AddInstruction(OpCode.SWAP);
AddInstruction(OpCode.MOD);
Expand Down
64 changes: 21 additions & 43 deletions src/Neo.Compiler.CSharp/Optimizer/DumpNef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,23 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;

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

static readonly Lazy<IReadOnlyDictionary<uint, string>> sysCallNames = new(
() => ApplicationEngine.Services.ToImmutableDictionary(kvp => kvp.Value.Hash, kvp => kvp.Value.Name));

public static string Unzip(string path)
{
using FileStream zippedBuffer = File.OpenRead(path);
using var archive = new ZipArchive(zippedBuffer, ZipArchiveMode.Read, false, Encoding.UTF8);
var entry = archive.Entries.FirstOrDefault();
if (entry != null)
{
using var unzippedEntryStream = entry.Open();
using var ms = new MemoryStream();
unzippedEntryStream.CopyTo(ms);
var unzippedArray = ms.ToArray();
return Encoding.UTF8.GetString(unzippedArray);
}
throw new ArgumentException("No file found in zip archive");
}

public static void Zip(string path, byte[] content, string innerFilename)
{
using FileStream fs = new(path, FileMode.Create, FileAccess.Write);
using ZipArchive archive = new(fs, ZipArchiveMode.Create);
using Stream stream = archive.CreateEntry(innerFilename).Open();
stream.Write(content);
}

public static string GetInstructionAddressPadding(this Script script)
{
var digitCount = EnumerateInstructions(script).Last().address switch
Expand Down Expand Up @@ -85,7 +65,7 @@ public static string WriteInstruction(int address, Instruction instruction, stri
instruction = script.GetInstruction(address);
opcode = instruction.OpCode;
if (print)
Console.WriteLine(WriteInstruction(address, instruction, "0000", new MethodToken[] { }));
Console.WriteLine(WriteInstruction(address, instruction, "0000", Array.Empty<MethodToken>()));
yield return (address, instruction);
}
if (opcode != OpCode.RET)
Expand Down Expand Up @@ -204,20 +184,18 @@ public static string GenerateDumpNef(NefFile nef, JToken debugInfo)
Dictionary<int, string> methodStartAddrToName = new();
Dictionary<int, string> methodEndAddrToName = new();
Dictionary<int, (int docId, int startLine, int startCol, int endLine, int endCol)> newAddrToSequencePoint = new();
Regex documentRegex = new Regex(@"\[(\d+)\](\d+)\:(\d+)\-(\d+)\:(\d+)", RegexOptions.Compiled);
Regex rangeRegex = new Regex(@"(\d+)\-(\d+)", RegexOptions.Compiled);
Regex sequencePointRegex = new Regex(@"(\d+)(\[\d+\]\d+\:\d+\-\d+\:\d+)", RegexOptions.Compiled);

foreach (JToken? method in (JArray)debugInfo["methods"]!)
{
GroupCollection rangeGroups = rangeRegex.Match(method!["range"]!.AsString()).Groups;
GroupCollection rangeGroups = RangeRegex.Match(method!["range"]!.AsString()).Groups;
(int methodStartAddr, int methodEndAddr) = (int.Parse(rangeGroups[1].ToString()), int.Parse(rangeGroups[2].ToString()));
methodStartAddrToName.Add(methodStartAddr, method!["id"]!.AsString()); // TODO: same format of method name as dumpnef
methodEndAddrToName.Add(methodEndAddr, method["id"]!.AsString());

foreach (JToken? sequencePoint in (JArray)method!["sequence-points"]!)
{
GroupCollection sequencePointGroups = sequencePointRegex.Match(sequencePoint!.AsString()).Groups;
GroupCollection documentGroups = documentRegex.Match(sequencePointGroups[2].ToString()).Groups;
GroupCollection sequencePointGroups = SequencePointRegex.Match(sequencePoint!.AsString()).Groups;
GroupCollection documentGroups = DocumentRegex.Match(sequencePointGroups[2].ToString()).Groups;
newAddrToSequencePoint.Add(int.Parse(sequencePointGroups[1].Value), (
int.Parse(documentGroups[1].ToString()),
int.Parse(documentGroups[2].ToString()),
Expand All @@ -238,25 +216,25 @@ public static string GenerateDumpNef(NefFile nef, JToken debugInfo)
dumpnef += $"# Method End {methodEndAddrToName[a]}\n";
if (newAddrToSequencePoint.ContainsKey(a))
{
var docInfo = newAddrToSequencePoint[a];
string docPath = debugInfo["documents"]![docInfo.docId]!.AsString();
var (docId, startLine, startCol, endLine, endCol) = newAddrToSequencePoint[a];
string docPath = debugInfo["documents"]![docId]!.AsString();
if (debugInfo["document-root"] != null)
docPath = Path.Combine(debugInfo["document-root"]!.AsString(), docPath);
if (!docPathToContent.ContainsKey(docPath))
docPathToContent.Add(docPath, File.ReadAllLines(docPath).ToArray());
if (docInfo.startLine == docInfo.endLine)
dumpnef += $"# Code {Path.GetFileName(docPath)} line {docInfo.startLine}: \"{docPathToContent[docPath][docInfo.startLine - 1][(docInfo.startCol - 1)..(docInfo.endCol - 1)]}\"\n";
if (startLine == endLine)
dumpnef += $"# Code {Path.GetFileName(docPath)} line {startLine}: \"{docPathToContent[docPath][startLine - 1][(startCol - 1)..(endCol - 1)]}\"\n";
else
for (int lineIndex = docInfo.startLine; lineIndex <= docInfo.endLine; lineIndex++)
for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++)
{
string src;
if (lineIndex == docInfo.startLine)
src = docPathToContent[docPath][lineIndex - 1][(docInfo.startCol - 1)..].Trim();
else if (lineIndex == docInfo.endLine)
src = docPathToContent[docPath][lineIndex - 1][..(docInfo.endCol - 1)].Trim();
if (lineIndex == startLine)
src = docPathToContent[docPath][lineIndex - 1][(startCol - 1)..].Trim();
else if (lineIndex == endLine)
src = docPathToContent[docPath][lineIndex - 1][..(endCol - 1)].Trim();
else
src = docPathToContent[docPath][lineIndex - 1].Trim();
dumpnef += $"# Code {Path.GetFileName(docPath)} line {docInfo.startLine}: \"{src}\"\n";
dumpnef += $"# Code {Path.GetFileName(docPath)} line {startLine}: \"{src}\"\n";
}
}
if (a < script.Length)
Expand Down
22 changes: 7 additions & 15 deletions src/Neo.Compiler.CSharp/Optimizer/JumpTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,14 @@ public static int ComputeJumpTarget(int addr, Instruction instruction)
return addr + instruction.TokenI8;
if (conditionalJump_L.Contains(instruction.OpCode))
return addr + instruction.TokenI32;
switch (instruction.OpCode)

return instruction.OpCode switch
{
case JMP:
case CALL:
case ENDTRY:
return addr + instruction.TokenI8;
case PUSHA:
case JMP_L:
case CALL_L:
case ENDTRY_L:
return addr + instruction.TokenI32;
case CALLA:
throw new NotImplementedException("CALLA is dynamic; not supported");
default:
throw new NotImplementedException($"Unknown instruction {instruction.OpCode}");
}
JMP or CALL or ENDTRY => addr + instruction.TokenI8,
PUSHA or JMP_L or CALL_L or ENDTRY_L => addr + instruction.TokenI32,
CALLA => throw new NotImplementedException("CALLA is dynamic; not supported"),
_ => throw new NotImplementedException($"Unknown instruction {instruction.OpCode}"),
};
}

public static (int catchTarget, int finallyTarget) ComputeTryTarget(int addr, Instruction instruction)
Expand Down
6 changes: 3 additions & 3 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace Neo.Optimizer
{
public class Optimizer
{
public static int[] OperandSizePrefixTable = new int[256];
public static int[] OperandSizeTable = new int[256];
public static Dictionary<string, Func<NefFile, ContractManifest, JToken, (NefFile nef, ContractManifest manifest, JToken debugInfo)>> strategies = new();
public static readonly int[] OperandSizePrefixTable = new int[256];
public static readonly int[] OperandSizeTable = new int[256];
public static readonly Dictionary<string, Func<NefFile, ContractManifest, JToken, (NefFile nef, ContractManifest manifest, JToken debugInfo)>> strategies = new();

static Optimizer()
{
Expand Down
56 changes: 29 additions & 27 deletions src/Neo.Compiler.CSharp/Optimizer/Strategies/Reachability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ namespace Neo.Optimizer
{
public static class Reachability
{
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.
private static readonly Regex RangeRegex = new(@"(\d+)\-(\d+)", RegexOptions.Compiled);
private static readonly Regex SequencePointRegex = new(@"(\d+)(\[\d+\]\d+\:\d+\-\d+\:\d+)", RegexOptions.Compiled);
private static readonly Regex DocumentRegex = new(@"\[(\d+)\](\d+)\:(\d+)\-(\d+)\:(\d+)", RegexOptions.Compiled);
#pragma warning restore SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.

public enum TryStack
{
ENTRY,
TRY,
CATCH,
FINALLY,
}

public enum BranchType
{
OK, // One of the branches may return without exception
THROW, // All branches surely has exceptions, but can be catched
ABORT, // All branches abort, and cannot be catched
}

[Strategy(Priority = int.MaxValue)]
public static (NefFile, ContractManifest, JToken) RemoveUncoveredInstructions(NefFile nef, ContractManifest manifest, JToken debugInfo)
{
Expand Down Expand Up @@ -80,9 +101,9 @@ public static (NefFile, ContractManifest, JToken) RemoveUncoveredInstructions(Ne
}
foreach (ContractMethodDescriptor method in manifest.Abi.Methods)
method.Offset = (int)simplifiedInstructionsToAddress[oldAddressToInstruction[method.Offset]]!;
Script newScript = new Script(simplifiedScript.ToArray());
Script newScript = new(simplifiedScript.ToArray());
nef.Script = newScript;
nef.Compiler = System.AppDomain.CurrentDomain.FriendlyName;
nef.Compiler = AppDomain.CurrentDomain.FriendlyName;
nef.CheckSum = NefFile.ComputeChecksum(nef);

Dictionary<int, (int docId, int startLine, int startCol, int endLine, int endCol)> newAddrToSequencePoint = new();
Expand All @@ -91,8 +112,7 @@ public static (NefFile, ContractManifest, JToken) RemoveUncoveredInstructions(Ne
HashSet<JToken> methodsToRemove = new();
foreach (JToken? method in (JArray)debugInfo["methods"]!)
{
Regex rangeRegex = new Regex(@"(\d+)\-(\d+)", RegexOptions.Compiled);
GroupCollection rangeGroups = rangeRegex.Match(method!["range"]!.AsString()).Groups;
GroupCollection rangeGroups = RangeRegex.Match(method!["range"]!.AsString()).Groups;
(int oldMethodStart, int oldMethodEnd) = (int.Parse(rangeGroups[1].ToString()), int.Parse(rangeGroups[2].ToString()));
if (!simplifiedInstructionsToAddress.Contains(oldAddressToInstruction[oldMethodStart]))
{
Expand All @@ -105,12 +125,11 @@ public static (NefFile, ContractManifest, JToken) RemoveUncoveredInstructions(Ne
newMethodEnd.Add(methodEnd, method["id"]!.AsString());
method["range"] = $"{methodStart}-{methodEnd}";

Regex sequencePointRegex = new Regex(@"(\d+)(\[\d+\]\d+\:\d+\-\d+\:\d+)", RegexOptions.Compiled);
int previousSequencePoint = methodStart;
JArray newSequencePoints = new();
foreach (JToken? sequencePoint in (JArray)method!["sequence-points"]!)
{
GroupCollection sequencePointGroups = sequencePointRegex.Match(sequencePoint!.AsString()).Groups;
GroupCollection sequencePointGroups = SequencePointRegex.Match(sequencePoint!.AsString()).Groups;
int startingInstructionAddress = int.Parse(sequencePointGroups[1].ToString());
Instruction oldInstruction = oldAddressToInstruction[startingInstructionAddress];
if (simplifiedInstructionsToAddress.Contains(oldInstruction))
Expand All @@ -121,8 +140,7 @@ public static (NefFile, ContractManifest, JToken) RemoveUncoveredInstructions(Ne
}
else
newSequencePoints.Add(new JString($"{previousSequencePoint}{sequencePointGroups[2]}"));
Regex documentRegex = new Regex(@"\[(\d+)\](\d+)\:(\d+)\-(\d+)\:(\d+)", RegexOptions.Compiled);
GroupCollection documentGroups = documentRegex.Match(sequencePointGroups[2].ToString()).Groups;
GroupCollection documentGroups = DocumentRegex.Match(sequencePointGroups[2].ToString()).Groups;
newAddrToSequencePoint.Add(previousSequencePoint, (
int.Parse(documentGroups[1].ToString()),
int.Parse(documentGroups[2].ToString()),
Expand Down Expand Up @@ -159,8 +177,8 @@ public static Dictionary<int, bool>
foreach (JToken? method in (JArray)debugInfo["methods"]!)
{
string name = method!["name"]!.AsString(); // NFTLoan.NFTLoan,RegisterRental
name = name.Substring(name.LastIndexOf(',') + 1); // RegisterRental
name = char.ToLower(name[0]) + name.Substring(1); // registerRental
name = name[(name.LastIndexOf(',') + 1)..]; // RegisterRental
name = char.ToLower(name[0]) + name[1..]; // registerRental
if (name == "_deploy")
{
int startAddr = int.Parse(method!["range"]!.AsString().Split("-")[0]);
Expand All @@ -170,21 +188,6 @@ public static Dictionary<int, bool>
return coveredMap;
}

public enum TryStack
{
ENTRY,
TRY,
CATCH,
FINALLY,
}

public enum BranchType
{
OK, // One of the branches may return without exception
THROW, // All branches surely has exceptions, but can be catched
ABORT, // All branches abort, and cannot be catched
}

/// <summary>
///
/// </summary>
Expand All @@ -196,8 +199,7 @@ public enum BranchType
/// <exception cref="NotImplementedException"></exception>
public static BranchType CoverInstruction(int addr, Script script, Dictionary<int, bool> coveredMap, Stack<((int returnAddr, int finallyAddr), TryStack stackType)>? stack = null, bool throwed = false)
{
if (stack == null)
stack = new();
stack ??= new();
if (stack.Count == 0)
stack.Push(((-1, -1), TryStack.ENTRY));
while (stack.Count > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ namespace Neo.Optimizer
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class StrategyAttribute : Attribute
{
/// <summary>
/// Strategy name
/// </summary>
public string? Name { get; init; }
public int Priority = 0; // greater num to be executed first

/// <summary>
/// Greater num to be executed first
/// </summary>
public int Priority = 0;
}
}
4 changes: 2 additions & 2 deletions tests/Neo.SmartContract.TestEngine/TestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public class TestEngine : ApplicationEngine

private static readonly List<MetadataReference> references = new();

public event EventHandler<ExecutionContext> OnPreExecuteTestCaseStandard;
public event EventHandler<ExecutionContext>? OnPreExecuteTestCaseStandard;

public NefFile? Nef { get; private set; }
public ContractManifest? Manifest { get; private set; }
public JObject DebugInfo { get; private set; }
public JObject? DebugInfo { get; private set; }

static TestEngine()
{
Expand Down

0 comments on commit 71582f7

Please sign in to comment.