- Rewrite blockinfo allocator et al. Use a template class so that this

can work with other types related to blockinfos.
- Add new method to compute checksums. This should permit code inlining
  and follow-ups of const_jumps without breaking the lazy cache invalidator.
  aka. chain infos for checksuming. TODO: Incomplete support thus disabled.
This commit is contained in:
gbeauche 2002-10-01 16:22:36 +00:00
parent 518f982775
commit 21909f1eed
2 changed files with 147 additions and 63 deletions

View File

@ -37,6 +37,9 @@ union cacheline {
*/
#define USE_SEPARATE_BIA 1
/* Use chain of checksum_info_t to compute the block checksum */
#define USE_CHECKSUM_INFO 0
#define USE_F_ALIAS 1
#define USE_OFFSET 1
#define COMP_DEBUG 1
@ -485,6 +488,14 @@ typedef struct dep_t {
struct dep_t* next;
} dependency;
typedef struct checksum_info_t {
uae_u8 *start_p;
uae_u32 length;
uae_u32 c1;
uae_u32 c2;
struct checksum_info_t *next;
} checksum_info;
typedef struct blockinfo_t {
uae_s32 count;
cpuop_func* direct_handler_to_use;
@ -497,19 +508,28 @@ typedef struct blockinfo_t {
cpuop_func* direct_pen;
cpuop_func* direct_pcc;
uae_u8* nexthandler;
uae_u8* pc_p;
#if USE_CHECKSUM_INFO
checksum_info *csi;
# define CSI_TYPE checksum_info
# define CSI_START_P(csi) (csi)->start_p
# define CSI_LENGTH(csi) (csi)->length
#else
uae_u32 c1;
uae_u32 c2;
uae_u32 len;
uae_u32 min_pcp;
# define CSI_TYPE blockinfo
# define CSI_START_P(csi) (csi)->min_pcp
# define CSI_LENGTH(csi) (csi)->len
#endif
struct blockinfo_t* next_same_cl;
struct blockinfo_t** prev_same_cl_p;
struct blockinfo_t* next;
struct blockinfo_t** prev_p;
uae_u32 min_pcp;
uae_u8 optlevel;
uae_u8 needed_flags;
uae_u8 status;

View File

@ -490,74 +490,113 @@ static void prepare_block(blockinfo* bi);
compiled. If the list of free blockinfos is empty, we allocate a new
pool of blockinfos and link the newly created blockinfos altogether
into the list of free blockinfos. Otherwise, we simply pop a structure
of the free list.
off the free list.
Blockinfo are lazily deallocated, i.e. chained altogether in the
list of free blockinfos whenvever a translation cache flush (hard or
soft) request occurs.
*/
#if USE_SEPARATE_BIA
const int BLOCKINFO_POOL_SIZE = 128;
struct blockinfo_pool {
blockinfo bi[BLOCKINFO_POOL_SIZE];
blockinfo_pool *next;
template< class T >
class LazyBlockAllocator
{
enum {
kPoolSize = 1 + 4096 / sizeof(T)
};
struct Pool {
T chunk[kPoolSize];
Pool * next;
};
Pool * mPools;
T * mChunks;
public:
LazyBlockAllocator() : mPools(0), mChunks(0) { }
~LazyBlockAllocator();
T * acquire();
void release(T * const);
};
static blockinfo_pool * blockinfo_pools = 0;
static blockinfo * free_blockinfos = 0;
template< class T >
LazyBlockAllocator<T>::~LazyBlockAllocator()
{
Pool * currentPool = mPools;
while (currentPool) {
Pool * deadPool = currentPool;
currentPool = currentPool->next;
free(deadPool);
}
}
template< class T >
T * LazyBlockAllocator<T>::acquire()
{
if (!mChunks) {
// There is no chunk left, allocate a new pool and link the
// chunks into the free list
Pool * newPool = (Pool *)malloc(sizeof(Pool));
for (T * chunk = &newPool->chunk[0]; chunk < &newPool->chunk[kPoolSize]; chunk++) {
chunk->next = mChunks;
mChunks = chunk;
}
newPool->next = mPools;
mPools = newPool;
}
T * chunk = mChunks;
mChunks = chunk->next;
return chunk;
}
template< class T >
void LazyBlockAllocator<T>::release(T * const chunk)
{
chunk->next = mChunks;
mChunks = chunk;
}
template< class T >
class HardBlockAllocator
{
public:
T * acquire() {
T * data = (T *)current_compile_p;
current_compile_p += sizeof(T);
return data;
}
void release(T * const chunk) {
// Deallocated on invalidation
}
};
#if USE_SEPARATE_BIA
static LazyBlockAllocator<blockinfo> BlockInfoAllocator;
static LazyBlockAllocator<checksum_info> ChecksumInfoAllocator;
#else
static HardBlockAllocator<blockinfo> BlockInfoAllocator;
static HardBlockAllocator<checksum_info> ChecksumInfoAllocator;
#endif
static __inline__ blockinfo *alloc_blockinfo(void)
{
#if USE_SEPARATE_BIA
if (!free_blockinfos) {
// There is no blockinfo struct left, allocate a new
// pool and link the chunks into the free list
blockinfo_pool *bi_pool = (blockinfo_pool *)malloc(sizeof(blockinfo_pool));
for (blockinfo *bi = &bi_pool->bi[0]; bi < &bi_pool->bi[BLOCKINFO_POOL_SIZE]; bi++) {
bi->next = free_blockinfos;
free_blockinfos = bi;
}
bi_pool->next = blockinfo_pools;
blockinfo_pools = bi_pool;
}
blockinfo *bi = free_blockinfos;
free_blockinfos = bi->next;
#else
blockinfo *bi = (blockinfo*)current_compile_p;
current_compile_p += sizeof(blockinfo);
blockinfo *bi = BlockInfoAllocator.acquire();
#if USE_CHECKSUM_INFO
bi->csi = NULL;
#endif
return bi;
}
static __inline__ void free_blockinfo(blockinfo *bi)
{
#if USE_SEPARATE_BIA
bi->next = free_blockinfos;
free_blockinfos = bi;
#endif
}
static void free_blockinfo_pools(void)
{
#if USE_SEPARATE_BIA
int blockinfo_pool_count = 0;
blockinfo_pool *curr_pool = blockinfo_pools;
while (curr_pool) {
blockinfo_pool_count++;
blockinfo_pool *dead_pool = curr_pool;
curr_pool = curr_pool->next;
free(dead_pool);
#if USE_CHECKSUM_INFO
checksum_info *csi = bi->csi;
while (csi != NULL) {
checksum_info *csi2 = csi->next;
ChecksumInfoAllocator.release(csi);
csi = csi2;
}
uae_u32 blockinfo_pools_size = blockinfo_pool_count * BLOCKINFO_POOL_SIZE * sizeof(blockinfo);
write_log("### Blockinfo allocation statistics\n");
write_log("Number of blockinfo pools : %d\n", blockinfo_pool_count);
write_log("Total number of blockinfos : %d (%d KB)\n",
blockinfo_pool_count * BLOCKINFO_POOL_SIZE,
blockinfo_pools_size / 1024);
write_log("\n");
#endif
BlockInfoAllocator.release(bi);
}
static __inline__ void alloc_blockinfos(void)
@ -4597,9 +4636,6 @@ void compiler_exit(void)
compiled_code = 0;
}
// Deallocate blockinfo pools
free_blockinfo_pools();
#ifndef WIN32
// Close /dev/zero
if (zero_fd > 0)
@ -5172,12 +5208,12 @@ void alloc_cache(void)
extern cpuop_rettype op_illg_1 (uae_u32 opcode) REGPARAM;
static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
static void calc_checksum(CSI_TYPE* csi, uae_u32* c1, uae_u32* c2)
{
uae_u32 k1=0;
uae_u32 k2=0;
uae_s32 len=bi->len;
uae_u32 tmp=bi->min_pcp;
uae_s32 len=CSI_LENGTH(csi);
uae_u32 tmp=(uae_u32)CSI_START_P(csi);
uae_u32* pos;
len+=(tmp&3);
@ -5200,12 +5236,12 @@ static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
}
}
static void show_checksum(blockinfo* bi)
static void show_checksum(CSI_TYPE* csi)
{
uae_u32 k1=0;
uae_u32 k2=0;
uae_s32 len=bi->len;
uae_u32 tmp=(uae_u32)bi->pc_p;
uae_s32 len=CSI_LENGTH(csi);
uae_u32 tmp=(uae_u32)CSI_START_P(csi);
uae_u32* pos;
len+=(tmp&3);
@ -5277,19 +5313,35 @@ static int called_check_checksum(blockinfo* bi);
static inline int block_check_checksum(blockinfo* bi)
{
uae_u32 c1,c2;
int isgood;
bool isgood;
if (bi->status!=BI_NEED_CHECK)
return 1; /* This block is in a checked state */
checksum_count++;
#if USE_CHECKSUM_INFO
checksum_info *csi = bi->csi;
Dif(!csi) abort();
isgood = true;
while (csi && isgood) {
if (csi->c1 || csi->c2)
calc_checksum(csi,&c1,&c2);
else
c1 = c2 = 1; /* Make sure it doesn't match */
isgood = isgood && (c1 == csi->c1 && c2 == csi->c2);
csi = csi->next;
}
#else
if (bi->c1 || bi->c2)
calc_checksum(bi,&c1,&c2);
else {
c1=c2=1; /* Make sure it doesn't match */
}
}
isgood=(c1==bi->c1 && c2==bi->c2);
#endif
if (isgood) {
/* This block is still OK. So we reactivate. Of course, that
means we have to move it into the needs-to-be-flushed list */
@ -6197,9 +6249,17 @@ static void compile_block(cpu_history* pc_hist, int blocklen)
max_pcp=next_pc_p+extra_len; /* extra_len covers flags magic */
else
max_pcp+=LONGEST_68K_INST;
#if USE_CHECKSUM_INFO
checksum_info *csi = (bi->csi = ChecksumInfoAllocator.acquire());
csi->next = NULL;
csi->length = max_pcp - min_pcp;
csi->start_p = (uae_u8 *)min_pcp;
#else
bi->len=max_pcp-min_pcp;
bi->min_pcp=min_pcp;
#endif
remove_from_list(bi);
if (isinrom(min_pcp) && isinrom(max_pcp)) {
add_to_dormant(bi); /* No need to checksum it on cache flush.
@ -6207,7 +6267,11 @@ static void compile_block(cpu_history* pc_hist, int blocklen)
flight! */
}
else {
#if USE_CHECKSUM_INFO
calc_checksum(csi,&csi->c1,&csi->c2);
#else
calc_checksum(bi,&(bi->c1),&(bi->c2));
#endif
add_to_active(bi);
}