JitCache: use a custom bit-set class.
Unfortunately, this appears to be necessary for the sake of performance; the standard library equivalents don't work well enough on Visual Studio 2013. vector<bool>::insert() is way too slow in debug builds to be usable, and std::bitset generates inefficient code in release builds.
This commit is contained in:
parent
6bb08de8a0
commit
282e9bd292
|
@ -109,8 +109,7 @@ 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);
|
||||
|
@ -165,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)
|
||||
|
@ -335,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
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Core/PowerPC/Gekko.h"
|
||||
|
@ -64,6 +65,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
|
||||
{
|
||||
|
@ -72,11 +107,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;
|
||||
|
|
Loading…
Reference in New Issue