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); }
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); }
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); }
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); }
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); }
public CacheBucket(TranslatedSub subroutine, LinkedListNode <long> node, int size) { Subroutine = subroutine; Size = size; UpdateNode(node); }
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); }
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)); }
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); }
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))); }
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; }
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); }); } }
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); }
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); } }
private void EmitStoreState(TranslatedSub callSub) { _ilBlock.Add(new ILOpCodeStoreState(_ilBlock, callSub)); }
private void ForceAheadOfTimeCompilation(TranslatedSub subroutine) { subroutine.Execute(_dummyThreadState, null); }
public ILOpCodeStoreState(ILBlock block, TranslatedSub callSub = null) { _block = block; _callSub = callSub; }
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); }