Example #1
0
        public static T Compile <T>(
            ControlFlowGraph cfg,
            OperandType[]    funcArgTypes,
            OperandType funcReturnType,
            CompilerOptions options)
        {
            Logger.StartPass(PassName.Dominance);

            Dominance.FindDominators(cfg);
            Dominance.FindDominanceFrontiers(cfg);

            Logger.EndPass(PassName.Dominance);

            Logger.StartPass(PassName.SsaConstruction);

            if ((options & CompilerOptions.SsaForm) != 0)
            {
                Ssa.Construct(cfg);
            }
            else
            {
                RegisterToLocal.Rename(cfg);
            }

            Logger.EndPass(PassName.SsaConstruction, cfg);

            CompilerContext cctx = new CompilerContext(cfg, funcArgTypes, funcReturnType, options);

            CompiledFunction func = CodeGenerator.Generate(cctx);

            IntPtr codePtr = JitCache.Map(func);

            return(Marshal.GetDelegateForFunctionPointer <T>(codePtr));
        }
Example #2
0
        internal TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode, bool hintRejit = false)
        {
            if (!_funcs.TryGetValue(address, out TranslatedFunction func))
            {
                func = Translate(_memory, _jumpTable, address, mode, highCq: false);

                TranslatedFunction getFunc = _funcs.GetOrAdd(address, func);

                if (getFunc != func)
                {
                    JitCache.Unmap(func.FuncPtr);
                    func = getFunc;
                }

                if (PtcProfiler.Enabled)
                {
                    PtcProfiler.AddEntry(address, mode, highCq: false);
                }
            }

            if (hintRejit && func.ShouldRejit())
            {
                _backgroundStack.Push(new RejitRequest(address, mode));
                _backgroundTranslatorEvent.Set();
            }

            return(func);
        }
Example #3
0
        public static T Compile <T>(ControlFlowGraph cfg, OperandType[] argTypes, OperandType retType, CompilerOptions options)
        {
            CompiledFunction func = Compile(cfg, argTypes, retType, options);

            IntPtr codePtr = JitCache.Map(func);

            return(Marshal.GetDelegateForFunctionPointer <T>(codePtr));
        }
Example #4
0
        public Translator(IJitMemoryAllocator allocator, IMemoryManager memory)
        {
            _memory = memory;

            _funcs = new ConcurrentDictionary <ulong, TranslatedFunction>();

            _jumpTable = new JumpTable(allocator);

            _backgroundQueue = new PriorityQueue <RejitRequest>(2);

            _backgroundTranslatorEvent = new AutoResetEvent(false);

            JitCache.Initialize(allocator);
            DirectCallStubs.InitializeStubs();
        }
Example #5
0
        public Translator(IJitMemoryAllocator allocator, IMemoryManager memory)
        {
            _allocator = allocator;
            _memory    = memory;

            _funcs    = new ConcurrentDictionary <ulong, TranslatedFunction>();
            _oldFuncs = new ConcurrentQueue <KeyValuePair <ulong, IntPtr> >();

            _backgroundStack           = new ConcurrentStack <RejitRequest>();
            _backgroundTranslatorEvent = new AutoResetEvent(false);
            _backgroundTranslatorLock  = new ReaderWriterLock();

            JitCache.Initialize(allocator);

            DirectCallStubs.InitializeStubs();
        }
Example #6
0
        private void ClearJitCache()
        {
            // Ensure no attempt will be made to compile new functions due to rejit.
            ClearRejitQueue(allowRequeue: false);

            foreach (var kv in _funcs)
            {
                JitCache.Unmap(kv.Value.FuncPtr);
            }

            _funcs.Clear();

            while (_oldFuncs.TryDequeue(out var kv))
            {
                JitCache.Unmap(kv.Value);
            }
        }
Example #7
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);
            }
        }
