1 /* This file is part of NIT ( http://www.nitlanguage.org ).
3 * Copyright 2009 Julien Chevalier <chevjulien@gmail.com>
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
18 # define assert(x) while(0)
21 void Nit_gc_init(void) {
22 heapActive
= malloc(sizeof(heap
));
23 heapInactive
= malloc(sizeof(heap
));
25 heapActive
->heapPointer
= malloc(HEAP_ACTIVE_SIZE_MIN
);
26 heapInactive
->heapPointer
= malloc(HEAP_ACTIVE_SIZE_MIN
);
28 if (heapActive
->heapPointer
==NULL
) exit(1);
29 if (heapInactive
->heapPointer
==NULL
) exit(1);
31 heapActive
->size
= HEAP_ACTIVE_SIZE_MIN
;
32 heapInactive
->size
= HEAP_ACTIVE_SIZE_MIN
;
34 allocationPointer
= heapActive
->heapPointer
;
36 evacuationPointer
= heapInactive
->heapPointer
;
37 scavengingPointer
= evacuationPointer
;
39 GC_List_Init(&staticObjects
);
42 val_t
GC_evacuation(obj_t object
) {
46 Nit_NativeArray array
;
49 assert(ISOBJ(object
) && !ISNULL(object
));
50 if (GET_MARKBIT(object
) != (bigint
)0) {
51 newAdress
= REMOVE_MARKBIT((bigint
)((object
)->vft
));
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
;
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
;
71 evacuationPointer
+= size
;
77 void GC_scavenging(void) {
78 obj_t object
= (obj_t
)scavengingPointer
;
81 obj_t referencedObject
;
83 Nit_NativeArray
*array
;
86 size
= sizeof(struct TBOX_struct
);
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
);
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
);
108 scavengingPointer
+= size
;
111 void GC_collect(void) {
116 struct trace_t
*frame
= tracehead
;
117 GC_static_object
*staticObject
= staticObjects
.top
;
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
);
128 staticObject
= staticObject
->next
;
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
);
138 if (frame
== frame
->prev
) break;
141 while (evacuationPointer
!= scavengingPointer
) {
145 /* pour tests seulement, pas necessaire */
146 memset(heapActive
->heapPointer
, 0, heapActive
->size
);
147 allocationPointer
= evacuationPointer
;
149 /* inverse le tas actif et le tas inactif */
150 tempPointer
= heapActive
;
151 heapActive
= heapInactive
;
152 heapInactive
= tempPointer
;
154 heapActiveUsedSize
= allocationPointer
- heapActive
->heapPointer
;
157 void GC_set_heap_size(size_t newHeapSize
) {
158 free(heapInactive
->heapPointer
);
159 heapInactive
->heapPointer
= malloc(newHeapSize
);
160 if (heapInactive
->heapPointer
== NULL
) {
163 heapInactive
->size
= newHeapSize
;
164 memset(heapInactive
->heapPointer
, 0, newHeapSize
);
167 void GC_detect_memory_needs(size_t size
) {
168 if (size
> (heapActive
->size
- heapActiveUsedSize
)) {
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);
173 GC_set_heap_size(heapActive
->size
);
176 if (size
> (heapActive
->size
- heapActiveUsedSize
)) {
177 int try_size
= heapInactive
->size
* 2;
178 while (size
> (try_size
- heapActiveUsedSize
)) {
181 GC_set_heap_size(try_size
);
183 GC_set_heap_size(heapActive
->size
);
187 void *Nit_gc_malloc(size_t size
) {
190 GC_detect_memory_needs(size
);
192 result
= allocationPointer
;
193 heapActiveUsedSize
+= size
;
194 allocationPointer
+= size
;
199 void GC_add_static_object(val_t
*pointer
) {
200 GC_List_Push(&staticObjects
, pointer
);