From ec18c8a2fbb6a89a268b772fded2a95c7b25b92e Mon Sep 17 00:00:00 2001 From: SarahW Date: Mon, 21 Jan 2019 21:52:32 +0000 Subject: [PATCH] Implement more intelligent out-of-memory algorithm. --- src/codegen.h | 1 + src/codegen_allocator.c | 14 +++++++++++--- src/codegen_allocator.h | 3 ++- src/codegen_backend.c | 8 +++++++- src/codegen_backend_x86-64.c | 2 +- src/codegen_backend_x86-64_ops.c | 2 +- src/codegen_backend_x86.c | 2 +- src/codegen_backend_x86_ops.c | 2 +- 8 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/codegen.h b/src/codegen.h index 39c101f..1438dab 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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(); diff --git a/src/codegen_allocator.c b/src/codegen_allocator.c index b6b8273..4b4ffd7 100644 --- a/src/codegen_allocator.c +++ b/src/codegen_allocator.c @@ -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; diff --git a/src/codegen_allocator.h b/src/codegen_allocator.h index ffe633c..1adb243 100644 --- a/src/codegen_allocator.h +++ b/src/codegen_allocator.h @@ -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*/ diff --git a/src/codegen_backend.c b/src/codegen_backend.c index 034ad61..c047ba3 100644 --- a/src/codegen_backend.c +++ b/src/codegen_backend.c @@ -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; diff --git a/src/codegen_backend_x86-64.c b/src/codegen_backend_x86-64.c index fff5942..2c1d970 100644 --- a/src/codegen_backend_x86-64.c +++ b/src/codegen_backend_x86-64.c @@ -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]); diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 956f4eb..90700fe 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -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*/ diff --git a/src/codegen_backend_x86.c b/src/codegen_backend_x86.c index 982f69d..6119ea2 100644 --- a/src/codegen_backend_x86.c +++ b/src/codegen_backend_x86.c @@ -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); diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 56bd27a..2d9ef2c 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -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*/