about summary refs log tree commit diff stats
path: root/src/custommem.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-19 11:15:53 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-19 11:15:53 +0200
commitdfd3d0ec932c327992764c5e2744fe9f0c0bff01 (patch)
tree80497af72f2f42ad844648e8eb1d734cc7806678 /src/custommem.c
parent1791c0937aedfabc496e12a41bfcf43cfb154ee7 (diff)
downloadbox64-dfd3d0ec932c327992764c5e2744fe9f0c0bff01.tar.gz
box64-dfd3d0ec932c327992764c5e2744fe9f0c0bff01.zip
[DYNAREC] Try to free dynablocks when no longer used
Diffstat (limited to 'src/custommem.c')
-rw-r--r--src/custommem.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/custommem.c b/src/custommem.c
index a3aa8358..151dad63 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -540,6 +540,14 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
     }
 }
 
+static int dynmapempty(void** mem)
+{
+    for (int i=0; i<(1<<DYNAMAP_SHIFT); ++i)
+        if(mem[i])
+            return 0;
+    return 1;
+}
+
 void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
 {
     dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
@@ -552,9 +560,24 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
         if(dynmap123[idx3] && dynmap123[idx3][idx2]) {
             dynablocklist_t* dblist = dynmap123[idx3][idx2][idx1];
             if(dblist) {
-                if(destroy)
-                    FreeRangeDynablock(dblist, addr, size);
-                else
+                if(destroy) {
+                    if(FreeRangeDynablock(dblist, addr, size)) {    // dblist is empty, check if we can delete more...
+                        if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
+                            free(dblist);
+                            dynablocklist_t** p = dynmap123[idx3][idx2];
+                            if(dynmapempty((void**)p)) {
+                                if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
+                                    free(p);
+                                    dynablocklist_t*** p2 = dynmap123[idx3];
+                                    if(dynmapempty((void**)p2)) {
+                                        if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2))
+                                            free(p2);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                } else
                     MarkRangeDynablock(dblist, addr, size);
             }
         }