Exemple #1
0
        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));
        }
Exemple #2
0
        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>();
        }
Exemple #4
0
        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();
        }
Exemple #5
0
        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>();
        }
Exemple #6
0
        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);
            }
        }
Exemple #7
0
        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;
            }
        }
Exemple #8
0
 static JumpTable()
 {
     Instance = new JumpTable();
 }