diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-06-19 11:15:53 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-06-19 11:15:53 +0200 |
| commit | dfd3d0ec932c327992764c5e2744fe9f0c0bff01 (patch) | |
| tree | 80497af72f2f42ad844648e8eb1d734cc7806678 /src | |
| parent | 1791c0937aedfabc496e12a41bfcf43cfb154ee7 (diff) | |
| download | box64-dfd3d0ec932c327992764c5e2744fe9f0c0bff01.tar.gz box64-dfd3d0ec932c327992764c5e2744fe9f0c0bff01.zip | |
[DYNAREC] Try to free dynablocks when no longer used
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 29 | ||||
| -rwxr-xr-x | src/dynarec/dynablock.c | 48 | ||||
| -rwxr-xr-x | src/include/dynablock.h | 3 |
3 files changed, 54 insertions, 26 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); } } diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index d4a79156..a592b28f 100755 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -165,10 +165,10 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t MarkDynablock(db); } -void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size) +int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size) { if(!dynablocks) - return; + return 1; if(dynablocks->direct) { dynablock_t* db; @@ -176,34 +176,38 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s khint_t k; kh_dynablocks_t *blocks = kh_init(dynablocks); // copy in a temporary list - if(dynablocks->direct) { - uintptr_t startdb = dynablocks->text; - uintptr_t enddb = startdb + dynablocks->textsz; - uintptr_t start = addr; - uintptr_t end = addr+size; - if(start<startdb) - start = startdb; - if(end>enddb) - end = enddb; - if(end>startdb && start<enddb) - for(uintptr_t i = start; i<end; ++i) { - db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0); - if(db) { - if(db->father) - db = db->father; - if(db->parent==dynablocks) { - k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret); - kh_value(blocks, k) = db; - } + uintptr_t startdb = dynablocks->text; + uintptr_t enddb = startdb + dynablocks->textsz; + uintptr_t start = addr; + uintptr_t end = addr+size; + if(start<startdb) + start = startdb; + if(end>enddb) + end = enddb; + if(end>startdb && start<enddb) + for(uintptr_t i = start; i<end; ++i) { + db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0); + if(db) { + if(db->father) + db = db->father; + if(db->parent==dynablocks) { + k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret); + kh_value(blocks, k) = db; } } - } + } // purge the list kh_foreach_value(blocks, db, FreeDynablock(db); ); kh_destroy(dynablocks, blocks); + // check emptyness + for(uintptr_t i=0; i<dynablocks->textsz; ++i) + if(dynablocks->direct[i]) + return 0; + return 1; } + return 1; } void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size) { diff --git a/src/include/dynablock.h b/src/include/dynablock.h index 76f1e5e0..618a3651 100755 --- a/src/include/dynablock.h +++ b/src/include/dynablock.h @@ -11,7 +11,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct); void FreeDynablockList(dynablocklist_t** dynablocks); void FreeDynablock(dynablock_t* db); void MarkDynablock(dynablock_t* db); -void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size); +//return 1 if Dynareblock is empty +int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size); void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size); dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h |