Commit 17b23c24 authored by Laszlo Domoszlai's avatar Laszlo Domoszlai
Browse files

GC

parent b26e73d7
TARGET = main
LIBS =
CC = clang++
CFLAGS = -O0 -g -x c++ -Wno-write-strings # -g -pg -fstack-usage
CFLAGS = -O3 -x c++ -Wno-write-strings # -g -pg -fstack-usage
.PHONY: default all clean
......@@ -17,7 +17,7 @@ HEADERS = $(wildcard *.h)
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -static -static-libgcc -static-libstdc++ -Wl,--stack,16777216 -Wall -g $(LIBS) -o $@ # -pg -g
$(CC) $(OBJECTS) -static -static-libgcc -static-libstdc++ -Wl,--stack,16777216 -Wall $(LIBS) -o $@ # -pg -g
clean:
-rm -f *.o
......
TARGET = main
LIBS =
CC = clang++
CFLAGS = -g -x c++ -Wno-write-strings # -fstack-usage
CFLAGS = -O3 -x c++ -Wno-write-strings # -fstack-usage
.PHONY: default all clean
......@@ -17,7 +17,7 @@ HEADERS = $(wildcard *.h)
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wl,-stack_size,0x1000000 -g -Wall $(LIBS) -o $@
$(CC) $(OBJECTS) -Wl,-stack_size,0x1000000 -Wall $(LIBS) -o $@
clean:
-rm -f *.o
......
......@@ -7,6 +7,7 @@
#include "code.h"
#include "mem.h"
#include "desc.h"
#include "gc.h"
// For compressing the source code a bit
......@@ -17,23 +18,14 @@
dst->desc = (Desc*) __FORWARD_PTR__; \
dst->_forward_ptr = thunk;
#define arg_from_thunk(descarg, arg) \
if(((FunEntry*) (descarg))->strictness & argmask && !arg->desc->hnf) \
{ \
push_a(eval(arg)); \
} \
else \
{ \
push_a(arg); \
} \
argmask <<= 1;
#define placeholder() \
push_a(alloc_b()); \
peek_a()->desc = (Desc*) __STACK_PLACEHOLDER__; \
#define arg_from_code(descarg, arg) \
if(((FunEntry*) (descarg))->strictness & argmask) \
{ \
Thunk* phl = alloc_b(); \
phl->desc = (Desc*) __STACK_PLACEHOLDER__; \
push_a(phl); \
placeholder(); \
exec(arg, frame_ptr, stack_top_a); \
} \
else \
......@@ -58,9 +50,15 @@ struct Thunk* create_thunk_app_static(Code* expr, int frame_ptr)
struct Thunk* create_thunk_app_dyn(Code* expr, int frame_ptr)
{
Thunk* basethunk = local(frame_ptr, ((AppEntry*)expr)->var.index);
if(!basethunk->desc->hnf) basethunk = eval(basethunk);
push_a(local(frame_ptr, ((AppEntry*)expr)->var.index));
int tmp = gc_enabled;
gc_enabled = 0;
peek_a()->desc->eval();
gc_enabled = tmp;
Thunk* basethunk = pop_a();
Desc* slice =
get_slice(basethunk->desc->type == FT_SLICE ?
((SliceEntry*) basethunk->desc)->forward_ptr : basethunk->desc, basethunk->desc->arity + expr->nr_args);
......@@ -148,10 +146,12 @@ void set_create_thunk_fun(Code* code)
void exec(Code* expr, int frame_ptr, int root_frame_ptr)
{
if(heap_curr > gc_trigger) gc();
int root_frame_ptr_b = stack_top_b;
while(1)
{
{
assert(expr != NULL);
assert(stack_top_a < STACK_SIZE_A);
assert(stack_top_b < STACK_SIZE_B);
......@@ -162,7 +162,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
switch (expr->type) {
case CT_APP_PRIM1:
{
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
......@@ -213,7 +213,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
case CT_APP_PRIM_TA:
{
push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[0])->thunk);
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
......@@ -223,7 +223,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
case CT_APP_PRIM_AT:
{
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
push_a(&((ThunkEntry*) ((AppEntry*) expr)->args[1])->thunk);
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
......@@ -234,7 +234,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
case CT_APP_PRIM_AS:
{
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[1])->index));
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
......@@ -246,7 +246,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
case CT_APP_PRIM_SA:
{
push_a(local(frame_ptr, ((VarEntry*) ((AppEntry*) expr)->args[0])->index));
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
......@@ -255,12 +255,12 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
return;
}
case CT_APP_PRIM2:
{
push_a(alloc_b());
{
placeholder();
exec(((AppEntry*) expr)->args[0], frame_ptr, stack_top_a);
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[1], frame_ptr, stack_top_a);
((PrimEntry*) ((AppEntry*) expr)->f)->exec(root_frame_ptr);
destroy_stack_frame(root_frame_ptr);
......@@ -297,7 +297,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
int new_frame_ptr = stack_top_a;
int argmask = 1;
for (int i = 0; i < expr->nr_args; i++) {
arg_from_code(slice, ((AppEntry*) expr)->args[i]);
}
......@@ -323,7 +323,7 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
thunk->desc = slice;
assert(thunk->desc->arity == expr->nr_args);
for (int i = 0; i < expr->nr_args; i++) {
thunk->_args[i]
= ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], frame_ptr);
......@@ -335,30 +335,31 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
case CT_APP_DYN:
{
Thunk* basethunk = local(frame_ptr, ((AppEntry*)expr)->var.index);
if(!basethunk->desc->hnf) basethunk = eval(basethunk);
push_a(local(frame_ptr, ((AppEntry*)expr)->var.index));
//if(!basethunk->desc->hnf) basethunk = basethunk->desc->eval();
//peek_a()->desc->eval();
//Thunk* basethunk = peek_a();
//basethunk->desc->eval();
Thunk** bt = &peek_a();
(*bt)->desc->eval();
Desc* slice =
get_slice(basethunk->desc->type == FT_SLICE ?
((SliceEntry*) basethunk->desc)->forward_ptr : basethunk->desc, basethunk->desc->arity + expr->nr_args);
get_slice((*bt)->desc->type == FT_SLICE ?
((SliceEntry*) (*bt)->desc)->forward_ptr : (*bt)->desc, (*bt)->desc->arity + expr->nr_args);
switch(slice->type) {
case FT_PRIM1:
case FT_PRIM2:
{
for (int i = 0; i < basethunk->desc->arity; i++) {
if(basethunk->_args[i]->desc->hnf)
{
push_a(basethunk->_args[i]);
}
else
{
push_a(eval(basethunk->_args[i]));
}
for (int i = 0; i < (*bt)->desc->arity; i++) {
push_a((*bt)->_args[i]);
/*if(!basethunk->_args[i]->desc->hnf)*/ (*bt)->_args[i]->desc->eval();
}
for (int i = 0; i < expr->nr_args; i++) {
push_a(alloc_b());
placeholder();
exec(((AppEntry*) expr)->args[i], frame_ptr, stack_top_a);
}
......@@ -372,8 +373,13 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
int new_frame_ptr = stack_top_a;
int argmask = 1;
for (int i = 0; i < basethunk->desc->arity; i++) {
arg_from_thunk(slice, basethunk->_args[i])
for (int i = 0; i < (*bt)->desc->arity; i++) {
push_a((*bt)->_args[i]);
if(((FunEntry*) (slice))->strictness & argmask /*&& !arg->desc->hnf*/)
{
(*bt)->_args[i]->desc->eval();
}
argmask <<= 1;
}
for (int i = 0; i < expr->nr_args; i++) {
......@@ -401,12 +407,12 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
thunk->desc = slice;
assert(thunk->desc->arity == basethunk->desc->arity + expr->nr_args);
assert(thunk->desc->arity == (*bt)->desc->arity + expr->nr_args);
memcpy(&thunk->_args, &basethunk->_args, sizeof(Thunk*) * basethunk->desc->arity);
memcpy(&thunk->_args, &(*bt)->_args, sizeof(Thunk*) * (*bt)->desc->arity);
for (int i = 0; i < expr->nr_args; i++) {
thunk->_args[basethunk->desc->arity + i]
thunk->_args[(*bt)->desc->arity + i]
= ((AppEntry*) expr)->args[i]->create_thunk(((AppEntry*) expr)->args[i], frame_ptr);
}
......@@ -457,13 +463,20 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
// Greatly reduces stack usage
destroy_stack_frame(root_frame_ptr);
destroy_stack_frame_b(root_frame_ptr_b);
frame_ptr = stack_top_a;
// Here frame_ptr == root_frame_ptr
int argmask = 1;
for (int i = 0; i < thunk->desc->arity; i++) {
arg_from_thunk(thunk->desc, thunk->_args[i]);
push_a(thunk->_args[i]);
if(((FunEntry*) (thunk->desc))->strictness & argmask /*&& !arg->desc->hnf*/)
{
thunk->_args[i]->desc->eval();
thunk = stack_a[root_frame_ptr-1];
}
argmask <<= 1;
}
expr = ((FunEntry*) thunk->desc)->body;
......@@ -474,13 +487,15 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
{
for (int i = 0; i < thunk->desc->arity; i++) {
push_a(eval(thunk->_args[i]));
push_a(thunk->_args[i]);
thunk->_args[i]->desc->eval();
thunk = stack_a[root_frame_ptr-1];
}
((PrimEntry*) thunk->desc)->exec(root_frame_ptr);
destroy_stack_frame(root_frame_ptr);
destroy_stack_frame_b(root_frame_ptr_b);
destroy_stack_frame_b(root_frame_ptr_b);
return;
}
case FT_CAF:
......@@ -506,10 +521,9 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
case CT_SELECT_LIT:
{
Thunk* lit = alloc_b();
push_a(lit);
placeholder();
exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
lit = pop_a();
Thunk* lit = pop_a();
bool handled = false;
......@@ -546,11 +560,9 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
{
SelectEntry* select = (SelectEntry*) expr;
Thunk* cons = alloc_b();
cons->desc = (Desc*) __STACK_PLACEHOLDER__;
push_a(cons);
placeholder();
exec(select->expr, frame_ptr, stack_top_a);
cons = pop_a();
Thunk* cons = pop_a();
expr = select->bodies[((ADTEntry*)cons->desc)->idx];
......@@ -575,10 +587,10 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
case CT_IF:
{
push_a(alloc_b());
placeholder();
exec(((IfEntry*) expr)->cond, frame_ptr, stack_top_a);
Thunk* cond = pop_a();
if (readB(cond)) {
expr = ((IfEntry*) expr)->texpr;
continue;
......@@ -592,56 +604,80 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
}
}
struct Thunk* eval(Thunk* thunk) {
assert(thunk != NULL);
follow_thunk(thunk);
switch(thunk->desc->type) {
case FT_FUN:
{
push_a(thunk);
int frame_ptr = stack_top_a;
int argmask = 1;
for (int i = 0; i < thunk->desc->arity; i++) {
arg_from_thunk(thunk->desc, thunk->_args[i]);
void eval_hnf()
{
return;
}
void eval_fun()
{
Thunk* thunk = peek_a();
int frame_ptr = stack_top_a;
int argmask = 1;
for (int i = 0; i < thunk->desc->arity; i++) {
push_a(thunk->_args[i]);
if(((FunEntry*) (thunk->desc))->strictness & argmask)
{
thunk->_args[i]->desc->eval();
thunk = stack_a[frame_ptr-1]; // refresh thunk ptr after eval
}
exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr);
thunk = pop_a();
return thunk;
argmask <<= 1;
}
case FT_PRIM1:
case FT_PRIM2:
{
push_a(thunk);
int frame_ptr = stack_top_a;
for (int i = 0; i < thunk->desc->arity; i++) {
if(thunk->_args[i]->desc->hnf)
{
push_a(thunk->_args[i]);
}
else
{
push_a(eval(thunk->_args[i]));
}
}
exec(((FunEntry*) thunk->desc)->body, frame_ptr, frame_ptr);
}
((PrimEntry*) thunk->desc)->exec(frame_ptr);
stack_top_a = frame_ptr;
thunk = pop_a();
return thunk;
void eval_prim()
{
Thunk* thunk = peek_a();
int frame_ptr = stack_top_a;
for (int i = 0; i < thunk->desc->arity; i++) {
push_a(thunk->_args[i]);
thunk->_args[i]->desc->eval();
thunk = stack_a[frame_ptr-1]; // refresh thunk ptr after eval
}
case FT_CAF:
case FT_CAF_REDUCED:
not_implemented("CAF");
case FT_SLICE:
case FT_ADT:
case FT_RECORD:
case FT_BOXED_LIT:
return thunk;
((PrimEntry*) thunk->desc)->exec(frame_ptr);
stack_top_a = frame_ptr;
}
void eval_fwd_ptr()
{
Thunk* thunk = pop_a();
follow_thunk(thunk);
push_a(thunk);
thunk->desc->eval();
}
void set_eval_fun(Desc* desc)
{
if(desc == (Desc*) __FORWARD_PTR__)
{
desc->eval = eval_fwd_ptr;
return;
}
switch(desc->type)
{
case FT_BOXED_LIT:
case FT_RECORD:
case FT_ADT:
case FT_CAF:
case FT_CAF_REDUCED:
case FT_SLICE:
desc->eval = eval_hnf;
break;
case FT_FUN:
desc->eval = eval_fun;
break;
case FT_PRIM1:
case FT_PRIM2:
desc->eval = eval_prim;
break;
}
}
......@@ -70,8 +70,8 @@ struct IfEntry {
typedef Thunk* (*create_thunk_fun)(Code*, int);
void set_create_thunk_fun(Code* code);
void set_eval_fun(Desc* desc);
void exec(Code* expr, int frame_ptr, int root_frame_ptr);
struct Thunk* eval(Thunk* thunk);
#endif // __CODE_H
\ No newline at end of file
......@@ -3,6 +3,8 @@
#include "debug.h"
int debug_cnt = 0;
void not_implemented(char* msg)
{
printf("Function not implemented: %s\n", msg);
......
......@@ -13,5 +13,7 @@
void not_implemented(char* msg);
void abort(char* msg);
extern int debug_cnt;
#endif /* DEBUG_H */
......@@ -27,6 +27,7 @@ khash_t(khStrPtr) * funHash = kh_init(khStrPtr);
void add_desc(char* fn, Desc* desc) {
khiter_t k; // used by the macros
kh_set(khStrPtr, funHash, fn, desc);
set_eval_fun(desc);
}
Desc* find_desc(char* fn) {
......@@ -48,6 +49,8 @@ FunEntry* alloc_prim(char* name, int unboxable) {
entry->base.unboxable = unboxable;
entry->base.hnf = 1;
memcpy(entry->name, name, len + 1);
set_eval_fun((Desc*) entry);
return entry;
}
......@@ -60,6 +63,8 @@ void gen_slices(SliceEntry* dest, Desc* forward_ptr, int arity) {
slice->base.unboxable = false;
slice->base.hnf = true;
slice->forward_ptr = forward_ptr;
set_eval_fun((Desc*) slice);
}
}
......@@ -89,6 +94,10 @@ int printDesc(Desc* f) {
}
void init_desc() {
__FORWARD_PTR__ = alloc_prim("FWD", 0);
__FORWARD_PTR__->base.hnf = false;
set_eval_fun((Desc*) __FORWARD_PTR__);
__INT__ = alloc_prim("INT", 1);
__INT_SHARED__ = alloc_prim("INT", 0);
__BOOL__ = alloc_prim("BOOL", 1);
......@@ -100,10 +109,7 @@ void init_desc() {
__STRING__ = alloc_prim("STRING", 0);
__ARRAY__ = alloc_prim("ARRAY", 0);
__FORWARD_PTR__ = alloc_prim("FWD", 0);
__FORWARD_PTR__->base.hnf = false;
// Avoid to be overwritten by updateF
__STACK_PLACEHOLDER__ = alloc_prim("PLACEHOLDER", 0);
__STACK_PLACEHOLDER__->base.thunk_size = 0;
......
......@@ -6,11 +6,16 @@ enum FunType {
};
struct Desc {
FunType type : 4;
unsigned int arity : 8; // LIMITATION: maximum 32 arguments
unsigned int thunk_size : 10; // It gives false result for strings and arrays
unsigned int unboxable : 1;
unsigned int hnf : 1;
struct
{
FunType type : 4;
unsigned int arity : 8; // LIMITATION: maximum 32 arguments
unsigned int thunk_size : 10; // It gives false result for strings and arrays
unsigned int unboxable : 1;
unsigned int hnf : 1;
};
void (*eval)();
};
#endif // __DESC_H
\ No newline at end of file
#include <string.h>
#include <stdio.h>
#include "debug.h"
#include "gc.h"
#include "thunk.h"
#include "desc.h"
#define follow_thunk(thunk) if (thunk->desc == (Desc*) __FORWARD_PTR__) thunk = thunk->_forward_ptr;
// http://stackoverflow.com/questions/17095324/fastest-way-to-determine-if-an-integer-is-between-two-integers-inclusive-with/17095534#17095534
//#define inheap(addr) ((unsigned)((int)addr-(int)heap_base_curr) < HEAP_SIZE)
#define inheap(addr) ((char*)addr >= heap_base_curr && (char*)addr < (heap_base_curr + HEAP_SIZE))
#define instackb(addr) ((char*)addr >= (char*) &stack_b[0] && (char*)addr < (char*) &stack_b[STACK_SIZE_B])
int gc_enabled = 1;
void gc()
{
if(!gc_enabled) return;
// gc_enabled = 0;
debug_cnt++;
/*
for(int i=0; i<stack_top_a; i++)
{
Thunk* ptr = stack_a[i];
while (ptr->desc == (Desc*) __FORWARD_PTR__)
{
ptr = ptr->_forward_ptr;
}
push_a(ptr);
print(false);
printf("\n");
}
*/
//printf("gc\n");
char* allocptr = heap_base_swap;
char* scanptr = heap_base_swap;
for(int i=0; i<stack_top_a; i++)
{
Thunk* ptr = stack_a[i];
// do not copy forward pointers
// also do it outside, because the final thunk may be out of the heap
//follow_thunk(ptr);
while (ptr->desc == (Desc*) __FORWARD_PTR__)
{
ptr = ptr->_forward_ptr;
stack_a[i] = ptr;
}
if(inheap(ptr)/*&& ptr->desc != NULL*/)
{
if(ptr->desc == NULL)