Refactor allocator to use offsets instead of absolute pointers

JLANG_malloc now returns size_t offsets relative to the heap buffer,
making all references stable across heap growth (realloc). Object API
updated accordingly: constructors return offsets, obj_print/obj_free
receive (allocator, offset). Added heap auto-grow when out of space.
This commit is contained in:
Jose Luis Montañes Ojados
2026-02-15 23:16:45 +01:00
parent 5dc0946a19
commit 13c9d052a0
3 changed files with 118 additions and 100 deletions

View File

@@ -7,24 +7,18 @@ int main() {
printf("memoryPtr=%p\n", allocPtr->memory); printf("memoryPtr=%p\n", allocPtr->memory);
printf("size=%zu\n", allocPtr->size); printf("size=%zu\n", allocPtr->size);
// Create object size_t stringVar1 = obj_new_string(allocPtr, "\nHello world!\n");
Object *intVar1 = obj_new_int(allocPtr, 66); obj_print(allocPtr, stringVar1);
obj_print(intVar1);
Object *stringVar1 = obj_new_string(allocPtr, "\nHello world!\n");
obj_print(stringVar1);
JLANG_visualize(allocPtr); JLANG_visualize(allocPtr);
for (int i = 0; i < 10; i++) { // obj_free(allocPtr, stringVar1);
Object *intVar1 = obj_new_int(allocPtr, 66);
obj_print(intVar1); for (int i = 0; i < 20; i++) {
obj_new_string(allocPtr, "FFFFFFFFFFFFFF");
} }
obj_free(allocPtr, intVar1); obj_print(allocPtr, stringVar1);
void* newPtr = JLANG_malloc(allocPtr, 8);
obj_print(stringVar1);
JLANG_visualize(allocPtr); JLANG_visualize(allocPtr);
return 0; return 0;
} }

View File

