Add while loops, GC mark-and-sweep, and malloc block reuse
- Lexer: add INDENT/DEDENT tokens, <, >, : operators, while keyword, closing DEDENT emission, include guards - Parser: add NODE_WHILE with while_loop union, parse while/cond/body blocks, include guards - Eval: add while loop evaluation, GC integration with roots from env, debug and gc flags, <, > comparison operators - GC: implement mark-and-sweep collector with 3 stages (mark roots, sweep unmarked, join free blocks) - Allocator: block reuse via first-fit search with splitting, exponential heap growth, NULL check on malloc, include guards, marked field in metadata - Object: add include guards, fix include to use allocator.h
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
#ifndef JLANG_ALLOCATOR_H
|
||||
#define JLANG_ALLOCATOR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -24,7 +27,7 @@
|
||||
typedef struct {
|
||||
size_t size; // 8 bytes
|
||||
int in_use; // 4 bytes
|
||||
// --- aquí el compilador mete 4 bytes invisibles ---
|
||||
int marked; // 4 bytes
|
||||
} JLANG_metadata;
|
||||
|
||||
/*
|
||||
@@ -94,44 +97,110 @@ void *JLANG_last_free(void *ptr) {
|
||||
size_t JLANG_malloc(void *ptr, size_t size) {
|
||||
JLANG_memory_allocator *allocPtr = (JLANG_memory_allocator *)ptr;
|
||||
|
||||
// 1. Hay bloques disponibles??
|
||||
size_t used = JLANG_used(ptr);
|
||||
size_t available = allocPtr->size - used;
|
||||
// Recorrer memoria hasta encontrar un hueco libre
|
||||
JLANG_metadata *currentHead = (JLANG_metadata *)allocPtr->memory;
|
||||
size_t used = 0;
|
||||
while (1) {
|
||||
used += currentHead->size;
|
||||
|
||||
if (currentHead->in_use == 0 && currentHead->size >= size) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentHead->size == 0) {
|
||||
size_t offset = (char *)currentHead - allocPtr->memory;
|
||||
if (offset + sizeof(JLANG_metadata) + size > allocPtr->size) {
|
||||
// No cabe, grow
|
||||
size_t newSize = allocPtr->size * 2;
|
||||
// asegurar que quepa la peticion
|
||||
while (newSize < offset + sizeof(JLANG_metadata) + size) {
|
||||
newSize *= 2;
|
||||
}
|
||||
|
||||
char *newBuffer = (char *)malloc(newSize); // pedir newSize bytes
|
||||
if (newBuffer == NULL) {
|
||||
printf("ERROR: out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
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 *)(allocPtr->memory + offset);
|
||||
freeHeader->size = size;
|
||||
freeHeader->in_use = 1;
|
||||
|
||||
void *payloadPtr = (char *)freeHeader + sizeof(JLANG_metadata);
|
||||
return (char *)payloadPtr - allocPtr->memory;
|
||||
}
|
||||
// Fin del heap, asignar aqui
|
||||
currentHead->size = size;
|
||||
currentHead->in_use = 1;
|
||||
return (char *)currentHead - allocPtr->memory + sizeof(JLANG_metadata);
|
||||
}
|
||||
|
||||
// Go next
|
||||
currentHead =
|
||||
(JLANG_metadata *)((char *)currentHead + sizeof(JLANG_metadata) +
|
||||
currentHead->size);
|
||||
}
|
||||
|
||||
// currentHead tiene sitio para nosotros, particionamos y usamos
|
||||
currentHead->in_use = 1;
|
||||
size_t oldSize = currentHead->size;
|
||||
currentHead->size = size;
|
||||
|
||||
if (oldSize > size + sizeof(JLANG_metadata)) {
|
||||
// creamos un bloque vacio con los bytes que sobran
|
||||
JLANG_metadata *emptyBlock =
|
||||
(JLANG_metadata *)((char *)currentHead + sizeof(JLANG_metadata) + size);
|
||||
emptyBlock->size = oldSize - size - sizeof(JLANG_metadata);
|
||||
}
|
||||
|
||||
return (char *)currentHead - allocPtr->memory + sizeof(JLANG_metadata);
|
||||
|
||||
/*
|
||||
// 1. Hay bloques disponibles??
|
||||
size_t used = JLANG_used(ptr);
|
||||
size_t available = allocPtr->size - used;
|
||||
|
||||
// chequear si hay suficiente espacio libre
|
||||
if (available > size + sizeof(JLANG_metadata)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Se necesita más espacio..
|
||||
|
||||
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
|
||||
|
||||
// chequear si hay suficiente espacio libre
|
||||
if (available > size + sizeof(JLANG_metadata)) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
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, size_t blockOffset) {
|
||||
@@ -254,3 +323,5 @@ void JLANG_visualize(void *ptr) {
|
||||
printf("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user