This update adds precise garbage collection to the compiler and the runtime.
[IRC.git] / Robust / src / Runtime / checkpoint.c
1 #include "checkpoint.h"
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include <string.h>
5
6 #define MALLOCSIZE 20*1024
7
8 struct malloclist {
9   struct malloclist *next;
10   int size;
11   char space[];
12 };
13
14 struct malloclist * top=NULL;
15 int offset=0;
16
17 void * cpmalloc(int size) {
18   int endoffset=offset+size;
19   if (top==NULL||endoffset>top->size) {
20     int basesize=MALLOCSIZE;
21     struct malloclist *tmp;
22     if (size>basesize)
23       basesize=size;
24     tmp=RUNMALLOC(sizeof(struct malloclist)+basesize);
25     tmp->next=top;
26     top=tmp;
27     top->size=basesize;
28     offset=0;
29   }
30   int tmpoffset=offset;
31   offset+=size;
32   return &top->space[tmpoffset];
33 }
34
35 void freemalloc() {
36   while(top!=NULL) {
37     struct malloclist *next=top->next;
38     RUNFREE(top);
39     top=next;
40   }
41 }
42
43
44 void ** makecheckpoint(int numparams, void ** srcpointer, struct RuntimeHash * forward, struct RuntimeHash * reverse) {
45 #ifdef PRECISE_GC
46   void **newarray=cpmalloc(sizeof(void *)*numparams);
47 #else
48   void **newarray=RUNMALLOC(sizeof(void *)*numparams);
49 #endif
50   struct RuntimeHash *todo=allocateRuntimeHash(100);
51   int i;
52   for(i=0;i<numparams;i++) {
53     void * objptr=srcpointer[i];
54     if (RuntimeHashcontainskey(forward, (int) objptr))
55       RuntimeHashget(forward,(int) objptr,(int *) &newarray[i]);
56     else {
57       void * copy=createcopy(objptr);
58       RuntimeHashadd(forward, (int) objptr, (int)copy);
59       RuntimeHashadd(reverse, (int) copy, (int) objptr);
60       RuntimeHashadd(todo, (int) objptr, (int) objptr);
61       newarray[i]=copy;
62     }
63   }
64   while(RuntimeHashcountset(todo)!=0) {
65     void * ptr=(void *) RuntimeHashfirstkey(todo);
66     int type=((int *)ptr)[0];
67     RuntimeHashremove(todo, (int) ptr, (int) ptr);
68     {
69       void *cpy;
70       RuntimeHashget(forward, (int) ptr, (int *) &cpy);
71       int * pointer=pointerarray[type];
72       if (pointer==0) {
73         /* Array of primitives */
74         /* Do nothing */
75       } else if (((int)pointer)==1) {
76         /* Array of pointers */
77         struct ArrayObject *ao=(struct ArrayObject *) ptr;
78         struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
79         int length=ao->___length___;
80         int i;
81         for(i=0;i<length;i++) {
82           void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
83           if (objptr==NULL) {
84             ((void **)(((char *)& ao->___length___)+sizeof(int)))[i]=NULL;
85           } else if (RuntimeHashcontainskey(forward, (int) objptr))
86             RuntimeHashget(forward,(int) objptr,(int *) &((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]);
87           else {
88             void * copy=createcopy(objptr);
89             RuntimeHashadd(forward, (int) objptr, (int)copy);
90             RuntimeHashadd(reverse, (int) copy, (int) objptr);
91             RuntimeHashadd(todo, (int) objptr, (int) objptr);
92             ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
93           }
94         }
95       } else {
96         int size=pointer[0];
97         int i;
98         for(i=1;i<=size;i++) {
99           int offset=pointer[i];
100           void * objptr=*((void **)(((int)ptr)+offset));
101           if (objptr==NULL) {
102             *((void **) (((int)cpy)+offset))=NULL;
103           } else if (RuntimeHashcontainskey(forward, (int) objptr))
104             RuntimeHashget(forward, (int) objptr, (int *) &(((char *)cpy)[offset]));
105           else {
106             void * copy=createcopy(objptr);
107             RuntimeHashadd(forward, (int) objptr, (int) copy);
108             RuntimeHashadd(reverse, (int) copy, (int) objptr);
109             RuntimeHashadd(todo, (int) objptr, (int) objptr);
110             *((void **) (((int)cpy)+offset))=copy;
111           }
112         }
113       }
114     }
115   }
116   return newarray;
117 }
118
119 void * createcopy(void * orig) {
120   if (orig==0)
121     return 0;
122   else {
123     int type=((int *)orig)[0];
124     if (type<NUMCLASSES) {
125       /* We have a normal object */
126       int size=classsize[type];
127 #ifdef PRECISE_GC
128       void *newobj=cpmalloc(size);
129 #else
130       void *newobj=RUNMALLOC(size);
131 #endif
132       memcpy(newobj, orig, size);
133       return newobj;
134     } else {
135       /* We have an array */
136       struct ArrayObject *ao=(struct ArrayObject *)orig;
137       int elementsize=classsize[type];
138       int length=ao->___length___;
139       int size=sizeof(struct ArrayObject)+length*elementsize;
140 #ifdef PRECISE_GC
141       void *newobj=cpmalloc(size);
142 #else
143       void *newobj=RUNMALLOC(size);
144 #endif
145       memcpy(newobj, orig, size);
146       return newobj;
147     }
148   }
149 }
150
151 void restorecheckpoint(int numparams, void ** original, void ** checkpoint, struct RuntimeHash *forward, struct RuntimeHash * reverse) {
152   struct RuntimeHash *todo=allocateRuntimeHash(100);
153   int i;
154
155   for(i=0;i<numparams;i++) {
156     RuntimeHashadd(todo, (int) checkpoint[i], (int) checkpoint[i]);
157   }
158
159   while(RuntimeHashcountset(todo)!=0) {
160     void * ptr=(void *) RuntimeHashfirstkey(todo);
161     int type=((int *)ptr)[0];
162     RuntimeHashremove(todo, (int) ptr, (int) ptr);
163     {
164       void *cpy;
165       int *pointer;
166       int size;
167       RuntimeHashget(reverse, (int) ptr, (int *) &cpy);
168       pointer=pointerarray[type];
169       size=classsize[type];
170
171       if (pointer==0) {
172         /* Array of primitives */
173         struct ArrayObject *ao=(struct ArrayObject *) ptr;
174         int length=ao->___length___;
175         int cpysize=sizeof(struct ArrayObject)+length*size;
176         memcpy(cpy, ptr, cpysize);
177
178       } else if ((int)pointer==1) {
179         /* Array of pointers */
180         struct ArrayObject *ao=(struct ArrayObject *) ptr;
181         struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
182         int length=ao->___length___;
183         int i;
184         int cpysize=sizeof(struct ArrayObject)+length*size;
185         memcpy(ao_cpy, ao, cpysize);
186
187         for(i=0;i<length;i++) {
188           void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
189           if (objptr==NULL)
190             ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=NULL;
191           else
192             RuntimeHashget(reverse, (int) objptr, (int *) &((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]);
193         }
194       } else {
195         int numptr=pointer[0];
196         int i;
197         void *flagptr;
198         if (hasflags[type]) {
199           flagptr=(void *) (((int *)cpy)[2]);
200         }
201         memcpy(cpy, ptr, size);
202         for(i=1;i<=numptr;i++) {
203           int offset=pointer[i];
204           void * objptr=*((void **)(((int)ptr)+offset));
205           if (objptr==NULL)
206             *((void **) (((int)cpy)+offset))=NULL;
207           else
208             RuntimeHashget(reverse, (int) objptr, (int *) &(((char *)cpy)[offset]));
209         }
210         if (hasflags[type]) {
211           (((void **)cpy)[2])=flagptr;
212           flagorand(cpy, 1, 0xFFFFFFFF);
213         }
214       }
215     }
216   }
217 }