internal static TranslatedFunction Translate(IMemoryManager memory, JumpTable jumpTable, ulong address, ExecutionMode mode, bool highCq) { ArmEmitterContext context = new ArmEmitterContext(memory, jumpTable, address, highCq, Aarch32Mode.User); Logger.StartPass(PassName.Decoding); Block[] blocks = Decoder.Decode(memory, address, mode, highCq, singleBlock: false); Logger.EndPass(PassName.Decoding); PreparePool(highCq ? 1 : 0); Logger.StartPass(PassName.Translation); EmitSynchronization(context); if (blocks[0].Address != address) { context.Branch(context.GetLabel(address)); } ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange); ulong funcSize = funcRange.End - funcRange.Start; Logger.EndPass(PassName.Translation); Logger.StartPass(PassName.RegisterUsage); RegisterUsage.RunPass(cfg, mode); Logger.EndPass(PassName.RegisterUsage); OperandType[] argTypes = new OperandType[] { OperandType.I64 }; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; GuestFunction func; if (Ptc.State == PtcState.Disabled) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options); ResetPool(highCq ? 1 : 0); } else { using PtcInfo ptcInfo = new PtcInfo(); func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); ResetPool(highCq ? 1 : 0); Hash128 hash = Ptc.ComputeHash(memory, address, funcSize); Ptc.WriteInfoCodeRelocUnwindInfo(address, funcSize, hash, highCq, ptcInfo); } return(new TranslatedFunction(func, funcSize, highCq)); }
internal static TranslatedFunction Translate(IMemoryManager memory, JumpTable jumpTable, ulong address, ExecutionMode mode, bool highCq) { ArmEmitterContext context = new ArmEmitterContext(memory, jumpTable, (long)address, highCq, Aarch32Mode.User); PrepareOperandPool(highCq); PrepareOperationPool(highCq); Logger.StartPass(PassName.Decoding); Block[] blocks = Decoder.DecodeFunction(memory, address, mode, highCq); Logger.EndPass(PassName.Decoding); Logger.StartPass(PassName.Translation); EmitSynchronization(context); if (blocks[0].Address != address) { context.Branch(context.GetLabel(address)); } ControlFlowGraph cfg = EmitAndGetCFG(context, blocks); Logger.EndPass(PassName.Translation); Logger.StartPass(PassName.RegisterUsage); RegisterUsage.RunPass(cfg, mode, isCompleteFunction: false); Logger.EndPass(PassName.RegisterUsage); OperandType[] argTypes = new OperandType[] { OperandType.I64 }; CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; GuestFunction func; if (Ptc.State == PtcState.Disabled) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options); } else { using (PtcInfo ptcInfo = new PtcInfo()) { func = Compiler.Compile <GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); Ptc.WriteInfoCodeReloc((long)address, highCq, ptcInfo); } } ResetOperandPool(highCq); ResetOperationPool(highCq); return(new TranslatedFunction(func, highCq)); }
public ArmEmitterContext(MemoryManager memory, JumpTable jumpTable, long baseAddress, bool highCq, Aarch32Mode mode) { Memory = memory; JumpTable = jumpTable; BaseAddress = baseAddress; HighCq = highCq; Mode = mode; _labels = new Dictionary <ulong, Operand>(); }
public Translator(MemoryManager memory) { _memory = memory; _funcs = new ConcurrentDictionary <ulong, TranslatedFunction>(); _jumpTable = JumpTable.Instance; _backgroundQueue = new PriorityQueue <RejitRequest>(2); _backgroundTranslatorEvent = new AutoResetEvent(false); DirectCallStubs.InitializeStubs(); }
public ArmEmitterContext( IMemoryManager memory, JumpTable jumpTable, EntryTable <uint> countTable, ulong entryAddress, bool highCq, Aarch32Mode mode) { Memory = memory; JumpTable = jumpTable; CountTable = countTable; EntryAddress = entryAddress; HighCq = highCq; Mode = mode; _labels = new Dictionary <ulong, Operand>(); }
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory) { _memory = memory; _funcs = new ConcurrentDictionary <ulong, TranslatedFunction>(); _backgroundStack = new ConcurrentStack <RejitRequest>(); _backgroundTranslatorEvent = new AutoResetEvent(false); _jumpTable = new JumpTable(allocator); JitCache.Initialize(allocator); DirectCallStubs.InitializeStubs(); if (Ptc.State == PtcState.Enabled) { Ptc.LoadTranslations(_funcs, memory.PageTablePointer, _jumpTable); } }
public void Execute(State.ExecutionContext context, ulong address) { if (Interlocked.Increment(ref _threadCount) == 1) { IsReadyForTranslation.WaitOne(); Debug.Assert(_jumpTable == null); _jumpTable = new JumpTable(_allocator); if (Ptc.State == PtcState.Enabled) { Debug.Assert(_funcs.Count == 0); Ptc.LoadTranslations(_funcs, _memory, _jumpTable); Ptc.MakeAndSaveTranslations(_funcs, _memory, _jumpTable); } PtcProfiler.Start(); Ptc.Disable(); // Simple heuristic, should be user configurable in future. (1 for 4 core/ht or less, 2 for 6 core+ht etc). // All threads are normal priority except from the last, which just fills as much of the last core as the os lets it with a low priority. // If we only have one rejit thread, it should be normal priority as highCq code is performance critical. // TODO: Use physical cores rather than logical. This only really makes sense for processors with hyperthreading. Requires OS specific code. int unboundedThreadCount = Math.Max(1, (Environment.ProcessorCount - 6) / 3); int threadCount = Math.Min(4, unboundedThreadCount); for (int i = 0; i < threadCount; i++) { bool last = i != 0 && i == unboundedThreadCount - 1; Thread backgroundTranslatorThread = new Thread(TranslateStackedSubs) { Name = "CPU.BackgroundTranslatorThread." + i, Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal }; backgroundTranslatorThread.Start(); } } Statistics.InitializeTimer(); NativeInterface.RegisterThread(context, _memory, this); do { address = ExecuteSingle(context, address); }while (context.Running && address != 0); NativeInterface.UnregisterThread(); if (Interlocked.Decrement(ref _threadCount) == 0) { _backgroundTranslatorEvent.Set(); ClearJitCache(); DisposePools(); _jumpTable.Dispose(); _jumpTable = null; GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; } }
static JumpTable() { Instance = new JumpTable(); }