Move the MakeOp to OpCodeTable class, for reduce the use of ConcurrentDictionary (#996)

This commit is contained in:
Chenj168 2020-03-20 13:15:37 +09:00 committed by GitHub
parent 8e64984158
commit 31b94f4641
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 47 deletions

View file

@ -3,9 +3,7 @@ using ARMeilleure.Instructions;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Emit;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
@ -19,15 +17,6 @@ namespace ARMeilleure.Decoders
// For lower code quality translation, we set a lower limit since we're blocking execution. // For lower code quality translation, we set a lower limit since we're blocking execution.
private const int MaxInstsPerFunctionLowCq = 500; private const int MaxInstsPerFunctionLowCq = 500;
private delegate object MakeOp(InstDescriptor inst, ulong address, int opCode);
private static ConcurrentDictionary<Type, MakeOp> _opActivators;
static Decoder()
{
_opActivators = new ConcurrentDictionary<Type, MakeOp>();
}
public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode) public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode)
{ {
Block block = new Block(address); Block block = new Block(address);
@ -319,56 +308,32 @@ namespace ARMeilleure.Decoders
InstDescriptor inst; InstDescriptor inst;
Type type; OpCodeTable.MakeOp makeOp;
if (mode == ExecutionMode.Aarch64) if (mode == ExecutionMode.Aarch64)
{ {
(inst, type) = OpCodeTable.GetInstA64(opCode); (inst, makeOp) = OpCodeTable.GetInstA64(opCode);
} }
else else
{ {
if (mode == ExecutionMode.Aarch32Arm) if (mode == ExecutionMode.Aarch32Arm)
{ {
(inst, type) = OpCodeTable.GetInstA32(opCode); (inst, makeOp) = OpCodeTable.GetInstA32(opCode);
} }
else /* if (mode == ExecutionMode.Aarch32Thumb) */ else /* if (mode == ExecutionMode.Aarch32Thumb) */
{ {
(inst, type) = OpCodeTable.GetInstT32(opCode); (inst, makeOp) = OpCodeTable.GetInstT32(opCode);
} }
} }
if (type != null) if (makeOp != null)
{ {
return MakeOpCode(inst, type, address, opCode); return (OpCode)makeOp(inst, address, opCode);
} }
else else
{ {
return new OpCode(inst, address, opCode); return new OpCode(inst, address, opCode);
} }
} }
private static OpCode MakeOpCode(InstDescriptor inst, Type type, ulong address, int opCode)
{
MakeOp createInstance = _opActivators.GetOrAdd(type, CacheOpActivator);
return (OpCode)createInstance(inst, address, opCode);
}
private static MakeOp CacheOpActivator(Type type)
{
Type[] argTypes = new Type[] { typeof(InstDescriptor), typeof(ulong), typeof(int) };
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 (MakeOp)mthd.CreateDelegate(typeof(MakeOp));
}
} }
} }

View file

@ -2,11 +2,14 @@ using ARMeilleure.Instructions;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection.Emit;
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
static class OpCodeTable static class OpCodeTable
{ {
public delegate object MakeOp(InstDescriptor inst, ulong address, int opCode);
private const int FastLookupSize = 0x1000; private const int FastLookupSize = 0x1000;
private struct InstInfo private struct InstInfo
@ -18,12 +21,32 @@ namespace ARMeilleure.Decoders
public Type Type { get; } public Type Type { get; }
public MakeOp MakeOp { get; }
public InstInfo(int mask, int value, InstDescriptor inst, Type type) public InstInfo(int mask, int value, InstDescriptor inst, Type type)
{ {
Mask = mask; Mask = mask;
Value = value; Value = value;
Inst = inst; Inst = inst;
Type = type; Type = type;
MakeOp = CacheOpActivator(type);
}
private static MakeOp CacheOpActivator(Type type)
{
Type[] argTypes = new Type[] { typeof(InstDescriptor), typeof(ulong), typeof(int) };
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 (MakeOp)mthd.CreateDelegate(typeof(MakeOp));
} }
} }
@ -1034,32 +1057,32 @@ namespace ARMeilleure.Decoders
} }
} }
public static (InstDescriptor inst, Type type) GetInstA32(int opCode) public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode)
{ {
return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode); return GetInstFromList(_instA32FastLookup[ToFastLookupIndex(opCode)], opCode);
} }
public static (InstDescriptor inst, Type type) GetInstT32(int opCode) public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode)
{ {
return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode); return GetInstFromList(_instT32FastLookup[ToFastLookupIndex(opCode)], opCode);
} }
public static (InstDescriptor inst, Type type) GetInstA64(int opCode) public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode)
{ {
return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode); return GetInstFromList(_instA64FastLookup[ToFastLookupIndex(opCode)], opCode);
} }
private static (InstDescriptor inst, Type type) GetInstFromList(InstInfo[] insts, int opCode) private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)
{ {
foreach (InstInfo info in insts) foreach (InstInfo info in insts)
{ {
if ((opCode & info.Mask) == info.Value) if ((opCode & info.Mask) == info.Value)
{ {
return (info.Inst, info.Type); return (info.Inst, info.MakeOp);
} }
} }
return (new InstDescriptor(InstName.Und, InstEmit.Und), typeof(OpCode)); return (new InstDescriptor(InstName.Und, InstEmit.Und), null);
} }
private static int ToFastLookupIndex(int value) private static int ToFastLookupIndex(int value)