From 31b94f4641894060349a55d56b22f47829c9bef6 Mon Sep 17 00:00:00 2001 From: Chenj168 <62330325+Chenj168@users.noreply.github.com> Date: Fri, 20 Mar 2020 13:15:37 +0900 Subject: [PATCH] Move the MakeOp to OpCodeTable class, for reduce the use of ConcurrentDictionary (#996) --- ARMeilleure/Decoders/Decoder.cs | 47 ++++------------------------- ARMeilleure/Decoders/OpCodeTable.cs | 35 +++++++++++++++++---- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs index 9675dc8db9..dd99f78ff6 100644 --- a/ARMeilleure/Decoders/Decoder.cs +++ b/ARMeilleure/Decoders/Decoder.cs @@ -3,9 +3,7 @@ using ARMeilleure.Instructions; using ARMeilleure.Memory; using ARMeilleure.State; using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Reflection.Emit; 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. private const int MaxInstsPerFunctionLowCq = 500; - private delegate object MakeOp(InstDescriptor inst, ulong address, int opCode); - - private static ConcurrentDictionary _opActivators; - - static Decoder() - { - _opActivators = new ConcurrentDictionary(); - } - public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode) { Block block = new Block(address); @@ -319,56 +308,32 @@ namespace ARMeilleure.Decoders InstDescriptor inst; - Type type; + OpCodeTable.MakeOp makeOp; if (mode == ExecutionMode.Aarch64) { - (inst, type) = OpCodeTable.GetInstA64(opCode); + (inst, makeOp) = OpCodeTable.GetInstA64(opCode); } else { if (mode == ExecutionMode.Aarch32Arm) { - (inst, type) = OpCodeTable.GetInstA32(opCode); + (inst, makeOp) = OpCodeTable.GetInstA32(opCode); } 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 { 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)); - } } } \ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index f255b528e8..93234b3fb7 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -2,11 +2,14 @@ using ARMeilleure.Instructions; using ARMeilleure.State; using System; using System.Collections.Generic; +using System.Reflection.Emit; namespace ARMeilleure.Decoders { static class OpCodeTable { + public delegate object MakeOp(InstDescriptor inst, ulong address, int opCode); + private const int FastLookupSize = 0x1000; private struct InstInfo @@ -18,12 +21,32 @@ namespace ARMeilleure.Decoders public Type Type { get; } + public MakeOp MakeOp { get; } + public InstInfo(int mask, int value, InstDescriptor inst, Type type) { Mask = mask; Value = value; Inst = inst; 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); } - public static (InstDescriptor inst, Type type) GetInstT32(int opCode) + public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int 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); } - 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) { 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)