Implement more intelligent out-of-memory algorithm.

This commit is contained in:
SarahW 2019-01-21 21:52:32 +00:00
commit ec18c8a2fb
8 changed files with 25 additions and 9 deletions

View file

@ -290,6 +290,7 @@ void codegen_block_remove();
void codegen_block_start_recompile(codeblock_t *block);
void codegen_block_end_recompile(codeblock_t *block);
void codegen_block_end();
void codegen_delete_block(codeblock_t *block);
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
void codegen_generate_seg_restore();
void codegen_set_op32();

View file

@ -14,6 +14,7 @@ typedef struct mem_block_t
{
uint32_t offset; /*Offset into mem_block_alloc*/
uint32_t next;
uint16_t code_block;
} mem_block_t;
static mem_block_t mem_blocks[MEM_BLOCK_NR];
@ -35,6 +36,7 @@ void codegen_allocator_init()
for (c = 0; c < MEM_BLOCK_NR; c++)
{
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
mem_blocks[c].code_block = BLOCK_INVALID;
if (c < MEM_BLOCK_NR-1)
mem_blocks[c].next = c+2;
else
@ -43,15 +45,19 @@ void codegen_allocator_init()
mem_block_free_list = 1;
}
mem_block_t *codegen_allocator_allocate(mem_block_t *parent)
mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block)
{
mem_block_t *block;
uint32_t block_nr;
while (!mem_block_free_list)
{
if (!codegen_purge_purgable_list())
codegen_delete_random_block(1);
/*Pick a random memory block and free the owning code block*/
block_nr = rand() & MEM_BLOCK_MASK;
block = &mem_blocks[block_nr];
if (block->code_block && block->code_block != code_block)
codegen_delete_block(&codeblock[block->code_block]);
}
// fatal("codegen_allocator_allocate: free list empty!\n");
@ -60,6 +66,7 @@ mem_block_t *codegen_allocator_allocate(mem_block_t *parent)
block = &mem_blocks[block_nr-1];
mem_block_free_list = block->next;
block->code_block = code_block;
if (parent)
{
/*Add to parent list*/
@ -88,6 +95,7 @@ void codegen_allocator_free(mem_block_t *block)
codegen_allocator_usage--;
block->next = mem_block_free_list;
block->code_block = BLOCK_INVALID;
mem_block_free_list = block_nr;
block_nr = next_block_nr;

View file

@ -19,13 +19,14 @@
#define MEM_BLOCK_NR 131072
#endif
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
#define MEM_BLOCK_SIZE 0x3c0
void codegen_allocator_init();
/*Allocate a mem_block_t, and the associated backing memory.
If parent is non-NULL, then the new block will be added to the list in
parent->next*/
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent);
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent, int code_block);
/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/
void codegen_allocator_free(struct mem_block_t *block);
/*Get a pointer to the backing memory associated with block*/

View file

@ -300,6 +300,12 @@ static void delete_block(codeblock_t *block)
block_free_list_add(block);
}
void codegen_delete_block(codeblock_t *block)
{
if (block->pc != BLOCK_PC_INVALID)
delete_block(block);
}
void codegen_delete_random_block(int required_mem_block)
{
int block_nr = rand() & BLOCK_MASK;
@ -419,7 +425,7 @@ void codegen_block_start_recompile(codeblock_t *block)
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
fatal("Recompile to used block!\n");
block->head_mem_block = codegen_allocator_allocate(NULL);
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block->status = cpu_cur_status;

View file

@ -298,7 +298,7 @@ void codegen_backend_init()
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL);
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current);
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
block_write_data = codeblock[block_current].data;
build_loadstore_routines(&codeblock[block_current]);

View file

@ -101,7 +101,7 @@ static inline void codegen_alloc_bytes(codeblock_t *block, int size)
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block);
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/

View file

@ -299,7 +299,7 @@ pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2));
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL);
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);

View file

@ -78,7 +78,7 @@ static inline void codegen_addquad(codeblock_t *block, uint64_t val)
static void codegen_allocate_new_block(codeblock_t *block)
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block);
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/