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; } }