Example #8
0
        private static unsafe RuntimeFunction *FunctionTableHandler(ulong controlPc, IntPtr context)
        {
            int offset = (int)((long)controlPc - context.ToInt64());

            if (!JitCache.TryFind(offset, out JitCacheEntry funcEntry))
            {
                // Not found.
                return(null);
            }

            var unwindInfo = funcEntry.UnwindInfo;

            int codeIndex = 0;

            int spOffset = unwindInfo.FixedAllocSize;

            foreach (var entry in unwindInfo.PushEntries)
            {
                if (entry.Type == RegisterType.Vector)
                {
                    spOffset -= 16;
                }
            }

            for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
            {
                var entry = unwindInfo.PushEntries[index];

                if (entry.Type == RegisterType.Vector)
                {
                    ushort uwop = PackUwop(UnwindOperation.SaveXmm128, entry.StreamEndOffset, entry.Index);

                    _unwindInfo->UnwindCodes[codeIndex++] = uwop;
                    _unwindInfo->UnwindCodes[codeIndex++] = (ushort)spOffset;

                    spOffset += 16;
                }
            }

            _unwindInfo->UnwindCodes[0] = PackUwop(UnwindOperation.AllocLarge, unwindInfo.PrologueSize, 1);
            _unwindInfo->UnwindCodes[1] = (ushort)(unwindInfo.FixedAllocSize >> 0);
            _unwindInfo->UnwindCodes[2] = (ushort)(unwindInfo.FixedAllocSize >> 16);

            codeIndex += 3;

            for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
            {
                var entry = unwindInfo.PushEntries[index];

                if (entry.Type == RegisterType.Integer)
                {
                    ushort uwop = PackUwop(UnwindOperation.PushNonvol, entry.StreamEndOffset, entry.Index);

                    _unwindInfo->UnwindCodes[codeIndex++] = uwop;
                }
            }

            _unwindInfo->VersionAndFlags    = 1;
            _unwindInfo->SizeOfProlog       = (byte)unwindInfo.PrologueSize;
            _unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
            _unwindInfo->FrameRegister      = 0;

            _runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
            _runtimeFunction->EndAddress   = (uint)(funcEntry.Offset + funcEntry.Size);
            _runtimeFunction->UnwindData   = (uint)_sizeOfRuntimeFunction;

            return(_runtimeFunction);
        }
Example #9
0
        private static unsafe RuntimeFunction *FunctionTableHandler(ulong controlPc, IntPtr context)
        {
            int offset = (int)((long)controlPc - context.ToInt64());

            if (!JitCache.TryFind(offset, out JitCacheEntry funcEntry))
            {
                return(null); // Not found.
            }

            var unwindInfo = funcEntry.UnwindInfo;

            int codeIndex = 0;

            for (int index = unwindInfo.PushEntries.Length - 1; index >= 0; index--)
            {
                var entry = unwindInfo.PushEntries[index];

                switch (entry.PseudoOp)
                {
                case UnwindPseudoOp.SaveXmm128:
                {
                    int stackOffset = entry.StackOffsetOrAllocSize;

                    Debug.Assert(stackOffset % 16 == 0);

                    if (stackOffset <= 0xFFFF0)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.SaveXmm128, entry.PrologOffset, entry.RegIndex);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
                    }
                    else
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
                    }

                    break;
                }

                case UnwindPseudoOp.AllocStack:
                {
                    int allocSize = entry.StackOffsetOrAllocSize;

                    Debug.Assert(allocSize % 8 == 0);

                    if (allocSize <= 128)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
                    }
                    else if (allocSize <= 0x7FFF8)
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocLarge, entry.PrologOffset, 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
                    }
                    else
                    {
                        _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.AllocLarge, entry.PrologOffset, 1);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
                        _unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
                    }

                    break;
                }

                case UnwindPseudoOp.PushReg:
                {
                    _unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOperation.PushNonvol, entry.PrologOffset, entry.RegIndex);

                    break;
                }

                default: throw new NotImplementedException($"({nameof(entry.PseudoOp)} = {entry.PseudoOp})");
                }
            }

            Debug.Assert(codeIndex <= MaxUnwindCodesArraySize);

            _unwindInfo->VersionAndFlags    = 1; // Flags: The function has no handler.
            _unwindInfo->SizeOfProlog       = (byte)unwindInfo.PrologSize;
            _unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
            _unwindInfo->FrameRegister      = 0;

            _runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
            _runtimeFunction->EndAddress   = (uint)(funcEntry.Offset + funcEntry.Size);
            _runtimeFunction->UnwindData   = (uint)_sizeOfRuntimeFunction;

            return(_runtimeFunction);
        }