123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #include <stdio.h>
- #include <stdlib.h>
- #include "vm/Arrays.h"
- #define MAX_ALLOCATED_BYTES (1024LL * 1024LL * 1024LL * 4LL)
- static long long allocatedBytes = 0;
- static int aGetSize(SnuviArray* a) {
- return (int)sizeof(Value) * a->realLength;
- }
- void asInit(SnuviArrays* as) {
- as->capacity = 0;
- as->usedStart = -1;
- as->freeStart = -1;
- as->data = NULL;
- }
- void asDelete(SnuviArrays* as) {
- for(int i = 0; i < as->capacity; i++) {
- allocatedBytes -= aGetSize(as->data + i);
- free(as->data[i].data);
- }
- allocatedBytes -= as->capacity * (int)sizeof(SnuviArray);
- free(as->data);
- }
- static void aInitArray(SnuviArray* a, int previous, int next) {
- a->realLength = 0;
- a->length = -1;
- a->next = next;
- a->previous = previous;
- a->data = NULL;
- }
- static void asInitArrays(SnuviArrays* as, int start) {
- int end = as->capacity - 1;
- aInitArray(as->data + start, -1, start + 1);
- for(int i = start + 1; i < end; i++) {
- aInitArray(as->data + i, i - 1, i + 1);
- }
- aInitArray(as->data + end, end - 1, -1);
- as->freeStart = start;
- }
- static bool asEnsureCapacity(SnuviArrays* as) {
- if(as->freeStart != -1) {
- return false;
- }
- int oldCapacity = as->capacity;
- int capacity = (as->data == NULL) ? 4 : as->capacity * 2;
- int oldBytes = (int)sizeof(SnuviArray) * oldCapacity;
- int bytes = (int)sizeof(SnuviArray) * capacity;
- if(bytes < 0 || allocatedBytes - oldBytes + bytes > MAX_ALLOCATED_BYTES) {
- return true;
- }
- allocatedBytes += bytes - oldBytes;
- as->data = (SnuviArray*)realloc(as->data, (size_t)bytes);
- as->capacity = capacity;
- asInitArrays(as, oldCapacity);
- return false;
- }
- static void asPrintDebug(SnuviArrays* as) {
- printf("Free: %d, Used: %d\n", as->freeStart, as->usedStart);
- for(int i = 0; i < as->capacity; i++) {
- SnuviArray* a = as->data + i;
- printf("%d: %s, realLength: %d, next: %d, previous: %d\n", i,
- a->data == NULL ? "null" : "valid", a->realLength, a->next,
- a->previous);
- }
- }
- int asAllocate(SnuviArrays* as, int typeSize, int length) {
- (void)asPrintDebug;
- if(asEnsureCapacity(as)) {
- return -1;
- }
- int bytes = (int)sizeof(Value) * typeSize * length;
- if(bytes < 0) {
- return -2;
- } else if(allocatedBytes + bytes > MAX_ALLOCATED_BYTES) {
- return -1;
- }
- allocatedBytes += bytes;
- int index = as->freeStart;
- SnuviArray* array = as->data + index;
- as->freeStart = array->next;
- if(array->next != -1) {
- as->data[array->next].previous = -1;
- }
- array->next = as->usedStart;
- if(as->usedStart != -1) {
- as->data[as->usedStart].previous = index;
- }
- as->usedStart = index;
- array->realLength = typeSize * length;
- array->length = length;
- array->data = (Value*)malloc((size_t)bytes);
- return index;
- }
- SnuviArray* asGet(SnuviArrays* as, int p) {
- if(p < 0 || p >= as->capacity || as->data[p].length == -1) {
- return NULL;
- }
- return as->data + p;
- }
- void asDeleteArray(SnuviArrays* as, SnuviArray* a, int p) {
- if(a->previous != -1) {
- as->data[a->previous].next = a->next;
- } else {
- as->usedStart = a->next;
- }
- if(a->next != -1) {
- as->data[a->next].previous = a->previous;
- }
- if(as->freeStart != -1) {
- a->next = as->freeStart;
- as->data[as->freeStart].previous = p;
- } else {
- a->next = -1;
- }
- as->freeStart = p;
- allocatedBytes -= aGetSize(a);
- a->previous = -1;
- a->realLength = 0;
- a->length = -1;
- free(a->data);
- a->data = NULL;
- }
|