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.
This commit is contained in:
Chenj168 2020-03-29 16:52:56 +08:00 committed by GitHub
parent 2816b2bf17
commit 7ad8b3ef75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 47 deletions

View file

@ -1,10 +1,8 @@
using Ryujinx.Graphics.Shader.Instructions; using Ryujinx.Graphics.Shader.Instructions;
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Emit;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
@ -12,15 +10,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
static class Decoder static class Decoder
{ {
private delegate object OpActivator(InstEmitter emitter, ulong address, long opCode);
private static ConcurrentDictionary<Type, OpActivator> _opActivators;
static Decoder()
{
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
}
public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize) public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
{ {
List<Block> blocks = new List<Block>(); List<Block> blocks = new List<Block>();
@ -245,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
long opCode = word0 | (long)word1 << 32; long opCode = word0 | (long)word1 << 32;
(InstEmitter emitter, Type opCodeType) = OpCodeTable.GetEmitter(opCode); (InstEmitter emitter, OpCodeTable.OpActivator opActivator) = OpCodeTable.GetEmitter(opCode);
if (emitter == null) if (emitter == null)
{ {
@ -256,7 +245,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
continue; 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); block.OpCodes.Add(op);
} }
@ -295,35 +289,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
return opCode is OpCodeExit; 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 private struct PathBlockState
{ {
public Block Block { get; } public Block Block { get; }

View file

@ -1,10 +1,13 @@
using Ryujinx.Graphics.Shader.Instructions; using Ryujinx.Graphics.Shader.Instructions;
using System; using System;
using System.Reflection.Emit;
namespace Ryujinx.Graphics.Shader.Decoders namespace Ryujinx.Graphics.Shader.Decoders
{ {
static class OpCodeTable static class OpCodeTable
{ {
public delegate object OpActivator(InstEmitter emitter, ulong address, long opCode);
private const int EncodingBits = 14; private const int EncodingBits = 14;
private class TableEntry private class TableEntry
@ -15,11 +18,31 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int XBits { get; } public int XBits { get; }
public OpActivator OpActivator { get; }
public TableEntry(InstEmitter emitter, Type opCodeType, int xBits) public TableEntry(InstEmitter emitter, Type opCodeType, int xBits)
{ {
Emitter = emitter; Emitter = emitter;
OpCodeType = opCodeType; OpCodeType = opCodeType;
XBits = xBits; 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)]; TableEntry entry = _opCodes[(ulong)opCode >> (64 - EncodingBits)];
if (entry != null) if (entry != null)
{ {
return (entry.Emitter, entry.OpCodeType); return (entry.Emitter, entry.OpActivator);
} }
return (null, null); return (null, null);