gc: superficial cleaning
[nit.git] / clib / gc.c
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2 *
3 * Copyright 2009 Julien Chevalier <chevjulien@gmail.com>
4 *
5 * This file is free software, which comes along with NIT. This software is
6 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 * PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 * is kept unaltered, and a notification of the changes is added.
10 * You are allowed to redistribute it and sell it, alone or is a part of
11 * another product.
12 */
13
14 #include "gc.h"
15 #ifdef DEBUG
16 # include <assert.h>
17 #else
18 # define assert(x) while(0)
19 #endif
20
21 void Nit_gc_init(void) {
22 heapActive = malloc(sizeof(heap));
23 heapInactive = malloc(sizeof(heap));
24
25 heapActive->heapPointer = malloc(HEAP_ACTIVE_SIZE_MIN);
26 heapInactive->heapPointer = malloc(HEAP_ACTIVE_SIZE_MIN);
27
28 if (heapActive->heapPointer==NULL) exit(1);
29 if (heapInactive->heapPointer==NULL) exit(1);
30
31 heapActive->size = HEAP_ACTIVE_SIZE_MIN;
32 heapInactive->size = HEAP_ACTIVE_SIZE_MIN;
33
34 allocationPointer = heapActive->heapPointer;
35
36 evacuationPointer = heapInactive->heapPointer;
37 scavengingPointer = evacuationPointer;
38
39 GC_List_Init(&staticObjects);
40 }
41
42 val_t GC_evacuation(obj_t object) {
43 bigint size;
44 bigint objectSize;
45 val_t newAdress;
46 Nit_NativeArray array;
47 BOX_struct box;
48
49 assert(ISOBJ(object) && !ISNULL(object));
50 if (GET_MARKBIT(object) != (bigint)0) {
51 newAdress = REMOVE_MARKBIT((bigint)((object)->vft));
52 } else {
53 newAdress = (val_t)evacuationPointer;
54 if (OBJ_IS_ARRAY(object)) {
55 array = (Nit_NativeArray)object;
56 size = sizeof(struct Nit_NativeArray) + ((array->size - 1) * sizeof(val_t));
57 memcpy(evacuationPointer, (array), size);
58 (array)->vft = (classtable_elt_t*)evacuationPointer;
59 } else if (IS_BOX(object)) {
60 box = (BOX_struct)object;
61 size = sizeof(struct TBOX_struct);
62 memcpy(evacuationPointer, object, size);
63 box->vft = (classtable_elt_t*)evacuationPointer;
64 } else {
65 objectSize = (bigint)((object)[0].vft[1].i);
66 size = (objectSize) * sizeof(val_t);
67 memcpy(evacuationPointer, object, size);
68 (object)[0].vft = (classtable_elt_t*)evacuationPointer;
69 }
70 SET_MARKBIT(object);
71 evacuationPointer += size;
72 }
73
74 return newAdress;
75 }
76
77 void GC_scavenging(void) {
78 obj_t object = (obj_t)scavengingPointer;
79 int size;
80 int i;
81 obj_t referencedObject;
82 bigint objectSize;
83 Nit_NativeArray *array;
84
85 if (IS_BOX(object)) {
86 size = sizeof(struct TBOX_struct);
87 } else {
88 array = (Nit_NativeArray*)&scavengingPointer;
89 if (OBJ_IS_ARRAY((obj_t)*array)) {
90 size = sizeof(struct Nit_NativeArray) + (((*array)->size - 1) * sizeof(val_t));
91 for (i = 0; i < (*array)->size; i++) {
92 referencedObject = (obj_t)((*array)->val[i]);
93 if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
94 (*array)->val[i] = (bigint)GC_evacuation(referencedObject);
95 }
96 }
97 } else {
98 objectSize = (bigint)((object)->vft[1].i);
99 size = (objectSize) * sizeof(val_t);
100 for (i = 2; i < objectSize; i++) {
101 referencedObject = (obj_t)(object[i].objectSize);
102 if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
103 ((object)[i].objectSize) = (bigint)GC_evacuation(referencedObject);
104 }
105 }
106 }
107 }
108 scavengingPointer += size;
109 }
110
111 void GC_collect(void) {
112 val_t **pointers;
113 val_t *pointer;
114 int i;
115 int j;
116 struct trace_t *frame = tracehead;
117 GC_static_object *staticObject = staticObjects.top;
118 val_t object;
119 heap *tempPointer;
120
121 evacuationPointer = heapInactive->heapPointer;
122 scavengingPointer = heapInactive->heapPointer;
123 for (i = 0; i < staticObjects.size; i++) {
124 object = *(val_t*)(staticObject->pointer);
125 if (!ISNULL(object) && ISOBJ(object)) {
126 *(staticObject->pointer) = (val_t)GC_evacuation((obj_t)object);
127 }
128 staticObject = staticObject->next;
129 }
130 while (frame != NULL) {
131 pointers = frame->REG_pointer;
132 for (j = 0; j < frame->REG_size; j++) {
133 object = (val_t)(pointers[j]);
134 if (!ISNULL(object) && ISOBJ(object)) {
135 pointers[j] = (val_t*)GC_evacuation((obj_t)object);
136 }
137 }
138 if (frame == frame->prev) break;
139 frame = frame->prev;
140 }
141 while (evacuationPointer != scavengingPointer) {
142 GC_scavenging();
143 }
144
145 /* pour tests seulement, pas necessaire */
146 memset(heapActive->heapPointer, 0, heapActive->size);
147 allocationPointer = evacuationPointer;
148
149 /* inverse le tas actif et le tas inactif */
150 tempPointer = heapActive;
151 heapActive = heapInactive;
152 heapInactive = tempPointer;
153
154 heapActiveUsedSize = allocationPointer - heapActive->heapPointer;
155 }
156
157 void GC_set_heap_size(size_t newHeapSize) {
158 free(heapInactive->heapPointer);
159 heapInactive->heapPointer = malloc(newHeapSize);
160 if (heapInactive->heapPointer == NULL) {
161 exit(1);
162 }
163 heapInactive->size = newHeapSize;
164 memset(heapInactive->heapPointer, 0, newHeapSize);
165 }
166
167 void GC_detect_memory_needs(size_t size) {
168 if (size > (heapActive->size - heapActiveUsedSize)) {
169 GC_collect();
170 if (heapActive->size - heapActiveUsedSize > heapActive->size / 2 && heapActive->size * 3 / 4 > HEAP_ACTIVE_SIZE_MIN) {
171 GC_set_heap_size(heapActive->size * 3 / 4);
172 GC_collect();
173 GC_set_heap_size(heapActive->size);
174 }
175 }
176 if (size > (heapActive->size - heapActiveUsedSize)) {
177 int try_size = heapInactive->size * 2;
178 while (size > (try_size - heapActiveUsedSize)) {
179 try_size *= 2;
180 }
181 GC_set_heap_size(try_size);
182 GC_collect();
183 GC_set_heap_size(heapActive->size);
184 }
185 }
186
187 void *Nit_gc_malloc(size_t size) {
188 char *result;
189
190 GC_detect_memory_needs(size);
191
192 result = allocationPointer;
193 heapActiveUsedSize += size;
194 allocationPointer += size;
195
196 return result;
197 }
198
199 void GC_add_static_object(val_t *pointer) {
200 GC_List_Push(&staticObjects, pointer);
201 }
202