summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2014-06-07 01:49:07 -0500
committerRyan Houdek <Sonicadvance1@gmail.com>2014-06-07 01:49:07 -0500
commitb778b43992c6086dac7db46f170290edfb1fdbf3 (patch)
treeb55ef190667ab0352570d756eb21bd89d26d413f /Source/Core
parent7d12a31cc255a49d76e2ba62bf176c3059718257 (diff)
parent282e9bd2922c58e23901cd44ad5cc1d540384788 (diff)
Merge pull request #404 from magumagu/jitcache-cleanup
JitCache cleanup
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/JitCache.cpp27
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/JitCache.h43
-rw-r--r--Source/Core/Core/PowerPC/JitInterface.cpp8
3 files changed, 47 insertions, 31 deletions
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
index 71143fc955..a3723253b5 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp
@@ -109,31 +109,12 @@ using namespace Gen;
links_to.clear();
block_map.clear();
- valid_block.clear();
- valid_block.resize(VALID_BLOCK_MASK_SIZE, false);
+ valid_block.ClearAll();
num_blocks = 0;
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
}
- void JitBaseBlockCache::ClearSafe()
- {
- memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
- memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
- memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
- }
-
- /*void JitBaseBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
- {
- for (int i = 0; i < num_blocks; i++)
- {
- if (blocks[i].flags & death_flag)
- {
- DestroyBlock(i, false);
- }
- }
- }*/
-
void JitBaseBlockCache::Reset()
{
Shutdown();
@@ -183,7 +164,7 @@ using namespace Gen;
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
for (u32 i = 0; i < (b.originalSize + 7) / 8; ++i)
- valid_block[pAddr / 32 + i] = true;
+ valid_block.Set(pAddr / 32 + i);
block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num;
if (block_link)
@@ -353,10 +334,10 @@ using namespace Gen;
bool destroy_block = true;
if (length == 32)
{
- if (!valid_block[pAddr / 32])
+ if (!valid_block.Test(pAddr / 32))
destroy_block = false;
else
- valid_block[pAddr / 32] = false;
+ valid_block.Clear(pAddr / 32);
}
// destroy JIT blocks
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h
index 4bf31c352b..2b0db88c64 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h
+++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h
@@ -6,6 +6,7 @@
#include <bitset>
#include <map>
+#include <memory>
#include <vector>
#include "Core/PowerPC/Gekko.h"
@@ -63,6 +64,40 @@ struct JitBlock
typedef void (*CompiledCode)();
+// This is essentially just an std::bitset, but Visual Studia 2013's
+// implementation of std::bitset is slow.
+class ValidBlockBitSet final
+{
+ enum
+ {
+ VALID_BLOCK_MASK_SIZE = 0x20000000 / 32,
+ VALID_BLOCK_ALLOC_ELEMENTS = VALID_BLOCK_MASK_SIZE / 32
+ };
+ std::unique_ptr<u32[]> m_valid_block;
+
+public:
+ ValidBlockBitSet()
+ {
+ m_valid_block.reset(new u32[VALID_BLOCK_ALLOC_ELEMENTS]);
+ ClearAll();
+ }
+ void Set(u32 bit)
+ {
+ m_valid_block[bit / 32] |= 1u << (bit % 32);
+ }
+ void Clear(u32 bit)
+ {
+ m_valid_block[bit / 32] &= ~(1u << (bit % 32));
+ }
+ void ClearAll()
+ {
+ memset(m_valid_block.get(), 0, sizeof(u32) * VALID_BLOCK_ALLOC_ELEMENTS);
+ }
+ bool Test(u32 bit)
+ {
+ return (m_valid_block[bit / 32] & (1u << (bit % 32))) != 0;
+ }
+};
class JitBaseBlockCache
{
@@ -71,11 +106,11 @@ class JitBaseBlockCache
int num_blocks;
std::multimap<u32, int> links_to;
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
- std::vector<bool> valid_block;
+ ValidBlockBitSet valid_block;
+
enum
{
MAX_NUM_BLOCKS = 65536*2,
- VALID_BLOCK_MASK_SIZE = 0x20000000 / 32,
};
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
@@ -95,7 +130,6 @@ public:
void FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr);
void Clear();
- void ClearSafe();
void Init();
void Shutdown();
void Reset();
@@ -121,9 +155,6 @@ public:
// DOES NOT WORK CORRECTLY WITH INLINING
void InvalidateICache(u32 address, const u32 length);
void DestroyBlock(int block_num, bool invalidate);
-
- // Not currently used
- //void DestroyBlocksWithFlag(BlockFlag death_flag);
};
// x86 BlockCache
diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp
index cc76690348..46ccb6f6a5 100644
--- a/Source/Core/Core/PowerPC/JitInterface.cpp
+++ b/Source/Core/Core/PowerPC/JitInterface.cpp
@@ -39,7 +39,7 @@ namespace JitInterface
void DoState(PointerWrap &p)
{
if (jit && p.GetMode() == PointerWrap::MODE_READ)
- jit->GetBlockCache()->ClearSafe();
+ jit->GetBlockCache()->Clear();
}
CPUCoreBase *InitJitCore(int core)
{
@@ -199,8 +199,12 @@ namespace JitInterface
}
void ClearSafe()
{
+ // This clear is "safe" in the sense that it's okay to run from
+ // inside a JIT'ed block: it clears the instruction cache, but not
+ // the JIT'ed code.
+ // TODO: There's probably a better way to handle this situation.
if (jit)
- jit->GetBlockCache()->ClearSafe();
+ jit->GetBlockCache()->Clear();
}
void InvalidateICache(u32 address, u32 size)