allocate memory in large blocks
[IRC.git] / Robust / src / Runtime / garbage.c
1 #include "garbage.h"
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include "Queue.h"
5 #include "SimpleHash.h"
6 #include "chash.h"
7 #include "GenericHashtable.h"
8 #include <string.h>
9 #if defined(THREADS) || defined(DSTM) || defined(STM)
10 #include "thread.h"
11 #endif
12
13 #ifdef DMALLOC
14 #include "dmalloc.h"
15 #endif
16 #ifdef DSTM
17 #include "dstm.h"
18 #endif
19 #ifdef STM
20 #include "tm.h"
21 #endif
22
23 #define NUMPTRS 100
24
25 #define INITIALHEAPSIZE 128*1024*1024
26 #define GCPOINT(x) ((int)((x)*0.95))
27 /* This define takes in how full the heap is initially and returns a new heap size to use */
28 #define HEAPSIZE(x,y) ((int)(x+y))*2
29
30 #ifdef TASK
31 extern struct genhashtable * activetasks;
32 #ifndef MULTICORE
33 extern struct parameterwrapper * objectqueues[NUMCLASSES];
34 #endif
35 extern struct genhashtable * failedtasks;
36 extern struct taskparamdescriptor *currtpd;
37 extern struct ctable *forward;
38 extern struct ctable *reverse;
39 extern struct RuntimeHash *fdtoobject;
40 #endif
41
42 #if defined(THREADS) || defined(DSTM) || defined(STM)
43 int needtocollect=0;
44 struct listitem * list=NULL;
45 int listcount=0;
46 #endif
47
48 //Need to check if pointers are transaction pointers
49 //this also catches the special flag value of 1 for local copies
50 #ifdef DSTM
51 #define ENQUEUE(orig, dst) \
52   if ((!(((unsigned int)orig)&0x1))) { \
53     if (orig>=curr_heapbase&&orig<curr_heaptop) { \
54       void *copy; \
55       if (gc_createcopy(orig,&copy)) \
56         enqueue(orig);\
57       dst=copy; \
58     } \
59   }
60 #elif defined(STM)
61 #define ENQUEUE(orig, dst) \
62   if (orig>=curr_heapbase&&orig<curr_heaptop) { \
63     void *copy; \
64     if (gc_createcopy(orig,&copy)) \
65       enqueue(orig);\
66     dst=copy; \
67   }
68 #define SENQUEUE(orig, dst) \
69   { \
70     void *copy; \
71     if (gc_createcopy(orig,&copy)) \
72       enqueue(orig);\
73     dst=copy; \
74   }
75 #elif defined(FASTCHECK)
76 #define ENQUEUE(orig, dst) \
77   if (((unsigned int)orig)!=1) { \
78     void *copy; \
79     if (gc_createcopy(orig,&copy)) \
80       enqueue(orig);\
81     dst=copy; }
82 #else
83 #define ENQUEUE(orig, dst) \
84   void *copy; \
85   if (gc_createcopy(orig,&copy)) \
86     enqueue(orig);\
87   dst=copy
88 #endif
89
90 struct pointerblock {
91   void * ptrs[NUMPTRS];
92   struct pointerblock *next;
93 };
94
95 void * curr_heapbase=0;
96 void * curr_heapptr=0;
97 void * curr_heapgcpoint=0;
98 void * curr_heaptop=0;
99
100 void * to_heapbase=0;
101 void * to_heapptr=0;
102 void * to_heaptop=0;
103 long lastgcsize=0;
104
105 struct pointerblock *head=NULL;
106 int headindex=0;
107 struct pointerblock *tail=NULL;
108 int tailindex=0;
109 struct pointerblock *spare=NULL;
110
111 void enqueue(void *ptr) {
112   if (headindex==NUMPTRS) {
113     struct pointerblock * tmp;
114     if (spare!=NULL) {
115       tmp=spare;
116       spare=NULL;
117     } else
118       tmp=malloc(sizeof(struct pointerblock));
119     head->next=tmp;
120     head=tmp;
121     headindex=0;
122   }
123   head->ptrs[headindex++]=ptr;
124 }
125
126 void * dequeue() {
127   if (tailindex==NUMPTRS) {
128     struct pointerblock *tmp=tail;
129     tail=tail->next;
130     tailindex=0;
131     if (spare!=NULL)
132       free(tmp);
133     else
134       spare=tmp;
135   }
136   return tail->ptrs[tailindex++];
137 }
138
139 #ifdef STM
140 void fixobjlist(struct objlist * ptr) {
141   while(ptr!=NULL) {
142     int i;
143     for(i=0;i<ptr->offset;i++) {
144       SENQUEUE(ptr->objs[i], ptr->objs[i]);
145     }
146     ptr=ptr->next;
147   }
148 }
149
150 void fixtable(chashlistnode_t ** tc_table, unsigned int tc_size) {
151   unsigned int mask=(tc_size<<3)-1;
152   chashlistnode_t *node=calloc(tc_size, sizeof(chashlistnode_t));
153   chashlistnode_t *ptr=*tc_table;
154   chashlistnode_t *curr;
155   unsigned int i;
156   unsigned int index;
157   int isfirst;
158   for(i=0;i<tc_size;i++) {
159     curr=&ptr[i];
160     isfirst=1;
161     do {                      //Inner loop to go through linked lists
162       void * key;
163       chashlistnode_t *tmp,*next;
164       
165       if ((key=(void *)curr->key) == 0) {             //Exit inner loop if there the first element is 0
166         break;                  //key = val =0 for element if not present within the hash table
167       }
168       SENQUEUE(key, key);
169       if (curr->val>=curr_heapbase&&curr->val<curr_heaptop) {
170         SENQUEUE(curr->val, curr->val);
171       } else {
172         //rewrite transaction cache entry
173         void *vptr=curr->val;
174         int type=((int *)vptr)[0];
175         unsigned int *pointer=pointerarray[type];
176         if (pointer==0) {
177           //array of primitives - do nothing
178           struct ArrayObject *ao=(struct ArrayObject *) vptr;
179           SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
180         } else if (((int)pointer)==1) {
181           //array of pointers
182           struct ArrayObject *ao=(struct ArrayObject *) vptr;
183           int length=ao->___length___;
184           int i;
185           SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
186           for(i=0; i<length; i++) {
187             void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
188             SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]);
189           }
190         } else {
191           int size=pointer[0];
192           int i;
193           for(i=1; i<=size; i++) {
194             unsigned int offset=pointer[i];
195             void * objptr=*((void **)(((int)vptr)+offset));
196             SENQUEUE(objptr, *((void **)(((int)vptr)+offset)));
197           }
198         }
199       }
200
201       next = curr->next;
202       index = (((unsigned int)key) & mask) >>3;
203
204       curr->key=(unsigned int)key;
205       tmp=&node[index];
206       // Insert into the new table
207       if(tmp->key == 0) {
208         tmp->key = curr->key;
209         tmp->val = curr->val;
210         if (!isfirst) {
211           free(curr);
212         }
213       } else if (isfirst) {
214         chashlistnode_t *newnode= calloc(1, sizeof(chashlistnode_t));
215         newnode->key = curr->key;
216         newnode->val = curr->val;
217         newnode->next = tmp->next;
218         tmp->next=newnode;
219       } else {
220         curr->next=tmp->next;
221         tmp->next=curr;
222       }
223       isfirst = 0;
224       curr = next;
225     } while(curr!=NULL);
226   }
227   free(ptr);
228   (*tc_table)=node;
229 }
230 #endif
231
232 int moreItems() {
233   if ((head==tail)&&(tailindex==headindex))
234     return 0;
235   return 1;
236 }
237
238 #ifdef TASK
239 struct pointerblock *taghead=NULL;
240 int tagindex=0;
241
242 void enqueuetag(struct ___TagDescriptor___ *ptr) {
243   if (tagindex==NUMPTRS) {
244     struct pointerblock * tmp=malloc(sizeof(struct pointerblock));
245     tmp->next=taghead;
246     taghead=tmp;
247     tagindex=0;
248   }
249   taghead->ptrs[tagindex++]=ptr;
250 }
251 #endif
252
253 #ifdef STM
254 __thread char * memorybase=NULL;
255 __thread char * memorytop=NULL;
256 #endif
257
258
259 void collect(struct garbagelist * stackptr) {
260 #if defined(THREADS)||defined(DSTM)||defined(STM)
261   needtocollect=1;
262   pthread_mutex_lock(&gclistlock);
263   while(1) {
264     if ((listcount+1)==threadcount) {
265       break; /* Have all other threads stopped */
266     }
267     pthread_cond_wait(&gccond, &gclistlock);
268   }
269 #endif
270
271   if (head==NULL) {
272     headindex=0;
273     tailindex=0;
274     head=tail=malloc(sizeof(struct pointerblock));
275   }
276
277 #ifdef TASK
278   if (taghead==NULL) {
279     tagindex=0;
280     taghead=malloc(sizeof(struct pointerblock));
281     taghead->next=NULL;
282   }
283 #endif
284
285 #ifdef STM
286   if (c_table!=NULL) {
287       fixtable(&c_table, c_size);
288       fixobjlist(newobjs);
289       memorybase=NULL;
290   }
291 #endif
292
293   /* Check current stack */
294 #if defined(THREADS)||defined(DSTM)||defined(STM)
295   {
296     struct listitem *listptr=list;
297     while(1) {
298 #endif
299
300   while(stackptr!=NULL) {
301     int i;
302     for(i=0; i<stackptr->size; i++) {
303       void * orig=stackptr->array[i];
304       ENQUEUE(orig, stackptr->array[i]);
305     }
306     stackptr=stackptr->next;
307   }
308 #if defined(THREADS)||defined(DSTM)||defined(STM)
309   /* Go to next thread */
310   if (listptr!=NULL) {
311 #ifdef THREADS
312     void * orig=listptr->locklist;
313     ENQUEUE(orig, listptr->locklist);
314 #endif
315 #ifdef STM
316     if ((*listptr->tc_table)!=NULL) {
317       fixtable(listptr->tc_table, listptr->tc_size);
318       fixobjlist(listptr->objlist);
319       (*listptr->base)=NULL;
320     }
321 #endif
322     stackptr=listptr->stackptr;
323     listptr=listptr->next;
324   } else
325     break;
326 }
327 }
328 #endif
329
330 #ifdef FASTCHECK
331   ENQUEUE(___fcrevert___, ___fcrevert___);
332 #endif
333
334 #ifdef TASK
335   {
336     /* Update objectsets */
337     int i;
338     for(i=0; i<NUMCLASSES; i++) {
339 #if !defined(MULTICORE)
340       struct parameterwrapper * p=objectqueues[i];
341       while(p!=NULL) {
342         struct ObjectHash * set=p->objectset;
343         struct ObjectNode * ptr=set->listhead;
344         while(ptr!=NULL) {
345           void *orig=(void *)ptr->key;
346           ENQUEUE(orig, *((void **)(&ptr->key)));
347           ptr=ptr->lnext;
348         }
349         ObjectHashrehash(set); /* Rehash the table */
350         p=p->next;
351       }
352 #endif
353     }
354   }
355
356 #ifndef FASTCHECK
357   if (forward!=NULL) {
358     struct cnode * ptr=forward->listhead;
359     while(ptr!=NULL) {
360       void * orig=(void *)ptr->key;
361       ENQUEUE(orig, *((void **)(&ptr->key)));
362       ptr=ptr->lnext;
363     }
364     crehash(forward); /* Rehash the table */
365   }
366
367   if (reverse!=NULL) {
368     struct cnode * ptr=reverse->listhead;
369     while(ptr!=NULL) {
370       void *orig=(void *)ptr->val;
371       ENQUEUE(orig, *((void**)(&ptr->val)));
372       ptr=ptr->lnext;
373     }
374   }
375 #endif
376
377   {
378     struct RuntimeNode * ptr=fdtoobject->listhead;
379     while(ptr!=NULL) {
380       void *orig=(void *)ptr->data;
381       ENQUEUE(orig, *((void**)(&ptr->data)));
382       ptr=ptr->lnext;
383     }
384   }
385
386   {
387     /* Update current task descriptor */
388     int i;
389     for(i=0; i<currtpd->numParameters; i++) {
390       void *orig=currtpd->parameterArray[i];
391       ENQUEUE(orig, currtpd->parameterArray[i]);
392     }
393
394   }
395
396   /* Update active tasks */
397   {
398     struct genpointerlist * ptr=activetasks->list;
399     while(ptr!=NULL) {
400       struct taskparamdescriptor *tpd=ptr->src;
401       int i;
402       for(i=0; i<tpd->numParameters; i++) {
403         void * orig=tpd->parameterArray[i];
404         ENQUEUE(orig, tpd->parameterArray[i]);
405       }
406       ptr=ptr->inext;
407     }
408     genrehash(activetasks);
409   }
410
411   /* Update failed tasks */
412   {
413     struct genpointerlist * ptr=failedtasks->list;
414     while(ptr!=NULL) {
415       struct taskparamdescriptor *tpd=ptr->src;
416       int i;
417       for(i=0; i<tpd->numParameters; i++) {
418         void * orig=tpd->parameterArray[i];
419         ENQUEUE(orig, tpd->parameterArray[i]);
420       }
421       ptr=ptr->inext;
422     }
423     genrehash(failedtasks);
424   }
425 #endif
426
427   while(moreItems()) {
428     void * ptr=dequeue();
429     void *cpy=((void **)ptr)[1];
430     int type=((int *)cpy)[0];
431     unsigned int * pointer;
432 #ifdef TASK
433     if(type==TAGTYPE) {
434       /* Enqueue Tag */
435       /* Nothing is inside */
436       enqueuetag(ptr);
437       continue;
438     }
439 #endif
440     pointer=pointerarray[type];
441     if (pointer==0) {
442       /* Array of primitives */
443       /* Do nothing */
444 #if defined(DSTM)||defined(FASTCHECK)
445       struct ArrayObject *ao=(struct ArrayObject *) ptr;
446       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
447       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
448       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
449 #endif
450 #if defined(STM)
451       struct ArrayObject *ao=(struct ArrayObject *) ptr;
452       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
453       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
454 #endif
455     } else if (((int)pointer)==1) {
456       /* Array of pointers */
457       struct ArrayObject *ao=(struct ArrayObject *) ptr;
458       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
459 #if (defined(DSTM)||defined(FASTCHECK))
460       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
461       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
462 #endif
463 #if defined(STM)
464       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
465 #endif
466       int length=ao->___length___;
467       int i;
468       for(i=0; i<length; i++) {
469         void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
470         ENQUEUE(objptr, ((void **)(((char *)&ao_cpy->___length___)+sizeof(int)))[i]);
471       }
472     } else {
473       int size=pointer[0];
474       int i;
475       for(i=1; i<=size; i++) {
476         unsigned int offset=pointer[i];
477         void * objptr=*((void **)(((int)ptr)+offset));
478         ENQUEUE(objptr, *((void **)(((int)cpy)+offset)));
479       }
480     }
481   }
482 #ifdef TASK
483   fixtags();
484 #endif
485
486 #if defined(THREADS)||defined(DSTM)||defined(STM)
487   needtocollect=0;
488   pthread_mutex_unlock(&gclistlock);
489 #endif
490 }
491
492 #ifdef TASK
493 /* Fix up the references from tags.  This can't be done earlier,
494    because we don't want tags to keep objects alive */
495 void fixtags() {
496   while(taghead!=NULL) {
497     int i;
498     struct pointerblock *tmp=taghead->next;
499     for(i=0; i<tagindex; i++) {
500       struct ___TagDescriptor___ *tagd=taghead->ptrs[i];
501       struct ___Object___ *obj=tagd->flagptr;
502       struct ___TagDescriptor___ *copy=((struct ___TagDescriptor___**)tagd)[1];
503       if (obj==NULL) {
504         /* Zero object case */
505       } else if (obj->type==-1) {
506         /* Single object case */
507         copy->flagptr=((struct ___Object___**)obj)[1];
508       } else if (obj->type==OBJECTARRAYTYPE) {
509         /* Array case */
510         struct ArrayObject *ao=(struct ArrayObject *) obj;
511         int livecount=0;
512         int j;
513         int k=0;
514         struct ArrayObject *aonew;
515
516         /* Count live objects */
517         for(j=0; j<ao->___cachedCode___; j++) {
518           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
519           if (tobj->type==-1)
520             livecount++;
521         }
522
523         livecount=((livecount-1)/OBJECTARRAYINTERVAL+1)*OBJECTARRAYINTERVAL;
524         aonew=(struct ArrayObject *) tomalloc(sizeof(struct ArrayObject)+sizeof(struct ___Object___*)*livecount);
525         memcpy(aonew, ao, sizeof(struct ArrayObject));
526         aonew->type=OBJECTARRAYTYPE;
527         aonew->___length___=livecount;
528         copy->flagptr=aonew;
529         for(j=0; j<ao->___cachedCode___; j++) {
530           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
531           if (tobj->type==-1) {
532             struct ___Object___ * tobjcpy=((struct ___Object___**)tobj)[1];
533             ARRAYSET(aonew, struct ___Object___*, k++,tobjcpy);
534           }
535         }
536         aonew->___cachedCode___=k;
537         for(; k<livecount; k++) {
538           ARRAYSET(aonew, struct ___Object___*, k, NULL);
539         }
540       } else {
541         /* No object live anymore */
542         copy->flagptr=NULL;
543       }
544     }
545     free(taghead);
546     taghead=tmp;
547     tagindex=NUMPTRS;
548   }
549 }
550 #endif
551
552 void * tomalloc(int size) {
553   void * ptr=to_heapptr;
554   if ((size&7)!=0)
555     size+=(8-(size%8));
556   to_heapptr+=size;
557   return ptr;
558 }
559
560 #if defined(THREADS)||defined(DSTM)||defined(STM)
561 void checkcollect(void * ptr) {
562   struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
563   pthread_mutex_lock(&gclock); // Wait for GC
564   restartaftergc(tmp);
565   pthread_mutex_unlock(&gclock);
566 }
567
568 #ifdef DSTM
569 void checkcollect2(void * ptr) {
570   int ptrarray[]={1, (int)ptr, (int) revertlist};
571   struct listitem * tmp=stopforgc((struct garbagelist *)ptrarray);
572   pthread_mutex_lock(&gclock); // Wait for GC
573   restartaftergc(tmp);
574   pthread_mutex_unlock(&gclock);
575   revertlist=(struct ___Object___*)ptrarray[2];
576 }
577 #endif
578
579 struct listitem * stopforgc(struct garbagelist * ptr) {
580   struct listitem * litem=malloc(sizeof(struct listitem));
581   litem->stackptr=ptr;
582 #ifdef THREADS
583   litem->locklist=pthread_getspecific(threadlocks);
584 #endif
585 #ifdef STM
586   litem->tc_size=c_size;
587   litem->tc_table=&c_table;
588   litem->objlist=newobjs;
589   litem->base=&memorybase;
590 #endif
591   litem->prev=NULL;
592   pthread_mutex_lock(&gclistlock);
593   litem->next=list;
594   if(list!=NULL)
595     list->prev=litem;
596   list=litem;
597   listcount++;
598   pthread_cond_signal(&gccond);
599   pthread_mutex_unlock(&gclistlock);
600   return litem;
601 }
602
603 void restartaftergc(struct listitem * litem) {
604   pthread_mutex_lock(&gclistlock);
605 #ifdef THREADS
606   pthread_setspecific(threadlocks, litem->locklist);
607 #endif
608   if (litem->prev==NULL) {
609     list=litem->next;
610   } else {
611     litem->prev->next=litem->next;
612   }
613   if (litem->next!=NULL) {
614     litem->next->prev=litem->prev;
615   }
616   listcount--;
617   pthread_mutex_unlock(&gclistlock);
618   free(litem);
619 }
620 #endif
621
622 #ifdef STM
623 #define MEMORYBLOCK 65536
624 void * helper(struct garbagelist *, int);
625 void * mygcmalloc(struct garbagelist * stackptr, int size) {
626   if ((size&7)!=0)
627     size=(size&~7)+8;
628   if (memorybase==NULL||(memorybase+size)>memorytop) {
629     int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK;
630     memorybase=helper(stackptr, toallocate);
631     memorytop=memorybase+toallocate;
632   }
633   char *retvalue=memorybase;
634   memorybase+=size;
635   return retvalue;
636 }
637
638 void * helper(struct garbagelist * stackptr, int size) {
639 #else
640 void * mygcmalloc(struct garbagelist * stackptr, int size) {
641 #endif
642   void *ptr;
643 #if defined(THREADS)||defined(DSTM)||defined(STM)
644   if (pthread_mutex_trylock(&gclock)!=0) {
645     struct listitem *tmp=stopforgc(stackptr);
646     pthread_mutex_lock(&gclock);
647     restartaftergc(tmp);
648   }
649 #endif
650   ptr=curr_heapptr;
651   if ((size&7)!=0)
652     size=(size&~7)+8;
653   curr_heapptr+=size;
654   if (curr_heapptr>curr_heapgcpoint) {
655     if (curr_heapbase==0) {
656       /* Need to allocate base heap */
657       curr_heapbase=malloc(INITIALHEAPSIZE);
658       bzero(curr_heapbase, INITIALHEAPSIZE);
659       curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
660       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
661       curr_heapptr=curr_heapbase+size;
662
663       to_heapbase=malloc(INITIALHEAPSIZE);
664       to_heaptop=to_heapbase+INITIALHEAPSIZE;
665       to_heapptr=to_heapbase;
666       ptr=curr_heapbase;
667 #if defined(THREADS)||defined(DSTM)||defined(STM)
668       pthread_mutex_unlock(&gclock);
669 #endif
670       return ptr;
671     }
672
673     /* Grow the to heap if necessary */
674     {
675       int curr_heapsize=curr_heaptop-curr_heapbase;
676       int to_heapsize=to_heaptop-to_heapbase;
677       int last_heapsize=0;
678       if (lastgcsize>0) {
679         last_heapsize=HEAPSIZE(lastgcsize, size);
680         if ((last_heapsize&7)!=0)
681           last_heapsize+=(8-(last_heapsize%8));
682       }
683       if (curr_heapsize>last_heapsize)
684         last_heapsize=curr_heapsize;
685       if (last_heapsize>to_heapsize) {
686         free(to_heapbase);
687         to_heapbase=malloc(last_heapsize);
688         if (to_heapbase==NULL) {
689           printf("Error Allocating enough memory\n");
690           exit(-1);
691         }
692         to_heaptop=to_heapbase+last_heapsize;
693         to_heapptr=to_heapbase;
694       }
695     }
696
697     /* Do our collection */
698     collect(stackptr);
699
700     /* Update stat on previous gc size */
701     lastgcsize=(to_heapptr-to_heapbase)+size;
702
703 #ifdef GARBAGESTATS
704     printf("Garbage collected: Old bytes: %u\n", curr_heapptr-curr_heapbase);
705     printf("New space: %u\n", to_heapptr-to_heapbase);
706     printf("Total space: %u\n", to_heaptop-to_heapbase);
707 #endif
708     /* Flip to/curr heaps */
709     {
710       void * tmp=to_heapbase;
711       to_heapbase=curr_heapbase;
712       curr_heapbase=tmp;
713
714       tmp=to_heaptop;
715       to_heaptop=curr_heaptop;
716       curr_heaptop=tmp;
717
718       tmp=to_heapptr;
719       curr_heapptr=to_heapptr+size;
720       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
721       to_heapptr=to_heapbase;
722
723       /* Not enough room :(, redo gc */
724       if (curr_heapptr>curr_heapgcpoint) {
725 #if defined(THREADS)||defined(DSTM)||defined(STM)
726         pthread_mutex_unlock(&gclock);
727 #endif
728         return mygcmalloc(stackptr, size);
729       }
730
731       bzero(tmp, curr_heaptop-tmp);
732 #if defined(THREADS)||defined(DSTM)||defined(STM)
733       pthread_mutex_unlock(&gclock);
734 #endif
735       return tmp;
736     }
737   } else {
738 #if defined(THREADS)||defined(DSTM)||defined(STM)
739     pthread_mutex_unlock(&gclock);
740 #endif
741     return ptr;
742   }
743 }
744
745
746 int gc_createcopy(void * orig, void ** copy_ptr) {
747   if (orig==0) {
748     *copy_ptr=NULL;
749     return 0;
750   } else {
751     int type=((int *)orig)[0];
752     if (type==-1) {
753       *copy_ptr=((void **)orig)[1];
754       return 0;
755     }
756     if (type<NUMCLASSES) {
757       /* We have a normal object */
758 #ifdef STM
759       int size=classsize[type]+sizeof(objheader_t);
760       void *newobj=tomalloc(size);
761       memcpy(newobj,((char *) orig)-sizeof(objheader_t), size);
762       newobj=((char *)newobj)+sizeof(objheader_t);
763 #else
764       int size=classsize[type];
765       void *newobj=tomalloc(size);
766       memcpy(newobj, orig, size);
767 #endif
768       ((int *)orig)[0]=-1;
769       ((void **)orig)[1]=newobj;
770       *copy_ptr=newobj;
771       return 1;
772     } else {
773       /* We have an array */
774       struct ArrayObject *ao=(struct ArrayObject *)orig;
775       int elementsize=classsize[type];
776       int length=ao->___length___;
777 #ifdef STM
778       int size=sizeof(struct ArrayObject)+length*elementsize+sizeof(objheader_t);
779       void *newobj=tomalloc(size);
780       memcpy(newobj, ((char*)orig)-sizeof(objheader_t), size);
781       newobj=((char *)newobj)+sizeof(objheader_t);
782 #else
783       int size=sizeof(struct ArrayObject)+length*elementsize;
784       void *newobj=tomalloc(size);
785       memcpy(newobj, orig, size);
786 #endif
787
788       ((int *)orig)[0]=-1;
789       ((void **)orig)[1]=newobj;
790       *copy_ptr=newobj;
791       return 1;
792     }
793   }
794 }