public bool TryGetSubroutine(long Position, out ATranslatedSub 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(ATranslatedSub); return(false); }
private ATranslatedSub TranslateTier0(AThreadState State, AMemory Memory, long Position) { ABlock Block = ADecoder.DecodeBasicBlock(State, Memory, Position); ABlock[] Graph = new ABlock[] { Block }; string SubName = GetSubroutineName(Position); AILEmitterCtx Context = new AILEmitterCtx(Cache, Graph, Block, SubName); do { Context.EmitOpCode(); }while (Context.AdvanceOpCode()); ATranslatedSub Subroutine = Context.GetSubroutine(); Subroutine.SetType(ATranslatedSubType.SubTier0); Cache.AddOrUpdate(Position, Subroutine, Block.OpCodes.Count); AOpCode LastOp = Block.GetLastOp(); return(Subroutine); }
public CacheBucket(ATranslatedSub Subroutine, LinkedListNode <long> Node, int Size) { this.Subroutine = Subroutine; this.Size = Size; UpdateNode(Node); }
internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) { if (OpCode.Emitter != AInstEmit.Bl) { Sub = null; return(false); } return(TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub)); }
private ATranslatedSub TranslateTier0(AMemory Memory, long Position) { ABlock Block = ADecoder.DecodeBasicBlock(this, Memory, Position); ABlock[] Graph = new ABlock[] { Block }; string SubName = GetSubName(Position); AILEmitterCtx Context = new AILEmitterCtx(this, Graph, Block, SubName); do { Context.EmitOpCode(); }while (Context.AdvanceOpCode()); ATranslatedSub Subroutine = Context.GetSubroutine(); lock (SubBlocks) { if (SubBlocks.Contains(Position)) { SubBlocks.Remove(Position); Subroutine.SetType(ATranslatedSubType.SubBlock); } else { Subroutine.SetType(ATranslatedSubType.SubTier0); } } CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); AOpCode LastOp = Block.GetLastOp(); lock (SubBlocks) { if (LastOp.Emitter != AInstEmit.Ret && LastOp.Emitter != AInstEmit.Br) { SubBlocks.Add(LastOp.Position + 4); } } return(Subroutine); }
private ATranslatedSub TranslateSubroutine(AMemory Memory, long Position) { (ABlock[] Graph, ABlock Root)Cfg = ADecoder.DecodeSubroutine(this, Memory, Position); string SubName = SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}"); PropagateName(Cfg.Graph, SubName); AILEmitterCtx Context = new AILEmitterCtx( this, Cfg.Graph, Cfg.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. foreach (ATranslatedSub TS in CachedSubs.Values) { if (TS.SubCalls.Contains(Position)) { TS.MarkForReJit(); } } ATranslatedSub Subroutine = Context.GetSubroutine(); CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); return(Subroutine); }
private void TranslateTier1(AThreadState State, AMemory Memory, long Position) { (ABlock[] Graph, ABlock Root)Cfg = ADecoder.DecodeSubroutine(State, this, Memory, Position); string SubName = GetSubName(Position); PropagateName(Cfg.Graph, SubName); AILEmitterCtx Context = new AILEmitterCtx(this, Cfg.Graph, Cfg.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 (CachedSubs.TryGetValue(Position, out ATranslatedSub OldSub)) { foreach (long CallerPos in OldSub.GetCallerPositions()) { if (CachedSubs.TryGetValue(Position, out ATranslatedSub CallerSub)) { CallerSub.MarkForReJit(); } } } ATranslatedSub Subroutine = Context.GetSubroutine(); Subroutine.SetType(ATranslatedSubType.SubTier1); CachedSubs.AddOrUpdate(Position, Subroutine, (Key, OldVal) => Subroutine); }
public void AddOrUpdate(long Position, ATranslatedSub Subroutine, int Size) { ClearCacheIfNeeded(); TotalSize += Size; lock (SortedCache) { 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); }); } }
private ATranslatedSub TranslateSubroutine(long Position) { (ABlock[] Graph, ABlock Root)Cfg = ADecoder.DecodeSubroutine(this, Position); AILEmitterCtx Context = new AILEmitterCtx( this, Cfg.Graph, Cfg.Root); 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. foreach (ATranslatedSub TS in CachedSubs.Values) { if (TS.SubCalls.Contains(Position)) { TS.MarkForReJit(); } } ATranslatedSub Subroutine = Context.GetSubroutine(); if (!CachedSubs.TryAdd(Position, Subroutine)) { CachedSubs[Position] = Subroutine; } return(Subroutine); }
internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub) { return(CachedSubs.TryGetValue(Position, out Sub)); }