fix+ref: small objects rework
- Add nested objects escape on ESCAPE opcode - Stabilize objects work in heap
This commit is contained in:
@@ -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
|
||||
|
||||
+99
-63
@@ -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("<null>\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("<null>\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);
|
||||
|
||||
+3
-1
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user