diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-03-10 20:45:21 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-03-10 20:45:26 +0100 |
| commit | a5a7d9382ec09c89779ae66f3af2ca2255ea3003 (patch) | |
| tree | 6e1e55079aee2a6190766cf3d533662c44f0f48e | |
| parent | bc770d908af3c310e2e0cd9e1fdc7ca6e0e80fb3 (diff) | |
| download | box64-a5a7d9382ec09c89779ae66f3af2ca2255ea3003.tar.gz box64-a5a7d9382ec09c89779ae66f3af2ca2255ea3003.zip | |
[DYNAREC] Limit temporary memory allocation on FillBlock64
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_pass0.h | 6 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native.c | 57 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native_pass.c | 7 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 4 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_pass0.h | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_pass0.h | 6 | ||||
| -rw-r--r-- | src/include/dynarec_native.h | 2 |
8 files changed, 42 insertions, 50 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index 812986a0..a335c6c5 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -22,11 +22,7 @@ #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 #define NEW_INST \ ++dyn->size; \ - if(dyn->size+3>=dyn->cap) { \ - dyn->insts = (instruction_native_t*)dynaRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\ - memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t)*dyn->cap); \ - dyn->cap *= 2; \ - } \ + memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t)); \ dyn->insts[ninst].x64.addr = ip; \ dyn->n.combined1 = dyn->n.combined2 = 0;\ dyn->n.swapped = 0; dyn->n.barrier = 0; \ diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c index 600d23d1..84e5d3dc 100644 --- a/src/dynarec/dynarec_native.c +++ b/src/dynarec/dynarec_native.c @@ -72,8 +72,7 @@ void add_next(dynarec_native_t *dyn, uintptr_t addr) { } // add slots if(dyn->next_sz == dyn->next_cap) { - dyn->next_cap += 64; - dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t)); + printf_log(LOG_NONE, "Warning, overallocating next\n"); } dyn->next[dyn->next_sz++] = addr; } @@ -97,8 +96,7 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) { void add_jump(dynarec_native_t *dyn, int ninst) { // add slots if(dyn->jmp_sz == dyn->jmp_cap) { - dyn->jmp_cap += 64; - dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int)); + printf_log(LOG_NONE, "Warning, overallocating jmps\n"); } dyn->jmps[dyn->jmp_sz++] = ninst; } @@ -289,15 +287,10 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass) idx = i; // not found, add it if(idx==-1) { - if(dyn->table64size == dyn->table64cap) { - dyn->table64cap+=16; - if(pass<3) // do not resize on pass3, it's not the same type of memory anymore - dyn->table64 = (uint64_t*)dynaRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t)); - } idx = dyn->table64size++; if(idx < dyn->table64cap) dyn->table64[idx] = val; - else + else if(pass==3) printf_log(LOG_NONE, "Warning, table64 bigger than expected %d vs %d\n", idx, dyn->table64cap); } // calculate offset @@ -305,7 +298,7 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass) return delta; } -static void fillPredecessors(dynarec_native_t* dyn) +static int sizePredecessors(dynarec_native_t* dyn) { int pred_sz = 1; // to be safe // compute total size of predecessor to allocate the array @@ -330,8 +323,10 @@ static void fillPredecessors(dynarec_native_t* dyn) dyn->insts[i+1].pred_sz++; } } - int alloc_size = pred_sz; - dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int)); + return pred_sz; +} +static void fillPredecessors(dynarec_native_t* dyn) +{ // fill pred pointer int* p = dyn->predecessor; for(int i=0; i<dyn->size; ++i) { @@ -406,12 +401,6 @@ void CancelBlock64(int need_lock) dynarec_native_t* helper = (dynarec_native_t*)current_helper; current_helper = NULL; if(helper) { - dynaFree(helper->next); - dynaFree(helper->jmps); - dynaFree(helper->insts); - dynaFree(helper->predecessor); - if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart)) - dynaFree(helper->table64); if(helper->dynablock && helper->dynablock->actual_block) { FreeDynarecMap((uintptr_t)helper->dynablock->actual_block); helper->dynablock->actual_block = NULL; @@ -449,6 +438,12 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) { return block; } +static int static_jmps[MAX_INSTS+2]; +static uintptr_t static_next[MAX_INSTS+2]; +static uint64_t static_table64[(MAX_INSTS+3)/4]; +static instruction_native_t static_insts[MAX_INSTS+2] = {0}; +// TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory + void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits) { /* A Block must have this layout: @@ -458,7 +453,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit A .. A+8*n : Table64: n 64bits values B .. B+7 : dynablock_t* : self (as part of JmpNext, that simulate another block) B+8 .. B+15 : 2 Native code for jmpnext (or jmp epilog in case of empty block) - B+16 .. B+23 : jmpnext (or jmp_epilog) address + B+16 .. B+23 : jmpnext (or jmp_epilog) address. jumpnext is used when the block needs testing B+24 .. B+31 : empty (in case an architecture needs more than 2 opcodes) B+32 .. B+32+sz : instsize (compressed array with each instruction length on x64 and native side) @@ -479,8 +474,14 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit helper.dynablock = block; helper.start = addr; uintptr_t start = addr; - helper.cap = 128; - helper.insts = (instruction_native_t*)dynaCalloc(helper.cap, sizeof(instruction_native_t)); + helper.cap = MAX_INSTS; + helper.insts = static_insts; + helper.jmps = static_jmps; + helper.jmp_cap = MAX_INSTS; + helper.next = static_next; + helper.next_cap = MAX_INSTS; + helper.table64 = static_table64; + helper.table64cap = sizeof(static_table64)/sizeof(uint64_t); // pass 0, addresses, x64 jump addresses, overall size of the block uintptr_t end = native_pass0(&helper, addr, alternate, is32bits); if(helper.abort) { @@ -550,13 +551,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit } } // no need for next and jmps anymore - dynaFree(helper.next); helper.next_sz = helper.next_cap = 0; helper.next = NULL; - dynaFree(helper.jmps); helper.jmp_sz = helper.jmp_cap = 0; helper.jmps = NULL; // fill predecessors with the jump address + int alloc_size = sizePredecessors(&helper); + helper.predecessor = (int*)alloca(alloc_size*sizeof(int)); fillPredecessors(&helper); int pos = helper.size; @@ -612,7 +613,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit helper.instsize = (instsize_t*)instsize; *(dynablock_t**)actual_p = block; helper.table64cap = helper.table64size; - dynaFree(helper.table64); helper.table64 = (uint64_t*)helper.tablestart; // pass 3, emit (log emit native opcode) if(box64_dynarec_dump) { @@ -634,12 +634,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit } // keep size of instructions for signal handling block->instsize = instsize; - // ok, free the helper now - dynaFree(helper.insts); - helper.insts = NULL; helper.table64 = NULL; helper.instsize = NULL; - dynaFree(helper.predecessor); helper.predecessor = NULL; block->size = sz; block->isize = helper.size; @@ -676,6 +672,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit CancelBlock64(0); return NULL; } + // ok, free the helper now + //dynaFree(helper.insts); + helper.insts = NULL; if(insts_rsize/sizeof(instsize_t)<helper.insts_size) { printf_log(LOG_NONE, "BOX64: Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t)); } diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 471e2c98..8c609da1 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -71,7 +71,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int // This test is here to prevent things like TABLE64 to be out of range // native_size is not exact at this point, but it should be larger, not smaller, and not by a huge margin anyway // so it's good enough to avoid overflow in relative to PC data fectching - if(dyn->native_size >= MAXBLOCK_SIZE) { + if((dyn->native_size >= MAXBLOCK_SIZE) || (ninst >= MAX_INSTS)) { need_epilog = 1; break; } @@ -98,8 +98,11 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } } reset_n = -1; - } else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1))) + } + #if STEP > 0 + else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1))) dyn->last_ip = 0; // reset IP if some jump are coming here + #endif fpu_propagate_stack(dyn, ninst); NEW_INST; #if STEP == 0 diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index a2503932..b1cb2fc0 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -403,8 +403,8 @@ #define ARCH_INIT() #if STEP < 2 -#define GETIP(A) -#define GETIP_(A) +#define GETIP(A) TABLE64(0, 0) +#define GETIP_(A) TABLE64(0, 0) #else // put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later... #define GETIP(A) \ diff --git a/src/dynarec/la64/dynarec_la64_pass0.h b/src/dynarec/la64/dynarec_la64_pass0.h index af2c29ba..5b3ce706 100644 --- a/src/dynarec/la64/dynarec_la64_pass0.h +++ b/src/dynarec/la64/dynarec_la64_pass0.h @@ -25,11 +25,7 @@ #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 #define NEW_INST \ ++dyn->size; \ - if (dyn->size + 3 >= dyn->cap) { \ - dyn->insts = (instruction_native_t*)dynaRealloc(dyn->insts, sizeof(instruction_native_t) * dyn->cap * 2); \ - memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t) * dyn->cap); \ - dyn->cap *= 2; \ - } \ + memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t)); \ dyn->insts[ninst].x64.addr = ip; \ dyn->insts[ninst].f_entry = dyn->f; \ if (ninst) { dyn->insts[ninst - 1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst - 1].x64.addr; } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index bb2572ad..1f2f43c5 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1002,8 +1002,8 @@ #if STEP < 2 -#define GETIP(A) -#define GETIP_(A) +#define GETIP(A) TABLE64(0, 0) +#define GETIP_(A) TABLE64(0, 0) #else // put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later... #define GETIP(A) \ diff --git a/src/dynarec/rv64/dynarec_rv64_pass0.h b/src/dynarec/rv64/dynarec_rv64_pass0.h index 13d4f115..0def2bed 100644 --- a/src/dynarec/rv64/dynarec_rv64_pass0.h +++ b/src/dynarec/rv64/dynarec_rv64_pass0.h @@ -22,11 +22,7 @@ #define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1 #define NEW_INST \ ++dyn->size; \ - if(dyn->size+3>=dyn->cap) { \ - dyn->insts = (instruction_native_t*)dynaRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\ - memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t)*dyn->cap); \ - dyn->cap *= 2; \ - } \ + memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t)); \ dyn->insts[ninst].x64.addr = ip; \ dyn->e.combined1 = dyn->e.combined2 = 0;\ dyn->e.swapped = 0; dyn->e.barrier = 0; \ diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h index 05bfc3b5..c61eb375 100644 --- a/src/include/dynarec_native.h +++ b/src/include/dynarec_native.h @@ -18,6 +18,8 @@ typedef struct instsize_s instsize_t; #define dynaFree box_free #endif +#define MAX_INSTS 8190 + void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size); void CancelBlock64(int need_lock); |