From 7ad8b3ef7556bd5cfc552cad90017ab2247ffa8c Mon Sep 17 00:00:00 2001 From: Chenj168 <62330325+Chenj168@users.noreply.github.com> Date: Sun, 29 Mar 2020 16:52:56 +0800 Subject: [PATCH] Move the OpActivator to OpCodeTable class for improve performance (#1001) * Move the OpActivator to OpCodeTable class, for reduce the use of ConcurrentDictionary * Modify code style. --- Ryujinx.Graphics.Shader/Decoders/Decoder.cs | 49 +++---------------- .../Decoders/OpCodeTable.cs | 33 +++++++++++-- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index cda88302a4..3e322e453e 100644 --- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs @@ -1,10 +1,8 @@ using Ryujinx.Graphics.Shader.Instructions; using System; using System.Buffers.Binary; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Reflection.Emit; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -12,15 +10,6 @@ namespace Ryujinx.Graphics.Shader.Decoders { static class Decoder { - private delegate object OpActivator(InstEmitter emitter, ulong address, long opCode); - - private static ConcurrentDictionary _opActivators; - - static Decoder() - { - _opActivators = new ConcurrentDictionary(); - } - public static Block[] Decode(ReadOnlySpan code, ulong headerSize) { List blocks = new List(); @@ -245,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.Decoders long opCode = word0 | (long)word1 << 32; - (InstEmitter emitter, Type opCodeType) = OpCodeTable.GetEmitter(opCode); + (InstEmitter emitter, OpCodeTable.OpActivator opActivator) = OpCodeTable.GetEmitter(opCode); if (emitter == null) { @@ -256,7 +245,12 @@ namespace Ryujinx.Graphics.Shader.Decoders continue; } - OpCode op = MakeOpCode(opCodeType, emitter, opAddress, opCode); + if (opActivator == null) + { + throw new ArgumentNullException(nameof(opActivator)); + } + + OpCode op = (OpCode)opActivator(emitter, opAddress, opCode); block.OpCodes.Add(op); } @@ -295,35 +289,6 @@ namespace Ryujinx.Graphics.Shader.Decoders return opCode is OpCodeExit; } - private static OpCode MakeOpCode(Type type, InstEmitter emitter, ulong address, long opCode) - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - - OpActivator createInstance = _opActivators.GetOrAdd(type, CacheOpActivator); - - return (OpCode)createInstance(emitter, address, opCode); - } - - private static OpActivator CacheOpActivator(Type type) - { - Type[] argTypes = new Type[] { typeof(InstEmitter), typeof(ulong), typeof(long) }; - - DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes); - - ILGenerator generator = mthd.GetILGenerator(); - - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldarg_1); - generator.Emit(OpCodes.Ldarg_2); - generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes)); - generator.Emit(OpCodes.Ret); - - return (OpActivator)mthd.CreateDelegate(typeof(OpActivator)); - } - private struct PathBlockState { public Block Block { get; } diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs index e71c31867e..9835be343c 100644 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs @@ -1,10 +1,13 @@ using Ryujinx.Graphics.Shader.Instructions; using System; +using System.Reflection.Emit; namespace Ryujinx.Graphics.Shader.Decoders { static class OpCodeTable { + public delegate object OpActivator(InstEmitter emitter, ulong address, long opCode); + private const int EncodingBits = 14; private class TableEntry @@ -15,11 +18,31 @@ namespace Ryujinx.Graphics.Shader.Decoders public int XBits { get; } + public OpActivator OpActivator { get; } + public TableEntry(InstEmitter emitter, Type opCodeType, int xBits) { - Emitter = emitter; - OpCodeType = opCodeType; - XBits = xBits; + Emitter = emitter; + OpCodeType = opCodeType; + XBits = xBits; + OpActivator = CacheOpActivator(opCodeType); + } + + private static OpActivator CacheOpActivator(Type type) + { + Type[] argTypes = new Type[] { typeof(InstEmitter), typeof(ulong), typeof(long) }; + + DynamicMethod mthd = new DynamicMethod($"Make{type.Name}", type, argTypes); + + ILGenerator generator = mthd.GetILGenerator(); + + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldarg_1); + generator.Emit(OpCodes.Ldarg_2); + generator.Emit(OpCodes.Newobj, type.GetConstructor(argTypes)); + generator.Emit(OpCodes.Ret); + + return (OpActivator)mthd.CreateDelegate(typeof(OpActivator)); } } @@ -266,13 +289,13 @@ namespace Ryujinx.Graphics.Shader.Decoders } } - public static (InstEmitter emitter, Type opCodeType) GetEmitter(long opCode) + public static (InstEmitter emitter, OpActivator opActivator) GetEmitter(long opCode) { TableEntry entry = _opCodes[(ulong)opCode >> (64 - EncodingBits)]; if (entry != null) { - return (entry.Emitter, entry.OpCodeType); + return (entry.Emitter, entry.OpActivator); } return (null, null);