use nitg to bootstrap; drop bootstrap of nitc
[nit.git] / c_src / clib / gc.c
diff --git a/c_src/clib/gc.c b/c_src/clib/gc.c
deleted file mode 100644 (file)
index ad051d9..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* This file is part of NIT ( http://www.nitlanguage.org ).
- *
- * Copyright 2009 Julien Chevalier <chevjulien@gmail.com>
- *
- * This file is free software, which comes along with NIT.  This software is
- * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
- * PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
- * is kept unaltered, and a notification of the changes is added.
- * You  are  allowed  to  redistribute it and sell it, alone or is a part of
- * another product.
- */
-
-#include "gc.h"
-#ifdef DEBUG
-#      include <assert.h>
-#else
-#      define assert(x) while(0)
-#endif
-#include <unistd.h>
-#include "gc_static_objects_list.h"
-
-/** The current active heap.
- * During GC collect, it is the destination (i.e. the next active heap). */
-char *gc_heap_pointer;
-
-/** The inactive heap.
- * During GC collect, is is the source (i.e. the previous active heap). */
-char *gc_old_heap_pointer;
-
-/** The size (total capacity) of the active heap. */
-size_t gc_heap_size;
-
-/** The total size of currently allocated objects. */
-size_t gc_used_size;
-
-/** Typedef used by boxing val. FIXME: Do someting better! */
-typedef struct TBOX_struct {
-       const classtable_elt_t *vft;
-       char *val;
-       bigint object_id;
-} *BOX_struct;
-
-/** First free position in the active heap. */
-char *gc_allocation_pointer;
-
-/** Position of objects copied but not yet visited (during GC collect). */
-char *gc_scavenging_pointer;
-
-/** List of global objects. */
-GC_List staticObjects;
-
-/** Size of a memory page. Used to grow or shrink the GC heap. */
-unsigned long page_size;
-
-/* Markbit manipulations */
-#define GET_MARKBIT(x) (((val_t)((x)[0].vft)) & 1)
-#define SET_MARKBIT(x) ((x)->vft = (void*)(((bigint)((x)->vft)) | 1))
-#define REMOVE_MARKBIT(x) ((x) ^ 1)
-
-void Nit_gc_init(void) {
-       page_size = sysconf(_SC_PAGESIZE);
-
-       gc_heap_pointer = calloc(1, page_size);
-       if (gc_heap_pointer==NULL) exit(1);
-       gc_heap_size = page_size;
-       gc_used_size = 0;
-
-       gc_allocation_pointer = gc_heap_pointer;
-
-       gc_old_heap_pointer = NULL;
-       gc_scavenging_pointer = NULL;
-
-       GC_List_Init(&staticObjects);
-}
-
-/** Copy object to the new heap if needed then return the address of the copy. */
-static val_t GC_evacuation(obj_t object) {
-       bigint size;
-       bigint objectSize;
-       val_t newAdress;
-       Nit_NativeArray array;
-
-       assert(ISOBJ(object) && !ISNULL(object));
-       if (GET_MARKBIT(object) != (bigint)0) {
-               /* Object already evacuated. So forward it. */
-               newAdress = REMOVE_MARKBIT((bigint)((object)->vft));
-       } else {
-               newAdress = (val_t)gc_allocation_pointer;
-               if (OBJ_IS_ARRAY(object)) {
-                       array = (Nit_NativeArray)object;
-                       size = sizeof(struct Nit_NativeArray) + ((array->size - 1) * sizeof(val_t));
-               } else if (OBJ_IS_BOX(object)) {
-                       size = sizeof(struct TBOX_struct);
-               } else {
-                       objectSize = (bigint)((object)[0].vft[1].i);
-                       size = (objectSize) * sizeof(val_t);
-               }
-               memcpy(gc_allocation_pointer, object, size);
-               (object)[0].vft = (classtable_elt_t*)gc_allocation_pointer;
-               SET_MARKBIT(object);
-               gc_allocation_pointer += size;
-       }
-
-       return newAdress;
-}
-
-/** Process the next evacuated object to copy/update its fields. */
-static void GC_scavenging(void) {
-       obj_t object;
-       int size;
-       int i;
-       val_t referencedObject;
-
-       object = (obj_t)gc_scavenging_pointer;
-       if (OBJ_IS_BOX(object)) {
-               size = sizeof(struct TBOX_struct);
-       } else if (OBJ_IS_ARRAY(object)) {
-               Nit_NativeArray array = (Nit_NativeArray)gc_scavenging_pointer;
-               size = sizeof(struct Nit_NativeArray) + ((array->size - 1) * sizeof(val_t));
-               for (i = 0; i < array->size; i++) {
-                       referencedObject = array->val[i];
-                       if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
-                               array->val[i] = GC_evacuation((obj_t)referencedObject);
-                       }
-               }
-       } else {
-               bigint objectSize = (bigint)((object)->vft[1].i);
-               size = (objectSize) * sizeof(val_t);
-               for (i = 2; i < objectSize; i++) {
-                       referencedObject = object[i].objectSize;
-                       if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
-                               object[i].objectSize = GC_evacuation((obj_t)referencedObject);
-                       }
-               }
-       }
-
-       gc_scavenging_pointer += size;
-}
-
-/** Collect live objects in the old head and copy them to the active heap. */
-static void GC_collect(void) {
-       val_t *pointer;
-       int i;
-       int j;
-       struct stack_frame_t *frame = stack_frame_head;
-       GC_static_object *staticObject = staticObjects.top;
-       val_t object;
-       struct nitni_ref *global_ref;
-       struct nitni_ref_array_link *local_ref_array_link; /* for native interface */
-
-       gc_allocation_pointer = gc_heap_pointer;
-       gc_scavenging_pointer = gc_heap_pointer;
-
-       /* Process global objects (registered by GC_add_static_object) */
-       for (i = 0; i < staticObjects.size; i++) {
-               object = *(val_t*)(staticObject->pointer);
-               if (!ISNULL(object) && ISOBJ(object)) {
-                       *(staticObject->pointer) = GC_evacuation((obj_t)object);
-               }
-               staticObject = staticObject->next;
-       }
-
-       /* Process global reference to Nit objects from C code */
-       global_ref = nitni_global_ref_list->head;
-       while (global_ref != NULL) {
-               object = global_ref->val;
-               if (!ISNULL(object) && ISOBJ(object)) {
-                       global_ref->val = GC_evacuation((obj_t)object);
-               }
-               global_ref = global_ref->next;
-       }
-
-       /* Process function frames (local variables) */
-       while (frame != NULL) {
-               for (j = 0; j < frame->REG_size; j++) {
-                       object = frame->REG[j];
-                       if (!ISNULL(object) && ISOBJ(object)) {
-                               frame->REG[j] = GC_evacuation((obj_t)object);
-                       }
-               }
-
-               /* Process C references to Nit objects */
-               local_ref_array_link = frame->nitni_local_ref_head;
-               while ( local_ref_array_link != NULL )
-               {
-                       for (j = 0; j < local_ref_array_link->count; j++) {
-                               object = local_ref_array_link->reg[j]->val;
-                               if (!ISNULL(object) && ISOBJ(object)) {
-                                       local_ref_array_link->reg[j]->val = GC_evacuation((obj_t)object);
-                               }
-                       }
-                       local_ref_array_link = local_ref_array_link->next;
-               }
-
-               if (frame == frame->prev) break;
-               frame = frame->prev;
-       }
-       while (gc_allocation_pointer != gc_scavenging_pointer) {
-               GC_scavenging();
-       }
-
-       gc_scavenging_pointer = NULL;
-
-       gc_used_size = gc_allocation_pointer - gc_heap_pointer;
-}
-
-/** Allocate a new active heap. */
-static void GC_prepare_heap_size(size_t size) {
-       assert(gc_old_heap_pointer == NULL);
-       gc_old_heap_pointer = gc_heap_pointer;
-
-       gc_heap_pointer = calloc(1, size);
-       if (gc_heap_pointer == NULL) {
-               exit(1);
-       }
-       gc_heap_size = size;
-}
-
-void Nit_gc_print_usage(void) {
-#if __STDC_VERSION >= 199901L
-       /* If we are compiling with standard C99 or more recent, we can use %zu. */
-       printf("GC: Size %zu usage %zu (%.2f%%)\n", gc_heap_size, gc_used_size, 100.0*gc_used_size/gc_heap_size);
-#else
-       /* We are not compiling with a standard that allows us to use %zu, let's cast the two unsigned integers into the biggest we can !*/
-       printf("GC: Size %lu usage %lu (%.2f%%)\n", (unsigned long)gc_heap_size, (unsigned long)gc_used_size, 100.0*gc_used_size/gc_heap_size);
-#endif
-}
-
-/** Enlarge the heap and collect dead objects. Can also shrink the heap.
- * Size is the aditionnal number of bytes required. */
-static void GC_enlarge_and_collect(size_t size) {
-       size_t try_size;
-
-       /* Heap grows exponentially. */
-       try_size = gc_heap_size;
-       while (size > (try_size - gc_used_size)) {
-               try_size = try_size * 1.5;
-       }
-
-       /* Build a new heap. */
-       GC_prepare_heap_size(try_size);
-
-       /* Collect. */
-       GC_collect();
-
-       /* Free the old heap. */
-       free(gc_old_heap_pointer);
-       gc_old_heap_pointer = NULL;
-
-       /* Shrink heap. */
-       while (gc_heap_size > 2*page_size && 3*(gc_used_size+size) < gc_heap_size)
-               gc_heap_size = gc_heap_size / 1.5;
-       /*Nit_gc_print_usage();*/
-}
-
-void *Nit_gc_malloc(size_t size) {
-       char *result;
-
-       if (size > (gc_heap_size - gc_used_size))
-               GC_enlarge_and_collect(size);
-
-       result = gc_allocation_pointer;
-       gc_allocation_pointer += size;
-       gc_used_size += size;
-
-       return result;
-}
-
-void GC_add_static_object(val_t *pointer) {
-       GC_List_Push(&staticObjects, pointer);
-}
-
-/* Is invoked by intern method Sys:force_garbage_collection */
-void Nit_gc_force_garbage_collection( void ) {
-       GC_enlarge_and_collect( 0 );
-}