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:
20
src/main.c
20
src/main.c
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user