Merge pull request #404 from magumagu/jitcache-cleanup
JitCache cleanup
This commit is contained in:
commit
b778b43992
|
@ -109,31 +109,12 @@ using namespace Gen;
|
||||||
links_to.clear();
|
links_to.clear();
|
||||||
block_map.clear();
|
block_map.clear();
|
||||||
|
|
||||||
valid_block.clear();
|
valid_block.ClearAll();
|
||||||
valid_block.resize(VALID_BLOCK_MASK_SIZE, false);
|
|
||||||
|
|
||||||
num_blocks = 0;
|
num_blocks = 0;
|
||||||
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
|
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()
|
void JitBaseBlockCache::Reset()
|
||||||
{
|
{
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
@ -183,7 +164,7 @@ using namespace Gen;
|
||||||
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
|
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
|
||||||
|
|
||||||
for (u32 i = 0; i < (b.originalSize + 7) / 8; ++i)
|
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;
|
block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num;
|
||||||
if (block_link)
|
if (block_link)
|
||||||
|
@ -353,10 +334,10 @@ using namespace Gen;
|
||||||
bool destroy_block = true;
|
bool destroy_block = true;
|
||||||
if (length == 32)
|
if (length == 32)
|
||||||
{
|
{
|
||||||
if (!valid_block[pAddr / 32])
|
if (!valid_block.Test(pAddr / 32))
|
||||||
destroy_block = false;
|
destroy_block = false;
|
||||||
else
|
else
|
||||||
valid_block[pAddr / 32] = false;
|
valid_block.Clear(pAddr / 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy JIT blocks
|
// destroy JIT blocks
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
|
@ -63,6 +64,40 @@ struct JitBlock
|
||||||
|
|
||||||
typedef void (*CompiledCode)();
|
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
|
class JitBaseBlockCache
|
||||||
{
|
{
|
||||||
|
@ -71,11 +106,11 @@ class JitBaseBlockCache
|
||||||
int num_blocks;
|
int num_blocks;
|
||||||
std::multimap<u32, int> links_to;
|
std::multimap<u32, int> links_to;
|
||||||
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
||||||
std::vector<bool> valid_block;
|
ValidBlockBitSet valid_block;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
MAX_NUM_BLOCKS = 65536*2,
|
MAX_NUM_BLOCKS = 65536*2,
|
||||||
VALID_BLOCK_MASK_SIZE = 0x20000000 / 32,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
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 FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void ClearSafe();
|
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Reset();
|
void Reset();
|
||||||
|
@ -121,9 +155,6 @@ public:
|
||||||
// DOES NOT WORK CORRECTLY WITH INLINING
|
// DOES NOT WORK CORRECTLY WITH INLINING
|
||||||
void InvalidateICache(u32 address, const u32 length);
|
void InvalidateICache(u32 address, const u32 length);
|
||||||
void DestroyBlock(int block_num, bool invalidate);
|
void DestroyBlock(int block_num, bool invalidate);
|
||||||
|
|
||||||
// Not currently used
|
|
||||||
//void DestroyBlocksWithFlag(BlockFlag death_flag);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// x86 BlockCache
|
// x86 BlockCache
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace JitInterface
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
if (jit && p.GetMode() == PointerWrap::MODE_READ)
|
if (jit && p.GetMode() == PointerWrap::MODE_READ)
|
||||||
jit->GetBlockCache()->ClearSafe();
|
jit->GetBlockCache()->Clear();
|
||||||
}
|
}
|
||||||
CPUCoreBase *InitJitCore(int core)
|
CPUCoreBase *InitJitCore(int core)
|
||||||
{
|
{
|
||||||
|
@ -199,8 +199,12 @@ namespace JitInterface
|
||||||
}
|
}
|
||||||
void ClearSafe()
|
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)
|
if (jit)
|
||||||
jit->GetBlockCache()->ClearSafe();
|
jit->GetBlockCache()->Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvalidateICache(u32 address, u32 size)
|
void InvalidateICache(u32 address, u32 size)
|
||||||
|
|
Loading…
Reference in New Issue