gc: add Nit GC
[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 #include <assert.h>
16
17 void Nit_gc_init(){
18 heapActive = malloc(sizeof(heap));
19 heapInactive = malloc(sizeof(heap));
20
21 heapActive->heapPointer = malloc(HEAP_ACTIVE_SIZE_MIN);
22 heapInactive->heapPointer = malloc(HEAP_ACTIVE_SIZE_MIN);
23
24 if (heapActive->heapPointer==NULL) exit(1);
25 if (heapInactive->heapPointer==NULL) exit(1);
26
27 heapActive->size = HEAP_ACTIVE_SIZE_MIN;
28 heapInactive->size = HEAP_ACTIVE_SIZE_MIN;
29
30 allocationPointer = heapActive->heapPointer;
31
32 evacuationPointer = heapInactive->heapPointer;
33 scavengingPointer = evacuationPointer;
34
35 GC_List_Init(&staticObjects);
36 }
37
38 val_t GC_evacuation(obj_t object){
39 bigint size;
40 bigint objectSize;
41 val_t newAdress;
42 Nit_NativeArray array;
43 BOX_struct box;
44
45 assert(ISOBJ(object) && !ISNULL(object));
46 if ( GET_MARKBIT(object) != (bigint)0) {
47 newAdress = REMOVE_MARKBIT((bigint)((object)->vft));
48 }else{
49 newAdress = (val_t)evacuationPointer;
50 if (OBJ_IS_ARRAY(object)) {
51 array = (Nit_NativeArray ) object;
52 size = sizeof(struct Nit_NativeArray) + ((array->size - 1) * sizeof(val_t));
53 memcpy((void *)evacuationPointer, (array), size);
54 (array)->vft = (classtable_elt_t*)evacuationPointer;
55 }else if(IS_BOX(object)){
56 box = (BOX_struct)object;
57 size = sizeof(struct TBOX_struct);
58 memcpy((void *)evacuationPointer, object, size);
59 box->vft = (classtable_elt_t*)evacuationPointer;
60 }else{
61 objectSize = (bigint)((object)[0].vft[1].i);
62 size = (objectSize) * sizeof(val_t);
63 memcpy((void *)evacuationPointer, object, size);
64 (object)[0].vft = (classtable_elt_t*)evacuationPointer;
65 }
66 SET_MARKBIT(object);
67 evacuationPointer += size;
68 }
69
70 return newAdress;
71 }
72
73 void GC_scavenging(){
74 obj_t object = (obj_t)scavengingPointer;
75 obj_t * object2 = (obj_t *)&scavengingPointer;
76 int size;
77 int i;
78 obj_t referencedObject;
79 bigint objectSize;
80 Nit_NativeArray * array;
81
82 if ( IS_BOX(object)) {
83 size = sizeof(struct TBOX_struct);
84 }else{
85 array = (Nit_NativeArray*)&scavengingPointer;
86 if (OBJ_IS_ARRAY((obj_t)*array)) {
87 size = sizeof(struct Nit_NativeArray) + (((*array)->size - 1) * sizeof(val_t));
88 for (i = 0; i < (*array)->size; i++) {
89 referencedObject = (obj_t)((*array)->val[i]);
90 if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
91 (*array)->val[i] = (bigint)GC_evacuation(referencedObject);
92 }
93 }
94 }else{
95 objectSize = (bigint)((object)->vft[1].i);
96 size = (objectSize) * sizeof(val_t);
97 for (i = 2; i < objectSize; i++) {
98 referencedObject = (obj_t)(object[i].objectSize);
99 if (!ISNULL(referencedObject) && ISOBJ(referencedObject)) {
100 ((object)[i].objectSize) = (bigint)GC_evacuation(referencedObject);
101 }
102 }
103 }
104 }
105 scavengingPointer += size;
106 }
107
108 void GC_collect(){
109 val_t ** pointers;
110 val_t * pointer;
111 int i;
112 int j;
113 struct trace_t * frame = tracehead;
114 GC_static_object * staticObject = staticObjects.top;
115 val_t object;
116 heap * tempPointer;
117
118 evacuationPointer = heapInactive->heapPointer;
119 scavengingPointer = heapInactive->heapPointer;
120 for (i = 0; i < staticObjects.size; i++) {
121 object = *(val_t*)(staticObject->pointer);
122 if(!ISNULL(object) && ISOBJ(object)){
123 *(staticObject->pointer) = (val_t)GC_evacuation((obj_t)object);
124 }
125 staticObject = staticObject->next;
126 }
127 while (frame != NULL) {
128 pointers = frame->REG_pointer;
129 for (j = 0; j < frame->REG_size; j++) {
130 object = (val_t)(pointers[j]);
131 if(!ISNULL(object) && ISOBJ(object)){
132 pointers[j] = (val_t*)GC_evacuation((obj_t)object);
133 }
134 }
135 if (frame == frame->prev) break;
136 frame = frame->prev;
137 }
138 while ( evacuationPointer != scavengingPointer) {
139 GC_scavenging();
140 }
141
142 /* pour tests seulement, pas necessaire */
143 memset((void *)heapActive->heapPointer, 0, heapActive->size);
144 allocationPointer = evacuationPointer;
145
146 /* inverse le tas actif et le tas inactif */
147 tempPointer = heapActive;
148 heapActive = heapInactive;
149 heapInactive = tempPointer;
150
151 heapActiveUsedSize = (int)allocationPointer - (int)heapActive->heapPointer;
152 }
153
154 void GC_set_heap_size(size_t newHeapSize){
155 free(heapInactive->heapPointer);
156 heapInactive->heapPointer = malloc(newHeapSize);
157 if(heapInactive->heapPointer == NULL) {
158 exit(1);
159 }
160 heapInactive->size = newHeapSize;
161 memset(heapInactive->heapPointer, 0, newHeapSize);
162 }
163
164 void GC_detect_memory_needs( size_t size ) {
165 if ( size > (heapActive->size - heapActiveUsedSize)) {
166 GC_collect();
167 if (heapActive->size - heapActiveUsedSize > heapActive->size / 2 && heapActive->size * 3 / 4 > HEAP_ACTIVE_SIZE_MIN){
168 GC_set_heap_size(heapActive->size * 3 / 4);
169 GC_collect();
170 GC_set_heap_size(heapActive->size);
171 }
172 }
173 if ( size > (heapActive->size - heapActiveUsedSize)) {
174 int try_size = heapInactive->size * 2;
175 while (size > (try_size - heapActiveUsedSize)){
176 try_size *= 2;
177 }
178 GC_set_heap_size(try_size);
179 GC_collect();
180 GC_set_heap_size(heapActive->size);
181 }
182 }
183
184 void *Nit_gc_malloc( size_t size ) {
185 char *result;
186
187 GC_detect_memory_needs(size);
188
189 result = allocationPointer;
190 heapActiveUsedSize += size;
191 allocationPointer += size;
192
193 return result;
194 }
195
196 void GC_add_static_object(val_t * pointer){
197 GC_List_Push(&staticObjects, pointer);
198 }
199