3 #include "multicoreruntime.h"
4 #include "runtime_arch.h"
5 #include "GenericHashtable.h"
7 // data structures for task invocation
8 struct genhashtable * activetasks;
9 struct taskparamdescriptor * currtpd;
11 // specific functions used inside critical sections
12 void enqueueObject_I(void * ptr,
13 struct parameterwrapper ** queues,
15 int enqueuetasks_I(struct parameterwrapper *parameter,
16 struct parameterwrapper *prevptr,
17 struct ___Object___ *ptr,
21 inline __attribute__((always_inline))
22 void initruntimedata() {
24 // initialize the arrays
25 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
26 // startup core to initialize corestatus[]
27 for(i = 0; i < NUMCORES; ++i) {
30 numreceiveobjs[i] = 0;
32 // initialize the profile data arrays
38 gcnumreceiveobjs[i] = 0;
40 gcrequiredmems[i] = 0;
42 gcfilledblocks[i] = 0;
44 } // for(i = 0; i < NUMCORES; ++i)
54 self_numreceiveobjs = 0;
56 for(i = 0; i < BAMBOO_MSG_BUF_LENGTH; ++i) {
61 msglength = BAMBOO_MSG_BUF_LENGTH;
62 for(i = 0; i < BAMBOO_OUT_BUF_LENGTH; ++i) {
72 bamboo_cur_msp = NULL;
78 gcphase = FINISHPHASE;
80 gcself_numsendobjs = 0;
81 gcself_numreceiveobjs = 0;
83 gcpointertbl = allocateRuntimeHash(20);
93 //gchead = gctail = gctail2 = NULL;
94 //gclobjhead = gclobjtail = gclobjtail2 = NULL;
95 //gcheadindex=gctailindex=gctailindex2 = 0;
96 //gclobjheadindex=gclobjtailindex=gclobjtailindex2 = 0;
100 // create the lock table, lockresult table and obj queue
103 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
104 /* Set allocation blocks*/
105 locktable.listhead=NULL;
106 locktable.listtail=NULL;
108 locktable.numelements = 0;
113 lockRedirectTbl = allocateRuntimeHash(20);
114 objRedirectLockTbl = allocateRuntimeHash(20);
119 objqueue.head = NULL;
120 objqueue.tail = NULL;
126 //isInterrupt = true;
129 taskInfoOverflow = false;
130 /*interruptInfoIndex = 0;
131 interruptInfoOverflow = false;*/
135 inline __attribute__((always_inline))
136 void disruntimedata() {
138 freeRuntimeHash(gcpointertbl);
140 freeRuntimeHash(lockRedirectTbl);
141 freeRuntimeHash(objRedirectLockTbl);
142 RUNFREE(locktable.bucket);
144 genfreehashtable(activetasks);
145 if(currtpd != NULL) {
146 RUNFREE(currtpd->parameterArray);
152 inline __attribute__((always_inline))
153 bool checkObjQueue() {
155 struct transObjInfo * objInfo = NULL;
159 #ifdef ACCURATEPROFILE
160 bool isChecking = false;
161 if(!isEmpty(&objqueue)) {
162 profileTaskStart("objqueue checking");
164 } // if(!isEmpty(&objqueue))
168 while(!isEmpty(&objqueue)) {
170 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
172 BAMBOO_DEBUGPRINT(0xf001);
175 //isInterrupt = false;
178 BAMBOO_DEBUGPRINT(0xeee1);
181 objInfo = (struct transObjInfo *)getItem(&objqueue);
182 obj = objInfo->objptr;
184 BAMBOO_DEBUGPRINT_REG((int)obj);
186 // grab lock and flush the obj
190 BAMBOO_WAITING_FOR_LOCK();
191 } // while(!lockflag)
194 BAMBOO_DEBUGPRINT_REG(grount);
209 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
210 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
211 classsize[((struct ___Object___ *)obj)->type]);
213 // enqueue the object
214 for(k = 0; k < objInfo->length; ++k) {
215 int taskindex = objInfo->queues[2 * k];
216 int paramindex = objInfo->queues[2 * k + 1];
217 struct parameterwrapper ** queues =
218 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
220 BAMBOO_DEBUGPRINT_REG(taskindex);
221 BAMBOO_DEBUGPRINT_REG(paramindex);
222 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
223 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
224 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
225 (long)obj, tmpptr->flag);
227 enqueueObject_I(obj, queues, 1);
229 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
231 } // for(k = 0; k < objInfo->length; ++k)
232 releasewritelock_I(obj);
233 RUNFREE(objInfo->queues);
237 // put it at the end of the queue if no update version in the queue
238 struct QueueItem * qitem = getHead(&objqueue);
239 struct QueueItem * prev = NULL;
240 while(qitem != NULL) {
241 struct transObjInfo * tmpinfo =
242 (struct transObjInfo *)(qitem->objectptr);
243 if(tmpinfo->objptr == obj) {
244 // the same object in the queue, which should be enqueued
245 // recently. Current one is outdate, do not re-enqueue it
246 RUNFREE(objInfo->queues);
251 } // if(tmpinfo->objptr == obj)
252 qitem = getNextQueueItem(prev);
253 } // while(qitem != NULL)
254 // try to execute active tasks already enqueued first
255 addNewItem_I(&objqueue, objInfo);
257 //isInterrupt = true;
260 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
262 BAMBOO_DEBUGPRINT(0xf000);
266 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
268 BAMBOO_DEBUGPRINT(0xf000);
270 } // while(!isEmpty(&objqueue))
273 #ifdef ACCURATEPROFILE
281 BAMBOO_DEBUGPRINT(0xee02);
286 inline __attribute__((always_inline))
287 void checkCoreStatus() {
288 bool allStall = false;
292 (waitconfirm && (numconfirm == 0))) {
294 BAMBOO_DEBUGPRINT(0xee04);
295 BAMBOO_DEBUGPRINT_REG(waitconfirm);
297 BAMBOO_START_CRITICAL_SECTION_STATUS();
299 BAMBOO_DEBUGPRINT(0xf001);
301 corestatus[BAMBOO_NUM_OF_CORE] = 0;
302 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
303 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
304 // check the status of all cores
307 BAMBOO_DEBUGPRINT_REG(NUMCORES);
309 for(i = 0; i < NUMCORES; ++i) {
311 BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
313 if(corestatus[i] != 0) {
317 } // for(i = 0; i < NUMCORES; ++i)
319 // check if the sum of send objs and receive obj are the same
320 // yes->check if the info is the latest; no->go on executing
322 for(i = 0; i < NUMCORES; ++i) {
323 sumsendobj += numsendobjs[i];
325 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
327 } // for(i = 0; i < NUMCORES; ++i)
328 for(i = 0; i < NUMCORES; ++i) {
329 sumsendobj -= numreceiveobjs[i];
331 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
333 } // for(i = 0; i < NUMCORES; ++i)
334 if(0 == sumsendobj) {
336 // the first time found all cores stall
337 // send out status confirm msg to all other cores
338 // reset the corestatus array too
340 BAMBOO_DEBUGPRINT(0xee05);
342 corestatus[BAMBOO_NUM_OF_CORE] = 1;
343 for(i = 1; i < NUMCORES; ++i) {
345 // send status confirm msg to core i
346 send_msg_1(i, STATUSCONFIRM);
347 } // for(i = 1; i < NUMCORES; ++i)
349 numconfirm = NUMCORES - 1;
351 // all the core status info are the latest
352 // terminate; for profiling mode, send request to all
353 // other cores to pour out profiling data
355 BAMBOO_DEBUGPRINT(0xee06);
359 totalexetime = BAMBOO_GET_EXE_TIME();
361 BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
362 BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
363 BAMBOO_DEBUGPRINT(0xbbbbbbbb);
365 // profile mode, send msgs to other cores to request pouring
366 // out progiling data
368 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
370 BAMBOO_DEBUGPRINT(0xf000);
372 for(i = 1; i < NUMCORES; ++i) {
373 // send profile request msg to core i
374 send_msg_2(i, PROFILEOUTPUT, totalexetime);
375 } // for(i = 1; i < NUMCORES; ++i)
376 // pour profiling data on startup core
379 BAMBOO_START_CRITICAL_SECTION_STATUS();
381 BAMBOO_DEBUGPRINT(0xf001);
383 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
384 // check the status of all cores
387 BAMBOO_DEBUGPRINT_REG(NUMCORES);
389 for(i = 0; i < NUMCORES; ++i) {
391 BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
393 if(profilestatus[i] != 0) {
397 } // for(i = 0; i < NUMCORES; ++i)
400 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
402 BAMBOO_DEBUGPRINT(0xf000);
412 terminate(); // All done.
413 } // if(!waitconfirm)
415 // still some objects on the fly on the network
416 // reset the waitconfirm and numconfirm
418 BAMBOO_DEBUGPRINT(0xee07);
422 } // if(0 == sumsendobj)
424 // not all cores are stall, keep on waiting
426 BAMBOO_DEBUGPRINT(0xee08);
431 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
433 BAMBOO_DEBUGPRINT(0xf000);
435 } // if((!waitconfirm) ||
438 // main function for each core
439 inline void run(void * arg) {
443 bool sendStall = false;
445 bool tocontinue = false;
447 corenum = BAMBOO_GET_NUM_OF_CORE();
449 BAMBOO_DEBUGPRINT(0xeeee);
450 BAMBOO_DEBUGPRINT_REG(corenum);
451 BAMBOO_DEBUGPRINT(STARTUPCORE);
454 // initialize runtime data structures
457 // other architecture related initialization
461 initializeexithandler();
463 // main process of the execution module
464 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
465 // non-executing cores, only processing communications
468 BAMBOO_DEBUGPRINT(0xee01);
469 BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
470 BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
471 profileTaskStart("msg handling");
475 //isInterrupt = false;
479 /* Create queue of active tasks */
481 genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
482 (int(*) (void *,void *)) &comparetpd);
484 /* Process task information */
487 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
488 /* Create startup object */
489 createstartupobject(argc, argv);
493 BAMBOO_DEBUGPRINT(0xee00);
498 // check if need to do GC
502 // check if there are new active tasks can be executed
509 while(receiveObject() != -1) {
514 BAMBOO_DEBUGPRINT(0xee01);
517 // check if there are some pending objects,
518 // if yes, enqueue them and executetasks again
519 tocontinue = checkObjQueue();
523 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
526 BAMBOO_DEBUGPRINT(0xee03);
534 BAMBOO_DEBUGPRINT(0xee09);
540 // wait for some time
543 BAMBOO_DEBUGPRINT(0xee0a);
549 // send StallMsg to startup core
551 BAMBOO_DEBUGPRINT(0xee0b);
554 send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE,
555 self_numsendobjs, self_numreceiveobjs);
567 BAMBOO_DEBUGPRINT(0xee0c);
570 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
573 } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
577 struct ___createstartupobject____I_locals {
580 struct ___StartupObject___ * ___startupobject___;
581 struct ArrayObject * ___stringarray___;
582 }; // struct ___createstartupobject____I_locals
584 void createstartupobject(int argc,
588 /* Allocate startup object */
590 struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
591 struct ___StartupObject___ *startupobject=
592 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
593 ___locals___.___startupobject___ = startupobject;
594 struct ArrayObject * stringarray=
595 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
596 ___locals___.___stringarray___ = stringarray;
598 struct ___StartupObject___ *startupobject=
599 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
600 struct ArrayObject * stringarray=
601 allocate_newarray(STRINGARRAYTYPE, argc-1);
603 /* Build array of strings */
604 startupobject->___parameters___=stringarray;
605 for(i=1; i<argc; i++) {
606 int length=strlen(argv[i]);
608 struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
610 struct ___String___ *newstring=NewString(argv[i],length);
612 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
616 startupobject->version = 0;
617 startupobject->lock = NULL;
619 /* Set initialized flag for startup object */
620 flagorandinit(startupobject,1,0xFFFFFFFF);
621 enqueueObject(startupobject, NULL, 0);
623 BAMBOO_CACHE_FLUSH_ALL();
627 int hashCodetpd(struct taskparamdescriptor *ftd) {
628 int hash=(int)ftd->task;
630 for(i=0; i<ftd->numParameters; i++) {
631 hash^=(int)ftd->parameterArray[i];
636 int comparetpd(struct taskparamdescriptor *ftd1,
637 struct taskparamdescriptor *ftd2) {
639 if (ftd1->task!=ftd2->task)
641 for(i=0; i<ftd1->numParameters; i++)
642 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
647 /* This function sets a tag. */
649 void tagset(void *ptr,
650 struct ___Object___ * obj,
651 struct ___TagDescriptor___ * tagd) {
653 void tagset(struct ___Object___ * obj,
654 struct ___TagDescriptor___ * tagd) {
656 struct ArrayObject * ao=NULL;
657 struct ___Object___ * tagptr=obj->___tags___;
659 obj->___tags___=(struct ___Object___ *)tagd;
661 /* Have to check if it is already set */
662 if (tagptr->type==TAGTYPE) {
663 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
668 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
669 struct ArrayObject * ao=
670 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
671 obj=(struct ___Object___ *)ptrarray[2];
672 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
673 td=(struct ___TagDescriptor___ *) obj->___tags___;
675 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
678 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
679 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
680 obj->___tags___=(struct ___Object___ *) ao;
681 ao->___cachedCode___=2;
685 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
686 for(i=0; i<ao->___cachedCode___; i++) {
687 struct ___TagDescriptor___ * td=
688 ARRAYGET(ao, struct ___TagDescriptor___*, i);
693 if (ao->___cachedCode___<ao->___length___) {
694 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
695 ao->___cachedCode___++;
698 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
699 struct ArrayObject * aonew=
700 allocate_newarray(&ptrarray,TAGARRAYTYPE,
701 TAGARRAYINTERVAL+ao->___length___);
702 obj=(struct ___Object___ *)ptrarray[2];
703 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
704 ao=(struct ArrayObject *)obj->___tags___;
706 struct ArrayObject * aonew=
707 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
710 aonew->___cachedCode___=ao->___length___+1;
711 for(i=0; i<ao->___length___; i++) {
712 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
713 ARRAYGET(ao, struct ___TagDescriptor___*, i));
715 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
721 struct ___Object___ * tagset=tagd->flagptr;
724 } else if (tagset->type!=OBJECTARRAYTYPE) {
726 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
727 struct ArrayObject * ao=
728 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
729 obj=(struct ___Object___ *)ptrarray[2];
730 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
732 struct ArrayObject * ao=
733 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
735 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
736 ARRAYSET(ao, struct ___Object___ *, 1, obj);
737 ao->___cachedCode___=2;
738 tagd->flagptr=(struct ___Object___ *)ao;
740 struct ArrayObject *ao=(struct ArrayObject *) tagset;
741 if (ao->___cachedCode___<ao->___length___) {
742 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
746 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
747 struct ArrayObject * aonew=
748 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
749 OBJECTARRAYINTERVAL+ao->___length___);
750 obj=(struct ___Object___ *)ptrarray[2];
751 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
752 ao=(struct ArrayObject *)tagd->flagptr;
754 struct ArrayObject * aonew=
755 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
757 aonew->___cachedCode___=ao->___cachedCode___+1;
758 for(i=0; i<ao->___length___; i++) {
759 ARRAYSET(aonew, struct ___Object___*, i,
760 ARRAYGET(ao, struct ___Object___*, i));
762 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
763 tagd->flagptr=(struct ___Object___ *) aonew;
769 /* This function clears a tag. */
771 void tagclear(void *ptr,
772 struct ___Object___ * obj,
773 struct ___TagDescriptor___ * tagd) {
775 void tagclear(struct ___Object___ * obj,
776 struct ___TagDescriptor___ * tagd) {
778 /* We'll assume that tag is alway there.
779 Need to statically check for this of course. */
780 struct ___Object___ * tagptr=obj->___tags___;
782 if (tagptr->type==TAGTYPE) {
783 if ((struct ___TagDescriptor___ *)tagptr==tagd)
784 obj->___tags___=NULL;
786 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
788 for(i=0; i<ao->___cachedCode___; i++) {
789 struct ___TagDescriptor___ * td=
790 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
792 ao->___cachedCode___--;
793 if (i<ao->___cachedCode___)
794 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
795 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
796 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
797 if (ao->___cachedCode___==0)
798 obj->___tags___=NULL;
805 struct ___Object___ *tagset=tagd->flagptr;
806 if (tagset->type!=OBJECTARRAYTYPE) {
810 struct ArrayObject *ao=(struct ArrayObject *) tagset;
812 for(i=0; i<ao->___cachedCode___; i++) {
813 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
815 ao->___cachedCode___--;
816 if (i<ao->___cachedCode___)
817 ARRAYSET(ao, struct ___Object___ *, i,
818 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
819 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
820 if (ao->___cachedCode___==0)
831 /* This function allocates a new tag. */
833 struct ___TagDescriptor___ * allocate_tag(void *ptr,
835 struct ___TagDescriptor___ * v=
836 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
839 struct ___TagDescriptor___ * allocate_tag(int index) {
840 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
849 /* This function updates the flag for object ptr. It or's the flag
850 with the or mask and and's it with the andmask. */
852 void flagbody(struct ___Object___ *ptr,
854 struct parameterwrapper ** queues,
858 int flagcomp(const int *val1, const int *val2) {
859 return (*val1)-(*val2);
862 void flagorand(void * ptr,
865 struct parameterwrapper ** queues,
868 int oldflag=((int *)ptr)[1];
869 int flag=ormask|oldflag;
871 flagbody(ptr, flag, queues, length, false);
875 bool intflagorand(void * ptr,
879 int oldflag=((int *)ptr)[1];
880 int flag=ormask|oldflag;
882 if (flag==oldflag) /* Don't do anything */
885 flagbody(ptr, flag, NULL, 0, false);
891 void flagorandinit(void * ptr,
894 int oldflag=((int *)ptr)[1];
895 int flag=ormask|oldflag;
897 flagbody(ptr,flag,NULL,0,true);
900 void flagbody(struct ___Object___ *ptr,
902 struct parameterwrapper ** vqueues,
905 struct parameterwrapper * flagptr = NULL;
907 struct parameterwrapper ** queues = vqueues;
908 int length = vlength;
911 int * enterflags = NULL;
912 if((!isnew) && (queues == NULL)) {
913 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
914 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
915 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
922 /*Remove object from all queues */
923 for(i = 0; i < length; ++i) {
925 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
926 (int *) &enterflags, &UNUSED, &UNUSED2);
927 ObjectHashremove(flagptr->objectset, (int)ptr);
928 if (enterflags!=NULL)
933 void enqueueObject(void * vptr,
934 struct parameterwrapper ** vqueues,
936 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
939 //struct QueueItem *tmpptr;
940 struct parameterwrapper * parameter=NULL;
943 struct parameterwrapper * prevptr=NULL;
944 struct ___Object___ *tagptr=NULL;
945 struct parameterwrapper ** queues = vqueues;
946 int length = vlength;
947 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
951 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
952 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
954 tagptr=ptr->___tags___;
956 /* Outer loop iterates through all parameter queues an object of
957 this type could be in. */
958 for(j = 0; j < length; ++j) {
959 parameter = queues[j];
961 if (parameter->numbertags>0) {
963 goto nextloop; //that means the object has no tag
964 //but that param needs tag
965 else if(tagptr->type==TAGTYPE) { //one tag
966 //struct ___TagDescriptor___ * tag=
967 //(struct ___TagDescriptor___*) tagptr;
968 for(i=0; i<parameter->numbertags; i++) {
969 //slotid is parameter->tagarray[2*i];
970 int tagid=parameter->tagarray[2*i+1];
971 if (tagid!=tagptr->flag)
972 goto nextloop; /*We don't have this tag */
974 } else { //multiple tags
975 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
976 for(i=0; i<parameter->numbertags; i++) {
977 //slotid is parameter->tagarray[2*i];
978 int tagid=parameter->tagarray[2*i+1];
980 for(j=0; j<ao->___cachedCode___; j++) {
981 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
992 for(i=0; i<parameter->numberofterms; i++) {
993 int andmask=parameter->intarray[i*2];
994 int checkmask=parameter->intarray[i*2+1];
995 if ((ptr->flag&andmask)==checkmask) {
996 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1007 void enqueueObject_I(void * vptr,
1008 struct parameterwrapper ** vqueues,
1010 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1013 //struct QueueItem *tmpptr;
1014 struct parameterwrapper * parameter=NULL;
1017 struct parameterwrapper * prevptr=NULL;
1018 struct ___Object___ *tagptr=NULL;
1019 struct parameterwrapper ** queues = vqueues;
1020 int length = vlength;
1021 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1024 if(queues == NULL) {
1025 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1026 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1028 tagptr=ptr->___tags___;
1030 /* Outer loop iterates through all parameter queues an object of
1031 this type could be in. */
1032 for(j = 0; j < length; ++j) {
1033 parameter = queues[j];
1035 if (parameter->numbertags>0) {
1037 goto nextloop; //that means the object has no tag
1038 //but that param needs tag
1039 else if(tagptr->type==TAGTYPE) { //one tag
1040 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1041 for(i=0; i<parameter->numbertags; i++) {
1042 //slotid is parameter->tagarray[2*i];
1043 int tagid=parameter->tagarray[2*i+1];
1044 if (tagid!=tagptr->flag)
1045 goto nextloop; /*We don't have this tag */
1047 } else { //multiple tags
1048 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1049 for(i=0; i<parameter->numbertags; i++) {
1050 //slotid is parameter->tagarray[2*i];
1051 int tagid=parameter->tagarray[2*i+1];
1053 for(j=0; j<ao->___cachedCode___; j++) {
1054 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1065 for(i=0; i<parameter->numberofterms; i++) {
1066 int andmask=parameter->intarray[i*2];
1067 int checkmask=parameter->intarray[i*2+1];
1068 if ((ptr->flag&andmask)==checkmask) {
1069 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1081 int * getAliasLock(void ** ptrs,
1083 struct RuntimeHash * tbl) {
1085 return (int*)(RUNMALLOC(sizeof(int)));
1090 bool redirect = false;
1091 int redirectlock = 0;
1092 for(; i < length; i++) {
1093 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1096 if(ptr->lock == NULL) {
1099 lock = (int)(ptr->lock);
1102 if(lock != redirectlock) {
1103 RuntimeHashadd(tbl, lock, redirectlock);
1106 if(RuntimeHashcontainskey(tbl, lock)) {
1107 // already redirected
1109 RuntimeHashget(tbl, lock, &redirectlock);
1110 for(; j < locklen; j++) {
1111 if(locks[j] != redirectlock) {
1112 RuntimeHashadd(tbl, locks[j], redirectlock);
1117 for(j = 0; j < locklen; j++) {
1118 if(locks[j] == lock) {
1121 } else if(locks[j] > lock) {
1128 locks[h] = locks[h-1];
1137 return (int *)redirectlock;
1139 return (int *)(locks[0]);
1144 void addAliasLock(void * ptr,
1146 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1147 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1148 // originally no alias lock associated or have a different alias lock
1149 // flush it as the new one
1150 obj->lock = (int *)lock;
1155 inline void setTaskExitIndex(int index) {
1156 taskInfoArray[taskInfoIndex]->exitIndex = index;
1159 inline void addNewObjInfo(void * nobj) {
1160 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1161 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1163 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1167 void * smemalloc(int size,
1172 // go through free mem list for suitable blocks
1173 struct freeMemItem * freemem = bamboo_free_mem_list->head;
1174 struct freeMemItem * prev = NULL;
1176 if(freemem->size >= isize) {
1181 freemem = freemem->next;
1182 } while(freemem != NULL);
1183 if(freemem != NULL) {
1184 mem = (void *)(freemem->ptr);
1185 // check the remaining space in this block
1186 int remain = (int)(mem-(BAMBOO_BASE_VA));
1187 int bound = (BAMBOO_SMEM_SIZE);
1188 if(remain < BAMBOO_LARGE_SMEM_BOUND) {
1189 bound = (BAMBOO_SMEM_SIZE_L);
1191 remain = bound - remain%bound;
1192 if(remain < isize) {
1193 // this object acrosses blocks
1194 // try to align the block if required a block
1195 if((isize == BAMBOO_SMEM_SIZE) && (freemem->size >= isize + remain)) {
1200 freemem->ptr = ((void*)freemem->ptr) + isize;
1201 freemem->size -= isize;
1204 mem = mspace_calloc(bamboo_free_msp, 1, isize);
1208 // no enough shared global memory
1214 BAMBOO_DEBUGPRINT(0xa001);
1215 BAMBOO_EXIT(0xa001);
1221 // receive object transferred from other cores
1222 // or the terminate message from other cores
1223 // Should be invoked in critical sections!!
1224 // NOTICE: following format is for threadsimulate version only
1225 // RAW version please see previous description
1226 // format: type + object
1227 // type: -1--stall msg
1229 // return value: 0--received an object
1230 // 1--received nothing
1231 // 2--received a Stall Msg
1232 // 3--received a lock Msg
1233 // RAW version: -1 -- received nothing
1234 // otherwise -- received msg type
1235 int receiveObject() {
1239 if(receiveMsg() == -1) {
1243 if(msgdataindex == msglength) {
1244 // received a whole msg
1249 // receive a object transfer msg
1250 struct transObjInfo * transObj =
1251 RUNMALLOC_I(sizeof(struct transObjInfo));
1255 BAMBOO_DEBUGPRINT(0xe880);
1258 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1260 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1262 BAMBOO_EXIT(0xa002);
1264 // store the object and its corresponding queue info, enqueue it later
1265 transObj->objptr = (void *)msgdata[2];
1266 transObj->length = (msglength - 3) / 2;
1267 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1268 for(k = 0; k < transObj->length; ++k) {
1269 transObj->queues[2*k] = msgdata[3+2*k];
1272 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1275 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1278 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1282 // check if there is an existing duplicate item
1284 struct QueueItem * qitem = getHead(&objqueue);
1285 struct QueueItem * prev = NULL;
1286 while(qitem != NULL) {
1287 struct transObjInfo * tmpinfo =
1288 (struct transObjInfo *)(qitem->objectptr);
1289 if(tmpinfo->objptr == transObj->objptr) {
1290 // the same object, remove outdate one
1291 removeItem(&objqueue, qitem);
1297 qitem = getHead(&objqueue);
1299 qitem = getNextQueueItem(prev);
1302 addNewItem_I(&objqueue, (void *)transObj);
1304 ++(self_numreceiveobjs);
1309 // receive a stall msg
1310 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1311 // non startup core can not receive stall msg
1313 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1315 BAMBOO_EXIT(0xa003);
1317 if(msgdata[1] < NUMCORES) {
1320 BAMBOO_DEBUGPRINT(0xe881);
1323 corestatus[msgdata[1]] = 0;
1324 numsendobjs[msgdata[1]] = msgdata[2];
1325 numreceiveobjs[msgdata[1]] = msgdata[3];
1330 // GC version have no lock msgs
1331 #ifndef MULTICORE_GC
1333 // receive lock request msg, handle it right now
1334 // check to see if there is a lock exist for the required obj
1335 // msgdata[1] -> lock type
1336 int data2 = msgdata[2]; // obj pointer
1337 int data3 = msgdata[3]; // lock
1338 int data4 = msgdata[4]; // request core
1339 // -1: redirected, 0: approved, 1: denied
1340 deny = processlockrequest(msgdata[1], data3, data2,
1341 data4, data4, true);
1343 // this lock request is redirected
1346 // send response msg
1347 // for 32 bit machine, the size is always 4 words
1348 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1350 cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1352 send_msg_4(data4, tmp, msgdata[1], data2, data3);
1359 // receive lock grount msg
1360 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1362 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1364 BAMBOO_EXIT(0xa004);
1366 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1369 BAMBOO_DEBUGPRINT(0xe882);
1378 // conflicts on lockresults
1380 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1382 BAMBOO_EXIT(0xa005);
1388 // receive lock deny msg
1389 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1391 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1393 BAMBOO_EXIT(0xa006);
1395 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1398 BAMBOO_DEBUGPRINT(0xe883);
1407 // conflicts on lockresults
1409 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1411 BAMBOO_EXIT(0xa007);
1417 // receive lock release msg
1418 processlockrelease(msgdata[1], msgdata[2], 0, false);
1424 case PROFILEOUTPUT: {
1425 // receive an output profile data request msg
1426 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1427 // startup core can not receive profile output finish msg
1428 BAMBOO_EXIT(0xa008);
1432 BAMBOO_DEBUGPRINT(0xe885);
1436 totalexetime = msgdata[1];
1437 outputProfileData();
1439 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1441 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1446 case PROFILEFINISH: {
1447 // receive a profile output finish msg
1448 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1449 // non startup core can not receive profile output finish msg
1451 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1453 BAMBOO_EXIT(0xa009);
1457 BAMBOO_DEBUGPRINT(0xe886);
1460 profilestatus[msgdata[1]] = 0;
1465 // GC version has no lock msgs
1466 #ifndef MULTICORE_GC
1467 case REDIRECTLOCK: {
1468 // receive a redirect lock request msg, handle it right now
1469 // check to see if there is a lock exist for the required obj
1470 int data1 = msgdata[1]; // lock type
1471 int data2 = msgdata[2]; // obj pointer
1472 int data3 = msgdata[3]; // redirect lock
1473 int data4 = msgdata[4]; // root request core
1474 int data5 = msgdata[5]; // request core
1475 deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1477 // this lock request is redirected
1480 // send response msg
1481 // for 32 bit machine, the size is always 4 words
1483 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1484 data1, data2, data3);
1486 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1487 data1, data2, data3);
1493 case REDIRECTGROUNT: {
1494 // receive a lock grant msg with redirect info
1495 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1497 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1499 BAMBOO_EXIT(0xa00a);
1501 if(lockobj == msgdata[2]) {
1504 BAMBOO_DEBUGPRINT(0xe891);
1509 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1514 // conflicts on lockresults
1516 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1518 BAMBOO_EXIT(0xa00b);
1523 case REDIRECTDENY: {
1524 // receive a lock deny msg with redirect info
1525 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1527 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1529 BAMBOO_EXIT(0xa00c);
1531 if(lockobj == msgdata[2]) {
1534 BAMBOO_DEBUGPRINT(0xe892);
1543 // conflicts on lockresults
1545 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1547 BAMBOO_EXIT(0xa00d);
1552 case REDIRECTRELEASE: {
1553 // receive a lock release msg with redirect info
1554 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1559 case STATUSCONFIRM: {
1560 // receive a status confirm info
1561 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1562 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1563 // wrong core to receive such msg
1564 BAMBOO_EXIT(0xa00e);
1566 // send response msg
1569 BAMBOO_DEBUGPRINT(0xe887);
1573 cache_msg_5(STARTUPCORE, STATUSREPORT,
1574 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1575 self_numsendobjs, self_numreceiveobjs);
1577 send_msg_5(STARTUPCORE, STATUSREPORT,
1578 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1579 self_numsendobjs, self_numreceiveobjs);
1585 case STATUSREPORT: {
1586 // receive a status confirm info
1587 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1588 // wrong core to receive such msg
1590 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1592 BAMBOO_EXIT(0xa00f);
1596 BAMBOO_DEBUGPRINT(0xe888);
1602 corestatus[msgdata[2]] = msgdata[1];
1603 numsendobjs[msgdata[2]] = msgdata[3];
1604 numreceiveobjs[msgdata[2]] = msgdata[4];
1610 // receive a terminate msg
1613 BAMBOO_DEBUGPRINT(0xe889);
1622 // receive a shared memory request msg
1623 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1624 // wrong core to receive such msg
1626 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1628 BAMBOO_EXIT(0xa010);
1632 BAMBOO_DEBUGPRINT(0xe88a);
1637 // is currently doing gc, dump this msg
1642 void * mem = smemalloc(msgdata[1], &allocsize);
1646 // send the start_va to request core
1648 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1650 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1657 // receive a shared memory response msg
1660 BAMBOO_DEBUGPRINT(0xe88b);
1665 // is currently doing gc, dump this msg
1669 if(msgdata[2] == 0) {
1670 bamboo_smem_size = 0;
1673 // fill header to store the size of this mem block
1674 (*((int*)msgdata[1])) = msgdata[2];
1675 bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1677 bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1680 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1681 msgdata[2]-BAMBOO_CACHE_LINE_SIZE,
1692 // receive a start GC msg
1695 BAMBOO_DEBUGPRINT(0xe88c);
1700 gcphase = MARKPHASE;
1702 // is waiting for response of mem request
1703 // let it return NULL and start gc
1704 bamboo_smem_size = 0;
1705 bamboo_cur_msp = NULL;
1711 case GCSTARTCOMPACT: {
1712 // a compact phase start msg
1713 gcblock2fill = msgdata[1];
1714 gcphase = COMPACTPHASE;
1718 case GCSTARTFLUSH: {
1719 // received a flush phase start msg
1720 gcphase = FLUSHPHASE;
1724 case GCFINISHMARK: {
1725 // received a mark phase finish msg
1726 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1727 // non startup core can not receive this msg
1729 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1731 BAMBOO_EXIT(0xb001);
1733 if(msgdata[1] < NUMCORES) {
1734 gccorestatus[msgdata[1]] = 0;
1735 gcnumsendobjs[msgdata[1]] = msgdata[2];
1736 gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1741 case GCFINISHCOMPACT: {
1742 // received a compact phase finish msg
1743 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1744 // non startup core can not receive this msg
1747 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1749 BAMBOO_EXIT(0xb002);
1751 int cnum = msgdata[1];
1752 int filledblocks = msgdata[2];
1753 int heaptop = msgdata[3];
1754 int data4 = msgdata[4];
1755 if(cnum < NUMCORES) {
1756 if(COMPACTPHASE == gcphase) {
1757 gcfilledblocks[cnum] = filledblocks;
1758 gcloads[cnum] = heaptop;
1765 if(gcfindSpareMem(&startaddr, &tomove, &dstcore, data4, cnum)) {
1766 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1769 gccorestatus[cnum] = 0;
1770 // check if there is pending move request
1771 if(gcmovepending > 0) {
1773 for(j = 0; j < NUMCORES; j++) {
1774 if(gcrequiredmems[j]>0) {
1782 gcrequiredmems[j] = assignSpareMem(cnum,
1786 if(STARTUPCORE == j) {
1789 gcmovestartaddr = startaddr;
1790 gcblock2fill = tomove;
1792 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1793 } // if(STARTUPCORE == j)
1794 if(gcrequiredmems[j] == 0) {
1797 } // if(j < NUMCORES)
1798 } // if(gcmovepending > 0)
1800 } // if(cnum < NUMCORES)
1804 case GCFINISHFLUSH: {
1805 // received a flush phase finish msg
1806 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1807 // non startup core can not receive this msg
1810 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1812 BAMBOO_EXIT(0xb003);
1814 if(msgdata[1] < NUMCORES) {
1815 gccorestatus[msgdata[1]] = 0;
1821 // received a GC finish msg
1822 gcphase = FINISHPHASE;
1826 case GCMARKCONFIRM: {
1827 // received a marked phase finish confirm request msg
1828 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1829 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1830 // wrong core to receive such msg
1831 BAMBOO_EXIT(0xb004);
1833 // send response msg
1835 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1836 gcbusystatus, gcself_numsendobjs,
1837 gcself_numreceiveobjs);
1839 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1840 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1846 case GCMARKREPORT: {
1847 // received a marked phase finish confirm response msg
1848 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1849 // wrong core to receive such msg
1851 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1853 BAMBOO_EXIT(0xb005);
1858 gccorestatus[msgdata[1]] = msgdata[2];
1859 gcnumsendobjs[msgdata[1]] = msgdata[3];
1860 gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1866 // received a markedObj msg
1867 gc_enqueue(msgdata[1]);
1868 gcself_numreceiveobjs++;
1869 gcbusystatus = true;
1874 // received a start moving objs msg
1876 gcdstcore = msgdata[1];
1877 gcmovestartaddr = msgdata[2];
1878 gcblock2fill = msgdata[3];
1882 case GCMAPREQUEST: {
1883 // received a mapping info request msg
1884 void * dstptr = NULL;
1885 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1886 if(NULL == dstptr) {
1887 // no such pointer in this core, something is wrong
1888 BAMBOO_EXIT(0xb006);
1890 // send back the mapping info
1892 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1894 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1901 // received a mapping info response msg
1902 if(msgdata[1] != gcobj2map) {
1903 // obj not matched, something is wrong
1904 BAMBOO_EXIT(0xb007);
1906 gcmappedobj = msgdata[2];
1907 RuntimeHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
1913 case GCLOBJREQUEST: {
1914 // received a large objs info request msg
1915 transferMarkResults();
1920 // received a large objs info response msg
1923 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1925 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1927 BAMBOO_EXIT(0xb008);
1929 // store the mark result info
1930 int cnum = msgdata[2];
1931 gcloads[cnum] = msgdata[3];
1932 if(gcheaptop < msgdata[4]) {
1933 gcheaptop = msgdata[4];
1935 // large obj info here
1936 for(int k = 5; k < msgdata[1];) {
1937 gc_lobjenqueue(msgdata[k++], msgdata[k++], cnum);
1939 } // for(int k = 5; k < msgdata[1];)
1943 case GCLOBJMAPPING: {
1944 // received a large obj mapping info msg
1945 RuntimeHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
1954 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1955 msgdata[msgdataindex] = -1;
1961 BAMBOO_DEBUGPRINT(0xe88d);
1965 if(BAMBOO_MSG_AVAIL() != 0) {
1978 BAMBOO_DEBUGPRINT(0xe88e);
1982 /* if(isInterrupt) {
1990 int enqueuetasks(struct parameterwrapper *parameter,
1991 struct parameterwrapper *prevptr,
1992 struct ___Object___ *ptr,
1994 int numenterflags) {
1995 void * taskpointerarray[MAXTASKPARAMS];
1997 //int numparams=parameter->task->numParameters;
1998 int numiterators=parameter->task->numTotal-1;
2001 struct taskdescriptor * task=parameter->task;
2003 //this add the object to parameterwrapper
2004 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
2005 numenterflags, enterflags==NULL);
2007 /* Add enqueued object to parameter vector */
2008 taskpointerarray[parameter->slot]=ptr;
2010 /* Reset iterators */
2011 for(j=0; j<numiterators; j++) {
2012 toiReset(¶meter->iterators[j]);
2015 /* Find initial state */
2016 for(j=0; j<numiterators; j++) {
2018 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2019 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2021 /* Need to backtrack */
2022 toiReset(¶meter->iterators[j]);
2026 /* Nothing to enqueue */
2032 /* Enqueue current state */
2034 struct taskparamdescriptor *tpd=
2035 RUNMALLOC(sizeof(struct taskparamdescriptor));
2037 tpd->numParameters=numiterators+1;
2038 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2040 for(j=0; j<=numiterators; j++) {
2041 //store the actual parameters
2042 tpd->parameterArray[j]=taskpointerarray[j];
2045 if ((/*!gencontains(failedtasks, tpd)&&*/
2046 !gencontains(activetasks,tpd))) {
2047 genputtable(activetasks, tpd, tpd);
2049 RUNFREE(tpd->parameterArray);
2053 /* This loop iterates to the next parameter combination */
2054 if (numiterators==0)
2057 for(j=numiterators-1; j<numiterators; j++) {
2059 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2060 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2062 /* Need to backtrack */
2063 toiReset(¶meter->iterators[j]);
2067 /* Nothing more to enqueue */
2075 int enqueuetasks_I(struct parameterwrapper *parameter,
2076 struct parameterwrapper *prevptr,
2077 struct ___Object___ *ptr,
2079 int numenterflags) {
2080 void * taskpointerarray[MAXTASKPARAMS];
2082 //int numparams=parameter->task->numParameters;
2083 int numiterators=parameter->task->numTotal-1;
2088 struct taskdescriptor * task=parameter->task;
2090 //this add the object to parameterwrapper
2091 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2092 numenterflags, enterflags==NULL);
2094 /* Add enqueued object to parameter vector */
2095 taskpointerarray[parameter->slot]=ptr;
2097 /* Reset iterators */
2098 for(j=0; j<numiterators; j++) {
2099 toiReset(¶meter->iterators[j]);
2102 /* Find initial state */
2103 for(j=0; j<numiterators; j++) {
2105 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2106 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2108 /* Need to backtrack */
2109 toiReset(¶meter->iterators[j]);
2113 /* Nothing to enqueue */
2119 /* Enqueue current state */
2121 struct taskparamdescriptor *tpd=
2122 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2124 tpd->numParameters=numiterators+1;
2125 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2127 for(j=0; j<=numiterators; j++) {
2128 //store the actual parameters
2129 tpd->parameterArray[j]=taskpointerarray[j];
2132 if ((/*!gencontains(failedtasks, tpd)&&*/
2133 !gencontains(activetasks,tpd))) {
2134 genputtable_I(activetasks, tpd, tpd);
2136 RUNFREE(tpd->parameterArray);
2140 /* This loop iterates to the next parameter combination */
2141 if (numiterators==0)
2144 for(j=numiterators-1; j<numiterators; j++) {
2146 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2147 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2149 /* Need to backtrack */
2150 toiReset(¶meter->iterators[j]);
2154 /* Nothing more to enqueue */
2168 int containstag(struct ___Object___ *ptr,
2169 struct ___TagDescriptor___ *tag);
2171 #ifndef MULTICORE_GC
2172 void releasewritelock_r(void * lock, void * redirectlock) {
2174 int reallock = (int)lock;
2175 targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2178 BAMBOO_DEBUGPRINT(0xe671);
2179 BAMBOO_DEBUGPRINT_REG((int)lock);
2180 BAMBOO_DEBUGPRINT_REG(reallock);
2181 BAMBOO_DEBUGPRINT_REG(targetcore);
2184 if(targetcore == BAMBOO_NUM_OF_CORE) {
2185 BAMBOO_START_CRITICAL_SECTION_LOCK();
2187 BAMBOO_DEBUGPRINT(0xf001);
2189 // reside on this core
2190 if(!RuntimeHashcontainskey(locktbl, reallock)) {
2191 // no locks for this object, something is wrong
2192 BAMBOO_EXIT(0xa011);
2195 struct LockValue * lockvalue = NULL;
2197 BAMBOO_DEBUGPRINT(0xe672);
2199 RuntimeHashget(locktbl, reallock, &rwlock_obj);
2200 lockvalue = (struct LockValue *)rwlock_obj;
2202 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2205 lockvalue->redirectlock = (int)redirectlock;
2207 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2210 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2212 BAMBOO_DEBUGPRINT(0xf000);
2216 // send lock release with redirect info msg
2217 // for 32 bit machine, the size is always 4 words
2218 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2223 void executetasks() {
2224 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2227 struct ___Object___ * tmpparam = NULL;
2228 struct parameterdescriptor * pd=NULL;
2229 struct parameterwrapper *pw=NULL;
2234 struct LockValue locks[MAXTASKPARAMS];
2242 while(hashsize(activetasks)>0) {
2247 BAMBOO_DEBUGPRINT(0xe990);
2250 /* See if there are any active tasks */
2251 if (hashsize(activetasks)>0) {
2254 #ifdef ACCURATEPROFILE
2255 profileTaskStart("tpd checking");
2259 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2260 genfreekey(activetasks, currtpd);
2262 numparams=currtpd->task->numParameters;
2263 numtotal=currtpd->task->numTotal;
2265 // clear the lockRedirectTbl
2266 // (TODO, this table should be empty after all locks are released)
2268 for(j = 0; j < MAXTASKPARAMS; j++) {
2269 locks[j].redirectlock = 0;
2272 // get all required locks
2274 // check which locks are needed
2275 for(i = 0; i < numparams; i++) {
2276 void * param = currtpd->parameterArray[i];
2280 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2282 taskpointerarray[i+OFFSET]=param;
2285 if(((struct ___Object___ *)param)->lock == NULL) {
2286 tmplock = (int)param;
2288 tmplock = (int)(((struct ___Object___ *)param)->lock);
2290 // insert into the locks array
2291 for(j = 0; j < locklen; j++) {
2292 if(locks[j].value == tmplock) {
2295 } else if(locks[j].value > tmplock) {
2302 locks[h].redirectlock = locks[h-1].redirectlock;
2303 locks[h].value = locks[h-1].value;
2305 locks[j].value = tmplock;
2306 locks[j].redirectlock = (int)param;
2309 } // line 2713: for(i = 0; i < numparams; i++)
2310 // grab these required locks
2312 BAMBOO_DEBUGPRINT(0xe991);
2314 for(i = 0; i < locklen; i++) {
2315 int * lock = (int *)(locks[i].redirectlock);
2317 // require locks for this parameter if it is not a startup object
2319 BAMBOO_DEBUGPRINT_REG((int)lock);
2320 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2323 BAMBOO_START_CRITICAL_SECTION();
2325 BAMBOO_DEBUGPRINT(0xf001);
2328 //isInterrupt = false;
2331 BAMBOO_WAITING_FOR_LOCK();
2335 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2339 grount = lockresult;
2349 //isInterrupt = true;
2351 BAMBOO_CLOSE_CRITICAL_SECTION();
2353 BAMBOO_DEBUGPRINT(0xf000);
2359 BAMBOO_DEBUGPRINT(0xe992);
2361 // can not get the lock, try later
2362 // releas all grabbed locks for previous parameters
2363 for(j = 0; j < i; ++j) {
2364 lock = (int*)(locks[j].redirectlock);
2365 releasewritelock(lock);
2367 genputtable(activetasks, currtpd, currtpd);
2368 if(hashsize(activetasks) == 1) {
2369 // only one task right now, wait a little while before next try
2375 #ifdef ACCURATEPROFILE
2376 // fail, set the end of the checkTaskInfo
2381 } // line 2794: if(grount == 0)
2382 } // line 2752: for(i = 0; i < locklen; i++)
2385 BAMBOO_DEBUGPRINT(0xe993);
2387 /* Make sure that the parameters are still in the queues */
2388 for(i=0; i<numparams; i++) {
2389 void * parameter=currtpd->parameterArray[i];
2393 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
2394 classsize[((struct ___Object___ *)parameter)->type]);
2396 tmpparam = (struct ___Object___ *)parameter;
2397 pd=currtpd->task->descriptorarray[i];
2398 pw=(struct parameterwrapper *) pd->queue;
2399 /* Check that object is still in queue */
2401 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2403 BAMBOO_DEBUGPRINT(0xe994);
2405 // release grabbed locks
2406 for(j = 0; j < locklen; ++j) {
2407 int * lock = (int *)(locks[j].redirectlock);
2408 releasewritelock(lock);
2410 RUNFREE(currtpd->parameterArray);
2416 /* Check if the object's flags still meets requirements */
2420 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2421 andmask=pw->intarray[tmpi*2];
2422 checkmask=pw->intarray[tmpi*2+1];
2423 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2429 // flags are never suitable
2430 // remove this obj from the queue
2432 int UNUSED, UNUSED2;
2435 BAMBOO_DEBUGPRINT(0xe995);
2437 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
2438 (int *) &enterflags, &UNUSED, &UNUSED2);
2439 ObjectHashremove(pw->objectset, (int)parameter);
2440 if (enterflags!=NULL)
2441 RUNFREE(enterflags);
2442 // release grabbed locks
2443 for(j = 0; j < locklen; ++j) {
2444 int * lock = (int *)(locks[j].redirectlock);
2445 releasewritelock(lock);
2447 RUNFREE(currtpd->parameterArray);
2451 #ifdef ACCURATEPROFILE
2452 // fail, set the end of the checkTaskInfo
2457 } // line 2878: if (!ismet)
2461 /* Check that object still has necessary tags */
2462 for(j=0; j<pd->numbertags; j++) {
2463 int slotid=pd->tagarray[2*j]+numparams;
2464 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2465 if (!containstag(parameter, tagd)) {
2467 BAMBOO_DEBUGPRINT(0xe996);
2470 // release grabbed locks
2472 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2473 int * lock = (int *)(locks[tmpj].redirectlock);
2474 releasewritelock(lock);
2477 RUNFREE(currtpd->parameterArray);
2481 } // line2911: if (!containstag(parameter, tagd))
2482 } // line 2808: for(j=0; j<pd->numbertags; j++)
2484 taskpointerarray[i+OFFSET]=parameter;
2485 } // line 2824: for(i=0; i<numparams; i++)
2487 for(; i<numtotal; i++) {
2488 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2493 /* Actually call task */
2495 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2496 taskpointerarray[1]=NULL;
2499 #ifdef ACCURATEPROFILE
2500 // check finish, set the end of the checkTaskInfo
2503 profileTaskStart(currtpd->task->name);
2507 BAMBOO_DEBUGPRINT(0xe997);
2509 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2511 #ifdef ACCURATEPROFILE
2512 // task finish, set the end of the checkTaskInfo
2514 // new a PostTaskInfo for the post-task execution
2515 profileTaskStart("post task execution");
2519 BAMBOO_DEBUGPRINT(0xe998);
2520 BAMBOO_DEBUGPRINT_REG(islock);
2525 BAMBOO_DEBUGPRINT(0xe999);
2527 for(i = 0; i < locklen; ++i) {
2528 void * ptr = (void *)(locks[i].redirectlock);
2529 int * lock = (int *)(locks[i].value);
2531 BAMBOO_DEBUGPRINT_REG((int)ptr);
2532 BAMBOO_DEBUGPRINT_REG((int)lock);
2534 #ifndef MULTICORE_GC
2535 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2537 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2538 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2539 releasewritelock_r(lock, (int *)redirectlock);
2544 releasewritelock(ptr);
2547 } // line 3015: if(islock)
2550 // post task execution finish, set the end of the postTaskInfo
2554 // Free up task parameter descriptor
2555 RUNFREE(currtpd->parameterArray);
2559 BAMBOO_DEBUGPRINT(0xe99a);
2562 } // if (hashsize(activetasks)>0)
2563 } // while(hashsize(activetasks)>0)
2565 BAMBOO_DEBUGPRINT(0xe99b);
2569 /* This function processes an objects tags */
2570 void processtags(struct parameterdescriptor *pd,
2572 struct parameterwrapper *parameter,
2573 int * iteratorcount,
2578 for(i=0; i<pd->numbertags; i++) {
2579 int slotid=pd->tagarray[2*i];
2580 int tagid=pd->tagarray[2*i+1];
2582 if (statusarray[slotid+numparams]==0) {
2583 parameter->iterators[*iteratorcount].istag=1;
2584 parameter->iterators[*iteratorcount].tagid=tagid;
2585 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2586 parameter->iterators[*iteratorcount].tagobjectslot=index;
2587 statusarray[slotid+numparams]=1;
2594 void processobject(struct parameterwrapper *parameter,
2596 struct parameterdescriptor *pd,
2602 struct ObjectHash * objectset=
2603 ((struct parameterwrapper *)pd->queue)->objectset;
2605 parameter->iterators[*iteratorcount].istag=0;
2606 parameter->iterators[*iteratorcount].slot=index;
2607 parameter->iterators[*iteratorcount].objectset=objectset;
2608 statusarray[index]=1;
2610 for(i=0; i<pd->numbertags; i++) {
2611 int slotid=pd->tagarray[2*i];
2612 //int tagid=pd->tagarray[2*i+1];
2613 if (statusarray[slotid+numparams]!=0) {
2614 /* This tag has already been enqueued, use it to narrow search */
2615 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2620 parameter->iterators[*iteratorcount].numtags=tagcount;
2625 /* This function builds the iterators for a task & parameter */
2627 void builditerators(struct taskdescriptor * task,
2629 struct parameterwrapper * parameter) {
2630 int statusarray[MAXTASKPARAMS];
2632 int numparams=task->numParameters;
2633 int iteratorcount=0;
2634 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2636 statusarray[index]=1; /* Initial parameter */
2637 /* Process tags for initial iterator */
2639 processtags(task->descriptorarray[index], index, parameter,
2640 &iteratorcount, statusarray, numparams);
2644 /* Check for objects with existing tags */
2645 for(i=0; i<numparams; i++) {
2646 if (statusarray[i]==0) {
2647 struct parameterdescriptor *pd=task->descriptorarray[i];
2649 for(j=0; j<pd->numbertags; j++) {
2650 int slotid=pd->tagarray[2*j];
2651 if(statusarray[slotid+numparams]!=0) {
2652 processobject(parameter, i, pd, &iteratorcount, statusarray,
2654 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2661 /* Next do objects w/ unbound tags*/
2663 for(i=0; i<numparams; i++) {
2664 if (statusarray[i]==0) {
2665 struct parameterdescriptor *pd=task->descriptorarray[i];
2666 if (pd->numbertags>0) {
2667 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2668 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2674 /* Nothing with a tag enqueued */
2676 for(i=0; i<numparams; i++) {
2677 if (statusarray[i]==0) {
2678 struct parameterdescriptor *pd=task->descriptorarray[i];
2679 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2680 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2693 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2696 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2697 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2699 printf("%s\n", task->name);
2701 for(j=0; j<task->numParameters; j++) {
2702 struct parameterdescriptor *param=task->descriptorarray[j];
2703 struct parameterwrapper *parameter=param->queue;
2704 struct ObjectHash * set=parameter->objectset;
2705 struct ObjectIterator objit;
2707 printf(" Parameter %d\n", j);
2709 ObjectHashiterator(set, &objit);
2710 while(ObjhasNext(&objit)) {
2711 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2712 struct ___Object___ * tagptr=obj->___tags___;
2713 int nonfailed=Objdata4(&objit);
2714 int numflags=Objdata3(&objit);
2715 int flags=Objdata2(&objit);
2718 printf(" Contains %lx\n", obj);
2719 printf(" flag=%d\n", obj->flag);
2722 } else if (tagptr->type==TAGTYPE) {
2724 printf(" tag=%lx\n",tagptr);
2730 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2731 for(; tagindex<ao->___cachedCode___; tagindex++) {
2733 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
2746 /* This function processes the task information to create queues for
2747 each parameter type. */
2749 void processtasks() {
2751 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2754 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2755 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2758 /* Build objectsets */
2759 for(j=0; j<task->numParameters; j++) {
2760 struct parameterdescriptor *param=task->descriptorarray[j];
2761 struct parameterwrapper *parameter=param->queue;
2762 parameter->objectset=allocateObjectHash(10);
2763 parameter->task=task;
2766 /* Build iterators for parameters */
2767 for(j=0; j<task->numParameters; j++) {
2768 struct parameterdescriptor *param=task->descriptorarray[j];
2769 struct parameterwrapper *parameter=param->queue;
2770 builditerators(task, j, parameter);
2775 void toiReset(struct tagobjectiterator * it) {
2778 } else if (it->numtags>0) {
2781 ObjectHashiterator(it->objectset, &it->it);
2785 int toiHasNext(struct tagobjectiterator *it,
2786 void ** objectarray OPTARG(int * failed)) {
2789 /* Get object with tags */
2790 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2791 struct ___Object___ *tagptr=obj->___tags___;
2792 if (tagptr->type==TAGTYPE) {
2793 if ((it->tagobjindex==0)&& /* First object */
2794 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2799 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2800 int tagindex=it->tagobjindex;
2801 for(; tagindex<ao->___cachedCode___; tagindex++) {
2802 struct ___TagDescriptor___ *td=
2803 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2804 if (td->flag==it->tagid) {
2805 it->tagobjindex=tagindex; /* Found right type of tag */
2811 } else if (it->numtags>0) {
2812 /* Use tags to locate appropriate objects */
2813 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2814 struct ___Object___ *objptr=tag->flagptr;
2816 if (objptr->type!=OBJECTARRAYTYPE) {
2817 if (it->tagobjindex>0)
2819 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2821 for(i=1; i<it->numtags; i++) {
2822 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2823 if (!containstag(objptr,tag2))
2828 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2831 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2832 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2833 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2835 for(i=1; i<it->numtags; i++) {
2836 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2837 if (!containstag(objptr,tag2))
2840 it->tagobjindex=tagindex;
2845 it->tagobjindex=tagindex;
2849 return ObjhasNext(&it->it);
2853 int containstag(struct ___Object___ *ptr,
2854 struct ___TagDescriptor___ *tag) {
2856 struct ___Object___ * objptr=tag->flagptr;
2857 if (objptr->type==OBJECTARRAYTYPE) {
2858 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2859 for(j=0; j<ao->___cachedCode___; j++) {
2860 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2868 void toiNext(struct tagobjectiterator *it,
2869 void ** objectarray OPTARG(int * failed)) {
2870 /* hasNext has all of the intelligence */
2873 /* Get object with tags */
2874 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2875 struct ___Object___ *tagptr=obj->___tags___;
2876 if (tagptr->type==TAGTYPE) {
2878 objectarray[it->slot]=tagptr;
2880 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2881 objectarray[it->slot]=
2882 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2884 } else if (it->numtags>0) {
2885 /* Use tags to locate appropriate objects */
2886 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2887 struct ___Object___ *objptr=tag->flagptr;
2888 if (objptr->type!=OBJECTARRAYTYPE) {
2890 objectarray[it->slot]=objptr;
2892 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2893 objectarray[it->slot]=
2894 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2897 /* Iterate object */
2898 objectarray[it->slot]=(void *)Objkey(&it->it);