예제 #1
0
        private TranslatedSub TranslateHighCq(long position, ExecutionMode mode, bool isComplete)
        {
            Block graph = Decoder.DecodeSubroutine(_memory, position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier1, graph);

            ILBlock[] ilBlocks = context.GetILBlocks();

            string subName = GetSubroutineName(position);

            bool isAarch64 = mode == ExecutionMode.Aarch64;

            isComplete &= !context.HasIndirectJump;

            ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName, isAarch64, isComplete);

            TranslatedSub subroutine = ilMthdBuilder.GetSubroutine(TranslationTier.Tier1, context.HasSlowCall);

            int ilOpCount = 0;

            foreach (ILBlock ilBlock in ilBlocks)
            {
                ilOpCount += ilBlock.Count;
            }

            ForceAheadOfTimeCompilation(subroutine);

            _cache.AddOrUpdate(position, subroutine, ilOpCount);

            return(subroutine);
        }
예제 #2
0
        private TranslatedSub TranslateHighCq(long position, ExecutionMode mode, bool isComplete)
        {
            Block[] blocks = Decoder.DecodeSubroutine(_memory, (ulong)position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier1);

            if (blocks[0].Address != (ulong)position)
            {
                context.Emit(OpCodes.Br, context.GetLabel(position));
            }

            BasicBlock[] bbs = EmitAndGetBlocks(context, blocks);

            isComplete &= !context.HasIndirectJump;

            TranslatedSubBuilder builder = new TranslatedSubBuilder(mode, isComplete);

            string name = GetSubroutineName(position);

            TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier1, context.HasSlowCall);

            ForceAheadOfTimeCompilation(subroutine);

            _cache.AddOrUpdate(position, subroutine, GetOpsCount(bbs));

            return(subroutine);
        }
예제 #3
0
        private void InitSubroutine()
        {
            List <Register> Params = new List <Register>();

            void SetParams(long inputs, RegisterType baseType)
            {
                for (int bit = 0; bit < 64; bit++)
                {
                    long mask = 1L << bit;

                    if ((inputs & mask) != 0)
                    {
                        Params.Add(GetRegFromBit(bit, baseType));
                    }
                }
            }

            SetParams(LocalAlloc.GetIntInputs(_root), RegisterType.Int);
            SetParams(LocalAlloc.GetVecInputs(_root), RegisterType.Vector);

            DynamicMethod mthd = new DynamicMethod(_subName, typeof(long), GetParamTypes(Params));

            Generator = mthd.GetILGenerator();

            _subroutine = new TranslatedSub(mthd, Params);
        }
예제 #4
0
        public TranslatedSub GetSubroutine(TranslationTier tier, bool isWorthOptimizing)
        {
            RegUsage = new RegisterUsage();

            RegUsage.BuildUses(_ilBlocks[0]);

            DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes);

            long intNiRegsMask = RegUsage.GetIntNotInputs(_ilBlocks[0]);
            long vecNiRegsMask = RegUsage.GetVecNotInputs(_ilBlocks[0]);

            TranslatedSub subroutine = new TranslatedSub(
                method,
                intNiRegsMask,
                vecNiRegsMask,
                tier,
                isWorthOptimizing);

            _locals = new Dictionary <Register, int>();

            _localsCount = 0;

            Generator = method.GetILGenerator();

            foreach (ILBlock ilBlock in _ilBlocks)
            {
                ilBlock.Emit(this);
            }

            subroutine.PrepareMethod();

            return(subroutine);
        }
예제 #5
0
        private void TranslateHighCq(long position, ExecutionMode mode)
        {
            Block graph = Decoder.DecodeSubroutine(_memory, position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_cache, _queue, TranslationTier.Tier1, graph);

            ILBlock[] ilBlocks = context.GetILBlocks();

            string subName = GetSubroutineName(position);

            ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName);

            TranslatedSub subroutine = ilMthdBuilder.GetSubroutine(TranslationTier.Tier1);

            int ilOpCount = 0;

            foreach (ILBlock ilBlock in ilBlocks)
            {
                ilOpCount += ilBlock.Count;
            }

            _cache.AddOrUpdate(position, subroutine, ilOpCount);

            ForceAheadOfTimeCompilation(subroutine);
        }
예제 #6
0
            public CacheBucket(TranslatedSub subroutine, LinkedListNode <long> node, int size)
            {
                Subroutine = subroutine;
                Size       = size;

                UpdateNode(node);
            }
