add gc
This commit is contained in:
parent
3c3d2716a5
commit
c3629d7150
@ -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)
|
||||
|
||||
104
GC.c
104
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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -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
|
||||
|
||||
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.
191
njvm.c
191
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
njvm.h
Normal file
11
njvm.h
Normal 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
|
||||
2
objref.c
2
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;
|
||||
|
||||
5
record.c
5
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;
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
#ifndef SUPPORT_C
|
||||
#define SUPPORT_C
|
||||
|
||||
#include "support.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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
|
||||
Loading…
x
Reference in New Issue
Block a user