aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Translation/TranslatorCache.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2019-10-31 19:09:03 +0100
committerAc_K <Acoustik666@gmail.com>2019-10-31 19:09:03 +0100
commiteee639d6ba544fa5dd9352426d55e91bc54e157d (patch)
tree1df440ca57d8c1725e84f403fbeecddb8e508a3a /ChocolArm64/Translation/TranslatorCache.cs
parent35443bac5a16ced668d84e0a22c21ca9076b3924 (diff)
.NET Core 3.0 is here! (#784)
* .NET Core 3.0 is here! * Remove IMemoryManager.cs and its references. * Add T Math/F.FusedMultiplyAdd(T, T, T). Nits. * Nit. * Update appveyor.yml * Revert "Resolve Visual Studio build issues" This reverts commit 1772128ce0fc058e6280001aace3a77a7a96897b. * Update SvcTable.cs
Diffstat (limited to 'ChocolArm64/Translation/TranslatorCache.cs')
-rw-r--r--ChocolArm64/Translation/TranslatorCache.cs196
1 files changed, 0 insertions, 196 deletions
diff --git a/ChocolArm64/Translation/TranslatorCache.cs b/ChocolArm64/Translation/TranslatorCache.cs
deleted file mode 100644
index cf6510ad..00000000
--- a/ChocolArm64/Translation/TranslatorCache.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Threading;
-
-namespace ChocolArm64.Translation
-{
- 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<long> 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<long> node, int size)
- {
- Subroutine = subroutine;
- Size = size;
-
- UpdateNode(node);
- }
-
- public void UpdateNode(LinkedListNode<long> node)
- {
- Node = node;
-
- Timestamp = GetTimestamp();
- }
- }
-
- private ConcurrentDictionary<long, CacheBucket> _cache;
-
- private LinkedList<long> _sortedCache;
-
- private int _totalSize;
-
- public TranslatorCache()
- {
- _cache = new ConcurrentDictionary<long, CacheBucket>();
-
- _sortedCache = new LinkedList<long>();
- }
-
- 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;
- }
- }
-
- 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 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<long> 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