예제 #7
0
        public TranslatedSub GetSubroutine(TranslationTier tier)
        {
            LocalAlloc = new LocalAlloc(_ilBlocks, _ilBlocks[0]);

            DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes);

            Generator = method.GetILGenerator();

            TranslatedSub subroutine = new TranslatedSub(method, tier);

            _locals = new Dictionary <Register, int>();

            _localsCount = 0;

            new ILOpCodeLoadState(_ilBlocks[0]).Emit(this);

            foreach (ILBlock ilBlock in _ilBlocks)
            {
                ilBlock.Emit(this);
            }

            subroutine.PrepareMethod();

            return(subroutine);
        }
예제 #8
0
        private TranslatedSub TranslateLowCq(long position, ExecutionMode mode)
        {
            Block block = Decoder.DecodeBasicBlock(_memory, position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_cache, _queue, TranslationTier.Tier0, block);

            string subName = GetSubroutineName(position);

            ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(context.GetILBlocks(), subName);

            TranslatedSub subroutine = ilMthdBuilder.GetSubroutine(TranslationTier.Tier0);

            return(_cache.GetOrAdd(position, subroutine, block.OpCodes.Count));
        }
예제 #9
0
        public TranslatedSub GetSubroutine()
        {
            LocalAlloc = new LocalAlloc(_ilBlocks, _ilBlocks[0]);

            List <Register> subArgs = new List <Register>();

            void SetArgs(long inputs, RegisterType baseType)
            {
                for (int bit = 0; bit < 64; bit++)
                {
                    long mask = 1L << bit;

                    if ((inputs & mask) != 0)
                    {
                        subArgs.Add(GetRegFromBit(bit, baseType));
                    }
                }
            }

            SetArgs(LocalAlloc.GetIntInputs(_ilBlocks[0]), RegisterType.Int);
            SetArgs(LocalAlloc.GetVecInputs(_ilBlocks[0]), RegisterType.Vector);

            DynamicMethod method = new DynamicMethod(_subName, typeof(long), GetArgumentTypes(subArgs));

            Generator = method.GetILGenerator();

            TranslatedSub subroutine = new TranslatedSub(method, subArgs);

            int argsStart = TranslatedSub.FixedArgTypes.Length;

            _locals = new Dictionary <Register, int>();

            _localsCount = 0;

            for (int index = 0; index < subroutine.SubArgs.Count; index++)
            {
                Register reg = subroutine.SubArgs[index];

                Generator.EmitLdarg(index + argsStart);
                Generator.EmitStloc(GetLocalIndex(reg));
            }

            foreach (ILBlock ilBlock in _ilBlocks)
            {
                ilBlock.Emit(this);
            }

            return(subroutine);
        }
예제 #10
0
        private TranslatedSub TranslateLowCq(long position, ExecutionMode mode)
        {
            Block[] blocks = Decoder.DecodeBasicBlock(_memory, (ulong)position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_memory, _cache, _queue, TranslationTier.Tier0);

            BasicBlock[] bbs = EmitAndGetBlocks(context, blocks);

            TranslatedSubBuilder builder = new TranslatedSubBuilder(mode);

            string name = GetSubroutineName(position);

            TranslatedSub subroutine = builder.Build(bbs, name, TranslationTier.Tier0);

            return(_cache.GetOrAdd(position, subroutine, GetOpsCount(bbs)));
        }
예제 #11
0
        private void ExecuteSubroutine(CpuThreadState state, long position)
        {
            state.CurrentTranslator = this;

            do
            {
                if (EnableCpuTrace)
                {
                    CpuTrace?.Invoke(this, new CpuTraceEventArgs(position));
                }

                TranslatedSub subroutine = GetOrTranslateSubroutine(state, position);

                position = subroutine.Execute(state, _memory);
            }while (position != 0 && state.Running);

            state.CurrentTranslator = null;
        }
예제 #12
0
        public void AddOrUpdate(long position, TranslatedSub subroutine, int size)
        {
            ClearCacheIfNeeded();

            lock (_sortedCache)
            {
                _totalSize += size;

                LinkedListNode <long> node = _sortedCache.AddLast(position);

                CacheBucket newBucket = new CacheBucket(subroutine, node, size);

                _cache.AddOrUpdate(position, newBucket, (key, bucket) =>
                {
                    _totalSize -= bucket.Size;

                    _sortedCache.Remove(bucket.Node);

                    return(newBucket);
                });
            }
        }
