diff --git a/CMakeLists.txt b/CMakeLists.txt index d44b8df..85bf666 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,8 @@ set(CMAKE_C_STANDARD 99) add_compile_options(-g -Wall -pedantic) -add_executable(njvm njvm.c) +add_executable(njvm njvm.c + njvm.h) # Include directories for njvm executable target_include_directories(njvm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bigint/build/include) diff --git a/GC.c b/GC.c index e02e026..898ded7 100644 --- a/GC.c +++ b/GC.c @@ -1,6 +1,6 @@ #ifndef GC #define GC -#define HAS_BROKENHEART_FLAG(objRef) (((objRef)->size & 1 << (7 * sizeof(unsigned int) -1)) == 0) + #include #include #include @@ -8,107 +8,7 @@ #include "objref.c" #include "instruktion.c" #include "support.c" +#include "bigint.h" -ObjRef heap; -ObjRef freePointer; -ObjRef middle; -ObjRef start; -ObjRef end; -ObjRef finalEnd; -ObjRef scanPtr; -ObjRef tmpEnd; - -unsigned int defaultHeap = 8192 * 1024; - -void heapAlloc(unsigned int size){ - heap = malloc(size); - if(heap == NULL){ - fatalError("Not enough memory on Heap\n"); - } - - start = heap; - freePointer = start; - middle = (heap + (defaultHeap/2)); - end = middle; - finalEnd = (middle + (defaultHeap/2)); -} - -void flip(void){ - freePointer = end; - tmpEnd = finalEnd; -} - -ObjRef copyObjToFreeMem(ObjRef obj){ - ObjRef tmp = freePointer; - memcpy(tmp, obj, obj->size); - if(IS_PRIMITIVE(tmp)){ - freePointer += sizeof(tmp) + tmp->size; - }else{ - freePointer += sizeof(tmp) + tmp->size * sizeof(void*); - } - return tmp; -} - -ObjRef rellocate(ObjRef orig){ - ObjRef copy; - if (orig == NULL){ - - copy = NULL; - } else { - unsigned int tmp = HAS_BROKENHEART_FLAG(orig); - if (tmp){ - copy = orig->forward_pointer; - } else { - copy = copyObjToFreeMem(orig); - orig->size = (1 | (1 << (7 * sizeof(unsigned int) -1))); - //SET_BROKENHEART_FLAG(orig); - orig->forward_pointer = copy; - } - } - return copy; -} - -void garbageColl(void){ - flip(); - for(int i = 0; i < program_size; i++){ - static_data_area[i] = rellocate(static_data_area[i]); // alte Objekte werden in neue akktive Halbspeicher geleitet bei relocate! - } - bip.op1 = rellocate(bip.op1); - bip.op2 = rellocate(bip.op2); - bip.res = rellocate(bip.res); - bip.rem = rellocate(bip.rem); - returnValueReg = rellocate(returnValueReg); - - scan(); - end = finalEnd; -} - -ObjRef garbageCollectorMalloc(unsigned int size){ - if((freePointer + size) > end){ - garbageColl(); - } else if((freePointer > finalEnd)){ - fatalError("Not enough memory on Heap\n"); - } - ObjRef obj = freePointer; - if(obj == NULL){ - fatalError("Object is Null\n"); - } - freePointer += size; - return obj; -} - - -void scan(void){ - scanPtr = start; //Zielspeicherzeiger; - while (scanPtr < freePointer){ - - if (!IS_PRIMITIVE(scanPtr)){ - - for (int i = 0; i < GET_ELEMENT_COUNT(scanPtr); i++){ - GET_REFS_PTR(scanPtr)[i] = rellocate(GET_REFS_PTR(scanPtr)[i]); - } - } - } -} #endif diff --git a/bigint/build/bin/testbip b/bigint/build/bin/testbip index 02f1195..5ed9446 100755 Binary files a/bigint/build/bin/testbip and b/bigint/build/bin/testbip differ diff --git a/bigint/build/lib/libbigint.a b/bigint/build/lib/libbigint.a index 01ff579..29fe716 100644 Binary files a/bigint/build/lib/libbigint.a and b/bigint/build/lib/libbigint.a differ diff --git a/bigint/src/bigint.o b/bigint/src/bigint.o index 4e68f95..162ad9f 100644 Binary files a/bigint/src/bigint.o and b/bigint/src/bigint.o differ diff --git a/bigint/src/libbigint.a b/bigint/src/libbigint.a index 01ff579..29fe716 100644 Binary files a/bigint/src/libbigint.a and b/bigint/src/libbigint.a differ diff --git a/bigint/tst/support.o b/bigint/tst/support.o index 2ad0cc0..0147bff 100644 Binary files a/bigint/tst/support.o and b/bigint/tst/support.o differ diff --git a/bigint/tst/testbip b/bigint/tst/testbip index 02f1195..5ed9446 100755 Binary files a/bigint/tst/testbip and b/bigint/tst/testbip differ diff --git a/bigint/tst/testbip.o b/bigint/tst/testbip.o index 8acdffd..d8aaf39 100644 Binary files a/bigint/tst/testbip.o and b/bigint/tst/testbip.o differ diff --git a/njvm.c b/njvm.c index c4dbc51..b7882c0 100644 --- a/njvm.c +++ b/njvm.c @@ -8,12 +8,17 @@ #include "debugMenu.c" #include "bigint.h" #include "record.c" -#include "GC.c" #include "SDA.c" // Debug int debug = 0; +// Purge Flag +int purgeFlag = false; + +// Heap Size +int argVheapSizeKiB = 8192; + // Program struct program program; @@ -22,7 +27,7 @@ struct sda sda; // Stack struct stack stack; -#define SIZE 64 +#define SIZE 10000 //Register struct stack reg; @@ -46,7 +51,7 @@ void execute(struct program program) { ObjRef tempObj2; int tempInt; for (i = 0; i < *program.size; ++i) { - if (debug == 1 || bp == i) debugMenu(fp, stack, &debug, i, &bp); + //if (debug == 1 || bp == i) debugMenu(fp, stack, &debug, i, &bp); if(debug == 1) printf("(%i)",i); switch (program.program[i] >> 24) { case HALT: @@ -315,9 +320,184 @@ void execute(struct program program) { void tests(void) { } +/* + * Garbage Collection + */ + +ObjRef *heap; +int heapSizeKiB; +char *memTargetPtr; //zielspeicherzeiger +char *freeHeapPtr; //freizeiger +char *halfHeapPtr; //halbspeicherende +int gcCount = 0; + +#define MSB (1 << (8 * sizeof(unsigned int) - 1)) +#define IS_PRIMITIVE(objRef) (((objRef)->size & MSB) == 0) +#define GET_SIZE(objRef)((objRef)->size& ~MSB) //Gets the size of an ObjRef +#define GET_REFS(objRef)((ObjRef *)((objRef)->data)) //Pointer on first ObjRef in Object + +ObjRef copyObjectToFreeMem(ObjRef orig) { + //printf("%s%d\n", "Size in CpyObj: ", GET_SIZE(orig) ); + int size; + if (IS_PRIMITIVE(orig)) { + size = GET_SIZE(orig); + } else { + size = sizeof(void *) + sizeof(unsigned int) + sizeof(bool) + GET_SIZE(orig) * sizeof(ObjRef *); + } + memcpy(freeHeapPtr, orig, size); + ObjRef oldPtr = (ObjRef) freeHeapPtr; + //printf("%s%d\n","size after memcpy ", GET_SIZE(oldPtr)); + //printf("%s%d\n","actual Size: ", size); + //oldPtr->size = size; + freeHeapPtr += size; + return oldPtr; +} + +ObjRef relocate(ObjRef orig) { + /* if (orig == NULL) { + printf("%s\n", "null"); + } else { + printf("%s%d\n","Size in relocate ", GET_SIZE(orig)); + } + */ + + ObjRef copy; + if (orig == NULL) { +/* relocate(nil) = nil */ + copy = NULL; + } else { + if (orig->brokenHeart == 1) { +/* Objekt ist bereits kopiert */ + copy = orig->forwardPointer; + //copy->size =orig->size; + //printf("%s\n", "already copied"); + } else { +/* Objekt muss noch kopiert werden*/ + copy = copyObjectToFreeMem(orig); + orig->brokenHeart = true; + orig->forwardPointer = copy; + } + } + + return copy; +} + + +void scan(void) { + char *scanPtr = memTargetPtr; + while (scanPtr < freeHeapPtr) { +/* es gibt noch Objekte, die +* gescannt werden müssen. +*/ ObjRef scanOr = (ObjRef) scanPtr; + // printf("%d\n", GET_SIZE(scanOr)); + if (!IS_PRIMITIVE(scanOr)) { +/* Ist ein Verbundobjekt */ + for (int i = 0; i < GET_SIZE(scanOr); i++) { + GET_REFS(scanOr)[i] = relocate(GET_REFS(scanOr)[i]); + } + scanPtr += sizeof(bool) + (GET_SIZE(scanOr) * sizeof(ObjRef *)) + sizeof(unsigned int) + sizeof(void *); + } else { + //printf("%s %d\n", "is primitive, size: ", GET_SIZE(scanOr)); + scanPtr += GET_SIZE(scanOr); + + } + } +} + +void swap() { + if (memTargetPtr == (char *) heap) { + //printf("%s\n", "swapped to second half"); + freeHeapPtr = halfHeapPtr; + memTargetPtr = halfHeapPtr; + halfHeapPtr = ((char *) heap) + (heapSizeKiB * 1024); + } else { + //printf("%s\n", "swapped to first half"); + freeHeapPtr = ((char *) heap); + memTargetPtr = ((char *) heap); + halfHeapPtr = ((char *) heap) + ((heapSizeKiB * 1024) / 2); + } +} + +void garbageCollector() { + char *memToPurgePtr = halfHeapPtr - ((heapSizeKiB * 1024) / 2); + swap(); + //printf("%s\n", "stack"); + for (int i = 0; i < stack.current; i++) { + if (stack.stack[i].isObjRef) { + stack.stack[i].u.objRef = relocate(stack.stack[i].u.objRef); + } + } + //printf("%s\n", "globals"); + for (int i = 0; i < sda.size; i++) { + sda.sda[i] = relocate(sda.sda[i]); + } + //printf("%s\n", "retVal"); + //returnValue = relocate(returnValue); + + //printf("%s\n", "op1"); + bip.op1 = relocate(bip.op1); + ObjRef b = bip.op1; + if(b!= NULL) + //printf("%d\n", GET_SIZE(b)); + + //printf("%s\n", "op2"); + bip.op2 = relocate(bip.op2); + b = bip.op2; + if(b!= NULL) + //printf("%d\n", GET_SIZE(b)); + + //printf("%s\n", "res"); + bip.res = relocate(bip.res); + b = bip.res; + if(b!= NULL) + //printf("%d\n", GET_SIZE(b)); + + //printf("%s\n", "rem"); + bip.rem = relocate(bip.rem); + b = bip.rem; + if(b!= NULL) + //printf("%d\n", GET_SIZE(b)); + + + scan(); + if (purgeFlag) { + memset(memToPurgePtr, 0, heapSizeKiB * 1024 / 2); + } + gcCount++; +} + +ObjRef alloc(unsigned int size) { + if (freeHeapPtr + size > halfHeapPtr) { + garbageCollector(); + if (freeHeapPtr + size > halfHeapPtr) { + fprintf(stderr, "Heap is full\n"); + exit(1); + } + } + ObjRef or; + or = (ObjRef) freeHeapPtr; + freeHeapPtr = freeHeapPtr + size; + return or; +} + +void heapAllocator(int n) { + heapSizeKiB = n; + if ((heap = malloc(n * 1024)) == NULL) { + perror("malloc"); + exit(1); + } + memTargetPtr = (char *) heap; + freeHeapPtr = memTargetPtr; + halfHeapPtr = (memTargetPtr + (n * 1024) / 2); +} + +/* + * Main + */ + int main(int argc, char *argv[]) { // Init the Heap - initHeap(1000); + //initHeap(1000); // Initialize the Stack int size = SIZE; @@ -372,6 +552,7 @@ int main(int argc, char *argv[]) { run = 1; } } + heapAllocator(argVheapSizeKiB); // Init the sda ObjRef s[sizeSDA]; sda.size = &sizeSDA; @@ -394,4 +575,4 @@ int main(int argc, char *argv[]) { printf("Error: no code file specified\n"); return 1; } -} +} \ No newline at end of file diff --git a/njvm.h b/njvm.h new file mode 100644 index 0000000..2979ce5 --- /dev/null +++ b/njvm.h @@ -0,0 +1,11 @@ +// +// Created by Elias Bennour on 28.01.24. +// +#include "objref.c" + +#ifndef NINJA_NJVM_H +#define NINJA_NJVM_H + +ObjRef alloc(unsigned int size); + +#endif //NINJA_NJVM_H diff --git a/njvm.o b/njvm.o index 649cde9..8a41421 100644 Binary files a/njvm.o and b/njvm.o differ diff --git a/objref.c b/objref.c index 82aca28..a525ef2 100644 --- a/objref.c +++ b/objref.c @@ -5,7 +5,7 @@ typedef struct ObjRef{ // if brkokenHeart and forward_pointer added at this point bip throws errors bool brokenHeart; - struct ObjRef *forward_pointer; + struct ObjRef *forwardPointer; unsigned int size; unsigned char data[1]; } *ObjRef; diff --git a/record.c b/record.c index 3d8086c..8df9f48 100644 --- a/record.c +++ b/record.c @@ -5,12 +5,13 @@ #define RECORD #include "stackslot.c" #include "instruktion.c" -#include "GC.c" +#include "njvm.h" + ObjRef newRecord(int size){ ObjRef record; unsigned int objSize; objSize = sizeof(*record) + (size * sizeof(void *)); - if((record = malloc(objSize)) == NULL){ + if((record = alloc(objSize)) == NULL){ perror("malloc"); } record->size = MSB; diff --git a/support.c b/support.c index 20d43cb..f5a885f 100644 --- a/support.c +++ b/support.c @@ -1,10 +1,13 @@ +#ifndef SUPPORT_C +#define SUPPORT_C #include "support.h" #include #include #include "objref.c" -#include "GC.c" +#include "njvm.h" + void fatalError(char *msg){ printf("Fatal error: %s\n", msg); exit(1); @@ -13,7 +16,7 @@ void fatalError(char *msg){ void * newPrimObject(int dataSize) { ObjRef bigObjRef; - bigObjRef = malloc(sizeof(unsigned int) + + bigObjRef = alloc(sizeof(unsigned int) + dataSize * sizeof(unsigned char)); if (bigObjRef == NULL) { fatalError("newPrimObject() got no memory"); @@ -26,3 +29,5 @@ void * getPrimObjectDataPointer(void * obj){ ObjRef oo = ((ObjRef) (obj)); return oo->data; } + +#endif \ No newline at end of file