From dce64e8b4dd34a5ba8b6d231a92ccded9527d7ad Mon Sep 17 00:00:00 2001 From: samsonium Date: Sun, 18 Oct 2026 17:38:49 +0300 Subject: [PATCH] fix+ref: small objects rework - Add nested objects escape on ESCAPE opcode - Stabilize objects work in heap --- include/vm/fzl_vm.h | 3 - src/vm/fzl_vm.c | 162 +++++++++++++++++++++++++++----------------- src/vm/fzl_vm_env.c | 4 +- 3 files changed, 102 insertions(+), 67 deletions(-) diff --git a/include/vm/fzl_vm.h b/include/vm/fzl_vm.h index 9d0075d..cdd820f 100644 --- a/include/vm/fzl_vm.h +++ b/include/vm/fzl_vm.h @@ -30,9 +30,6 @@ typedef struct // Environment stack fzl_vm_env_t *estack[256]; size_t etop; - - fzl_vm_object_t *objects[256]; - size_t objects_count; } fzl_vm_t; // Allocate FZL VM diff --git a/src/vm/fzl_vm.c b/src/vm/fzl_vm.c index 9c8f041..1cce290 100644 --- a/src/vm/fzl_vm.c +++ b/src/vm/fzl_vm.c @@ -25,20 +25,18 @@ fzl_vm_t *fzl_mkvm(const char *filepath) return NULL; } - vm->consts = NULL; - vm->consts_count = 0; - vm->ops = NULL; - vm->ops_count = 0; - vm->ip = 0; - vm->dtop = 0; - vm->ctop = 0; - vm->etop = 0; - vm->objects_count = 0; + vm->consts = NULL; + vm->consts_count = 0; + vm->ops = NULL; + vm->ops_count = 0; + vm->ip = 0; + vm->dtop = 0; + vm->ctop = 0; + vm->etop = 0; memset(vm->dstack, 0, sizeof(vm->dstack)); memset(vm->cstack, 0, sizeof(vm->cstack)); memset(vm->estack, 0, sizeof(vm->estack)); - memset(vm->objects, 0, sizeof(vm->objects)); FILE *fd = fopen(filepath, "rb"); if (!fd) @@ -110,6 +108,57 @@ fzl_vm_t *fzl_mkvm(const char *filepath) return vm; } +// Escape objects with nested objects check +static void escape_recursive(fzl_vm_env_t *current, fzl_vm_env_t *parent, + fzl_vm_object_t *obj) +{ + if (!current || !parent || !obj) + return; + + bool found_in_current = false; + for (size_t i = 0; i < current->owned_objects_count; i++) + { + if (current->owned_objects[i] == obj) + { + current->owned_objects[i] = NULL; + found_in_current = true; + break; + } + } + + if (found_in_current) + { + bool found_in_parent = false; + for (size_t i = 0; i < parent->owned_objects_count; i++) + { + if (parent->owned_objects[i] == obj) + { + found_in_parent = true; + break; + } + } + + if (!found_in_parent) + { + if (parent->owned_objects_remainder <= parent->owned_objects_count) + { + parent->owned_objects_remainder *= 2; + parent->owned_objects = + realloc(parent->owned_objects, parent->owned_objects_remainder * + sizeof(fzl_vm_object_t *)); + } + + parent->owned_objects[parent->owned_objects_count++] = obj; + } + } + + for (size_t i = 0; i < obj->values_count; i++) + { + if (obj->values[i].type == FZL_TYPE_OBJECT && obj->values[i].as.obj != NULL) + escape_recursive(current, parent, obj->values[i].as.obj); + } +} + void print_object(fzl_vm_object_t *obj) { if (!obj) @@ -153,25 +202,32 @@ void print_err_data(fzl_vm_t *vm) printf("> Caused on IP: %zu\n", vm->ip); printf("\n> Data stack:\n"); - for (ssize_t i = vm->dtop - 1; i >= 0; i--) + if (vm->dtop > 0) { - printf("\t> [%d] ", vm->dstack[i].type); - switch (vm->dstack[i].type) + for (ssize_t i = vm->dtop - 1; i >= 0; i--) { - case FZL_TYPE_OBJECT: - printf("ref: %p\n", vm->dstack[i].as.obj); - break; - case FZL_TYPE_STRING: - printf("str: '%s'\n", vm->dstack[i].as.s.value); - break; - case FZL_TYPE_NULL: - printf("\n"); - break; - default: - printf("%lu\n", vm->dstack[i].as.u); - break; + printf("\t> [%d] ", vm->dstack[i].type); + switch (vm->dstack[i].type) + { + case FZL_TYPE_OBJECT: + printf("ref: %p\n", vm->dstack[i].as.obj); + break; + case FZL_TYPE_STRING: + printf("str: '%s'\n", vm->dstack[i].as.s.value); + break; + case FZL_TYPE_NULL: + printf("\n"); + break; + default: + printf("%lu\n", vm->dstack[i].as.u); + break; + } } } + else + { + printf("\tEmpty\n"); + } printf("\n> Environments:\n"); for (ssize_t i = vm->etop - 1; i >= 0; i--) @@ -187,8 +243,20 @@ void print_err_data(fzl_vm_t *vm) printf("\t\t> Local entries (%zu/%zu):\n", env->size, env->remainder); for (size_t j = 0; j < env->size; j++) - printf("\t\t\t> [%d] %s = %lu\n", env->table[j].value.type, - env->table[j].name, env->table[j].value.as.u); + { + switch (env->table[j].value.type) + { + case FZL_TYPE_OBJECT: + printf("\t\t\t> [%d] %s = ref %p\n", env->table[j].value.type, + env->table[j].name, env->table[j].value.as.obj); + break; + + default: + printf("\t\t\t> [%d] %s = %lu\n", env->table[j].value.type, + env->table[j].name, env->table[j].value.as.u); + break; + } + } } printf("\n> Call stack:\n"); @@ -260,7 +328,7 @@ int fzl_vm_run(fzl_vm_t *vm) fzl_value_t right = vm->dstack[--vm->dtop]; vm->dstack[vm->dtop++] = (fzl_value_t){ - .type = FZL_TYPE_BOOL, .as.b = &left.as.obj == &right.as.obj}; + .type = FZL_TYPE_BOOL, .as.b = left.as.obj == right.as.obj}; break; } @@ -277,11 +345,10 @@ int fzl_vm_run(fzl_vm_t *vm) fzl_value_t right = vm->dstack[--vm->dtop]; vm->dstack[vm->dtop++] = (fzl_value_t){ - .type = FZL_TYPE_BOOL, .as.b = &left.as.obj != &right.as.obj}; + .type = FZL_TYPE_BOOL, .as.b = left.as.obj != right.as.obj}; break; } - // NOTE: make recursive owning transfer for nested objects! case FZL_OPCODE_ESCAPE_OBJECT: { if (vm->dtop < 1) @@ -302,7 +369,7 @@ int fzl_vm_run(fzl_vm_t *vm) fzl_vm_env_t *parent = vm->estack[vm->etop - 2]; fzl_vm_env_t *current = vm->estack[vm->etop - 1]; - if (!parent || vm->etop < 2) + if (vm->etop < 2) { snprintf(last_err, sizeof(last_err), "runtime error - cannot escape object from global env"); @@ -310,32 +377,7 @@ int fzl_vm_run(fzl_vm_t *vm) return -1; } - bool found = false; - if (obj.as.u != 0) - { - for (size_t i = 0; i < current->owned_objects_count; i++) - { - if (obj.as.obj == current->owned_objects[i]) - { - found = true; - current->owned_objects[i] = NULL; - break; - } - } - } - - if (found) - { - if (parent->owned_objects_remainder <= parent->owned_objects_count) - { - parent->owned_objects_remainder *= 2; - parent->owned_objects = - realloc(parent->owned_objects, parent->owned_objects_remainder * - sizeof(fzl_vm_object_t *)); - } - - parent->owned_objects[parent->owned_objects_count++] = obj.as.obj; - } + escape_recursive(current, parent, obj.as.obj); vm->dstack[vm->dtop++] = obj; break; @@ -900,12 +942,6 @@ void fzl_freevm(fzl_vm_t *vm) free((void *)vm->consts[i].as.string.chars); } - for (size_t i = 0; i < vm->objects_count; i++) - { - free(vm->objects[i]->values); - free(vm->objects[i]); - } - free(vm->consts); free(vm->ops); free(vm); diff --git a/src/vm/fzl_vm_env.c b/src/vm/fzl_vm_env.c index 1abe7d1..a7c98e6 100644 --- a/src/vm/fzl_vm_env.c +++ b/src/vm/fzl_vm_env.c @@ -109,7 +109,9 @@ void fzl_freeenv(fzl_vm_env_t *env) if (!env->owned_objects[i]) continue; - free(env->owned_objects[i]->values); + if (env->owned_objects[i]->values) + free(env->owned_objects[i]->values); + free(env->owned_objects[i]); }