예제 #13
0
        public bool TryGetSubroutine(long position, out TranslatedSub subroutine)
        {
            if (_cache.TryGetValue(position, out CacheBucket bucket))
            {
                if (bucket.CallCount++ > MinCallCountForUpdate)
                {
                    if (Monitor.TryEnter(_sortedCache))
                    {
                        try
                        {
                            // The bucket value on the dictionary may have changed between the
                            // time we get the value from the dictionary, and we acquire the
                            // lock. So we need to ensure we are working with the latest value,
                            // we can do that by getting the value again, inside the lock.
                            if (_cache.TryGetValue(position, out CacheBucket latestBucket))
                            {
                                latestBucket.CallCount = 0;

                                _sortedCache.Remove(latestBucket.Node);

                                latestBucket.UpdateNode(_sortedCache.AddLast(position));
                            }
                        }
                        finally
                        {
                            Monitor.Exit(_sortedCache);
                        }
                    }
                }

                subroutine = bucket.Subroutine;

                return(true);
            }

            subroutine = default(TranslatedSub);

            return(false);
        }
예제 #14
0
        public TranslatedSub GetOrAdd(long position, TranslatedSub subroutine, int size)
        {
            ClearCacheIfNeeded();

            lock (_sortedCache)
            {
                LinkedListNode <long> node = _sortedCache.AddLast(position);

                CacheBucket bucket = new CacheBucket(subroutine, node, size);

                bucket = _cache.GetOrAdd(position, bucket);

                if (bucket.Node == node)
                {
                    _totalSize += size;
                }
                else
                {
                    _sortedCache.Remove(node);
                }

                return(bucket.Subroutine);
            }
        }
예제 #15
0
 private void EmitStoreState(TranslatedSub callSub)
 {
     _ilBlock.Add(new ILOpCodeStoreState(_ilBlock, callSub));
 }
예제 #16
0
 private void ForceAheadOfTimeCompilation(TranslatedSub subroutine)
 {
     subroutine.Execute(_dummyThreadState, null);
 }
예제 #17
0
 public ILOpCodeStoreState(ILBlock block, TranslatedSub callSub = null)
 {
     _block   = block;
     _callSub = callSub;
 }
예제 #18
0
        public TranslatedSub Build(BasicBlock[] blocks, string name, TranslationTier tier, bool rejit = true)
        {
            _regUsage = new RegisterUsage(blocks[0], blocks.Length);

            DynamicMethod method = new DynamicMethod(name, typeof(long), TranslatedSub.FixedArgTypes);

            TranslatedSub subroutine = new TranslatedSub(method, tier, rejit);

            _locals = new Dictionary <Register, int>();

            Dictionary <ILLabel, Label> labels = new Dictionary <ILLabel, Label>();

            ILGenerator generator = method.GetILGenerator();

            Label GetLabel(ILLabel label)
            {
                if (!labels.TryGetValue(label, out Label ilLabel))
                {
                    ilLabel = generator.DefineLabel();

                    labels.Add(label, ilLabel);
                }

                return(ilLabel);
            }

            foreach (BasicBlock block in blocks)
            {
                for (int index = 0; index < block.Count; index++)
                {
                    Operation operation = block.GetOperation(index);

                    switch (operation.Type)
                    {
                    case OperationType.Call:
                        generator.Emit(OpCodes.Call, operation.GetArg <MethodInfo>(0));
                        break;

                    case OperationType.CallVirtual:
                        generator.Emit(OpCodes.Callvirt, operation.GetArg <MethodInfo>(0));
                        break;

                    case OperationType.IL:
                        generator.Emit(operation.GetArg <OpCode>(0));
                        break;

                    case OperationType.ILBranch:
                        generator.Emit(operation.GetArg <OpCode>(0), GetLabel(operation.GetArg <ILLabel>(1)));
                        break;

                    case OperationType.LoadArgument:
                        generator.EmitLdarg(operation.GetArg <int>(0));
                        break;

                    case OperationType.LoadConstant:
                        EmitLoadConstant(generator, operation.GetArg(0));
                        break;

                    case OperationType.LoadContext:
                        EmitLoadContext(generator, operation.Parent);
                        break;

                    case OperationType.LoadField:
                        generator.Emit(OpCodes.Ldfld, operation.GetArg <FieldInfo>(0));
                        break;

                    case OperationType.LoadLocal:
                        EmitLoadLocal(
                            generator,
                            operation.GetArg <int>(0),
                            operation.GetArg <RegisterType>(1),
                            operation.GetArg <RegisterSize>(2));
                        break;

                    case OperationType.MarkLabel:
                        generator.MarkLabel(GetLabel(operation.GetArg <ILLabel>(0)));
                        break;

                    case OperationType.StoreContext:
                        EmitStoreContext(generator, operation.Parent);
                        break;

                    case OperationType.StoreLocal:
                        EmitStoreLocal(
                            generator,
                            operation.GetArg <int>(0),
                            operation.GetArg <RegisterType>(1),
                            operation.GetArg <RegisterSize>(2));
                        break;
                    }
                }
            }

            subroutine.PrepareMethod();

            return(subroutine);
        }