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

Add abi offset #219

Merged
merged 48 commits into from
Apr 26, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d353ee9
add abi offset
Mar 24, 2020
c90cb3e
fix
Mar 24, 2020
fcb7dc2
clean optimizer
lightszero Mar 24, 2020
4af85aa
Clean code
shargon Mar 24, 2020
132a190
Update NefOptimizeTool.cs
shargon Mar 24, 2020
5e7e947
fix GetAddrConvertTable bug,return all offsets now
lightszero Mar 25, 2020
432605c
format
Mar 25, 2020
1fd03cd
format
Mar 25, 2020
1de60d1
Merge branch 'master' into add-abi-offset
erikzhang Mar 25, 2020
e8aee62
Clean code
shargon Mar 25, 2020
0fd7964
add abi-offset-unitTest
Mar 25, 2020
e27f299
Merge branch 'add-abi-offset' of https://github.com/ShawnYun/neo-devp…
Mar 25, 2020
739f653
Rename Contract_AbiOffset.cs to Contract_ABIOffset.cs
ShawnYun Mar 25, 2020
1c74e62
fix
Mar 26, 2020
d469495
Clean code
shargon Mar 26, 2020
a524038
Optimize
shargon Mar 26, 2020
4262ba4
Fix
shargon Mar 26, 2020
b162242
fix NDEBUG
shargon Mar 26, 2020
1b0ce50
Fix NDEBUG
shargon Mar 26, 2020
1331c73
Merge branch 'master' into add-abi-offset
lightszero Mar 29, 2020
f770a97
Merge branch 'master' into add-abi-offset
shargon Mar 30, 2020
57b94ac
modify abi offset uintTest
Mar 31, 2020
71869a9
Merge branch 'master' into add-abi-offset
shargon Apr 7, 2020
24fec80
Merge branch 'master' into add-abi-offset
lightszero Apr 13, 2020
d933683
Merge branch 'master' of https://github.com/neo-project/neo-devpack-d…
Apr 16, 2020
c9453a6
Merge branch 'master' into add-abi-offset
lightszero Apr 16, 2020
93f292a
add initializing static variables
Apr 20, 2020
4b46326
Merge branch 'add-abi-offset' of https://github.com/ShawnYun/neo-devp…
Apr 20, 2020
9af0429
format
Apr 20, 2020
1faaebd
format
Apr 20, 2020
8d767bb
modify UTs
Apr 21, 2020
bcaa2e4
fix and rename
Apr 21, 2020
a7dcd5f
modify ContractTest
Apr 23, 2020
2d23cbc
fix conflicts
Apr 23, 2020
e7b114f
format
Apr 23, 2020
9c6243e
fix
Apr 24, 2020
bfde89a
fix TestEngine and modify _initialize
Apr 24, 2020
ab99dc3
fix
Apr 24, 2020
3165a34
fix conflicts
Apr 24, 2020
3b5b466
format
Apr 24, 2020
b3cd688
fix void return
Apr 24, 2020
a424b24
Update Opcodes
shargon Apr 24, 2020
806f988
resolve review issues
Apr 24, 2020
f70aa8d
Merge branch 'add-abi-offset' of https://github.com/ShawnYun/neo-devp…
Apr 24, 2020
9140bbb
fix
Apr 24, 2020
54ad1b0
fix
Apr 24, 2020
5c01853
fix
Apr 24, 2020
575c3d7
resolve conflicts
Apr 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 4 additions & 18 deletions src/Neo.Compiler.MSIL/FuncExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static string ConvType(string _type)
return "Unknown:" + _type;
}

public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script)
public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, Dictionary<int, int> addrConvTable)
{
var sha256 = System.Security.Cryptography.SHA256.Create();
byte[] hash256 = sha256.ComputeHash(script);
Expand All @@ -81,14 +81,6 @@ public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script)
}
outjson.SetDictValue("hash", sb.ToString());

//entrypoint
var entryPoint = "main";
var mainmethod = module.mapMethods[module.mainMethod];
if (mainmethod != null)
{
entryPoint = mainmethod.displayName;
}

//functions
var methods = new MyJson.JsonNode_Array();
outjson["methods"] = methods;
Expand All @@ -103,21 +95,15 @@ public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script)
continue;

