From 91ac96298111a656feebb4485cc65c77e8a5916c Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sat, 3 Feb 2024 21:51:41 -0800 Subject: [PATCH 1/6] Pops and Pushes of complex types --- dergwasm_mod/Dergwasm/Runtime/Frame.cs | 77 +++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/dergwasm_mod/Dergwasm/Runtime/Frame.cs b/dergwasm_mod/Dergwasm/Runtime/Frame.cs index 7417d7e..90e49fd 100644 --- a/dergwasm_mod/Dergwasm/Runtime/Frame.cs +++ b/dergwasm_mod/Dergwasm/Runtime/Frame.cs @@ -2,7 +2,10 @@ using System.Collections.Generic; using System.Linq; using Derg.Instructions; +using Derg.Resonite; +using Derg.Wasm; using Dergwasm.Runtime; +using FrooxEngine; namespace Derg.Runtime { @@ -99,6 +102,50 @@ public List Code public T Pop() => Pop().As(); + public void Pop(out bool val) => val = (Pop().s32 != 0 ? true : false); + + public void Pop(out int val) => val = Pop().s32; + + public void Pop(out uint val) => val = Pop().u32; + + public void Pop(out long val) => val = Pop().s64; + + public void Pop(out ulong val) => val = Pop().u64; + + public void Pop(out float val) => val = Pop().f32; + + public void Pop(out double val) => val = Pop().f64; + + public void Pop(out ResoniteError val) => val = (ResoniteError)Pop().s32; + + public void Pop(out ResoniteEnv.ResoniteType val) => + val = (ResoniteEnv.ResoniteType)Pop().s32; + + public void Pop(out WasmRefID refId) + where T : class, IWorldElement => refId = new WasmRefID(Pop().u64); + + public void Pop(out Ptr ptr) + where T : struct => ptr = new Ptr(Pop().s32); + + public void Pop(out NullTerminatedString ptr) => ptr = new NullTerminatedString(Pop().s32); + + public void Pop(out Output ptr) + where T : struct => ptr = new Output(Pop().s32); + + public void Pop(out WasmArray ptr) + where T : struct => ptr = new WasmArray(Pop().s32); + + public void Pop(out Buff buff) + where T : struct + { + // The first value pushed is the first call arg. + // The first value popped is the last call arg. + // A buff argument is (data, len), so in pop order, it's (len, data). + int len = Pop().s32; + int data = Pop().s32; + buff = new Buff(len, data); + } + public void Push(in T value) => value_stack.Push(Value.From(value)); public void Push(Value val) => value_stack.Push(val); @@ -117,6 +164,32 @@ public List Code public void Push(double val) => Push(new Value { f64 = val }); + public void Push(ResoniteError val) => Push((int)val); + + public void Push(ResoniteEnv.ResoniteType val) => Push((int)val); + + public void Push(WasmRefID val) + where T : class, IWorldElement => Push(val.Id); + + public void Push(Ptr val) + where T : struct => Push(val.Addr); + + public void Push(NullTerminatedString val) => Push(val.Data.Addr); + + public void Push(Output val) + where T : struct => Push(val.Ptr.Addr); + + public void Push(WasmArray val) + where T : struct => Push(val.Data.Addr); + + public void Push(Buff val) + where T : struct + { + // A buff argument is (data, len). + Push(val.Ptr.Addr); + Push(val.Length); + } + public int StackLevel() => value_stack.Count; public Label PopLabel() => label_stack.Pop(); @@ -160,8 +233,8 @@ void InvokeHostFunc(Machine machine, HostFunc f) Frame next_frame = new HostFrame(f, Module, this); - // The first value pushed is the first local. - // The first value popped is the first local. + // The first value pushed is the first local (first call arg). + // The first value popped is the last local (last call arg). for (int i = args - 1; i >= 0; --i) { next_frame.Locals[i] = value_stack.Pop(); From 48e5b27149346490f97e0eab772de63376544f69 Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sun, 4 Feb 2024 10:11:52 -0800 Subject: [PATCH 2/6] Attempt at pop --- dergwasm_mod/Benchmarks/Program.cs | 56 +++++----- .../Dergwasm/Modules/ModuleReflector.cs | 103 +++++++++++++----- dergwasm_mod/DergwasmTests/FrameTests.cs | 66 +++++++++++ 3 files changed, 172 insertions(+), 53 deletions(-) create mode 100644 dergwasm_mod/DergwasmTests/FrameTests.cs diff --git a/dergwasm_mod/Benchmarks/Program.cs b/dergwasm_mod/Benchmarks/Program.cs index a005311..325f616 100644 --- a/dergwasm_mod/Benchmarks/Program.cs +++ b/dergwasm_mod/Benchmarks/Program.cs @@ -13,6 +13,7 @@ using FrooxEngine; using static Derg.ResoniteEnv; using Dergwasm.Runtime; +using System.Reflection; namespace DergwasmTests { @@ -136,19 +137,20 @@ public void Nop() } } - // BenchmarkDotNet v0.13.10, Windows 10 (10.0.19045.3693/22H2/2022Update) - // Intel Core i7-7660U CPU 2.50GHz(Kaby Lake), 1 CPU, 4 logical and 2 physical cores - // [Host] : .NET Framework 4.8.1 (4.8.9195.0), X64 RyuJIT VectorSize=256 [AttachedDebugger] - // .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9195.0), X64 RyuJIT VectorSize=256 + // BenchmarkDotNet v0.13.10, Windows 11 (10.0.22621.3007/22H2/2022Update/SunValley2) + // 11th Gen Intel Core i7-11700K 3.60GHz, 1 CPU, 16 logical and 8 physical cores + // [Host] : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 [AttachedDebugger] + // .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 // // Job=.NET Framework 4.7.2 Runtime=.NET Framework 4.7.2 // - // | Method | N | Mean | Error | StdDev | Ratio | RatioSD | - // |------------------- |---- |---------:|----------:|----------:|------:|--------:| - // | BaselinePushPopInt | 100 | 1.223 us | 0.0092 us | 0.0082 us | 1.00 | 0.00 | - // | PopAsInt | 100 | 1.506 us | 0.0191 us | 0.0169 us | 1.23 | 0.02 | - // | PushOverloadInt | 100 | 1.240 us | 0.0225 us | 0.0350 us | 1.03 | 0.04 | - // | PushGenericInt | 100 | 1.485 us | 0.0120 us | 0.0106 us | 1.21 | 0.01 | + // | Method | N | Mean | Error | StdDev | Ratio | + // |------------------- |---- |---------:|----------:|----------:|------:| + // | BaselinePushPopInt | 100 | 1.111 us | 0.0015 us | 0.0014 us | 1.00 | + // | PopAsInt | 100 | 1.357 us | 0.0012 us | 0.0010 us | 1.22 | + // | PopOutInt | 100 | 1.122 us | 0.0022 us | 0.0021 us | 1.01 | + // | PushOverloadInt | 100 | 1.121 us | 0.0012 us | 0.0011 us | 1.01 | + // | PushGenericInt | 100 | 1.280 us | 0.0013 us | 0.0011 us | 1.15 | [SimpleJob(RuntimeMoniker.Net472, baseline: true)] public class PushPop : TestMachine { @@ -163,16 +165,6 @@ public void Setup() frame = CreateFrame(); } - // BenchmarkDotNet v0.13.10, Windows 11 (10.0.22621.2428/22H2/2022Update/SunValley2) - // 11th Gen Intel Core i7-11700K 3.60GHz, 1 CPU, 16 logical and 8 physical cores - // [Host] : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 - // .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 - // - // Job=.NET Framework 4.7.2 Runtime=.NET Framework 4.7.2 - // - // | Method | Mean | Error | StdDev | Median | Ratio | - // |----------- |---------:|---------:|---------:|---------:|------:| - // | PushPopInt | 22.30 ns | 0.414 ns | 0.991 ns | 21.96 ns | 1.00 | [Benchmark(Baseline = true)] public int BaselinePushPopInt() { @@ -197,6 +189,20 @@ public int PopAsInt() return x; } + [Benchmark] + public int PopOutInt() + { + int x = 0; + int y; + for (int i = 0; i < N; i++) + { + frame.Push(new Value { s32 = 1 }); + frame.Pop(out y); + x += y; + } + return x; + } + [Benchmark] public int PushOverloadInt() { @@ -222,16 +228,16 @@ public int PushGenericInt() } } - // BenchmarkDotNet v0.13.10, Windows 10 (10.0.19045.3930/22H2/2022Update) - // Intel Core i7-7660U CPU 2.50GHz(Kaby Lake), 1 CPU, 4 logical and 2 physical cores - // [Host] : .NET Framework 4.8.1 (4.8.9195.0), X64 RyuJIT VectorSize=256 [AttachedDebugger] - // .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9195.0), X64 RyuJIT VectorSize=256 + // BenchmarkDotNet v0.13.10, Windows 11 (10.0.22621.3007/22H2/2022Update/SunValley2) + // 11th Gen Intel Core i7-11700K 3.60GHz, 1 CPU, 16 logical and 8 physical cores + // [Host] : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 [AttachedDebugger] + // .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256 // // Job=.NET Framework 4.7.2 Runtime=.NET Framework 4.7.2 // // | Method | N | Mean | Error | StdDev | Ratio | // |------------- |----- |---------:|--------:|--------:|------:| - // | HostFuncCall | 1000 | 314.0 us | 4.39 us | 4.11 us | 1.00 | + // | HostFuncCall | 1000 | 291.5 us | 0.76 us | 0.59 us | 1.00 | [SimpleJob(RuntimeMoniker.Net472, baseline: true)] public class HostFuncCallBenchmark : InstructionTestFixture { diff --git a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs index 35cee04..3c7cd7e 100644 --- a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs +++ b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs @@ -157,49 +157,96 @@ ApiFunc funcData var machine = Expression.Parameter(typeof(Machine), "machine"); var frame = Expression.Parameter(typeof(Frame), "frame"); - // Parameter Processing - var argsCount = 0; - var parameters = new List(); + var expressions = new List(); foreach (var param in method.GetParameters()) { if (param.ParameterType == typeof(Machine)) { - parameters.Add(machine); + expressions.Add(machine); + continue; } else if (param.ParameterType == typeof(Frame)) { - parameters.Add(frame); + expressions.Add(frame); + continue; } - else + + // Declare a local var for the popped value. + ParameterExpression poppedValue = Expression.Variable( + param.ParameterType, + param.Name + ); + expressions.Add(poppedValue); + + // Call the appropriate pop method for the type. + string refTypeName = param.ParameterType.MakeByRefType().Name; + MethodInfo popper = typeof(Frame) + .GetMethods() + .Where(m => m.Name == "Pop") + .Where(m => m.GetParameters().Length == 1) + .Where(m => m.GetParameters()[0].IsOut) + .Where(m => m.GetParameters()[0].ParameterType.Name == refTypeName) + .First(); + MethodCallExpression popperCaller = Expression.Call(frame, popper, poppedValue); + expressions.Add(popperCaller); + + funcData.Parameters.Add( + new Parameter + { + Name = param.Name, + Type = ValueTypeFor(param.ParameterType), + CSType = param.ParameterType.GetNiceName() + } + ); + funcData.ParameterValueTypes.Add(ValueTypeFor(param.ParameterType)); + } + + if (false) + { + // Parameter Processing + var argsCount = 0; + var parameters = new List(); + foreach (var param in method.GetParameters()) { - parameters.Add( - Expression.Call( - Expression.ArrayIndex( - Expression.PropertyOrField(frame, nameof(Frame.Locals)), - Expression.Constant(argsCount) - ), - typeof(Value) - .GetMethod(nameof(Value.As)) - .MakeGenericMethod(param.ParameterType) - ) - ); + if (param.ParameterType == typeof(Machine)) + { + parameters.Add(machine); + } + else if (param.ParameterType == typeof(Frame)) + { + parameters.Add(frame); + } + else + { + parameters.Add( + Expression.Call( + Expression.ArrayIndex( + Expression.PropertyOrField(frame, nameof(Frame.Locals)), + Expression.Constant(argsCount) + ), + typeof(Value) + .GetMethod(nameof(Value.As)) + .MakeGenericMethod(param.ParameterType) + ) + ); - funcData.Parameters.Add( - new Parameter - { - Name = param.Name, - Type = ValueTypeFor(param.ParameterType), - CSType = param.ParameterType.GetNiceName() - } - ); - funcData.ParameterValueTypes.Add(ValueTypeFor(param.ParameterType)); + funcData.Parameters.Add( + new Parameter + { + Name = param.Name, + Type = ValueTypeFor(param.ParameterType), + CSType = param.ParameterType.GetNiceName() + } + ); + funcData.ParameterValueTypes.Add(ValueTypeFor(param.ParameterType)); - argsCount++; + argsCount++; + } } } // The actual inner call. - var result = Expression.Call(method.IsStatic ? null : context, method, parameters); + var result = Expression.Call(method.IsStatic ? null : context, method, expressions); var returnsCount = 0; if (method.ReturnType != typeof(void)) diff --git a/dergwasm_mod/DergwasmTests/FrameTests.cs b/dergwasm_mod/DergwasmTests/FrameTests.cs new file mode 100644 index 0000000..b0f7888 --- /dev/null +++ b/dergwasm_mod/DergwasmTests/FrameTests.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Derg.Wasm; +using Derg.Runtime; +using Elements.Core; +using FrooxEngine; +using Xunit; +using Derg; +using System.Reflection; +using System.Linq.Expressions; + +namespace DergwasmTests +{ + public class FrameTests + { + [Fact] + public void TestFrame() + { + Frame f = new Frame(null, null, null); + f.Push(2); + f.Push(3); + + var expressions = new List(); + + MethodInfo method = typeof(Frame) + .GetMethods() + .Where(m => m.Name == "Pop") + .Where(m => m.GetParameters().Length == 1) + .Where(m => m.GetParameters()[0].IsOut) + .Where( + m => m.GetParameters()[0].ParameterType.Name == typeof(int).MakeByRefType().Name + ) + .First(); + + var locals = new List(); + var popperCallers = new List(); + + ParameterExpression frame = Expression.Variable(typeof(Frame), "frame"); + ParameterExpression x = Expression.Variable(typeof(int), "x"); + ParameterExpression y = Expression.Variable(typeof(int), "y"); + locals.Add(frame); + locals.Add(x); + locals.Add(y); + + MethodCallExpression callx = Expression.Call(frame, method, x); + MethodCallExpression cally = Expression.Call(frame, method, y); + popperCallers.Add(callx); + popperCallers.Add(cally); + + BlockExpression block = Expression.Block( + new[] { x, y }, + callx, + cally, + Expression.AddAssign(x, y), + x + ); + + var thing = Expression.Lambda>(block, frame).Compile(); + + Assert.Equal(5, thing(f)); + } + } +} From 8bacd874d2d26254dc177310215457b48dccdc5b Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sun, 4 Feb 2024 11:12:04 -0800 Subject: [PATCH 3/6] Corrects poppers --- .../Dergwasm/Modules/ModuleReflector.cs | 28 +++++++++---- dergwasm_mod/Dergwasm/Runtime/Frame.cs | 16 ++++---- dergwasm_mod/DergwasmTests/FrameTests.cs | 39 +++++++++++-------- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs index 3c7cd7e..8ce82dd 100644 --- a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs +++ b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs @@ -157,17 +157,19 @@ ApiFunc funcData var machine = Expression.Parameter(typeof(Machine), "machine"); var frame = Expression.Parameter(typeof(Frame), "frame"); - var expressions = new List(); + var poppers = new List(); + var callParams = new List(); + var outVars = new List(); foreach (var param in method.GetParameters()) { if (param.ParameterType == typeof(Machine)) { - expressions.Add(machine); + callParams.Add(machine); continue; } else if (param.ParameterType == typeof(Frame)) { - expressions.Add(frame); + callParams.Add(frame); continue; } @@ -176,7 +178,8 @@ ApiFunc funcData param.ParameterType, param.Name ); - expressions.Add(poppedValue); + callParams.Add(poppedValue); + outVars.Add(poppedValue); // Call the appropriate pop method for the type. string refTypeName = param.ParameterType.MakeByRefType().Name; @@ -187,8 +190,12 @@ ApiFunc funcData .Where(m => m.GetParameters()[0].IsOut) .Where(m => m.GetParameters()[0].ParameterType.Name == refTypeName) .First(); + if (param.ParameterType.IsGenericType) + { + popper = popper.MakeGenericMethod(param.ParameterType.GetGenericArguments()); + } MethodCallExpression popperCaller = Expression.Call(frame, popper, poppedValue); - expressions.Add(popperCaller); + poppers.Add(popperCaller); funcData.Parameters.Add( new Parameter @@ -201,6 +208,10 @@ ApiFunc funcData funcData.ParameterValueTypes.Add(ValueTypeFor(param.ParameterType)); } + // The poppers need to be reversed. The first value pushed is the first call arg, + // which means that the first value popped is the *last* call arg. + poppers.Reverse(); + if (false) { // Parameter Processing @@ -246,7 +257,7 @@ ApiFunc funcData } // The actual inner call. - var result = Expression.Call(method.IsStatic ? null : context, method, expressions); + var result = Expression.Call(method.IsStatic ? null : context, method, callParams); var returnsCount = 0; if (method.ReturnType != typeof(void)) @@ -273,9 +284,12 @@ ApiFunc funcData // TODO: Add the ability to process value tuple based return values. } + poppers.Add(result); + + BlockExpression block = Expression.Block(outVars.ToArray(), poppers); // This is the invoked callsite. To improve per-call performance, optimize the expression structure going into this compilation. - var callImpl = Expression.Lambda(result, machine, frame); + var callImpl = Expression.Lambda(block, machine, frame); var funcCtor = Expression.New( typeof(HostFunc).GetConstructors().First(), diff --git a/dergwasm_mod/Dergwasm/Runtime/Frame.cs b/dergwasm_mod/Dergwasm/Runtime/Frame.cs index 90e49fd..02c43e4 100644 --- a/dergwasm_mod/Dergwasm/Runtime/Frame.cs +++ b/dergwasm_mod/Dergwasm/Runtime/Frame.cs @@ -231,21 +231,21 @@ void InvokeHostFunc(Machine machine, HostFunc f) int arity = f.Signature.returns.Length; int args = f.Signature.args.Length; - Frame next_frame = new HostFrame(f, Module, this); + //Frame next_frame = new HostFrame(f, Module, this); // The first value pushed is the first local (first call arg). // The first value popped is the last local (last call arg). - for (int i = args - 1; i >= 0; --i) - { - next_frame.Locals[i] = value_stack.Pop(); - } + //for (int i = args - 1; i >= 0; --i) + //{ + // next_frame.Locals[i] = value_stack.Pop(); + //} // For consistency, we also stick a label in. - next_frame.Label = new Label(arity, 0); + //next_frame.Label = new Label(arity, 0); - f.Proxy.Invoke(machine, next_frame); + f.Proxy.Invoke(machine, this); - next_frame.EndFrame(); + //next_frame.EndFrame(); } // Executes a module function call. This sets up a new frame, pops the args off the current frame and diff --git a/dergwasm_mod/DergwasmTests/FrameTests.cs b/dergwasm_mod/DergwasmTests/FrameTests.cs index b0f7888..8127895 100644 --- a/dergwasm_mod/DergwasmTests/FrameTests.cs +++ b/dergwasm_mod/DergwasmTests/FrameTests.cs @@ -20,8 +20,8 @@ public class FrameTests public void TestFrame() { Frame f = new Frame(null, null, null); - f.Push(2); - f.Push(3); + f.Push(2UL); + f.Push(3UL); var expressions = new List(); @@ -31,36 +31,43 @@ public void TestFrame() .Where(m => m.GetParameters().Length == 1) .Where(m => m.GetParameters()[0].IsOut) .Where( - m => m.GetParameters()[0].ParameterType.Name == typeof(int).MakeByRefType().Name + m => + m.GetParameters()[0].ParameterType.Name + == typeof(WasmRefID).MakeByRefType().Name ) .First(); + Type t = typeof(WasmRefID); + Type innerType = t.GetGenericArguments()[0]; + var locals = new List(); var popperCallers = new List(); ParameterExpression frame = Expression.Variable(typeof(Frame), "frame"); - ParameterExpression x = Expression.Variable(typeof(int), "x"); - ParameterExpression y = Expression.Variable(typeof(int), "y"); + ParameterExpression x = Expression.Variable(t, "x"); + ParameterExpression y = Expression.Variable(t, "y"); locals.Add(frame); locals.Add(x); locals.Add(y); - MethodCallExpression callx = Expression.Call(frame, method, x); - MethodCallExpression cally = Expression.Call(frame, method, y); + MethodCallExpression callx = Expression.Call( + frame, + method.MakeGenericMethod(innerType), + x + ); + MethodCallExpression cally = Expression.Call( + frame, + method.MakeGenericMethod(innerType), + y + ); popperCallers.Add(callx); popperCallers.Add(cally); - BlockExpression block = Expression.Block( - new[] { x, y }, - callx, - cally, - Expression.AddAssign(x, y), - x - ); + BlockExpression block = Expression.Block(new[] { x, y }, callx, cally, x); - var thing = Expression.Lambda>(block, frame).Compile(); + var thing = Expression.Lambda>>(block, frame).Compile(); - Assert.Equal(5, thing(f)); + Assert.Equal(3UL, thing(f).Id); } } } From bd59835db44e9e76b7e514f5aedc695705c08d68 Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sun, 4 Feb 2024 11:25:26 -0800 Subject: [PATCH 4/6] Updates benchmark numbers for HostFuncCallBenchmark --- dergwasm_mod/Benchmarks/Program.cs | 2 ++ dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dergwasm_mod/Benchmarks/Program.cs b/dergwasm_mod/Benchmarks/Program.cs index 325f616..cdb0576 100644 --- a/dergwasm_mod/Benchmarks/Program.cs +++ b/dergwasm_mod/Benchmarks/Program.cs @@ -238,7 +238,9 @@ public int PushGenericInt() // | Method | N | Mean | Error | StdDev | Ratio | // |------------- |----- |---------:|--------:|--------:|------:| // | HostFuncCall | 1000 | 291.5 us | 0.76 us | 0.59 us | 1.00 | + // | HostFuncCall | 1000 | 152.0 us | 0.33 us | 0.25 us | 1.00 | [SimpleJob(RuntimeMoniker.Net472, baseline: true)] + [MemoryDiagnoser] public class HostFuncCallBenchmark : InstructionTestFixture { [Params(1000)] diff --git a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs index 8ce82dd..12554c6 100644 --- a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs +++ b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs @@ -256,7 +256,7 @@ ApiFunc funcData } } - // The actual inner call. + // The actual inner call to the host func. var result = Expression.Call(method.IsStatic ? null : context, method, callParams); var returnsCount = 0; @@ -288,7 +288,8 @@ ApiFunc funcData BlockExpression block = Expression.Block(outVars.ToArray(), poppers); - // This is the invoked callsite. To improve per-call performance, optimize the expression structure going into this compilation. + // This is the invoked callsite. To improve per-call performance, optimize the expression + // structure going into this compilation. var callImpl = Expression.Lambda(block, machine, frame); var funcCtor = Expression.New( From 6b4b58fb06c9c3e13d256090a3dd6182b0d26148 Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sun, 4 Feb 2024 11:32:03 -0800 Subject: [PATCH 5/6] Update benchmark with memory --- dergwasm_mod/Benchmarks/Program.cs | 7 ++- .../Dergwasm/Modules/ModuleReflector.cs | 44 ------------------- 2 files changed, 3 insertions(+), 48 deletions(-) diff --git a/dergwasm_mod/Benchmarks/Program.cs b/dergwasm_mod/Benchmarks/Program.cs index cdb0576..7b9a890 100644 --- a/dergwasm_mod/Benchmarks/Program.cs +++ b/dergwasm_mod/Benchmarks/Program.cs @@ -235,10 +235,9 @@ public int PushGenericInt() // // Job=.NET Framework 4.7.2 Runtime=.NET Framework 4.7.2 // - // | Method | N | Mean | Error | StdDev | Ratio | - // |------------- |----- |---------:|--------:|--------:|------:| - // | HostFuncCall | 1000 | 291.5 us | 0.76 us | 0.59 us | 1.00 | - // | HostFuncCall | 1000 | 152.0 us | 0.33 us | 0.25 us | 1.00 | + // | Method | N | Mean | Error | StdDev | Ratio | Allocated | Alloc Ratio | + // |------------- |----- |---------:|--------:|--------:|------:|----------:|------------:| + // | HostFuncCall | 1000 | 151.0 us | 0.18 us | 0.17 us | 1.00 | - | NA | [SimpleJob(RuntimeMoniker.Net472, baseline: true)] [MemoryDiagnoser] public class HostFuncCallBenchmark : InstructionTestFixture diff --git a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs index 12554c6..0e8f6cc 100644 --- a/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs +++ b/dergwasm_mod/Dergwasm/Modules/ModuleReflector.cs @@ -212,50 +212,6 @@ ApiFunc funcData // which means that the first value popped is the *last* call arg. poppers.Reverse(); - if (false) - { - // Parameter Processing - var argsCount = 0; - var parameters = new List(); - foreach (var param in method.GetParameters()) - { - if (param.ParameterType == typeof(Machine)) - { - parameters.Add(machine); - } - else if (param.ParameterType == typeof(Frame)) - { - parameters.Add(frame); - } - else - { - parameters.Add( - Expression.Call( - Expression.ArrayIndex( - Expression.PropertyOrField(frame, nameof(Frame.Locals)), - Expression.Constant(argsCount) - ), - typeof(Value) - .GetMethod(nameof(Value.As)) - .MakeGenericMethod(param.ParameterType) - ) - ); - - funcData.Parameters.Add( - new Parameter - { - Name = param.Name, - Type = ValueTypeFor(param.ParameterType), - CSType = param.ParameterType.GetNiceName() - } - ); - funcData.ParameterValueTypes.Add(ValueTypeFor(param.ParameterType)); - - argsCount++; - } - } - } - // The actual inner call to the host func. var result = Expression.Call(method.IsStatic ? null : context, method, callParams); From e1e8f13113d8d451e0a6bc3808a12e4f04e977e6 Mon Sep 17 00:00:00 2001 From: Robert Baruch Date: Sun, 4 Feb 2024 11:33:57 -0800 Subject: [PATCH 6/6] Cleans up InvokeHostFunc --- dergwasm_mod/Dergwasm/Runtime/Frame.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/dergwasm_mod/Dergwasm/Runtime/Frame.cs b/dergwasm_mod/Dergwasm/Runtime/Frame.cs index 02c43e4..d6a0876 100644 --- a/dergwasm_mod/Dergwasm/Runtime/Frame.cs +++ b/dergwasm_mod/Dergwasm/Runtime/Frame.cs @@ -228,24 +228,7 @@ void InvokeHostFunc(Machine machine, HostFunc f) if (machine.Debug) Console.WriteLine($"Invoking host func {f.ModuleName}.{f.Name}"); - int arity = f.Signature.returns.Length; - int args = f.Signature.args.Length; - - //Frame next_frame = new HostFrame(f, Module, this); - - // The first value pushed is the first local (first call arg). - // The first value popped is the last local (last call arg). - //for (int i = args - 1; i >= 0; --i) - //{ - // next_frame.Locals[i] = value_stack.Pop(); - //} - - // For consistency, we also stick a label in. - //next_frame.Label = new Label(arity, 0); - f.Proxy.Invoke(machine, this); - - //next_frame.EndFrame(); } // Executes a module function call. This sets up a new frame, pops the args off the current frame and