This commit is contained in:
Elias Bennour 2024-01-28 17:32:30 +01:00
parent 3c3d2716a5
commit c3629d7150
15 changed files with 212 additions and 113 deletions

View File

@ -5,7 +5,8 @@ set(CMAKE_C_STANDARD 99)
add_compile_options(-g -Wall -pedantic) add_compile_options(-g -Wall -pedantic)
add_executable(njvm njvm.c) add_executable(njvm njvm.c
njvm.h)
# Include directories for njvm executable # Include directories for njvm executable
target_include_directories(njvm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bigint/build/include) target_include_directories(njvm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bigint/build/include)

104
GC.c
View File

@ -1,6 +1,6 @@
#ifndef GC #ifndef GC
#define GC #define GC
#define HAS_BROKENHEART_FLAG(objRef) (((objRef)->size & 1 << (7 * sizeof(unsigned int) -1)) == 0)
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -8,107 +8,7 @@
#include "objref.c" #include "objref.c"
#include "instruktion.c" #include "instruktion.c"
#include "support.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 #endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

189
njvm.c
View File

@ -8,12 +8,17 @@
#include "debugMenu.c" #include "debugMenu.c"
#include "bigint.h" #include "bigint.h"
#include "record.c" #include "record.c"
#include "GC.c"
#include "SDA.c" #include "SDA.c"
// Debug // Debug
int debug = 0; int debug = 0;
// Purge Flag
int purgeFlag = false;
// Heap Size
int argVheapSizeKiB = 8192;
// Program // Program
struct program program; struct program program;
@ -22,7 +27,7 @@ struct sda sda;
// Stack // Stack
struct stack stack; struct stack stack;
#define SIZE 64 #define SIZE 10000
//Register //Register
struct stack reg; struct stack reg;
@ -46,7 +51,7 @@ void execute(struct program program) {
ObjRef tempObj2; ObjRef tempObj2;
int tempInt; int tempInt;
for (i = 0; i < *program.size; ++i) { 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); if(debug == 1) printf("(%i)",i);
switch (program.program[i] >> 24) { switch (program.program[i] >> 24) {
case HALT: case HALT:
@ -315,9 +320,184 @@ void execute(struct program program) {
void tests(void) { 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[]) { int main(int argc, char *argv[]) {
// Init the Heap // Init the Heap
initHeap(1000); //initHeap(1000);
// Initialize the Stack // Initialize the Stack
int size = SIZE; int size = SIZE;
@ -372,6 +552,7 @@ int main(int argc, char *argv[]) {
run = 1; run = 1;
} }
} }
heapAllocator(argVheapSizeKiB);
// Init the sda // Init the sda
ObjRef s[sizeSDA]; ObjRef s[sizeSDA];
sda.size = &sizeSDA; sda.size = &sizeSDA;

11
njvm.h Normal file
View File

@ -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

BIN
njvm.o

Binary file not shown.

View File

@ -5,7 +5,7 @@
typedef struct ObjRef{ typedef struct ObjRef{
// if brkokenHeart and forward_pointer added at this point bip throws errors // if brkokenHeart and forward_pointer added at this point bip throws errors
bool brokenHeart; bool brokenHeart;
struct ObjRef *forward_pointer; struct ObjRef *forwardPointer;
unsigned int size; unsigned int size;
unsigned char data[1]; unsigned char data[1];
} *ObjRef; } *ObjRef;

View File

@ -5,12 +5,13 @@
#define RECORD #define RECORD
#include "stackslot.c" #include "stackslot.c"
#include "instruktion.c" #include "instruktion.c"
#include "GC.c" #include "njvm.h"
ObjRef newRecord(int size){ ObjRef newRecord(int size){
ObjRef record; ObjRef record;
unsigned int objSize; unsigned int objSize;
objSize = sizeof(*record) + (size * sizeof(void *)); objSize = sizeof(*record) + (size * sizeof(void *));
if((record = malloc(objSize)) == NULL){ if((record = alloc(objSize)) == NULL){
perror("malloc"); perror("malloc");
} }
record->size = MSB; record->size = MSB;

View File

@ -1,10 +1,13 @@
#ifndef SUPPORT_C
#define SUPPORT_C
#include "support.h" #include "support.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "objref.c" #include "objref.c"
#include "GC.c" #include "njvm.h"
void fatalError(char *msg){ void fatalError(char *msg){
printf("Fatal error: %s\n", msg); printf("Fatal error: %s\n", msg);
exit(1); exit(1);
@ -13,7 +16,7 @@ void fatalError(char *msg){
void * newPrimObject(int dataSize) { void * newPrimObject(int dataSize) {
ObjRef bigObjRef; ObjRef bigObjRef;
bigObjRef = malloc(sizeof(unsigned int) + bigObjRef = alloc(sizeof(unsigned int) +
dataSize * sizeof(unsigned char)); dataSize * sizeof(unsigned char));
if (bigObjRef == NULL) { if (bigObjRef == NULL) {
fatalError("newPrimObject() got no memory"); fatalError("newPrimObject() got no memory");
@ -26,3 +29,5 @@ void * getPrimObjectDataPointer(void * obj){
ObjRef oo = ((ObjRef) (obj)); ObjRef oo = ((ObjRef) (obj));
return oo->data; return oo->data;
} }
#endif