var funcsign = new MyJson.JsonNode_Object();
if (function.Value.displayName == entryPoint)
{
// This is the entryPoint
outjson.SetDictValue("entryPoint", funcsign);
}
else
{
methods.Add(funcsign);
}
methods.Add(funcsign);
funcsign.SetDictValue("name", function.Value.displayName);
if (names.Contains(function.Value.displayName))
{
throw new Exception("abi not allow same name functions");
}
names.Add(function.Value.displayName);
var offset = addrConvTable?[function.Value.funcaddr] ?? function.Value.funcaddr;
funcsign.SetDictValue("offset", offset.ToString());
MyJson.JsonNode_Array funcparams = new MyJson.JsonNode_Array();
funcsign["parameters"] = funcparams;
if (mm.paramtypes != null)
Expand Down
2 changes: 1 addition & 1 deletion src/Neo.Compiler.MSIL/MSIL/Converter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public NeoModule Convert(ILModule _in, ConvOption option = null)
if (l.Value == m)
{
if (mainmethod != "")
throw new Exception("Have too mush EntryPoint,Check it.");
throw new Exception("Have too much EntryPoint,Check it.");
mainmethod = key;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/Neo.Compiler.MSIL/Optimizer/NefInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class NefInstruction : INefItem
private uint DataSize => DataPrefixSize > 0 ? (uint)(Data?.Length ?? 0) : GetOperandSize(OpCode);

public byte[] Data { get; private set; }
public int OffsetInit { get; private set; }
public int Offset { get; private set; }
public string[] Labels { get; private set; }

Expand Down Expand Up @@ -46,10 +47,11 @@ static NefInstruction()
}
}

public NefInstruction(OpCode opCode, byte[] data = null, int offset = -1)
public NefInstruction(OpCode opCode, byte[] data, int offset)
{
SetOpCode(opCode);
SetData(data);
OffsetInit = offset;
SetOffset(offset);
}

Expand Down
18 changes: 16 additions & 2 deletions src/Neo.Compiler.MSIL/Optimizer/NefOptimizeTool.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;

namespace Neo.Compiler.Optimizer
Expand All @@ -12,7 +13,19 @@ public static class NefOptimizeTool
/// <returns>Optimized script</returns>
public static byte[] Optimize(byte[] script)
{
return Optimize(script, new OptimizeParserType[] { OptimizeParserType.DELETE_DEAD_CODDE, OptimizeParserType.USE_SHORT_ADDRESS });
return Optimize(script, new OptimizeParserType[] { OptimizeParserType.DELETE_DEAD_CODDE, OptimizeParserType.USE_SHORT_ADDRESS }
, out _);
}

public static byte[] Optimize(byte[] script, out Dictionary<int, int> addrConvertTable)
{
return Optimize(script, new OptimizeParserType[] { OptimizeParserType.DELETE_DEAD_CODDE, OptimizeParserType.USE_SHORT_ADDRESS }
, out addrConvertTable);
}

public static byte[] Optimize(byte[] script, OptimizeParserType[] parserTypes)
{
return Optimize(script, parserTypes, out _);
}

/// <summary>
Expand All @@ -25,7 +38,7 @@ public static byte[] Optimize(byte[] script)
/// <para> DELETE_NOP -- delete nop parser</para>
/// <para> DELETE_USELESS_JMP -- delete useless jmp parser, eg: JPM 2</para></param>
/// <returns>Optimized script</returns>
public static byte[] Optimize(byte[] script, OptimizeParserType[] parserTypes)
public static byte[] Optimize(byte[] script, OptimizeParserType[] parserTypes, out Dictionary<int, int> addrConvertTable)
{
var optimizer = new NefOptimizer();

Expand Down Expand Up @@ -53,6 +66,7 @@ public static byte[] Optimize(byte[] script, OptimizeParserType[] parserTypes)
using (var ms = new MemoryStream())
{
optimizer.LinkNef(ms);
addrConvertTable = optimizer.GetAddrConvertTable();
var bytes = ms.ToArray();
return bytes;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Neo.Compiler.MSIL/Optimizer/NefOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public NefOptimizer(byte[] script = null)
}
}

public Dictionary<int, int> GetAddrConvertTable()
{
var addrConvertTable = new Dictionary<int, int>();
foreach (var item in Items)
{
if (item is NefInstruction inst)
{
addrConvertTable[inst.OffsetInit] = inst.Offset;
}
}
return addrConvertTable;
}

