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

                UpdateNode(node);
            }
예제 #2
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
                        {
                            bucket.CallCount = 0;

                            _sortedCache.Remove(bucket.Node);

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

                subroutine = bucket.Subroutine;

                return(true);
            }

            subroutine = default(TranslatedSub);

            return(false);
        }
예제 #3
0
        private TranslatedSub TranslateTier0(CpuThreadState state, MemoryManager memory, long position)
        {
            Block block = Decoder.DecodeBasicBlock(state, memory, position);

            Block[] graph = new Block[] { block };

            string subName = GetSubroutineName(position);

            ILEmitterCtx context = new ILEmitterCtx(_cache, graph, block, subName);

            do
            {
                context.EmitOpCode();
            }while (context.AdvanceOpCode());

            TranslatedSub subroutine = context.GetSubroutine();

            subroutine.SetType(TranslatedSubType.SubTier0);

            _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);

            OpCode64 lastOp = block.GetLastOp();

            return(subroutine);
        }
예제 #4
0
        private TranslatedSub TranslateTier0(MemoryManager memory, long position, ExecutionMode mode)
        {
            Block block = Decoder.DecodeBasicBlock(memory, position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_cache, block);

            string subName = GetSubroutineName(position);

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

            TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();

            subroutine.SetType(TranslatedSubType.SubTier0);

            _cache.AddOrUpdate(position, subroutine, block.OpCodes.Count);

            return(subroutine);
        }
예제 #5
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);
        }
예제 #6
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);
                });
            }
        }
예제 #7
0
        private void TranslateTier1(MemoryManager memory, long position, ExecutionMode mode)
        {
            Block graph = Decoder.DecodeSubroutine(_cache, memory, position, mode);

            ILEmitterCtx context = new ILEmitterCtx(_cache, graph);

            ILBlock[] ilBlocks = context.GetILBlocks();

            string subName = GetSubroutineName(position);

            ILMethodBuilder ilMthdBuilder = new ILMethodBuilder(ilBlocks, subName);

            TranslatedSub subroutine = ilMthdBuilder.GetSubroutine();

            subroutine.SetType(TranslatedSubType.SubTier1);

            int ilOpCount = 0;

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

            _cache.AddOrUpdate(position, subroutine, ilOpCount);

            //Mark all methods that calls this method for ReJiting,
            //since we can now call it directly which is faster.
            if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
            {
                foreach (long callerPos in oldSub.GetCallerPositions())
                {
                    if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
                    {
                        callerSub.MarkForReJit();
                    }
                }
            }
        }
예제 #8
0
        private void TranslateTier1(CpuThreadState state, MemoryManager memory, long position)
        {
            (Block[] graph, Block root) = Decoder.DecodeSubroutine(_cache, state, memory, position);

            string subName = GetSubroutineName(position);

            ILEmitterCtx context = new ILEmitterCtx(_cache, graph, root, subName);

            if (context.CurrBlock.Position != position)
            {
                context.Emit(OpCodes.Br, context.GetLabel(position));
            }

            do
            {
                context.EmitOpCode();
            }while (context.AdvanceOpCode());

            //Mark all methods that calls this method for ReJiting,
            //since we can now call it directly which is faster.
            if (_cache.TryGetSubroutine(position, out TranslatedSub oldSub))
            {
                foreach (long callerPos in oldSub.GetCallerPositions())
                {
                    if (_cache.TryGetSubroutine(position, out TranslatedSub callerSub))
                    {
                        callerSub.MarkForReJit();
                    }
                }
            }

            TranslatedSub subroutine = context.GetSubroutine();

            subroutine.SetType(TranslatedSubType.SubTier1);

            _cache.AddOrUpdate(position, subroutine, GetGraphInstCount(graph));
        }