Login
7 branches 0 tags
Ben (X13/Arch) Fixed most issues! Tests succeed! 6583585 2 years ago 964 Commits
nujel / lib / allocator.c
/* Nujel - Copyright (C) 2020-2022 - Benjamin Vincent Schulenburg
 * This project uses the MIT license, a copy should be included under /LICENSE */
#ifndef NUJEL_AMALGAMATION
#include "nujel-private.h"
#endif

#include <stdlib.h>
#include <string.h>

bool lGCShouldRunSoon = false;

#define defineAllocator(T, typeMax) \
T T##List[typeMax]; \
uint T##Max = 0; \
uint T##Active = 0; \
T * T##FFree = NULL; \
T * T##AllocRaw (){\
	T *ret;\
	if((T##FFree) == NULL){			\
		if(unlikely(T##Max >= typeMax-1)){	\
			fprintf(stderr, "OOM: static %s heap exhausted \n", #T);\
			exit(123);\
		}else{\
			ret = &(T##List)[(T##Max)++];	\
		}\
	}else{\
		ret = T ## FFree;\
		(T##FFree) = ret->nextFree;	\
	}\
	(T##Active)++;							\
	if(unlikely((typeMax - (T##Active)) < 32)){lGCShouldRunSoon = true;} \
	memset(ret, 0, sizeof(T));\
	return ret;\
}
allocatorTypes()
#undef defineAllocator

lNFunc   lNFuncList[NFN_MAX];
uint     lNFuncMax    = 0;


int lBufferViewTypeSize(lBufferViewType T){
	switch(T){
	default:
		exit(4);
	case lbvtU8:
	case lbvtS8:
		return 1;
	case lbvtS16:
	case lbvtU16:
		return 2;
	case lbvtF32:
	case lbvtS32:
	case lbvtU32:
		return 4;
	case lbvtF64:
	case lbvtS64:
		return 8;
	}
}


lBuffer *lBufferAlloc(size_t length, bool immutable){
	lBuffer *ret = lBufferAllocRaw();
	ret->length = length;
	if(immutable){
		ret->flags = BUFFER_IMMUTABLE;
	}else{
		ret->buf = calloc(length, 1);
	}
	return ret;
}

void lBufferFree(lBuffer *buf){
	if(unlikely(buf == NULL)){return;}
	free(buf->buf);
	buf->nextFree = lBufferFFree;
	lBufferActive--;
	lBufferFFree = buf;
}

lBufferView *lBufferViewAlloc(lBuffer *buf, lBufferViewType type, size_t offset, size_t length, bool immutable){
	lBufferView *ret = lBufferViewAllocRaw();
	ret->buf    = buf;
	ret->offset = offset;
	ret->length = length;
	ret->flags  = immutable;
	ret->type   = type;
	return ret;
}

void lBufferViewFree(lBufferView *buf){
	if(unlikely(buf == NULL)){return;}
	buf->buf = NULL;
	buf->nextFree = lBufferViewFFree;
	lBufferViewActive--;
	lBufferViewFFree = buf;
}

lBytecodeArray *lBytecodeArrayAlloc(size_t len){
	lBytecodeArray *ret = lBytecodeArrayAllocRaw();
	ret->data = calloc(len, sizeof(lBytecodeOp));
	if(unlikely(ret->data == NULL)){
		lExceptionThrowValClo("out-of-memory", "Couldn't allocate a new BC array", lValInt(len), NULL);
	}
	ret->dataEnd = &ret->data[len];
	ret->closureStackUsage = 16;
	ret->valueStackUsage = 128;
	return ret;
}

void lBytecodeArrayFree(lBytecodeArray *v){
	if(unlikely(v == NULL)){return;}
	free(v->data);
	v->data     = NULL;
	v->nextFree = lBytecodeArrayFFree;
	lBytecodeArrayActive--;
	lBytecodeArrayFFree = v;
}

lArray *lArrayAlloc(size_t len){
	lArray *ret = lArrayAllocRaw();
	ret->data = calloc(len, sizeof(lVal));
	if(unlikely(ret->data == NULL)){
		lExceptionThrowValClo("out-of-memory", "Couldn't allocate a new array", lValInt(len), NULL);
	}
	ret->length = len;
	return ret;
}

lNFunc *lNFuncAlloc(){
	if(unlikely(lNFuncMax >= NFN_MAX-1)){
		exit(124);
	}
	memset(&lNFuncList[lNFuncMax++], 0, sizeof(ltNativeFunc));
	return &lNFuncList[lNFuncMax++];
}

void lNFuncFree(lNFunc *n){
	(void)n;
}

void lArrayFree(lArray *v){
	if(unlikely(v == NULL)){return;}
	free(v->data);
	v->data     = NULL;
	v->nextFree = lArrayFFree;
	lArrayFFree = v;
	lArrayActive--;
}

void lClosureFree(lClosure *clo){
	if(unlikely(clo == NULL)){return;}
	clo->nextFree = lClosureFFree;
	lClosureFFree = clo;
	lClosureActive--;
}

void lTreeFree(lTree *t){
	if(unlikely(t == NULL)){return;}
	t->nextFree = lTreeFFree;
	lTreeFFree = t;
	lTreeActive--;
}

void lTreeRootFree(lTreeRoot *t){
	if(unlikely(t == NULL)){return;}
	t->nextFree = lTreeRootFFree;
	lTreeRootFFree = t;
	lTreeRootActive--;
}

void lPairFree(lPair *cons){
	if(unlikely(cons == NULL)){return;}
	cons->car = NIL;
	cons->nextFree = lPairFFree;
	lPairFFree = cons;
	lPairActive--;
}