public void AddOptimizeParser(IOptimizeParser function)
{
OptimizeFunctions.Add(function);
Expand Down Expand Up @@ -150,7 +163,9 @@ public void LinkNef(Stream stream)
foreach (var inst in this.Items)
{
if (inst is NefInstruction i)
{
i.WriteTo(stream);
}
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/Neo.Compiler.MSIL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,23 @@ public static int Compile(Options options)
module = conv.Convert(mod, option);
bytes = module.Build();
log.Log("convert succ");

Dictionary<int, int> addrConvTable = null;
if (options.Optimize)
{
var optimize = NefOptimizeTool.Optimize(bytes);
var optimize = NefOptimizeTool.Optimize(bytes, out addrConvTable);
log.Log("optimization succ " + (((bytes.Length / (optimize.Length + 0.0)) * 100.0) - 100).ToString("0.00 '%'"));
foreach (var func in module.mapMethods)
{
int srcaddr = func.Value.funcaddr;
int opaddr = addrConvTable[srcaddr];
log.Log("func addr from " + srcaddr + "=>" + opaddr);
}
bytes = optimize;
}

try
{
var outjson = vmtool.FuncExport.Export(module, bytes);
var outjson = vmtool.FuncExport.Export(module, bytes, addrConvTable);
StringBuilder sb = new StringBuilder();
outjson.ConvertToStringWithFormat(sb, 0);
jsonstr = sb.ToString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace Neo.Compiler.MSIL.UnitTests.TestClasses
{
public class Contract_ABIOffset : SmartContract.Framework.SmartContract
{
public static void Main(string method, object[] args)
{
UnitTest_001();
UnitTest_002();
UnitTest_003();
UnitTest_004();
}
public static byte[] UnitTest_001()
{
var nb = new byte[] { 1, 2, 3, 4 };
return nb;
}
public static byte[] UnitTest_002()
{
var nb = new byte[] { 1, 2, 3, 4 };
return nb;
}
public static byte[] UnitTest_003()
{
var nb = new byte[] { 1, 2, 3, 4 };
return nb;
}
public static byte[] UnitTest_004()
{
var nb = new byte[] { 1, 2, 3, 4 };
return nb;
}

}
}
41 changes: 41 additions & 0 deletions tests/Neo.Compiler.MSIL.UnitTests/UnitTest_ABI_Offset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Compiler.MSIL.UnitTests.Utils;
using Neo.VM.Types;
using System;

namespace Neo.Compiler.MSIL.UnitTests
{
[TestClass]
public class UnitTest_ABI_Offset
{
[TestMethod]
public void UnitTest_TestABIOffsetWithoutOptimizer()
{
var testengine = new TestEngine();
testengine.AddEntryScript("./TestClasses/Contract_ABIOffset.cs", true, false);
var abi = testengine.ScriptEntry.finialABI;

var methodsABI = abi["methods"].AsList();
Assert.AreEqual("0", methodsABI[0].GetDictItem("offset").ToString());
Assert.AreEqual("32", methodsABI[1].GetDictItem("offset").ToString());
Assert.AreEqual("39", methodsABI[2].GetDictItem("offset").ToString());
Assert.AreEqual("46", methodsABI[3].GetDictItem("offset").ToString());
Assert.AreEqual("53", methodsABI[4].GetDictItem("offset").ToString());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good. it would be good to have a method with different size in order to emphasize that the offset is dynamic, right
?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this sense, we could have a non-linear relation with the optimizer as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has been modified.

}

[TestMethod]
public void UnitTest_TestABIOffsetWithOptimizer()
{
var testengine = new TestEngine();
testengine.AddEntryScript("./TestClasses/Contract_ABIOffset.cs", true, true);
var abi = testengine.ScriptEntry.finialABI;

var methodsABI = abi["methods"].AsList();
Assert.AreEqual("0", methodsABI[0].GetDictItem("offset").ToString());
Assert.AreEqual("16", methodsABI[1].GetDictItem("offset").ToString());
Assert.AreEqual("23", methodsABI[2].GetDictItem("offset").ToString());
Assert.AreEqual("30", methodsABI[3].GetDictItem("offset").ToString());
Assert.AreEqual("37", methodsABI[4].GetDictItem("offset").ToString());
}
}
}
11 changes: 9 additions & 2 deletions tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public bool IsBuild
get;
private set;
}
public bool UseOptimizer
{
get;
private set;
}
public Exception Error
{
get;
Expand Down Expand Up @@ -44,6 +49,7 @@ public void Build(Stream fs, Stream fspdb, bool optimizer)
{
this.IsBuild = false;
this.Error = null;
this.UseOptimizer = optimizer;

var log = new DefLogger();
this.modIL = new ILModule(log);
Expand All @@ -59,6 +65,7 @@ public void Build(Stream fs, Stream fspdb, bool optimizer)
}

converterIL = new ModuleConverter(log);
Dictionary<int, int> addrConvTable = null;
ConvOption option = new ConvOption();
#if NDEBUG
try
Expand All @@ -69,7 +76,7 @@ public void Build(Stream fs, Stream fspdb, bool optimizer)
finalNEF = converterIL.outModule.Build();
if (optimizer)
{
var opbytes = NefOptimizeTool.Optimize(finalNEF);
var opbytes = NefOptimizeTool.Optimize(finalNEF, out addrConvTable);
float ratio = (opbytes.Length * 100.0f) / (float)finalNEF.Length;
log.Log("optimization ratio = " + ratio + "%");
finalNEF = opbytes;
Expand All @@ -86,7 +93,7 @@ public void Build(Stream fs, Stream fspdb, bool optimizer)
#endif
try
{
finialABI = vmtool.FuncExport.Export(converterIL.outModule, finalNEF);
finialABI = vmtool.FuncExport.Export(converterIL.outModule, finalNEF, addrConvTable);
}
catch
{
Expand Down
4 changes: 3 additions & 1 deletion tests/Neo.Compiler.MSIL.UnitTests/Utils/TestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public TestEngine(TriggerType trigger = TriggerType.Application, IVerifiable ver

public BuildScript Build(string filename, bool releaseMode = false, bool optimizer = true)
{
if (scriptsAll.ContainsKey(filename) == false)
var contains = scriptsAll.ContainsKey(filename);

if (!contains || (contains && scriptsAll[filename].UseOptimizer != optimizer))
{
scriptsAll[filename] = NeonTestTool.BuildScript(filename, releaseMode, optimizer);
}
Expand Down