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) {
115 struct stack_frame_t
*frame
= stack_frame_head
;
116 GC_static_object
*staticObject
= staticObjects
.top
;
120 evacuationPointer
= heapInactive
->heapPointer
;
121 scavengingPointer
= heapInactive
->heapPointer
;
122 for (i
= 0; i
< staticObjects
.size
; i
++) {
123 object
= *(val_t
*)(staticObject
->pointer
);
124 if (!ISNULL(object
) && ISOBJ(object
)) {
125 *(staticObject
->pointer
) = GC_evacuation((obj_t
)object
);
127 staticObject
= staticObject
->next
;
129 while (frame
!= NULL
) {
130 for (j
= 0; j
< frame
->REG_size
; j
++) {
131 object
= frame
->REG
[j
];
132 if (!ISNULL(object
) && ISOBJ(object
)) {
133 frame
->REG
[j
] = GC_evacuation((obj_t
)object
);
136 if (frame
== frame
->prev
) break;
139 while (evacuationPointer
!= scavengingPointer
) {
143 /* pour tests seulement, pas necessaire */
144 memset(heapActive
->heapPointer
, 0, heapActive
->size
);
145 allocationPointer
= evacuationPointer
;
147 /* inverse le tas actif et le tas inactif */
148 tempPointer
= heapActive
;
149 heapActive
= heapInactive
;
150 heapInactive
= tempPointer
;
152 heapActiveUsedSize
= allocationPointer
- heapActive
->heapPointer
;
155 void GC_set_heap_size(size_t newHeapSize
) {
156 free(heapInactive
->heapPointer
);
157 heapInactive
->heapPointer
= malloc(newHeapSize
);
158 if (heapInactive
->heapPointer
== NULL
) {
161 heapInactive
->size
= newHeapSize
;
162 memset(heapInactive
->heapPointer
, 0, newHeapSize
);
165 void GC_detect_memory_needs(size_t size
) {
166 if (size
> (heapActive
->size
- heapActiveUsedSize
)) {
168 if (heapActive
->size
- heapActiveUsedSize
> heapActive
->size
/ 2 && heapActive
->size
* 3 / 4 > HEAP_ACTIVE_SIZE_MIN
) {
169 GC_set_heap_size(heapActive
->size
* 3 / 4);
171 GC_set_heap_size(heapActive
->size
);
174 if (size
> (heapActive
->size
- heapActiveUsedSize
)) {
175 int try_size
= heapInactive
->size
* 2;
176 while (size
> (try_size
- heapActiveUsedSize
)) {
179 GC_set_heap_size(try_size
);
181 GC_set_heap_size(heapActive
->size
);
185 void *Nit_gc_malloc(size_t size
) {
188 GC_detect_memory_needs(size
);
190 result
= allocationPointer
;
191 heapActiveUsedSize
+= size
;
192 allocationPointer
+= size
;
197 void GC_add_static_object(val_t
*pointer
) {
198 GC_List_Push(&staticObjects
, pointer
);