add JLANG_free and Object

This commit is contained in:
Jose Luis Montañes Ojados
2026-02-15 22:12:19 +01:00
parent c90883ac27
commit 5dc0946a19
4 changed files with 262 additions and 151 deletions

BIN
run.exe

Binary file not shown.

View File

@@ -1,4 +1,4 @@
#include "memory/allocator.h"
#include "objects/object.h"
int main() {
JLANG_memory_allocator *allocPtr = JLANG_CreateAllocator();
@@ -7,12 +7,24 @@ int main() {
printf("memoryPtr=%p\n", allocPtr->memory);
printf("size=%zu\n", allocPtr->size);
JLANG_visualize(allocPtr);
// Create object
Object *intVar1 = obj_new_int(allocPtr, 66);
obj_print(intVar1);
void *var1 = JLANG_malloc(allocPtr, 512);
printf("var1Ptr=%p\n", var1);
Object *stringVar1 = obj_new_string(allocPtr, "\nHello world!\n");
obj_print(stringVar1);
JLANG_visualize(allocPtr);
for (int i = 0; i < 10; i++) {
Object *intVar1 = obj_new_int(allocPtr, 66);
obj_print(intVar1);
}
obj_free(allocPtr, intVar1);
void* newPtr = JLANG_malloc(allocPtr, 8);
obj_print(stringVar1);
JLANG_visualize(allocPtr);
return 0;
}

View File

@@ -1,11 +1,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Custom Memory Allocator
Implementacion custom de un memory allocator que opera sobre un array de bytes usandolo como "heap"
Implementacion custom de un memory allocator que opera sobre un array de
bytes usandolo como "heap"
*/
#define JLANG_OK 0
@@ -15,82 +16,79 @@
#define JLANG_PAYLOAD 2
/*
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si está en uso.
Se añadirá al principio de cada bloque
[BLOCK_METADATA] + [BLOCK_BYTES]
La estructura de Metadata se encarga de almacenar el tamaño del bloque y si
está en uso. Se añadirá al principio de cada bloque [BLOCK_METADATA] +
[BLOCK_BYTES]
*/
typedef struct
{
typedef struct {
size_t size; // 8 bytes
int in_use; // 4 bytes
// --- aquí el compilador mete 4 bytes invisibles ---
} JLANG_metadata;
/*
La estructura de Memory Allocator se encarga de almancenar el array de memoria y el tamaño de esta.
La estructura de Memory Allocator se encarga de almancenar el array de
memoria y el tamaño de esta.
*/
typedef struct
{
typedef struct {
char *memory; // 8 bytes
size_t size; // 8 bytes
} JLANG_memory_allocator;
void *JLANG_CreateAllocator()
{
void *JLANG_CreateAllocator() {
// Allocate memory in heap for JLANG_memory_allocator
JLANG_memory_allocator *allocator = (JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
JLANG_memory_allocator *allocator =
(JLANG_memory_allocator *)malloc(sizeof(JLANG_memory_allocator));
// Assign default free bytes
allocator->memory = (char *)malloc(1 * 1024);
allocator->size = 1 * 1024;
// ensure all memory is zero
for (int i = 0; i < 1 * 1024; i++)
{
for (int i = 0; i < 1 * 1024; i++) {
allocator->memory[i] = 0;
}
return allocator;
}
size_t JLANG_used(void *ptr)
{
size_t JLANG_used(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
while (currentHeader->in_use != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
return used;
}
void *JLANG_last_free(void *ptr)
{
void *JLANG_last_free(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Iterate memory parsing only metadata
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
size_t used = 0;
while (currentHeader->in_use != 0 && used < allocPtr->size)
{
while (currentHeader->in_use != 0 && used < allocPtr->size) {
used += sizeof(JLANG_metadata) + currentHeader->size;
// Current block is in_use, jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
return currentHeader;
}
void *JLANG_malloc(void *ptr, size_t size)
{
void *JLANG_malloc(void *ptr, size_t size) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// 1. Hay bloques disponibles??
@@ -98,8 +96,7 @@ void *JLANG_malloc(void *ptr, size_t size)
size_t available = allocPtr->size - used;
// chequear si hay suficiente espacio libre
if (available > size + sizeof(JLANG_metadata))
{
if (available > size + sizeof(JLANG_metadata)) {
JLANG_metadata *freeHeader = (JLANG_metadata *)JLANG_last_free(ptr);
freeHeader->size = size;
freeHeader->in_use = 1;
@@ -110,26 +107,34 @@ void *JLANG_malloc(void *ptr, size_t size)
return NULL; // TODO
}
void JLANG_free(void *ptr, void *blockPtr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Get block header
JLANG_metadata *blockHeader =
(JLANG_metadata *)((char *)blockPtr - sizeof(JLANG_metadata));
// Set block as not_used
blockHeader->in_use = 0;
}
/*
Debug Visualization
[FF FF FF FF FF FF FF ]
*/
int _ceil(float v)
{
int _ceil(float v) {
int n = (int)v;
float r = v - n;
if (r > 0)
{
if (r > 0) {
return n + 1;
}
return n;
}
void JLANG_visualize(void *ptr)
{
void JLANG_visualize(void *ptr) {
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
// Step 1. Get byte type
@@ -138,10 +143,8 @@ void JLANG_visualize(void *ptr)
JLANG_metadata *currentHeader = (JLANG_metadata *)allocPtr->memory;
long used = 0;
while (used < allocPtr->size)
{
while (used < allocPtr->size) {
long blockIndex = (char *)currentHeader - (char *)allocPtr->memory;
printf("blockIndex=%u\n", blockIndex);
used += sizeof(JLANG_metadata) + currentHeader->size;
/*
@@ -149,19 +152,16 @@ void JLANG_visualize(void *ptr)
blockIndex + sizeof(JLANG_metadata)
*/
if (currentHeader->size > 0)
{
if (currentHeader->size > 0) {
byteMapPtr[blockIndex] = JLANG_HEADER;
for (int i = 0; i < sizeof(JLANG_metadata); i++)
{
for (int i = 0; i < sizeof(JLANG_metadata); i++) {
byteMapPtr[blockIndex + i] = JLANG_HEADER;
}
/*
PAYLOAD
*/
for (int i = 0; i < currentHeader->size; i++)
{
for (int i = 0; i < currentHeader->size; i++) {
byteMapPtr[blockIndex + sizeof(JLANG_metadata) + i] = JLANG_PAYLOAD;
}
} else {
@@ -169,7 +169,9 @@ void JLANG_visualize(void *ptr)
}
// Jump to next block
currentHeader = (JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) + currentHeader->size);
currentHeader =
(JLANG_metadata *)((char *)currentHeader + sizeof(JLANG_metadata) +
currentHeader->size);
}
// Step 2. Draw
@@ -180,16 +182,13 @@ void JLANG_visualize(void *ptr)
char *currentMemPtr = allocPtr->memory;
for (int i = 0; i < totalRows; i++)
{
for (int i = 0; i < totalRows; i++) {
printf("[");
for (int n = 0; n < bytePerRow; n++)
{
for (int n = 0; n < bytePerRow; n++) {
int index = n + i * bytePerRow;
switch (byteMapPtr[index])
{
switch (byteMapPtr[index]) {
case JLANG_HEADER:
printf("\033[46m");
break;
@@ -203,8 +202,7 @@ void JLANG_visualize(void *ptr)
printf("%.2x", (unsigned char)*(currentMemPtr + (n + i * bytePerRow)));
if (n < bytePerRow - 1)
{
if (n < bytePerRow - 1) {
printf(" ");
}

101
src/objects/object.h Normal file
View File

@@ -0,0 +1,101 @@
#include "../memory/allocator.h"
typedef enum
{
OBJ_INT,
OBJ_FLOAT,
OBJ_STRING,
OBJ_LIST,
OBJ_NONE
} ObjectType;
typedef struct Object
{
ObjectType type;
union
{
int int_val;
double float_val;
struct
{
char *chars;
int length;
} string_val;
struct
{
struct Object **items;
int count;
int capacity;
} list_val;
} data;
} Object;
Object *obj_new_int(void *allocator, int value)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_INT;
objPtr->data.int_val = value;
return objPtr;
}
Object *obj_new_float(void *allocator, float value)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_FLOAT;
objPtr->data.float_val = value;
return objPtr;
}
Object *obj_new_string(void *allocator, const char *str)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_STRING;
int len = strlen(str);
char *buffer = (char *)JLANG_malloc(allocator, len + 1);
memcpy(buffer, str, len + 1);
objPtr->data.string_val.chars = buffer;
objPtr->data.string_val.length = len;
return objPtr;
}
Object *obj_new_list(void *allocator)
{
Object *objPtr = (Object *)JLANG_malloc(allocator, sizeof(Object));
objPtr->type = OBJ_LIST;
return objPtr;
}
void obj_free(void *allocator, Object* obj) {
if (obj->type == OBJ_STRING) {
JLANG_free(allocator, obj->data.string_val.chars);
}
JLANG_free(allocator, obj);
}
void obj_print(Object *obj)
{
switch (obj->type)
{
case OBJ_INT:
printf("%d", obj->data.int_val);
break;
case OBJ_FLOAT:
printf("%f", obj->data.float_val);
break;
case OBJ_LIST:
for (int i = 0; i < obj->data.list_val.count; i++)
{
obj_print(obj->data.list_val.items[i]);
}
break;
case OBJ_STRING:
printf("%s", obj->data.string_val.chars);
break;
default:
break;
}
}