@@ -58,7 +58,7 @@ size_t JLANG_used(void *ptr) {
// Iterate memory parsing only metadata // Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory; JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0; size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size) { while (currentHeader->size != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size; used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block // Current block is in_use, jump to next block
@@ -76,7 +76,7 @@ void *JLANG_last_free(void *ptr) {
// Iterate memory parsing only metadata // Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory; JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0; size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size) { while (currentHeader->size != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size; used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block // Current block is in_use, jump to next block
@@ -88,7 +88,9 @@ void *JLANG_last_free(void *ptr) {
return currentHeader; return currentHeader;
} }
void *JLANG_malloc(void *ptr, size_t size) { // JLANG_malloc devuelve un offset a la memoria del heap. No un absoluto a la
// memoria del proceso
size_t JLANG_malloc(void *ptr, size_t size) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr; JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// 1. Hay bloques disponibles?? // 1. Hay bloques disponibles??
@@ -101,16 +103,42 @@ void *JLANG_malloc(void *ptr, size_t size) {
freeHeader->size = size; freeHeader->size = size;
freeHeader->in_use = 1; freeHeader->in_use = 1;
return (char *)freeHeader + sizeof(JLANG_metadata); void *payloadPtr = (char *)freeHeader + sizeof(JLANG_metadata);
return (char *)payloadPtr - allocPtr->memory;
} }
return NULL; // TODO /*
Se necesita más espacio..
De momento vamos a pedir otro array más grande y liberar el antiguo
Mantenemos toda la memoria contigua
*/
int newSize = allocPtr->size + 1024;
char *newBuffer = (char *)malloc(newSize); // Otro 1KB
memset(newBuffer, 0, newSize);
memcpy(newBuffer, allocPtr->memory,
allocPtr->size); // Copiamos al nuevo buffer
allocPtr->size = newSize;
free(allocPtr->memory); // Liberamos el buffer antiguo
allocPtr->memory = newBuffer; // Seteamos el nuevo buffer
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
freeHeader->size = size;
freeHeader->in_use = 1;
void *payloadPtr = (char *) freeHeader + sizeof(JLANG_metadata);
return (char *)payloadPtr - allocPtr->memory;
} }
void JLANG_free(void *ptr, void *blockPtr) { void JLANG_free(void *ptr, size_t blockOffset) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr; JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Get block header // Get block header
void *blockPtr = allocPtr->memory + blockOffset;
JLANG_metadata *blockHeader = JLANG_metadata *blockHeader =
(JLANG_metadata *)((char *)blockPtr - sizeof(JLANG_metadata)); (JLANG_metadata *)((char *)blockPtr - sizeof(JLANG_metadata));

View File

@@ -1,28 +1,20 @@
#include "../memory/allocator.h" #include "../memory/allocator.h"
typedef enum #define JLANG_RESOLVE(alloc, offset) \
{ ((void *)(((JLANG_memory_allocator *)(alloc))->memory + (offset)))
OBJ_INT,
OBJ_FLOAT,
OBJ_STRING,
OBJ_LIST,
OBJ_NONE
} ObjectType;
typedef struct Object typedef enum { OBJ_INT, OBJ_FLOAT, OBJ_STRING, OBJ_LIST, OBJ_NONE } ObjectType;
{
typedef struct Object {
ObjectType type; ObjectType type;
union union {
{
int int_val; int int_val;
double float_val; double float_val;
struct struct {
{ size_t chars;
char *chars;
int length; int length;
} string_val; } string_val;
struct struct {
{
struct Object **items; struct Object **items;
int count; int count;
int capacity; int capacity;
@@ -30,70 +22,74 @@ typedef struct Object
} data; } data;
} Object; } Object;
Object *obj_new_int(void *allocator, int value) size_t obj_new_int(void *allocator, int value) {
{ // Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object)); size_t offset = JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->type = OBJ_INT; objPtr->type = OBJ_INT;
objPtr->data.int_val = value; objPtr->data.int_val = value;
return objPtr; return offset;
} }
Object *obj_new_float(void *allocator, float value) size_t obj_new_float(void *allocator, float value) {
{ size_t offset = JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object)); Object *objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->type = OBJ_FLOAT; objPtr->type = OBJ_FLOAT;
objPtr->data.float_val = value; objPtr->data.float_val = value;
return objPtr; return offset;
} }
Object *obj_new_string(void *allocator, const char *str) size_t obj_new_string(void *allocator, const char *str) {
{ size_t offset = JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object)); Object *objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->type = OBJ_STRING; objPtr->type = OBJ_STRING;
int len = strlen(str); int len = strlen(str);
char *buffer = (char *)JLANG_malloc(allocator, len + 1);
// !! CUIDADO CON ESTE DOBLE MALLOC SI DISPARA EL GROW !!
size_t bufferOffset = JLANG_malloc(allocator, len + 1);
char *buffer = (char *)JLANG_RESOLVE(allocator, bufferOffset);
memcpy(buffer, str, len + 1); memcpy(buffer, str, len + 1);
objPtr->data.string_val.chars = buffer; objPtr->data.string_val.chars = bufferOffset;
objPtr->data.string_val.length = len; objPtr->data.string_val.length = len;
return objPtr; return offset;
} }
Object *obj_new_list(void *allocator) size_t obj_new_list(void *allocator) {
{ size_t offset = JLANG_malloc(allocator, sizeof(Object));
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object)); Object *objPtr = (Object *)JLANG_RESOLVE(allocator, offset);
objPtr->type = OBJ_LIST; objPtr->type = OBJ_LIST;
return objPtr; return offset;
} }
void obj_free(void *allocator, Object* obj) { void obj_free(void *allocator, size_t offset) {
if (obj->type == OBJ_STRING) { // if (obj->type == OBJ_STRING) {
JLANG_free(allocator, obj->data.string_val.chars); // JLANG_free(allocator, obj->data.string_val.chars);
// }
JLANG_free(allocator, offset);
} }
JLANG_free(allocator, obj); void obj_print(void *allocator, size_t offset) {
} Object *obj = (Object *)JLANG_RESOLVE(allocator, offset);
void obj_print(Object *obj) switch (obj->type) {
{
switch (obj->type)
{
case OBJ_INT: case OBJ_INT:
printf("%d", obj->data.int_val); printf("%d", obj->data.int_val);
break; break;
case OBJ_FLOAT: case OBJ_FLOAT:
printf("%f", obj->data.float_val); printf("%f", obj->data.float_val);
break; break;
case OBJ_LIST: // case OBJ_LIST:
for (int i = 0; i < obj->data.list_val.count; i++) // for (int i = 0; i < obj->data.list_val.count; i++) {
{ // obj_print(obj->data.list_val.items[i]);
obj_print(obj->data.list_val.items[i]); // }
} // break;
break;
case OBJ_STRING: case OBJ_STRING:
printf("%s", obj->data.string_val.chars); printf("%s", (char *)JLANG_RESOLVE(allocator, obj->data.string_val.chars));
break; break;
default: default:
break; break;