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