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;
124 //isInterrupt = true;
127 taskInfoOverflow = false;
128 /*interruptInfoIndex = 0;
129 interruptInfoOverflow = false;*/
133 inline __attribute__((always_inline))
134 void disruntimedata() {
136 freeRuntimeHash(gcpointertbl);
138 freeRuntimeHash(lockRedirectTbl);
139 freeRuntimeHash(objRedirectLockTbl);
140 RUNFREE(locktable.bucket);
142 genfreehashtable(activetasks);
146 inline __attribute__((always_inline))
147 bool checkObjQueue() {
149 struct transObjInfo * objInfo = NULL;
153 #ifdef ACCURATEPROFILE
154 bool isChecking = false;
155 if(!isEmpty(&objqueue)) {
156 profileTaskStart("objqueue checking");
158 } // if(!isEmpty(&objqueue))
162 while(!isEmpty(&objqueue)) {
164 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
166 BAMBOO_DEBUGPRINT(0xf001);
169 //isInterrupt = false;
172 BAMBOO_DEBUGPRINT(0xeee1);
175 objInfo = (struct transObjInfo *)getItem(&objqueue);
176 obj = objInfo->objptr;
178 BAMBOO_DEBUGPRINT_REG((int)obj);
180 // grab lock and flush the obj
184 BAMBOO_WAITING_FOR_LOCK();
185 } // while(!lockflag)
188 BAMBOO_DEBUGPRINT_REG(grount);
203 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
204 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
205 classsize[((struct ___Object___ *)obj)->type]);
207 // enqueue the object
208 for(k = 0; k < objInfo->length; ++k) {
209 int taskindex = objInfo->queues[2 * k];
210 int paramindex = objInfo->queues[2 * k + 1];
211 struct parameterwrapper ** queues =
212 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
214 BAMBOO_DEBUGPRINT_REG(taskindex);
215 BAMBOO_DEBUGPRINT_REG(paramindex);
216 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
217 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
218 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
219 (long)obj, tmpptr->flag);
221 enqueueObject_I(obj, queues, 1);
223 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
225 } // for(k = 0; k < objInfo->length; ++k)
226 releasewritelock_I(obj);
227 RUNFREE(objInfo->queues);
231 // put it at the end of the queue if no update version in the queue
232 struct QueueItem * qitem = getHead(&objqueue);
233 struct QueueItem * prev = NULL;
234 while(qitem != NULL) {
235 struct transObjInfo * tmpinfo =
236 (struct transObjInfo *)(qitem->objectptr);
237 if(tmpinfo->objptr == obj) {
238 // the same object in the queue, which should be enqueued
239 // recently. Current one is outdate, do not re-enqueue it
240 RUNFREE(objInfo->queues);
245 } // if(tmpinfo->objptr == obj)
246 qitem = getNextQueueItem(prev);
247 } // while(qitem != NULL)
248 // try to execute active tasks already enqueued first
249 addNewItem_I(&objqueue, objInfo);
251 //isInterrupt = true;
254 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
256 BAMBOO_DEBUGPRINT(0xf000);
260 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
262 BAMBOO_DEBUGPRINT(0xf000);
264 } // while(!isEmpty(&objqueue))
267 #ifdef ACCURATEPROFILE
275 BAMBOO_DEBUGPRINT(0xee02);
280 inline __attribute__((always_inline))
281 void checkCoreStatus() {
282 bool allStall = false;
286 (waitconfirm && (numconfirm == 0))) {
288 BAMBOO_DEBUGPRINT(0xee04);
289 BAMBOO_DEBUGPRINT_REG(waitconfirm);
291 BAMBOO_START_CRITICAL_SECTION_STATUS();
293 BAMBOO_DEBUGPRINT(0xf001);
295 corestatus[BAMBOO_NUM_OF_CORE] = 0;
296 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
297 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
298 // check the status of all cores
301 BAMBOO_DEBUGPRINT_REG(NUMCORES);
303 for(i = 0; i < NUMCORES; ++i) {
305 BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
307 if(corestatus[i] != 0) {
311 } // for(i = 0; i < NUMCORES; ++i)
313 // check if the sum of send objs and receive obj are the same
314 // yes->check if the info is the latest; no->go on executing
316 for(i = 0; i < NUMCORES; ++i) {
317 sumsendobj += numsendobjs[i];
319 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
321 } // for(i = 0; i < NUMCORES; ++i)
322 for(i = 0; i < NUMCORES; ++i) {
323 sumsendobj -= numreceiveobjs[i];
325 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
327 } // for(i = 0; i < NUMCORES; ++i)
328 if(0 == sumsendobj) {
330 // the first time found all cores stall
331 // send out status confirm msg to all other cores
332 // reset the corestatus array too
334 BAMBOO_DEBUGPRINT(0xee05);
336 corestatus[BAMBOO_NUM_OF_CORE] = 1;
337 for(i = 1; i < NUMCORES; ++i) {
339 // send status confirm msg to core i
340 send_msg_1(i, STATUSCONFIRM);
341 } // for(i = 1; i < NUMCORES; ++i)
343 numconfirm = NUMCORES - 1;
345 // all the core status info are the latest
346 // terminate; for profiling mode, send request to all
347 // other cores to pour out profiling data
349 BAMBOO_DEBUGPRINT(0xee06);
353 totalexetime = BAMBOO_GET_EXE_TIME();
355 BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
356 BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
357 BAMBOO_DEBUGPRINT(0xbbbbbbbb);
359 // profile mode, send msgs to other cores to request pouring
360 // out progiling data
362 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
364 BAMBOO_DEBUGPRINT(0xf000);
366 for(i = 1; i < NUMCORES; ++i) {
367 // send profile request msg to core i
368 send_msg_2(i, PROFILEOUTPUT, totalexetime);
369 } // for(i = 1; i < NUMCORES; ++i)
370 // pour profiling data on startup core
373 BAMBOO_START_CRITICAL_SECTION_STATUS();
375 BAMBOO_DEBUGPRINT(0xf001);
377 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
378 // check the status of all cores
381 BAMBOO_DEBUGPRINT_REG(NUMCORES);
383 for(i = 0; i < NUMCORES; ++i) {
385 BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
387 if(profilestatus[i] != 0) {
391 } // for(i = 0; i < NUMCORES; ++i)
394 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
396 BAMBOO_DEBUGPRINT(0xf000);
406 terminate(); // All done.
407 } // if(!waitconfirm)
409 // still some objects on the fly on the network
410 // reset the waitconfirm and numconfirm
412 BAMBOO_DEBUGPRINT(0xee07);
416 } // if(0 == sumsendobj)
418 // not all cores are stall, keep on waiting
420 BAMBOO_DEBUGPRINT(0xee08);
425 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
427 BAMBOO_DEBUGPRINT(0xf000);
429 } // if((!waitconfirm) ||
432 // main function for each core
433 inline void run(void * arg) {
437 bool sendStall = false;
439 bool tocontinue = false;
441 corenum = BAMBOO_GET_NUM_OF_CORE();
443 BAMBOO_DEBUGPRINT(0xeeee);
444 BAMBOO_DEBUGPRINT_REG(corenum);
445 BAMBOO_DEBUGPRINT(STARTUPCORE);
448 // initialize runtime data structures
451 // other architecture related initialization
455 initializeexithandler();
457 // main process of the execution module
458 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
459 // non-executing cores, only processing communications
462 BAMBOO_DEBUGPRINT(0xee01);
463 BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
464 BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
465 profileTaskStart("msg handling");
469 //isInterrupt = false;
473 /* Create queue of active tasks */
475 genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
476 (int(*) (void *,void *)) &comparetpd);
478 /* Process task information */
481 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
482 /* Create startup object */
483 createstartupobject(argc, argv);
487 BAMBOO_DEBUGPRINT(0xee00);
492 // check if need to do GC
496 // check if there are new active tasks can be executed
503 while(receiveObject() != -1) {
508 BAMBOO_DEBUGPRINT(0xee01);
511 // check if there are some pending objects,
512 // if yes, enqueue them and executetasks again
513 tocontinue = checkObjQueue();
517 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
520 BAMBOO_DEBUGPRINT(0xee03);
528 BAMBOO_DEBUGPRINT(0xee09);
534 // wait for some time
537 BAMBOO_DEBUGPRINT(0xee0a);
543 // send StallMsg to startup core
545 BAMBOO_DEBUGPRINT(0xee0b);
548 send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE,
549 self_numsendobjs, self_numreceiveobjs);
561 BAMBOO_DEBUGPRINT(0xee0c);
564 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
567 } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
571 struct ___createstartupobject____I_locals {
574 struct ___StartupObject___ * ___startupobject___;
575 struct ArrayObject * ___stringarray___;
576 }; // struct ___createstartupobject____I_locals
578 void createstartupobject(int argc,
582 /* Allocate startup object */
584 struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
585 struct ___StartupObject___ *startupobject=
586 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
587 ___locals___.___startupobject___ = startupobject;
588 struct ArrayObject * stringarray=
589 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
590 ___locals___.___stringarray___ = stringarray;
592 struct ___StartupObject___ *startupobject=
593 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
594 struct ArrayObject * stringarray=
595 allocate_newarray(STRINGARRAYTYPE, argc-1);
597 /* Build array of strings */
598 startupobject->___parameters___=stringarray;
599 for(i=1; i<argc; i++) {
600 int length=strlen(argv[i]);
602 struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
604 struct ___String___ *newstring=NewString(argv[i],length);
606 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
610 startupobject->version = 0;
611 startupobject->lock = NULL;
613 /* Set initialized flag for startup object */
614 flagorandinit(startupobject,1,0xFFFFFFFF);
615 enqueueObject(startupobject, NULL, 0);
617 BAMBOO_CACHE_FLUSH_ALL();
621 int hashCodetpd(struct taskparamdescriptor *ftd) {
622 int hash=(int)ftd->task;
624 for(i=0; i<ftd->numParameters; i++) {
625 hash^=(int)ftd->parameterArray[i];
630 int comparetpd(struct taskparamdescriptor *ftd1,
631 struct taskparamdescriptor *ftd2) {
633 if (ftd1->task!=ftd2->task)
635 for(i=0; i<ftd1->numParameters; i++)
636 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
641 /* This function sets a tag. */
643 void tagset(void *ptr,
644 struct ___Object___ * obj,
645 struct ___TagDescriptor___ * tagd) {
647 void tagset(struct ___Object___ * obj,
648 struct ___TagDescriptor___ * tagd) {
650 struct ArrayObject * ao=NULL;
651 struct ___Object___ * tagptr=obj->___tags___;
653 obj->___tags___=(struct ___Object___ *)tagd;
655 /* Have to check if it is already set */
656 if (tagptr->type==TAGTYPE) {
657 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
662 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
663 struct ArrayObject * ao=
664 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
665 obj=(struct ___Object___ *)ptrarray[2];
666 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
667 td=(struct ___TagDescriptor___ *) obj->___tags___;
669 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
672 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
673 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
674 obj->___tags___=(struct ___Object___ *) ao;
675 ao->___cachedCode___=2;
679 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
680 for(i=0; i<ao->___cachedCode___; i++) {
681 struct ___TagDescriptor___ * td=
682 ARRAYGET(ao, struct ___TagDescriptor___*, i);
687 if (ao->___cachedCode___<ao->___length___) {
688 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
689 ao->___cachedCode___++;
692 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
693 struct ArrayObject * aonew=
694 allocate_newarray(&ptrarray,TAGARRAYTYPE,
695 TAGARRAYINTERVAL+ao->___length___);
696 obj=(struct ___Object___ *)ptrarray[2];
697 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
698 ao=(struct ArrayObject *)obj->___tags___;
700 struct ArrayObject * aonew=
701 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
704 aonew->___cachedCode___=ao->___length___+1;
705 for(i=0; i<ao->___length___; i++) {
706 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
707 ARRAYGET(ao, struct ___TagDescriptor___*, i));
709 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
715 struct ___Object___ * tagset=tagd->flagptr;
718 } else if (tagset->type!=OBJECTARRAYTYPE) {
720 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
721 struct ArrayObject * ao=
722 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
723 obj=(struct ___Object___ *)ptrarray[2];
724 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
726 struct ArrayObject * ao=
727 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
729 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
730 ARRAYSET(ao, struct ___Object___ *, 1, obj);
731 ao->___cachedCode___=2;
732 tagd->flagptr=(struct ___Object___ *)ao;
734 struct ArrayObject *ao=(struct ArrayObject *) tagset;
735 if (ao->___cachedCode___<ao->___length___) {
736 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
740 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
741 struct ArrayObject * aonew=
742 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
743 OBJECTARRAYINTERVAL+ao->___length___);
744 obj=(struct ___Object___ *)ptrarray[2];
745 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
746 ao=(struct ArrayObject *)tagd->flagptr;
748 struct ArrayObject * aonew=
749 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
751 aonew->___cachedCode___=ao->___cachedCode___+1;
752 for(i=0; i<ao->___length___; i++) {
753 ARRAYSET(aonew, struct ___Object___*, i,
754 ARRAYGET(ao, struct ___Object___*, i));
756 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
757 tagd->flagptr=(struct ___Object___ *) aonew;
763 /* This function clears a tag. */
765 void tagclear(void *ptr,
766 struct ___Object___ * obj,
767 struct ___TagDescriptor___ * tagd) {
769 void tagclear(struct ___Object___ * obj,
770 struct ___TagDescriptor___ * tagd) {
772 /* We'll assume that tag is alway there.
773 Need to statically check for this of course. */
774 struct ___Object___ * tagptr=obj->___tags___;
776 if (tagptr->type==TAGTYPE) {
777 if ((struct ___TagDescriptor___ *)tagptr==tagd)
778 obj->___tags___=NULL;
780 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
782 for(i=0; i<ao->___cachedCode___; i++) {
783 struct ___TagDescriptor___ * td=
784 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
786 ao->___cachedCode___--;
787 if (i<ao->___cachedCode___)
788 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
789 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
790 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
791 if (ao->___cachedCode___==0)
792 obj->___tags___=NULL;
799 struct ___Object___ *tagset=tagd->flagptr;
800 if (tagset->type!=OBJECTARRAYTYPE) {
804 struct ArrayObject *ao=(struct ArrayObject *) tagset;
806 for(i=0; i<ao->___cachedCode___; i++) {
807 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
809 ao->___cachedCode___--;
810 if (i<ao->___cachedCode___)
811 ARRAYSET(ao, struct ___Object___ *, i,
812 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
813 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
814 if (ao->___cachedCode___==0)
825 /* This function allocates a new tag. */
827 struct ___TagDescriptor___ * allocate_tag(void *ptr,
829 struct ___TagDescriptor___ * v=
830 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
833 struct ___TagDescriptor___ * allocate_tag(int index) {
834 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
843 /* This function updates the flag for object ptr. It or's the flag
844 with the or mask and and's it with the andmask. */
846 void flagbody(struct ___Object___ *ptr,
848 struct parameterwrapper ** queues,
852 int flagcomp(const int *val1, const int *val2) {
853 return (*val1)-(*val2);
856 void flagorand(void * ptr,
859 struct parameterwrapper ** queues,
862 int oldflag=((int *)ptr)[1];
863 int flag=ormask|oldflag;
865 flagbody(ptr, flag, queues, length, false);
869 bool intflagorand(void * ptr,
873 int oldflag=((int *)ptr)[1];
874 int flag=ormask|oldflag;
876 if (flag==oldflag) /* Don't do anything */
879 flagbody(ptr, flag, NULL, 0, false);
885 void flagorandinit(void * ptr,
888 int oldflag=((int *)ptr)[1];
889 int flag=ormask|oldflag;
891 flagbody(ptr,flag,NULL,0,true);
894 void flagbody(struct ___Object___ *ptr,
896 struct parameterwrapper ** vqueues,
899 struct parameterwrapper * flagptr = NULL;
901 struct parameterwrapper ** queues = vqueues;
902 int length = vlength;
905 int * enterflags = NULL;
906 if((!isnew) && (queues == NULL)) {
907 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
908 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
909 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
916 /*Remove object from all queues */
917 for(i = 0; i < length; ++i) {
919 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
920 (int *) &enterflags, &UNUSED, &UNUSED2);
921 ObjectHashremove(flagptr->objectset, (int)ptr);
922 if (enterflags!=NULL)
927 void enqueueObject(void * vptr,
928 struct parameterwrapper ** vqueues,
930 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
933 //struct QueueItem *tmpptr;
934 struct parameterwrapper * parameter=NULL;
937 struct parameterwrapper * prevptr=NULL;
938 struct ___Object___ *tagptr=NULL;
939 struct parameterwrapper ** queues = vqueues;
940 int length = vlength;
941 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
945 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
946 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
948 tagptr=ptr->___tags___;
950 /* Outer loop iterates through all parameter queues an object of
951 this type could be in. */
952 for(j = 0; j < length; ++j) {
953 parameter = queues[j];
955 if (parameter->numbertags>0) {
957 goto nextloop; //that means the object has no tag
958 //but that param needs tag
959 else if(tagptr->type==TAGTYPE) { //one tag
960 //struct ___TagDescriptor___ * tag=
961 //(struct ___TagDescriptor___*) tagptr;
962 for(i=0; i<parameter->numbertags; i++) {
963 //slotid is parameter->tagarray[2*i];
964 int tagid=parameter->tagarray[2*i+1];
965 if (tagid!=tagptr->flag)
966 goto nextloop; /*We don't have this tag */
968 } else { //multiple tags
969 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
970 for(i=0; i<parameter->numbertags; i++) {
971 //slotid is parameter->tagarray[2*i];
972 int tagid=parameter->tagarray[2*i+1];
974 for(j=0; j<ao->___cachedCode___; j++) {
975 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
986 for(i=0; i<parameter->numberofterms; i++) {
987 int andmask=parameter->intarray[i*2];
988 int checkmask=parameter->intarray[i*2+1];
989 if ((ptr->flag&andmask)==checkmask) {
990 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1001 void enqueueObject_I(void * vptr,
1002 struct parameterwrapper ** vqueues,
1004 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1007 //struct QueueItem *tmpptr;
1008 struct parameterwrapper * parameter=NULL;
1011 struct parameterwrapper * prevptr=NULL;
1012 struct ___Object___ *tagptr=NULL;
1013 struct parameterwrapper ** queues = vqueues;
1014 int length = vlength;
1015 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1018 if(queues == NULL) {
1019 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1020 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1022 tagptr=ptr->___tags___;
1024 /* Outer loop iterates through all parameter queues an object of
1025 this type could be in. */
1026 for(j = 0; j < length; ++j) {
1027 parameter = queues[j];
1029 if (parameter->numbertags>0) {
1031 goto nextloop; //that means the object has no tag
1032 //but that param needs tag
1033 else if(tagptr->type==TAGTYPE) { //one tag
1034 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1035 for(i=0; i<parameter->numbertags; i++) {
1036 //slotid is parameter->tagarray[2*i];
1037 int tagid=parameter->tagarray[2*i+1];
1038 if (tagid!=tagptr->flag)
1039 goto nextloop; /*We don't have this tag */
1041 } else { //multiple tags
1042 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1043 for(i=0; i<parameter->numbertags; i++) {
1044 //slotid is parameter->tagarray[2*i];
1045 int tagid=parameter->tagarray[2*i+1];
1047 for(j=0; j<ao->___cachedCode___; j++) {
1048 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1059 for(i=0; i<parameter->numberofterms; i++) {
1060 int andmask=parameter->intarray[i*2];
1061 int checkmask=parameter->intarray[i*2+1];
1062 if ((ptr->flag&andmask)==checkmask) {
1063 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1075 int * getAliasLock(void ** ptrs,
1077 struct RuntimeHash * tbl) {
1079 return (int*)(RUNMALLOC(sizeof(int)));
1084 bool redirect = false;
1085 int redirectlock = 0;
1086 for(; i < length; i++) {
1087 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1090 if(ptr->lock == NULL) {
1093 lock = (int)(ptr->lock);
1096 if(lock != redirectlock) {
1097 RuntimeHashadd(tbl, lock, redirectlock);
1100 if(RuntimeHashcontainskey(tbl, lock)) {
1101 // already redirected
1103 RuntimeHashget(tbl, lock, &redirectlock);
1104 for(; j < locklen; j++) {
1105 if(locks[j] != redirectlock) {
1106 RuntimeHashadd(tbl, locks[j], redirectlock);
1111 for(j = 0; j < locklen; j++) {
1112 if(locks[j] == lock) {
1115 } else if(locks[j] > lock) {
1122 locks[h] = locks[h-1];
1131 return (int *)redirectlock;
1133 return (int *)(locks[0]);
1138 void addAliasLock(void * ptr,
1140 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1141 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1142 // originally no alias lock associated or have a different alias lock
1143 // flush it as the new one
1144 obj->lock = (int *)lock;
1149 inline void setTaskExitIndex(int index) {
1150 taskInfoArray[taskInfoIndex]->exitIndex = index;
1153 inline void addNewObjInfo(void * nobj) {
1154 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1155 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1157 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1161 void * smemalloc(int size,
1165 // go through free mem list for suitable blocks
1166 struct freeMemItem * freemem = bamboo_free_mem_list->head;
1167 struct freeMemItem * prev = NULL;
1169 if(freemem->size >= size) {
1174 freemem = freemem->next;
1175 } while(freemem != NULL);
1176 if(freemem != NULL) {
1177 mem = (void *)(freemem->ptr);
1179 freemem->ptr = ((void*)freemem->ptr) + size;
1180 freemem->size -= size;
1181 // check how many blocks it acrosses
1183 BLOCKINDEX(mem, &b);
1184 // check the remaining space in this block
1185 int remain = (b < NUMCORES? (b+1)*BAMBOO_SMEM_SIZE_L
1186 : BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES+1)*BAMBOO_SMEM_SIZE)
1187 -((int)mem-BAMBOO_BASE_VA);
1189 // this object acrosses blocks
1190 int tmpsbs = 1+(size-remain-1)/BAMBOO_SMEM_SIZE;
1191 for(int k = 0; k < tmpsbs-1; k++) {
1192 gcsbstarttbl[k+b] = (INTPTR)(-1);
1194 if((size-remain)%BAMBOO_SMEM_SIZE == 0) {
1195 gcsbstarttbl[b+tmpsbs-1] = (INTPTR)(-1);
1197 gcsbstarttbl[b+tmpsbs-1] = (INTPTR)(mem+size);
1202 mem = mspace_calloc(bamboo_free_msp, 1, size);
1206 // no enough shared global memory
1212 BAMBOO_DEBUGPRINT(0xa001);
1213 BAMBOO_EXIT(0xa001);
1219 // receive object transferred from other cores
1220 // or the terminate message from other cores
1221 // Should be invoked in critical sections!!
1222 // NOTICE: following format is for threadsimulate version only
1223 // RAW version please see previous description
1224 // format: type + object
1225 // type: -1--stall msg
1227 // return value: 0--received an object
1228 // 1--received nothing
1229 // 2--received a Stall Msg
1230 // 3--received a lock Msg
1231 // RAW version: -1 -- received nothing
1232 // otherwise -- received msg type
1233 int receiveObject() {
1237 if(receiveMsg() == -1) {
1241 if(msgdataindex == msglength) {
1242 // received a whole msg
1247 // receive a object transfer msg
1248 struct transObjInfo * transObj =
1249 RUNMALLOC_I(sizeof(struct transObjInfo));
1253 BAMBOO_DEBUGPRINT(0xe880);
1256 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1258 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1260 BAMBOO_EXIT(0xa002);
1262 // store the object and its corresponding queue info, enqueue it later
1263 transObj->objptr = (void *)msgdata[2];
1264 transObj->length = (msglength - 3) / 2;
1265 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1266 for(k = 0; k < transObj->length; ++k) {
1267 transObj->queues[2*k] = msgdata[3+2*k];
1270 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1273 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1276 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1280 // check if there is an existing duplicate item
1282 struct QueueItem * qitem = getHead(&objqueue);
1283 struct QueueItem * prev = NULL;
1284 while(qitem != NULL) {
1285 struct transObjInfo * tmpinfo =
1286 (struct transObjInfo *)(qitem->objectptr);
1287 if(tmpinfo->objptr == transObj->objptr) {
1288 // the same object, remove outdate one
1289 removeItem(&objqueue, qitem);
1295 qitem = getHead(&objqueue);
1297 qitem = getNextQueueItem(prev);
1300 addNewItem_I(&objqueue, (void *)transObj);
1302 ++(self_numreceiveobjs);
1307 // receive a stall msg
1308 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1309 // non startup core can not receive stall msg
1311 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1313 BAMBOO_EXIT(0xa003);
1315 if(msgdata[1] < NUMCORES) {
1318 BAMBOO_DEBUGPRINT(0xe881);
1321 corestatus[msgdata[1]] = 0;
1322 numsendobjs[msgdata[1]] = msgdata[2];
1323 numreceiveobjs[msgdata[1]] = msgdata[3];
1328 // GC version have no lock msgs
1329 #ifndef MULTICORE_GC
1331 // receive lock request msg, handle it right now
1332 // check to see if there is a lock exist for the required obj
1333 // msgdata[1] -> lock type
1334 int data2 = msgdata[2]; // obj pointer
1335 int data3 = msgdata[3]; // lock
1336 int data4 = msgdata[4]; // request core
1337 // -1: redirected, 0: approved, 1: denied
1338 deny = processlockrequest(msgdata[1], data3, data2,
1339 data4, data4, true);
1341 // this lock request is redirected
1344 // send response msg
1345 // for 32 bit machine, the size is always 4 words
1346 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1348 cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1350 send_msg_4(data4, tmp, msgdata[1], data2, data3);
1357 // receive lock grount msg
1358 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1360 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1362 BAMBOO_EXIT(0xa004);
1364 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1367 BAMBOO_DEBUGPRINT(0xe882);
1376 // conflicts on lockresults
1378 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1380 BAMBOO_EXIT(0xa005);
1386 // receive lock deny msg
1387 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1389 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1391 BAMBOO_EXIT(0xa006);
1393 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1396 BAMBOO_DEBUGPRINT(0xe883);
1405 // conflicts on lockresults
1407 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1409 BAMBOO_EXIT(0xa007);
1415 // receive lock release msg
1416 processlockrelease(msgdata[1], msgdata[2], 0, false);
1422 case PROFILEOUTPUT: {
1423 // receive an output profile data request msg
1424 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1425 // startup core can not receive profile output finish msg
1426 BAMBOO_EXIT(0xa008);
1430 BAMBOO_DEBUGPRINT(0xe885);
1434 totalexetime = msgdata[1];
1435 outputProfileData();
1437 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1439 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1444 case PROFILEFINISH: {
1445 // receive a profile output finish msg
1446 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1447 // non startup core can not receive profile output finish msg
1449 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1451 BAMBOO_EXIT(0xa009);
1455 BAMBOO_DEBUGPRINT(0xe886);
1458 profilestatus[msgdata[1]] = 0;
1463 // GC version has no lock msgs
1464 #ifndef MULTICORE_GC
1465 case REDIRECTLOCK: {
1466 // receive a redirect lock request msg, handle it right now
1467 // check to see if there is a lock exist for the required obj
1468 int data1 = msgdata[1]; // lock type
1469 int data2 = msgdata[2]; // obj pointer
1470 int data3 = msgdata[3]; // redirect lock
1471 int data4 = msgdata[4]; // root request core
1472 int data5 = msgdata[5]; // request core
1473 deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1475 // this lock request is redirected
1478 // send response msg
1479 // for 32 bit machine, the size is always 4 words
1481 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1482 data1, data2, data3);
1484 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1485 data1, data2, data3);
1491 case REDIRECTGROUNT: {
1492 // receive a lock grant msg with redirect info
1493 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1495 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1497 BAMBOO_EXIT(0xa00a);
1499 if(lockobj == msgdata[2]) {
1502 BAMBOO_DEBUGPRINT(0xe891);
1507 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1512 // conflicts on lockresults
1514 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1516 BAMBOO_EXIT(0xa00b);
1521 case REDIRECTDENY: {
1522 // receive a lock deny msg with redirect info
1523 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1525 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1527 BAMBOO_EXIT(0xa00c);
1529 if(lockobj == msgdata[2]) {
1532 BAMBOO_DEBUGPRINT(0xe892);
1541 // conflicts on lockresults
1543 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1545 BAMBOO_EXIT(0xa00d);
1550 case REDIRECTRELEASE: {
1551 // receive a lock release msg with redirect info
1552 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1557 case STATUSCONFIRM: {
1558 // receive a status confirm info
1559 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1560 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1561 // wrong core to receive such msg
1562 BAMBOO_EXIT(0xa00e);
1564 // send response msg
1567 BAMBOO_DEBUGPRINT(0xe887);
1571 cache_msg_5(STARTUPCORE, STATUSREPORT,
1572 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1573 self_numsendobjs, self_numreceiveobjs);
1575 send_msg_5(STARTUPCORE, STATUSREPORT,
1576 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1577 self_numsendobjs, self_numreceiveobjs);
1583 case STATUSREPORT: {
1584 // receive a status confirm info
1585 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1586 // wrong core to receive such msg
1588 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1590 BAMBOO_EXIT(0xa00f);
1594 BAMBOO_DEBUGPRINT(0xe888);
1600 corestatus[msgdata[2]] = msgdata[1];
1601 numsendobjs[msgdata[2]] = msgdata[3];
1602 numreceiveobjs[msgdata[2]] = msgdata[4];
1608 // receive a terminate msg
1611 BAMBOO_DEBUGPRINT(0xe889);
1620 // receive a shared memory request msg
1621 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1622 // wrong core to receive such msg
1624 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1626 BAMBOO_EXIT(0xa010);
1630 BAMBOO_DEBUGPRINT(0xe88a);
1635 // is currently doing gc, dump this msg
1640 void * mem = smemalloc(msgdata[1], &allocsize);
1644 // send the start_va to request core
1646 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1648 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1655 // receive a shared memory response msg
1658 BAMBOO_DEBUGPRINT(0xe88b);
1663 // is currently doing gc, dump this msg
1667 if(msgdata[2] == 0) {
1668 bamboo_smem_size = 0;
1671 // fill header to store the size of this mem block
1672 (*((int*)msgdata[1])) = msgdata[2];
1673 bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1675 bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1678 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1679 msgdata[2]-BAMBOO_CACHE_LINE_SIZE,
1690 // receive a start GC msg
1693 BAMBOO_DEBUGPRINT(0xe88c);
1698 gcphase = MARKPHASE;
1700 // is waiting for response of mem request
1701 // let it return NULL and start gc
1702 bamboo_smem_size = 0;
1703 bamboo_cur_msp = NULL;
1709 case GCSTARTCOMPACT: {
1710 // a compact phase start msg
1711 gcblock2fill = msgdata[1];
1712 gcphase = COMPACTPHASE;
1716 case GCSTARTFLUSH: {
1717 // received a flush phase start msg
1718 gcphase = FLUSHPHASE;
1722 case GCFINISHMARK: {
1723 // received a mark phase finish msg
1724 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1725 // non startup core can not receive this msg
1727 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1729 BAMBOO_EXIT(0xb001);
1731 if(msgdata[1] < NUMCORES) {
1732 gccorestatus[msgdata[1]] = 0;
1733 gcnumsendobjs[msgdata[1]] = msgdata[2];
1734 gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1739 case GCFINISHCOMPACT: {
1740 // received a compact phase finish msg
1741 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1742 // non startup core can not receive this msg
1745 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1747 BAMBOO_EXIT(0xb002);
1749 int cnum = msgdata[1];
1750 int filledblocks = msgdata[2];
1751 int heaptop = msgdata[3];
1752 int data4 = msgdata[4];
1753 if(cnum < NUMCORES) {
1754 if(COMPACTPHASE == gcphase) {
1755 gcfilledblocks[cnum] = filledblocks;
1756 gcloads[cnum] = heaptop;
1763 if(gcfindSpareMem(&startaddr, &tomove, &dstcore, data4, cnum)) {
1764 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1767 gccorestatus[cnum] = 0;
1768 // check if there is pending move request
1769 if(gcmovepending > 0) {
1771 for(j = 0; j < NUMCORES; j++) {
1772 if(gcrequiredmems[j]>0) {
1780 gcrequiredmems[j] = assignSpareMem(cnum,
1784 if(STARTUPCORE == j) {
1787 gcmovestartaddr = startaddr;
1788 gcblock2fill = tomove;
1790 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1791 } // if(STARTUPCORE == j)
1792 if(gcrequiredmems[j] == 0) {
1795 } // if(j < NUMCORES)
1796 } // if(gcmovepending > 0)
1798 } // if(cnum < NUMCORES)
1802 case GCFINISHFLUSH: {
1803 // received a flush phase finish msg
1804 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1805 // non startup core can not receive this msg
1808 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1810 BAMBOO_EXIT(0xb003);
1812 if(msgdata[1] < NUMCORES) {
1813 gccorestatus[msgdata[1]] = 0;
1819 // received a GC finish msg
1820 gcphase = FINISHPHASE;
1824 case GCMARKCONFIRM: {
1825 // received a marked phase finish confirm request msg
1826 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1827 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1828 // wrong core to receive such msg
1829 BAMBOO_EXIT(0xb004);
1831 // send response msg
1833 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1834 gcbusystatus, gcself_numsendobjs,
1835 gcself_numreceiveobjs);
1837 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1838 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1844 case GCMARKREPORT: {
1845 // received a marked phase finish confirm response msg
1846 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1847 // wrong core to receive such msg
1849 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1851 BAMBOO_EXIT(0xb005);
1856 gccorestatus[msgdata[1]] = msgdata[2];
1857 gcnumsendobjs[msgdata[1]] = msgdata[3];
1858 gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1864 // received a markedObj msg
1865 gc_enqueue(msgdata[1]);
1866 gcself_numreceiveobjs++;
1867 gcbusystatus = true;
1872 // received a start moving objs msg
1874 gcdstcore = msgdata[1];
1875 gcmovestartaddr = msgdata[2];
1876 gcblock2fill = msgdata[3];
1880 case GCMAPREQUEST: {
1881 // received a mapping info request msg
1882 void * dstptr = NULL;
1883 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1884 if(NULL == dstptr) {
1885 // no such pointer in this core, something is wrong
1886 BAMBOO_EXIT(0xb006);
1888 // send back the mapping info
1890 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1892 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1899 // received a mapping info response msg
1900 if(msgdata[1] != gcobj2map) {
1901 // obj not matched, something is wrong
1902 BAMBOO_EXIT(0xb007);
1904 gcmappedobj = msgdata[2];
1905 RuntimeHashadd(gcpointertbl, gcobj2map, gcmappedobj);
1911 case GCLOBJREQUEST: {
1912 // received a large objs info request msg
1913 transferMarkResults();
1918 // received a large objs info response msg
1921 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1923 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1925 BAMBOO_EXIT(0xb008);
1927 // store the mark result info
1928 int cnum = msgdata[2];
1929 gcloads[cnum] = msgdata[3];
1930 if(gcheaptop < msgdata[4]) {
1931 gcheaptop = msgdata[4];
1933 // large obj info here
1934 for(int k = 5; k < msgdata[1];) {
1935 gc_lobjenqueue(msgdata[k++], msgdata[k++], cnum);
1936 } // for(int k = 5; k < msgdata[1];)
1940 case GCLOBJMAPPING: {
1941 // received a large obj mapping info msg
1942 RuntimeHashadd(gcpointertbl, msgdata[1], msgdata[2]);
1951 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1952 msgdata[msgdataindex] = -1;
1958 BAMBOO_DEBUGPRINT(0xe88d);
1962 if(BAMBOO_MSG_AVAIL() != 0) {
1975 BAMBOO_DEBUGPRINT(0xe88e);
1979 /* if(isInterrupt) {
1987 int enqueuetasks(struct parameterwrapper *parameter,
1988 struct parameterwrapper *prevptr,
1989 struct ___Object___ *ptr,
1991 int numenterflags) {
1992 void * taskpointerarray[MAXTASKPARAMS];
1994 //int numparams=parameter->task->numParameters;
1995 int numiterators=parameter->task->numTotal-1;
1998 struct taskdescriptor * task=parameter->task;
2000 //this add the object to parameterwrapper
2001 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
2002 numenterflags, enterflags==NULL);
2004 /* Add enqueued object to parameter vector */
2005 taskpointerarray[parameter->slot]=ptr;
2007 /* Reset iterators */
2008 for(j=0; j<numiterators; j++) {
2009 toiReset(¶meter->iterators[j]);
2012 /* Find initial state */
2013 for(j=0; j<numiterators; j++) {
2015 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2016 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2018 /* Need to backtrack */
2019 toiReset(¶meter->iterators[j]);
2023 /* Nothing to enqueue */
2029 /* Enqueue current state */
2031 struct taskparamdescriptor *tpd=
2032 RUNMALLOC(sizeof(struct taskparamdescriptor));
2034 tpd->numParameters=numiterators+1;
2035 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2037 for(j=0; j<=numiterators; j++) {
2038 //store the actual parameters
2039 tpd->parameterArray[j]=taskpointerarray[j];
2042 if ((/*!gencontains(failedtasks, tpd)&&*/
2043 !gencontains(activetasks,tpd))) {
2044 genputtable(activetasks, tpd, tpd);
2046 RUNFREE(tpd->parameterArray);
2050 /* This loop iterates to the next parameter combination */
2051 if (numiterators==0)
2054 for(j=numiterators-1; j<numiterators; j++) {
2056 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2057 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2059 /* Need to backtrack */
2060 toiReset(¶meter->iterators[j]);
2064 /* Nothing more to enqueue */
2072 int enqueuetasks_I(struct parameterwrapper *parameter,
2073 struct parameterwrapper *prevptr,
2074 struct ___Object___ *ptr,
2076 int numenterflags) {
2077 void * taskpointerarray[MAXTASKPARAMS];
2079 //int numparams=parameter->task->numParameters;
2080 int numiterators=parameter->task->numTotal-1;
2085 struct taskdescriptor * task=parameter->task;
2087 //this add the object to parameterwrapper
2088 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2089 numenterflags, enterflags==NULL);
2091 /* Add enqueued object to parameter vector */
2092 taskpointerarray[parameter->slot]=ptr;
2094 /* Reset iterators */
2095 for(j=0; j<numiterators; j++) {
2096 toiReset(¶meter->iterators[j]);
2099 /* Find initial state */
2100 for(j=0; j<numiterators; j++) {
2102 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2103 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2105 /* Need to backtrack */
2106 toiReset(¶meter->iterators[j]);
2110 /* Nothing to enqueue */
2116 /* Enqueue current state */
2118 struct taskparamdescriptor *tpd=
2119 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2121 tpd->numParameters=numiterators+1;
2122 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2124 for(j=0; j<=numiterators; j++) {
2125 //store the actual parameters
2126 tpd->parameterArray[j]=taskpointerarray[j];
2129 if ((/*!gencontains(failedtasks, tpd)&&*/
2130 !gencontains(activetasks,tpd))) {
2131 genputtable_I(activetasks, tpd, tpd);
2133 RUNFREE(tpd->parameterArray);
2137 /* This loop iterates to the next parameter combination */
2138 if (numiterators==0)
2141 for(j=numiterators-1; j<numiterators; j++) {
2143 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2144 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2146 /* Need to backtrack */
2147 toiReset(¶meter->iterators[j]);
2151 /* Nothing more to enqueue */
2165 int containstag(struct ___Object___ *ptr,
2166 struct ___TagDescriptor___ *tag);
2168 #ifndef MULTICORE_GC
2169 void releasewritelock_r(void * lock, void * redirectlock) {
2171 int reallock = (int)lock;
2172 targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2175 BAMBOO_DEBUGPRINT(0xe671);
2176 BAMBOO_DEBUGPRINT_REG((int)lock);
2177 BAMBOO_DEBUGPRINT_REG(reallock);
2178 BAMBOO_DEBUGPRINT_REG(targetcore);
2181 if(targetcore == BAMBOO_NUM_OF_CORE) {
2182 BAMBOO_START_CRITICAL_SECTION_LOCK();
2184 BAMBOO_DEBUGPRINT(0xf001);
2186 // reside on this core
2187 if(!RuntimeHashcontainskey(locktbl, reallock)) {
2188 // no locks for this object, something is wrong
2189 BAMBOO_EXIT(0xa011);
2192 struct LockValue * lockvalue = NULL;
2194 BAMBOO_DEBUGPRINT(0xe672);
2196 RuntimeHashget(locktbl, reallock, &rwlock_obj);
2197 lockvalue = (struct LockValue *)rwlock_obj;
2199 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2202 lockvalue->redirectlock = (int)redirectlock;
2204 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2207 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2209 BAMBOO_DEBUGPRINT(0xf000);
2213 // send lock release with redirect info msg
2214 // for 32 bit machine, the size is always 4 words
2215 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2220 void executetasks() {
2221 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2224 struct ___Object___ * tmpparam = NULL;
2225 struct parameterdescriptor * pd=NULL;
2226 struct parameterwrapper *pw=NULL;
2231 struct LockValue locks[MAXTASKPARAMS];
2239 while(hashsize(activetasks)>0) {
2244 BAMBOO_DEBUGPRINT(0xe990);
2247 /* See if there are any active tasks */
2248 if (hashsize(activetasks)>0) {
2251 #ifdef ACCURATEPROFILE
2252 profileTaskStart("tpd checking");
2256 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2257 genfreekey(activetasks, currtpd);
2259 numparams=currtpd->task->numParameters;
2260 numtotal=currtpd->task->numTotal;
2262 // clear the lockRedirectTbl
2263 // (TODO, this table should be empty after all locks are released)
2265 for(j = 0; j < MAXTASKPARAMS; j++) {
2266 locks[j].redirectlock = 0;
2269 // get all required locks
2271 // check which locks are needed
2272 for(i = 0; i < numparams; i++) {
2273 void * param = currtpd->parameterArray[i];
2277 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2279 taskpointerarray[i+OFFSET]=param;
2282 if(((struct ___Object___ *)param)->lock == NULL) {
2283 tmplock = (int)param;
2285 tmplock = (int)(((struct ___Object___ *)param)->lock);
2287 // insert into the locks array
2288 for(j = 0; j < locklen; j++) {
2289 if(locks[j].value == tmplock) {
2292 } else if(locks[j].value > tmplock) {
2299 locks[h].redirectlock = locks[h-1].redirectlock;
2300 locks[h].value = locks[h-1].value;
2302 locks[j].value = tmplock;
2303 locks[j].redirectlock = (int)param;
2306 } // line 2713: for(i = 0; i < numparams; i++)
2307 // grab these required locks
2309 BAMBOO_DEBUGPRINT(0xe991);
2311 for(i = 0; i < locklen; i++) {
2312 int * lock = (int *)(locks[i].redirectlock);
2314 // require locks for this parameter if it is not a startup object
2316 BAMBOO_DEBUGPRINT_REG((int)lock);
2317 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2320 BAMBOO_START_CRITICAL_SECTION();
2322 BAMBOO_DEBUGPRINT(0xf001);
2325 //isInterrupt = false;
2328 BAMBOO_WAITING_FOR_LOCK();
2332 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2336 grount = lockresult;
2346 //isInterrupt = true;
2348 BAMBOO_CLOSE_CRITICAL_SECTION();
2350 BAMBOO_DEBUGPRINT(0xf000);
2356 BAMBOO_DEBUGPRINT(0xe992);
2358 // can not get the lock, try later
2359 // releas all grabbed locks for previous parameters
2360 for(j = 0; j < i; ++j) {
2361 lock = (int*)(locks[j].redirectlock);
2362 releasewritelock(lock);
2364 genputtable(activetasks, currtpd, currtpd);
2365 if(hashsize(activetasks) == 1) {
2366 // only one task right now, wait a little while before next try
2372 #ifdef ACCURATEPROFILE
2373 // fail, set the end of the checkTaskInfo
2378 } // line 2794: if(grount == 0)
2379 } // line 2752: for(i = 0; i < locklen; i++)
2382 BAMBOO_DEBUGPRINT(0xe993);
2384 /* Make sure that the parameters are still in the queues */
2385 for(i=0; i<numparams; i++) {
2386 void * parameter=currtpd->parameterArray[i];
2390 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
2391 classsize[((struct ___Object___ *)parameter)->type]);
2393 tmpparam = (struct ___Object___ *)parameter;
2394 pd=currtpd->task->descriptorarray[i];
2395 pw=(struct parameterwrapper *) pd->queue;
2396 /* Check that object is still in queue */
2398 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2400 BAMBOO_DEBUGPRINT(0xe994);
2402 // release grabbed locks
2403 for(j = 0; j < locklen; ++j) {
2404 int * lock = (int *)(locks[j].redirectlock);
2405 releasewritelock(lock);
2407 RUNFREE(currtpd->parameterArray);
2412 /* Check if the object's flags still meets requirements */
2416 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2417 andmask=pw->intarray[tmpi*2];
2418 checkmask=pw->intarray[tmpi*2+1];
2419 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2425 // flags are never suitable
2426 // remove this obj from the queue
2428 int UNUSED, UNUSED2;
2431 BAMBOO_DEBUGPRINT(0xe995);
2433 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
2434 (int *) &enterflags, &UNUSED, &UNUSED2);
2435 ObjectHashremove(pw->objectset, (int)parameter);
2436 if (enterflags!=NULL)
2437 RUNFREE(enterflags);
2438 // release grabbed locks
2439 for(j = 0; j < locklen; ++j) {
2440 int * lock = (int *)(locks[j].redirectlock);
2441 releasewritelock(lock);
2443 RUNFREE(currtpd->parameterArray);
2446 #ifdef ACCURATEPROFILE
2447 // fail, set the end of the checkTaskInfo
2452 } // line 2878: if (!ismet)
2456 /* Check that object still has necessary tags */
2457 for(j=0; j<pd->numbertags; j++) {
2458 int slotid=pd->tagarray[2*j]+numparams;
2459 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2460 if (!containstag(parameter, tagd)) {
2462 BAMBOO_DEBUGPRINT(0xe996);
2465 // release grabbed locks
2467 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2468 int * lock = (int *)(locks[tmpj].redirectlock);
2469 releasewritelock(lock);
2472 RUNFREE(currtpd->parameterArray);
2475 } // line2911: if (!containstag(parameter, tagd))
2476 } // line 2808: for(j=0; j<pd->numbertags; j++)
2478 taskpointerarray[i+OFFSET]=parameter;
2479 } // line 2824: for(i=0; i<numparams; i++)
2481 for(; i<numtotal; i++) {
2482 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2486 /* Actually call task */
2488 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2489 taskpointerarray[1]=NULL;
2493 #ifdef ACCURATEPROFILE
2494 // check finish, set the end of the checkTaskInfo
2497 profileTaskStart(currtpd->task->name);
2501 BAMBOO_DEBUGPRINT(0xe997);
2503 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2505 #ifdef ACCURATEPROFILE
2506 // task finish, set the end of the checkTaskInfo
2508 // new a PostTaskInfo for the post-task execution
2509 profileTaskStart("post task execution");
2513 BAMBOO_DEBUGPRINT(0xe998);
2514 BAMBOO_DEBUGPRINT_REG(islock);
2519 BAMBOO_DEBUGPRINT(0xe999);
2521 for(i = 0; i < locklen; ++i) {
2522 void * ptr = (void *)(locks[i].redirectlock);
2523 int * lock = (int *)(locks[i].value);
2525 BAMBOO_DEBUGPRINT_REG((int)ptr);
2526 BAMBOO_DEBUGPRINT_REG((int)lock);
2528 #ifndef MULTICORE_GC
2529 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2531 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2532 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2533 releasewritelock_r(lock, (int *)redirectlock);
2538 releasewritelock(ptr);
2541 } // line 3015: if(islock)
2544 // post task execution finish, set the end of the postTaskInfo
2548 // Free up task parameter descriptor
2549 RUNFREE(currtpd->parameterArray);
2552 BAMBOO_DEBUGPRINT(0xe99a);
2555 } // if (hashsize(activetasks)>0)
2556 } // while(hashsize(activetasks)>0)
2558 BAMBOO_DEBUGPRINT(0xe99b);
2562 /* This function processes an objects tags */
2563 void processtags(struct parameterdescriptor *pd,
2565 struct parameterwrapper *parameter,
2566 int * iteratorcount,
2571 for(i=0; i<pd->numbertags; i++) {
2572 int slotid=pd->tagarray[2*i];
2573 int tagid=pd->tagarray[2*i+1];
2575 if (statusarray[slotid+numparams]==0) {
2576 parameter->iterators[*iteratorcount].istag=1;
2577 parameter->iterators[*iteratorcount].tagid=tagid;
2578 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2579 parameter->iterators[*iteratorcount].tagobjectslot=index;
2580 statusarray[slotid+numparams]=1;
2587 void processobject(struct parameterwrapper *parameter,
2589 struct parameterdescriptor *pd,
2595 struct ObjectHash * objectset=
2596 ((struct parameterwrapper *)pd->queue)->objectset;
2598 parameter->iterators[*iteratorcount].istag=0;
2599 parameter->iterators[*iteratorcount].slot=index;
2600 parameter->iterators[*iteratorcount].objectset=objectset;
2601 statusarray[index]=1;
2603 for(i=0; i<pd->numbertags; i++) {
2604 int slotid=pd->tagarray[2*i];
2605 //int tagid=pd->tagarray[2*i+1];
2606 if (statusarray[slotid+numparams]!=0) {
2607 /* This tag has already been enqueued, use it to narrow search */
2608 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2613 parameter->iterators[*iteratorcount].numtags=tagcount;
2618 /* This function builds the iterators for a task & parameter */
2620 void builditerators(struct taskdescriptor * task,
2622 struct parameterwrapper * parameter) {
2623 int statusarray[MAXTASKPARAMS];
2625 int numparams=task->numParameters;
2626 int iteratorcount=0;
2627 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2629 statusarray[index]=1; /* Initial parameter */
2630 /* Process tags for initial iterator */
2632 processtags(task->descriptorarray[index], index, parameter,
2633 &iteratorcount, statusarray, numparams);
2637 /* Check for objects with existing tags */
2638 for(i=0; i<numparams; i++) {
2639 if (statusarray[i]==0) {
2640 struct parameterdescriptor *pd=task->descriptorarray[i];
2642 for(j=0; j<pd->numbertags; j++) {
2643 int slotid=pd->tagarray[2*j];
2644 if(statusarray[slotid+numparams]!=0) {
2645 processobject(parameter, i, pd, &iteratorcount, statusarray,
2647 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2654 /* Next do objects w/ unbound tags*/
2656 for(i=0; i<numparams; i++) {
2657 if (statusarray[i]==0) {
2658 struct parameterdescriptor *pd=task->descriptorarray[i];
2659 if (pd->numbertags>0) {
2660 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2661 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2667 /* Nothing with a tag enqueued */
2669 for(i=0; i<numparams; i++) {
2670 if (statusarray[i]==0) {
2671 struct parameterdescriptor *pd=task->descriptorarray[i];
2672 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2673 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2686 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2689 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2690 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2692 printf("%s\n", task->name);
2694 for(j=0; j<task->numParameters; j++) {
2695 struct parameterdescriptor *param=task->descriptorarray[j];
2696 struct parameterwrapper *parameter=param->queue;
2697 struct ObjectHash * set=parameter->objectset;
2698 struct ObjectIterator objit;
2700 printf(" Parameter %d\n", j);
2702 ObjectHashiterator(set, &objit);
2703 while(ObjhasNext(&objit)) {
2704 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2705 struct ___Object___ * tagptr=obj->___tags___;
2706 int nonfailed=Objdata4(&objit);
2707 int numflags=Objdata3(&objit);
2708 int flags=Objdata2(&objit);
2711 printf(" Contains %lx\n", obj);
2712 printf(" flag=%d\n", obj->flag);
2715 } else if (tagptr->type==TAGTYPE) {
2717 printf(" tag=%lx\n",tagptr);
2723 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2724 for(; tagindex<ao->___cachedCode___; tagindex++) {
2726 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
2739 /* This function processes the task information to create queues for
2740 each parameter type. */
2742 void processtasks() {
2744 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2747 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2748 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2751 /* Build objectsets */
2752 for(j=0; j<task->numParameters; j++) {
2753 struct parameterdescriptor *param=task->descriptorarray[j];
2754 struct parameterwrapper *parameter=param->queue;
2755 parameter->objectset=allocateObjectHash(10);
2756 parameter->task=task;
2759 /* Build iterators for parameters */
2760 for(j=0; j<task->numParameters; j++) {
2761 struct parameterdescriptor *param=task->descriptorarray[j];
2762 struct parameterwrapper *parameter=param->queue;
2763 builditerators(task, j, parameter);
2768 void toiReset(struct tagobjectiterator * it) {
2771 } else if (it->numtags>0) {
2774 ObjectHashiterator(it->objectset, &it->it);
2778 int toiHasNext(struct tagobjectiterator *it,
2779 void ** objectarray OPTARG(int * failed)) {
2782 /* Get object with tags */
2783 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2784 struct ___Object___ *tagptr=obj->___tags___;
2785 if (tagptr->type==TAGTYPE) {
2786 if ((it->tagobjindex==0)&& /* First object */
2787 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2792 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2793 int tagindex=it->tagobjindex;
2794 for(; tagindex<ao->___cachedCode___; tagindex++) {
2795 struct ___TagDescriptor___ *td=
2796 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2797 if (td->flag==it->tagid) {
2798 it->tagobjindex=tagindex; /* Found right type of tag */
2804 } else if (it->numtags>0) {
2805 /* Use tags to locate appropriate objects */
2806 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2807 struct ___Object___ *objptr=tag->flagptr;
2809 if (objptr->type!=OBJECTARRAYTYPE) {
2810 if (it->tagobjindex>0)
2812 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2814 for(i=1; i<it->numtags; i++) {
2815 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2816 if (!containstag(objptr,tag2))
2821 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2824 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2825 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2826 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2828 for(i=1; i<it->numtags; i++) {
2829 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2830 if (!containstag(objptr,tag2))
2833 it->tagobjindex=tagindex;
2838 it->tagobjindex=tagindex;
2842 return ObjhasNext(&it->it);
2846 int containstag(struct ___Object___ *ptr,
2847 struct ___TagDescriptor___ *tag) {
2849 struct ___Object___ * objptr=tag->flagptr;
2850 if (objptr->type==OBJECTARRAYTYPE) {
2851 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2852 for(j=0; j<ao->___cachedCode___; j++) {
2853 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2861 void toiNext(struct tagobjectiterator *it,
2862 void ** objectarray OPTARG(int * failed)) {
2863 /* hasNext has all of the intelligence */
2866 /* Get object with tags */
2867 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2868 struct ___Object___ *tagptr=obj->___tags___;
2869 if (tagptr->type==TAGTYPE) {
2871 objectarray[it->slot]=tagptr;
2873 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2874 objectarray[it->slot]=
2875 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2877 } else if (it->numtags>0) {
2878 /* Use tags to locate appropriate objects */
2879 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2880 struct ___Object___ *objptr=tag->flagptr;
2881 if (objptr->type!=OBJECTARRAYTYPE) {
2883 objectarray[it->slot]=objptr;
2885 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2886 objectarray[it->slot]=
2887 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2890 /* Iterate object */
2891 objectarray[it->slot]=(void *)Objkey(&it->it);