From a694420d11ef74e4f0bf473be2b6f64635bc89c7 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 4 Feb 2019 18:26:05 -0300 Subject: Implement speculative translation on the CPU (#515) * Implement speculative translation on the cpu, and change the way how branches to unknown or untranslated addresses works * Port t0opt changes and other cleanups * Change namespace from translation related classes to ChocolArm64.Translation, other minor tweaks * Fix typo * Translate higher quality code for indirect jumps aswell, and on some cases that were missed when lower quality (tier 0) code was available * Remove debug print * Remove direct argument passing optimization, and enable tail calls for BR instructions * Call delegates directly with Callvirt rather than calling Execute, do not emit calls for tier 0 code * Remove unused property * Rename argument on ArmSubroutine delegate --- ChocolArm64/TranslatorCache.cs | 171 ----------------------------------------- 1 file changed, 171 deletions(-) delete mode 100644 ChocolArm64/TranslatorCache.cs (limited to 'ChocolArm64/TranslatorCache.cs') diff --git a/ChocolArm64/TranslatorCache.cs b/ChocolArm64/TranslatorCache.cs deleted file mode 100644 index 9903ccaa..00000000 --- a/ChocolArm64/TranslatorCache.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace ChocolArm64 -{ - class TranslatorCache - { - //Maximum size of the cache, the unit used is completely arbitrary. - private const int MaxTotalSize = 0x800000; - - //Minimum time required in milliseconds for a method to be eligible for deletion. - private const int MinTimeDelta = 2 * 60000; - - //Minimum number of calls required to update the timestamp. - private const int MinCallCountForUpdate = 250; - - private class CacheBucket - { - public TranslatedSub Subroutine { get; private set; } - - public LinkedListNode Node { get; private set; } - - public int CallCount { get; set; } - - public int Size { get; private set; } - - public long Timestamp { get; private set; } - - public CacheBucket(TranslatedSub subroutine, LinkedListNode node, int size) - { - Subroutine = subroutine; - Size = size; - - UpdateNode(node); - } - - public void UpdateNode(LinkedListNode node) - { - Node = node; - - Timestamp = GetTimestamp(); - } - } - - private ConcurrentDictionary _cache; - - private LinkedList _sortedCache; - - private int _totalSize; - - public TranslatorCache() - { - _cache = new ConcurrentDictionary(); - - _sortedCache = new LinkedList(); - } - - public void AddOrUpdate(long position, TranslatedSub subroutine, int size) - { - ClearCacheIfNeeded(); - - lock (_sortedCache) - { - _totalSize += size; - - LinkedListNode 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 HasSubroutine(long position) - { - return _cache.ContainsKey(position); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - 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; - } - - private void ClearCacheIfNeeded() - { - long timestamp = GetTimestamp(); - - while (_totalSize > MaxTotalSize) - { - lock (_sortedCache) - { - LinkedListNode node = _sortedCache.First; - - if (node == null) - { - break; - } - - CacheBucket bucket = _cache[node.Value]; - - long timeDelta = timestamp - bucket.Timestamp; - - if (timeDelta <= MinTimeDelta) - { - break; - } - - if (_cache.TryRemove(node.Value, out bucket)) - { - _totalSize -= bucket.Size; - - _sortedCache.Remove(bucket.Node); - } - } - } - } - - private static long GetTimestamp() - { - long timestamp = Stopwatch.GetTimestamp(); - - return timestamp / (Stopwatch.Frequency / 1000); - } - } -} \ No newline at end of file -- cgit v1.2.3