Optimize memory handling (#1963)

* optimize ram block handling

Save the last element of the ram_list. This allows to
faster find where to add new elements when they are not
bigger then page size.

* save ram_list freed

this keeps the optimization for find_ram_offset() intact after snapshot
restore.

* cow only clear the tlb of affected pages

* update flatview when possible

Building each flatview new when the memory has changed is quite
expensive when many MemoryRegions are used. This is an issue when using
snapshots.

* update benchmark for new api

* save flatview in context

this avoids rebuilding the flatview when restore a context.

* init context flatview with zero

* address_space_dispatch_clear remove subpage with higher priority

* docutemnt the options for UC_CTL_CONTEXT_MODE

Specialy stress that with UC_CTL_CONTEXT_MEMORY it is not possible to
use the context with a different unicorn object.
This commit is contained in:
PhilippTakacs
2024-10-16 15:51:13 +02:00
committed by GitHub
parent fea3411803
commit e8ca3cbea5
27 changed files with 236 additions and 45 deletions

23
uc.c
View File

@@ -2106,6 +2106,7 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context)
(*_context)->context_size = size - sizeof(uc_context);
(*_context)->arch = uc->arch;
(*_context)->mode = uc->mode;
(*_context)->fv = NULL;
restore_jit_state(uc);
return UC_ERR_OK;
} else {
@@ -2142,11 +2143,23 @@ uc_err uc_context_save(uc_engine *uc, uc_context *context)
uc_err ret = UC_ERR_OK;
if (uc->context_content & UC_CTL_CONTEXT_MEMORY) {
if (!context->fv) {
context->fv = g_malloc0(sizeof(*context->fv));
}
if (!context->fv) {
return UC_ERR_NOMEM;
}
if (!uc->flatview_copy(uc, context->fv, uc->address_space_memory.current_map, false)) {
restore_jit_state(uc);
return UC_ERR_NOMEM;
}
ret = uc_snapshot(uc);
if (ret != UC_ERR_OK) {
restore_jit_state(uc);
return ret;
}
context->ramblock_freed = uc->ram_list.freed;
context->last_block = uc->ram_list.last_block;
}
context->snapshot_level = uc->snapshot_level;
@@ -2418,6 +2431,11 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context)
return ret;
}
uc_snapshot(uc);
uc->ram_list.freed = context->ramblock_freed;
uc->ram_list.last_block = context->last_block;
if (!uc->flatview_copy(uc, uc->address_space_memory.current_map, context->fv, true)) {
return UC_ERR_NOMEM;
}
}
if (uc->context_content & UC_CTL_CONTEXT_CPU) {
@@ -2434,6 +2452,10 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context)
UNICORN_EXPORT
uc_err uc_context_free(uc_context *context)
{
if (context->fv) {
free(context->fv->ranges);
g_free(context->fv);
}
return uc_free(context);
}
@@ -2870,6 +2892,7 @@ static uc_err uc_restore_latest_snapshot(struct uc_struct *uc)
g_array_remove_range(uc->unmapped_regions, i, 1);
}
uc->snapshot_level--;
return UC_ERR_OK;
}