Arrays.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "vm/Arrays.h"
  4. #define MAX_ALLOCATED_BYTES (1024LL * 1024LL * 1024LL * 4LL)
  5. static long long allocatedBytes = 0;
  6. static int aGetSize(SnuviArray* a) {
  7. return (int)sizeof(Value) * a->realLength;
  8. }
  9. void asInit(SnuviArrays* as) {
  10. as->capacity = 0;
  11. as->usedStart = -1;
  12. as->freeStart = -1;
  13. as->data = NULL;
  14. }
  15. void asDelete(SnuviArrays* as) {
  16. for(int i = 0; i < as->capacity; i++) {
  17. allocatedBytes -= aGetSize(as->data + i);
  18. free(as->data[i].data);
  19. }
  20. allocatedBytes -= as->capacity * (int)sizeof(SnuviArray);
  21. free(as->data);
  22. }
  23. static void aInitArray(SnuviArray* a, int previous, int next) {
  24. a->realLength = 0;
  25. a->length = -1;
  26. a->next = next;
  27. a->previous = previous;
  28. a->data = NULL;
  29. }
  30. static void asInitArrays(SnuviArrays* as, int start) {
  31. int end = as->capacity - 1;
  32. aInitArray(as->data + start, -1, start + 1);
  33. for(int i = start + 1; i < end; i++) {
  34. aInitArray(as->data + i, i - 1, i + 1);
  35. }
  36. aInitArray(as->data + end, end - 1, -1);
  37. as->freeStart = start;
  38. }
  39. static bool asEnsureCapacity(SnuviArrays* as) {
  40. if(as->freeStart != -1) {
  41. return false;
  42. }
  43. int oldCapacity = as->capacity;
  44. int capacity = (as->data == NULL) ? 4 : as->capacity * 2;
  45. int oldBytes = (int)sizeof(SnuviArray) * oldCapacity;
  46. int bytes = (int)sizeof(SnuviArray) * capacity;
  47. if(bytes < 0 || allocatedBytes - oldBytes + bytes > MAX_ALLOCATED_BYTES) {
  48. return true;
  49. }
  50. allocatedBytes += bytes - oldBytes;
  51. as->data = (SnuviArray*)realloc(as->data, (size_t)bytes);
  52. as->capacity = capacity;
  53. asInitArrays(as, oldCapacity);
  54. return false;
  55. }
  56. static void asPrintDebug(SnuviArrays* as) {
  57. printf("Free: %d, Used: %d\n", as->freeStart, as->usedStart);
  58. for(int i = 0; i < as->capacity; i++) {
  59. SnuviArray* a = as->data + i;
  60. printf("%d: %s, realLength: %d, next: %d, previous: %d\n", i,
  61. a->data == NULL ? "null" : "valid", a->realLength, a->next,
  62. a->previous);
  63. }
  64. }
  65. int asAllocate(SnuviArrays* as, int typeSize, int length) {
  66. (void)asPrintDebug;
  67. if(asEnsureCapacity(as)) {
  68. return -1;
  69. }
  70. int bytes = (int)sizeof(Value) * typeSize * length;
  71. if(bytes < 0) {
  72. return -2;
  73. } else if(allocatedBytes + bytes > MAX_ALLOCATED_BYTES) {
  74. return -1;
  75. }
  76. allocatedBytes += bytes;
  77. int index = as->freeStart;
  78. SnuviArray* array = as->data + index;
  79. as->freeStart = array->next;
  80. if(array->next != -1) {
  81. as->data[array->next].previous = -1;
  82. }
  83. array->next = as->usedStart;
  84. if(as->usedStart != -1) {
  85. as->data[as->usedStart].previous = index;
  86. }
  87. as->usedStart = index;
  88. array->realLength = typeSize * length;
  89. array->length = length;
  90. array->data = (Value*)malloc((size_t)bytes);
  91. return index;
  92. }
  93. SnuviArray* asGet(SnuviArrays* as, int p) {
  94. if(p < 0 || p >= as->capacity || as->data[p].length == -1) {
  95. return NULL;
  96. }
  97. return as->data + p;
  98. }
  99. void asDeleteArray(SnuviArrays* as, SnuviArray* a, int p) {
  100. if(a->previous != -1) {
  101. as->data[a->previous].next = a->next;
  102. } else {
  103. as->usedStart = a->next;
  104. }
  105. if(a->next != -1) {
  106. as->data[a->next].previous = a->previous;
  107. }
  108. if(as->freeStart != -1) {
  109. a->next = as->freeStart;
  110. as->data[as->freeStart].previous = p;
  111. } else {
  112. a->next = -1;
  113. }
  114. as->freeStart = p;
  115. allocatedBytes -= aGetSize(a);
  116. a->previous = -1;
  117. a->realLength = 0;
  118. a->length = -1;
  119. free(a->data);
  120. a->data = NULL;
  121. }