about summary refs log tree commit diff stats
path: root/src/dynarec/dynarec_native.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-03-10 20:45:21 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-03-10 20:45:26 +0100
commita5a7d9382ec09c89779ae66f3af2ca2255ea3003 (patch)
tree6e1e55079aee2a6190766cf3d533662c44f0f48e /src/dynarec/dynarec_native.c
parentbc770d908af3c310e2e0cd9e1fdc7ca6e0e80fb3 (diff)
downloadbox64-a5a7d9382ec09c89779ae66f3af2ca2255ea3003.tar.gz
box64-a5a7d9382ec09c89779ae66f3af2ca2255ea3003.zip
[DYNAREC] Limit temporary memory allocation on FillBlock64
Diffstat (limited to 'src/dynarec/dynarec_native.c')
-rw-r--r--src/dynarec/dynarec_native.c57
1 files changed, 28 insertions, 29 deletions
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));
     }