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;
74 totransobjqueue = createQueue();
79 gcphase = FINISHPHASE;
81 gcself_numsendobjs = 0;
82 gcself_numreceiveobjs = 0;
84 gcpointertbl = allocateRuntimeHash(20);
96 gcsbstarttbl = BAMBOO_BASE_VA;
98 // create the lock table, lockresult table and obj queue
101 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
102 /* Set allocation blocks*/
103 locktable.listhead=NULL;
104 locktable.listtail=NULL;
106 locktable.numelements = 0;
111 lockRedirectTbl = allocateRuntimeHash(20);
112 objRedirectLockTbl = allocateRuntimeHash(20);
117 objqueue.head = NULL;
118 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);
143 if(currtpd != NULL) {
144 RUNFREE(currtpd->parameterArray);
150 inline __attribute__((always_inline))
151 bool checkObjQueue() {
153 struct transObjInfo * objInfo = NULL;
157 #ifdef ACCURATEPROFILE
158 bool isChecking = false;
159 if(!isEmpty(&objqueue)) {
160 profileTaskStart("objqueue checking");
162 } // if(!isEmpty(&objqueue))
166 while(!isEmpty(&objqueue)) {
168 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
170 BAMBOO_DEBUGPRINT(0xf001);
173 //isInterrupt = false;
176 BAMBOO_DEBUGPRINT(0xeee1);
179 objInfo = (struct transObjInfo *)getItem(&objqueue);
180 obj = objInfo->objptr;
182 BAMBOO_DEBUGPRINT_REG((int)obj);
184 // grab lock and flush the obj
188 BAMBOO_WAITING_FOR_LOCK();
189 } // while(!lockflag)
192 BAMBOO_DEBUGPRINT_REG(grount);
207 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
208 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
209 classsize[((struct ___Object___ *)obj)->type]);
211 // enqueue the object
212 for(k = 0; k < objInfo->length; ++k) {
213 int taskindex = objInfo->queues[2 * k];
214 int paramindex = objInfo->queues[2 * k + 1];
215 struct parameterwrapper ** queues =
216 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
218 BAMBOO_DEBUGPRINT_REG(taskindex);
219 BAMBOO_DEBUGPRINT_REG(paramindex);
220 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
221 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
222 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
223 (long)obj, tmpptr->flag);
225 enqueueObject_I(obj, queues, 1);
227 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
229 } // for(k = 0; k < objInfo->length; ++k)
230 releasewritelock_I(obj);
231 RUNFREE(objInfo->queues);
235 // put it at the end of the queue if no update version in the queue
236 struct QueueItem * qitem = getHead(&objqueue);
237 struct QueueItem * prev = NULL;
238 while(qitem != NULL) {
239 struct transObjInfo * tmpinfo =
240 (struct transObjInfo *)(qitem->objectptr);
241 if(tmpinfo->objptr == obj) {
242 // the same object in the queue, which should be enqueued
243 // recently. Current one is outdate, do not re-enqueue it
244 RUNFREE(objInfo->queues);
249 } // if(tmpinfo->objptr == obj)
250 qitem = getNextQueueItem(prev);
251 } // while(qitem != NULL)
252 // try to execute active tasks already enqueued first
253 addNewItem_I(&objqueue, objInfo);
255 //isInterrupt = true;
258 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
260 BAMBOO_DEBUGPRINT(0xf000);
264 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
266 BAMBOO_DEBUGPRINT(0xf000);
268 } // while(!isEmpty(&objqueue))
271 #ifdef ACCURATEPROFILE
279 BAMBOO_DEBUGPRINT(0xee02);
284 inline __attribute__((always_inline))
285 void checkCoreStatus() {
286 bool allStall = false;
290 (waitconfirm && (numconfirm == 0))) {
292 BAMBOO_DEBUGPRINT(0xee04);
293 BAMBOO_DEBUGPRINT_REG(waitconfirm);
295 BAMBOO_START_CRITICAL_SECTION_STATUS();
297 BAMBOO_DEBUGPRINT(0xf001);
299 corestatus[BAMBOO_NUM_OF_CORE] = 0;
300 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
301 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
302 // check the status of all cores
305 BAMBOO_DEBUGPRINT_REG(NUMCORES);
307 for(i = 0; i < NUMCORES; ++i) {
309 BAMBOO_DEBUGPRINT(0xe000 + corestatus[i]);
311 if(corestatus[i] != 0) {
315 } // for(i = 0; i < NUMCORES; ++i)
317 // check if the sum of send objs and receive obj are the same
318 // yes->check if the info is the latest; no->go on executing
320 for(i = 0; i < NUMCORES; ++i) {
321 sumsendobj += numsendobjs[i];
323 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
325 } // for(i = 0; i < NUMCORES; ++i)
326 for(i = 0; i < NUMCORES; ++i) {
327 sumsendobj -= numreceiveobjs[i];
329 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
331 } // for(i = 0; i < NUMCORES; ++i)
332 if(0 == sumsendobj) {
334 // the first time found all cores stall
335 // send out status confirm msg to all other cores
336 // reset the corestatus array too
338 BAMBOO_DEBUGPRINT(0xee05);
340 corestatus[BAMBOO_NUM_OF_CORE] = 1;
341 for(i = 1; i < NUMCORES; ++i) {
343 // send status confirm msg to core i
344 send_msg_1(i, STATUSCONFIRM);
345 } // for(i = 1; i < NUMCORES; ++i)
347 numconfirm = NUMCORES - 1;
349 // all the core status info are the latest
350 // terminate; for profiling mode, send request to all
351 // other cores to pour out profiling data
353 BAMBOO_DEBUGPRINT(0xee06);
357 totalexetime = BAMBOO_GET_EXE_TIME();
359 BAMBOO_DEBUGPRINT(BAMBOO_GET_EXE_TIME());
360 BAMBOO_DEBUGPRINT_REG(total_num_t6); // TODO for test
361 BAMBOO_DEBUGPRINT(0xbbbbbbbb);
363 // profile mode, send msgs to other cores to request pouring
364 // out progiling data
366 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
368 BAMBOO_DEBUGPRINT(0xf000);
370 for(i = 1; i < NUMCORES; ++i) {
371 // send profile request msg to core i
372 send_msg_2(i, PROFILEOUTPUT, totalexetime);
373 } // for(i = 1; i < NUMCORES; ++i)
374 // pour profiling data on startup core
377 BAMBOO_START_CRITICAL_SECTION_STATUS();
379 BAMBOO_DEBUGPRINT(0xf001);
381 profilestatus[BAMBOO_NUM_OF_CORE] = 0;
382 // check the status of all cores
385 BAMBOO_DEBUGPRINT_REG(NUMCORES);
387 for(i = 0; i < NUMCORES; ++i) {
389 BAMBOO_DEBUGPRINT(0xe000 + profilestatus[i]);
391 if(profilestatus[i] != 0) {
395 } // for(i = 0; i < NUMCORES; ++i)
398 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
400 BAMBOO_DEBUGPRINT(0xf000);
410 terminate(); // All done.
411 } // if(!waitconfirm)
413 // still some objects on the fly on the network
414 // reset the waitconfirm and numconfirm
416 BAMBOO_DEBUGPRINT(0xee07);
420 } // if(0 == sumsendobj)
422 // not all cores are stall, keep on waiting
424 BAMBOO_DEBUGPRINT(0xee08);
429 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
431 BAMBOO_DEBUGPRINT(0xf000);
433 } // if((!waitconfirm) ||
436 // main function for each core
437 inline void run(void * arg) {
441 bool sendStall = false;
443 bool tocontinue = false;
445 corenum = BAMBOO_GET_NUM_OF_CORE();
447 BAMBOO_DEBUGPRINT(0xeeee);
448 BAMBOO_DEBUGPRINT_REG(corenum);
449 BAMBOO_DEBUGPRINT(STARTUPCORE);
452 // initialize runtime data structures
455 // other architecture related initialization
459 initializeexithandler();
461 // main process of the execution module
462 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
463 // non-executing cores, only processing communications
466 BAMBOO_DEBUGPRINT(0xee01);
467 BAMBOO_DEBUGPRINT_REG(taskInfoIndex);
468 BAMBOO_DEBUGPRINT_REG(taskInfoOverflow);
469 profileTaskStart("msg handling");
473 //isInterrupt = false;
477 /* Create queue of active tasks */
479 genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
480 (int(*) (void *,void *)) &comparetpd);
482 /* Process task information */
485 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
486 /* Create startup object */
487 createstartupobject(argc, argv);
491 BAMBOO_DEBUGPRINT(0xee00);
496 // check if need to do GC
500 // check if there are new active tasks can be executed
507 while(receiveObject() != -1) {
512 BAMBOO_DEBUGPRINT(0xee01);
515 // check if there are some pending objects,
516 // if yes, enqueue them and executetasks again
517 tocontinue = checkObjQueue();
521 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
524 BAMBOO_DEBUGPRINT(0xee03);
532 BAMBOO_DEBUGPRINT(0xee09);
538 // wait for some time
541 BAMBOO_DEBUGPRINT(0xee0a);
547 // send StallMsg to startup core
549 BAMBOO_DEBUGPRINT(0xee0b);
552 send_msg_4(STARTUPCORE, TRANSTALL, BAMBOO_NUM_OF_CORE,
553 self_numsendobjs, self_numreceiveobjs);
565 BAMBOO_DEBUGPRINT(0xee0c);
568 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
571 } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
575 struct ___createstartupobject____I_locals {
578 struct ___StartupObject___ * ___startupobject___;
579 struct ArrayObject * ___stringarray___;
580 }; // struct ___createstartupobject____I_locals
582 void createstartupobject(int argc,
586 /* Allocate startup object */
588 struct ___createstartupobject____I_locals ___locals___={2, NULL, NULL, NULL};
589 struct ___StartupObject___ *startupobject=
590 (struct ___StartupObject___*) allocate_new(&___locals___, STARTUPTYPE);
591 ___locals___.___startupobject___ = startupobject;
592 struct ArrayObject * stringarray=
593 allocate_newarray(&___locals___, STRINGARRAYTYPE, argc-1);
594 ___locals___.___stringarray___ = stringarray;
596 struct ___StartupObject___ *startupobject=
597 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
598 struct ArrayObject * stringarray=
599 allocate_newarray(STRINGARRAYTYPE, argc-1);
601 /* Build array of strings */
602 startupobject->___parameters___=stringarray;
603 for(i=1; i<argc; i++) {
604 int length=strlen(argv[i]);
606 struct ___String___ *newstring=NewString(&___locals___, argv[i],length);
608 struct ___String___ *newstring=NewString(argv[i],length);
610 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
614 startupobject->version = 0;
615 startupobject->lock = NULL;
617 /* Set initialized flag for startup object */
618 flagorandinit(startupobject,1,0xFFFFFFFF);
619 enqueueObject(startupobject, NULL, 0);
621 BAMBOO_CACHE_FLUSH_ALL();
625 int hashCodetpd(struct taskparamdescriptor *ftd) {
626 int hash=(int)ftd->task;
628 for(i=0; i<ftd->numParameters; i++) {
629 hash^=(int)ftd->parameterArray[i];
634 int comparetpd(struct taskparamdescriptor *ftd1,
635 struct taskparamdescriptor *ftd2) {
637 if (ftd1->task!=ftd2->task)
639 for(i=0; i<ftd1->numParameters; i++)
640 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
645 /* This function sets a tag. */
647 void tagset(void *ptr,
648 struct ___Object___ * obj,
649 struct ___TagDescriptor___ * tagd) {
651 void tagset(struct ___Object___ * obj,
652 struct ___TagDescriptor___ * tagd) {
654 struct ArrayObject * ao=NULL;
655 struct ___Object___ * tagptr=obj->___tags___;
657 obj->___tags___=(struct ___Object___ *)tagd;
659 /* Have to check if it is already set */
660 if (tagptr->type==TAGTYPE) {
661 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
666 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
667 struct ArrayObject * ao=
668 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
669 obj=(struct ___Object___ *)ptrarray[2];
670 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
671 td=(struct ___TagDescriptor___ *) obj->___tags___;
673 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
676 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
677 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
678 obj->___tags___=(struct ___Object___ *) ao;
679 ao->___cachedCode___=2;
683 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
684 for(i=0; i<ao->___cachedCode___; i++) {
685 struct ___TagDescriptor___ * td=
686 ARRAYGET(ao, struct ___TagDescriptor___*, i);
691 if (ao->___cachedCode___<ao->___length___) {
692 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
693 ao->___cachedCode___++;
696 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
697 struct ArrayObject * aonew=
698 allocate_newarray(&ptrarray,TAGARRAYTYPE,
699 TAGARRAYINTERVAL+ao->___length___);
700 obj=(struct ___Object___ *)ptrarray[2];
701 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
702 ao=(struct ArrayObject *)obj->___tags___;
704 struct ArrayObject * aonew=
705 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
708 aonew->___cachedCode___=ao->___length___+1;
709 for(i=0; i<ao->___length___; i++) {
710 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
711 ARRAYGET(ao, struct ___TagDescriptor___*, i));
713 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
719 struct ___Object___ * tagset=tagd->flagptr;
722 } else if (tagset->type!=OBJECTARRAYTYPE) {
724 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
725 struct ArrayObject * ao=
726 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
727 obj=(struct ___Object___ *)ptrarray[2];
728 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
730 struct ArrayObject * ao=
731 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
733 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
734 ARRAYSET(ao, struct ___Object___ *, 1, obj);
735 ao->___cachedCode___=2;
736 tagd->flagptr=(struct ___Object___ *)ao;
738 struct ArrayObject *ao=(struct ArrayObject *) tagset;
739 if (ao->___cachedCode___<ao->___length___) {
740 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
744 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
745 struct ArrayObject * aonew=
746 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
747 OBJECTARRAYINTERVAL+ao->___length___);
748 obj=(struct ___Object___ *)ptrarray[2];
749 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
750 ao=(struct ArrayObject *)tagd->flagptr;
752 struct ArrayObject * aonew=
753 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
755 aonew->___cachedCode___=ao->___cachedCode___+1;
756 for(i=0; i<ao->___length___; i++) {
757 ARRAYSET(aonew, struct ___Object___*, i,
758 ARRAYGET(ao, struct ___Object___*, i));
760 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
761 tagd->flagptr=(struct ___Object___ *) aonew;
767 /* This function clears a tag. */
769 void tagclear(void *ptr,
770 struct ___Object___ * obj,
771 struct ___TagDescriptor___ * tagd) {
773 void tagclear(struct ___Object___ * obj,
774 struct ___TagDescriptor___ * tagd) {
776 /* We'll assume that tag is alway there.
777 Need to statically check for this of course. */
778 struct ___Object___ * tagptr=obj->___tags___;
780 if (tagptr->type==TAGTYPE) {
781 if ((struct ___TagDescriptor___ *)tagptr==tagd)
782 obj->___tags___=NULL;
784 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
786 for(i=0; i<ao->___cachedCode___; i++) {
787 struct ___TagDescriptor___ * td=
788 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
790 ao->___cachedCode___--;
791 if (i<ao->___cachedCode___)
792 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
793 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
794 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
795 if (ao->___cachedCode___==0)
796 obj->___tags___=NULL;
803 struct ___Object___ *tagset=tagd->flagptr;
804 if (tagset->type!=OBJECTARRAYTYPE) {
808 struct ArrayObject *ao=(struct ArrayObject *) tagset;
810 for(i=0; i<ao->___cachedCode___; i++) {
811 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
813 ao->___cachedCode___--;
814 if (i<ao->___cachedCode___)
815 ARRAYSET(ao, struct ___Object___ *, i,
816 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
817 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
818 if (ao->___cachedCode___==0)
829 /* This function allocates a new tag. */
831 struct ___TagDescriptor___ * allocate_tag(void *ptr,
833 struct ___TagDescriptor___ * v=
834 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
837 struct ___TagDescriptor___ * allocate_tag(int index) {
838 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
847 /* This function updates the flag for object ptr. It or's the flag
848 with the or mask and and's it with the andmask. */
850 void flagbody(struct ___Object___ *ptr,
852 struct parameterwrapper ** queues,
856 int flagcomp(const int *val1, const int *val2) {
857 return (*val1)-(*val2);
860 void flagorand(void * ptr,
863 struct parameterwrapper ** queues,
866 int oldflag=((int *)ptr)[1];
867 int flag=ormask|oldflag;
869 flagbody(ptr, flag, queues, length, false);
873 bool intflagorand(void * ptr,
877 int oldflag=((int *)ptr)[1];
878 int flag=ormask|oldflag;
880 if (flag==oldflag) /* Don't do anything */
883 flagbody(ptr, flag, NULL, 0, false);
889 void flagorandinit(void * ptr,
892 int oldflag=((int *)ptr)[1];
893 int flag=ormask|oldflag;
895 flagbody(ptr,flag,NULL,0,true);
898 void flagbody(struct ___Object___ *ptr,
900 struct parameterwrapper ** vqueues,
903 struct parameterwrapper * flagptr = NULL;
905 struct parameterwrapper ** queues = vqueues;
906 int length = vlength;
909 int * enterflags = NULL;
910 if((!isnew) && (queues == NULL)) {
911 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
912 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
913 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
920 /*Remove object from all queues */
921 for(i = 0; i < length; ++i) {
923 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
924 (int *) &enterflags, &UNUSED, &UNUSED2);
925 ObjectHashremove(flagptr->objectset, (int)ptr);
926 if (enterflags!=NULL)
931 void enqueueObject(void * vptr,
932 struct parameterwrapper ** vqueues,
934 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
937 //struct QueueItem *tmpptr;
938 struct parameterwrapper * parameter=NULL;
941 struct parameterwrapper * prevptr=NULL;
942 struct ___Object___ *tagptr=NULL;
943 struct parameterwrapper ** queues = vqueues;
944 int length = vlength;
945 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
949 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
950 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
952 tagptr=ptr->___tags___;
954 /* Outer loop iterates through all parameter queues an object of
955 this type could be in. */
956 for(j = 0; j < length; ++j) {
957 parameter = queues[j];
959 if (parameter->numbertags>0) {
961 goto nextloop; //that means the object has no tag
962 //but that param needs tag
963 else if(tagptr->type==TAGTYPE) { //one tag
964 //struct ___TagDescriptor___ * tag=
965 //(struct ___TagDescriptor___*) tagptr;
966 for(i=0; i<parameter->numbertags; i++) {
967 //slotid is parameter->tagarray[2*i];
968 int tagid=parameter->tagarray[2*i+1];
969 if (tagid!=tagptr->flag)
970 goto nextloop; /*We don't have this tag */
972 } else { //multiple tags
973 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
974 for(i=0; i<parameter->numbertags; i++) {
975 //slotid is parameter->tagarray[2*i];
976 int tagid=parameter->tagarray[2*i+1];
978 for(j=0; j<ao->___cachedCode___; j++) {
979 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
990 for(i=0; i<parameter->numberofterms; i++) {
991 int andmask=parameter->intarray[i*2];
992 int checkmask=parameter->intarray[i*2+1];
993 if ((ptr->flag&andmask)==checkmask) {
994 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
1005 void enqueueObject_I(void * vptr,
1006 struct parameterwrapper ** vqueues,
1008 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
1011 //struct QueueItem *tmpptr;
1012 struct parameterwrapper * parameter=NULL;
1015 struct parameterwrapper * prevptr=NULL;
1016 struct ___Object___ *tagptr=NULL;
1017 struct parameterwrapper ** queues = vqueues;
1018 int length = vlength;
1019 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1022 if(queues == NULL) {
1023 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1024 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1026 tagptr=ptr->___tags___;
1028 /* Outer loop iterates through all parameter queues an object of
1029 this type could be in. */
1030 for(j = 0; j < length; ++j) {
1031 parameter = queues[j];
1033 if (parameter->numbertags>0) {
1035 goto nextloop; //that means the object has no tag
1036 //but that param needs tag
1037 else if(tagptr->type==TAGTYPE) { //one tag
1038 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1039 for(i=0; i<parameter->numbertags; i++) {
1040 //slotid is parameter->tagarray[2*i];
1041 int tagid=parameter->tagarray[2*i+1];
1042 if (tagid!=tagptr->flag)
1043 goto nextloop; /*We don't have this tag */
1045 } else { //multiple tags
1046 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1047 for(i=0; i<parameter->numbertags; i++) {
1048 //slotid is parameter->tagarray[2*i];
1049 int tagid=parameter->tagarray[2*i+1];
1051 for(j=0; j<ao->___cachedCode___; j++) {
1052 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1063 for(i=0; i<parameter->numberofterms; i++) {
1064 int andmask=parameter->intarray[i*2];
1065 int checkmask=parameter->intarray[i*2+1];
1066 if ((ptr->flag&andmask)==checkmask) {
1067 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1079 int * getAliasLock(void ** ptrs,
1081 struct RuntimeHash * tbl) {
1083 return (int*)(RUNMALLOC(sizeof(int)));
1088 bool redirect = false;
1089 int redirectlock = 0;
1090 for(; i < length; i++) {
1091 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1094 if(ptr->lock == NULL) {
1097 lock = (int)(ptr->lock);
1100 if(lock != redirectlock) {
1101 RuntimeHashadd(tbl, lock, redirectlock);
1104 if(RuntimeHashcontainskey(tbl, lock)) {
1105 // already redirected
1107 RuntimeHashget(tbl, lock, &redirectlock);
1108 for(; j < locklen; j++) {
1109 if(locks[j] != redirectlock) {
1110 RuntimeHashadd(tbl, locks[j], redirectlock);
1115 for(j = 0; j < locklen; j++) {
1116 if(locks[j] == lock) {
1119 } else if(locks[j] > lock) {
1126 locks[h] = locks[h-1];
1135 return (int *)redirectlock;
1137 return (int *)(locks[0]);
1142 void addAliasLock(void * ptr,
1144 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1145 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1146 // originally no alias lock associated or have a different alias lock
1147 // flush it as the new one
1148 obj->lock = (int *)lock;
1153 inline void setTaskExitIndex(int index) {
1154 taskInfoArray[taskInfoIndex]->exitIndex = index;
1157 inline void addNewObjInfo(void * nobj) {
1158 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1159 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1161 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1165 void * smemalloc(int size,
1168 int isize = size+(BAMBOO_CACHE_LINE_SIZE);
1169 int toallocate = ((size+(BAMBOO_CACHE_LINE_SIZE))>(BAMBOO_SMEM_SIZE)) ?
1170 (size+(BAMBOO_CACHE_LINE_SIZE)):(BAMBOO_SMEM_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
1196 // round the asigned block to the end of the current block
1197 *allocsize = remain;
1199 freemem->ptr = ((void*)freemem->ptr) + (*allocsize);
1200 freemem->size -= *allocsize;
1203 mem = mspace_calloc(bamboo_free_msp, 1, isize);
1207 // no enough shared global memory
1213 BAMBOO_DEBUGPRINT(0xa001);
1214 BAMBOO_EXIT(0xa001);
1220 // receive object transferred from other cores
1221 // or the terminate message from other cores
1222 // Should be invoked in critical sections!!
1223 // NOTICE: following format is for threadsimulate version only
1224 // RAW version please see previous description
1225 // format: type + object
1226 // type: -1--stall msg
1228 // return value: 0--received an object
1229 // 1--received nothing
1230 // 2--received a Stall Msg
1231 // 3--received a lock Msg
1232 // RAW version: -1 -- received nothing
1233 // otherwise -- received msg type
1234 int receiveObject() {
1238 if(receiveMsg() == -1) {
1242 if(msgdataindex == msglength) {
1243 // received a whole msg
1248 // receive a object transfer msg
1249 struct transObjInfo * transObj =
1250 RUNMALLOC_I(sizeof(struct transObjInfo));
1254 BAMBOO_DEBUGPRINT(0xe880);
1257 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1259 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1261 BAMBOO_EXIT(0xa002);
1263 // store the object and its corresponding queue info, enqueue it later
1264 transObj->objptr = (void *)msgdata[2];
1265 transObj->length = (msglength - 3) / 2;
1266 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1267 for(k = 0; k < transObj->length; ++k) {
1268 transObj->queues[2*k] = msgdata[3+2*k];
1271 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1274 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1277 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1281 // check if there is an existing duplicate item
1283 struct QueueItem * qitem = getHead(&objqueue);
1284 struct QueueItem * prev = NULL;
1285 while(qitem != NULL) {
1286 struct transObjInfo * tmpinfo =
1287 (struct transObjInfo *)(qitem->objectptr);
1288 if(tmpinfo->objptr == transObj->objptr) {
1289 // the same object, remove outdate one
1290 removeItem(&objqueue, qitem);
1296 qitem = getHead(&objqueue);
1298 qitem = getNextQueueItem(prev);
1301 addNewItem_I(&objqueue, (void *)transObj);
1303 ++(self_numreceiveobjs);
1308 // receive a stall msg
1309 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1310 // non startup core can not receive stall msg
1312 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1314 BAMBOO_EXIT(0xa003);
1316 if(msgdata[1] < NUMCORES) {
1319 BAMBOO_DEBUGPRINT(0xe881);
1322 corestatus[msgdata[1]] = 0;
1323 numsendobjs[msgdata[1]] = msgdata[2];
1324 numreceiveobjs[msgdata[1]] = msgdata[3];
1329 // GC version have no lock msgs
1330 #ifndef MULTICORE_GC
1332 // receive lock request msg, handle it right now
1333 // check to see if there is a lock exist for the required obj
1334 // msgdata[1] -> lock type
1335 int data2 = msgdata[2]; // obj pointer
1336 int data3 = msgdata[3]; // lock
1337 int data4 = msgdata[4]; // request core
1338 // -1: redirected, 0: approved, 1: denied
1339 deny = processlockrequest(msgdata[1], data3, data2,
1340 data4, data4, true);
1342 // this lock request is redirected
1345 // send response msg
1346 // for 32 bit machine, the size is always 4 words
1347 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1349 cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1351 send_msg_4(data4, tmp, msgdata[1], data2, data3);
1358 // receive lock grount msg
1359 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1361 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1363 BAMBOO_EXIT(0xa004);
1365 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1368 BAMBOO_DEBUGPRINT(0xe882);
1377 // conflicts on lockresults
1379 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1381 BAMBOO_EXIT(0xa005);
1387 // receive lock deny msg
1388 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1390 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1392 BAMBOO_EXIT(0xa006);
1394 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1397 BAMBOO_DEBUGPRINT(0xe883);
1406 // conflicts on lockresults
1408 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1410 BAMBOO_EXIT(0xa007);
1416 // receive lock release msg
1417 processlockrelease(msgdata[1], msgdata[2], 0, false);
1423 case PROFILEOUTPUT: {
1424 // receive an output profile data request msg
1425 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1426 // startup core can not receive profile output finish msg
1427 BAMBOO_EXIT(0xa008);
1431 BAMBOO_DEBUGPRINT(0xe885);
1435 totalexetime = msgdata[1];
1436 outputProfileData();
1438 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1440 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1445 case PROFILEFINISH: {
1446 // receive a profile output finish msg
1447 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1448 // non startup core can not receive profile output finish msg
1450 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1452 BAMBOO_EXIT(0xa009);
1456 BAMBOO_DEBUGPRINT(0xe886);
1459 profilestatus[msgdata[1]] = 0;
1464 // GC version has no lock msgs
1465 #ifndef MULTICORE_GC
1466 case REDIRECTLOCK: {
1467 // receive a redirect lock request msg, handle it right now
1468 // check to see if there is a lock exist for the required obj
1469 int data1 = msgdata[1]; // lock type
1470 int data2 = msgdata[2]; // obj pointer
1471 int data3 = msgdata[3]; // redirect lock
1472 int data4 = msgdata[4]; // root request core
1473 int data5 = msgdata[5]; // request core
1474 deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1476 // this lock request is redirected
1479 // send response msg
1480 // for 32 bit machine, the size is always 4 words
1482 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1483 data1, data2, data3);
1485 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1486 data1, data2, data3);
1492 case REDIRECTGROUNT: {
1493 // receive a lock grant msg with redirect info
1494 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1496 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1498 BAMBOO_EXIT(0xa00a);
1500 if(lockobj == msgdata[2]) {
1503 BAMBOO_DEBUGPRINT(0xe891);
1508 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1513 // conflicts on lockresults
1515 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1517 BAMBOO_EXIT(0xa00b);
1522 case REDIRECTDENY: {
1523 // receive a lock deny msg with redirect info
1524 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1526 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1528 BAMBOO_EXIT(0xa00c);
1530 if(lockobj == msgdata[2]) {
1533 BAMBOO_DEBUGPRINT(0xe892);
1542 // conflicts on lockresults
1544 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1546 BAMBOO_EXIT(0xa00d);
1551 case REDIRECTRELEASE: {
1552 // receive a lock release msg with redirect info
1553 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1558 case STATUSCONFIRM: {
1559 // receive a status confirm info
1560 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1561 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1562 // wrong core to receive such msg
1563 BAMBOO_EXIT(0xa00e);
1565 // send response msg
1568 BAMBOO_DEBUGPRINT(0xe887);
1572 cache_msg_5(STARTUPCORE, STATUSREPORT,
1573 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1574 self_numsendobjs, self_numreceiveobjs);
1576 send_msg_5(STARTUPCORE, STATUSREPORT,
1577 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1578 self_numsendobjs, self_numreceiveobjs);
1584 case STATUSREPORT: {
1585 // receive a status confirm info
1586 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1587 // wrong core to receive such msg
1589 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1591 BAMBOO_EXIT(0xa00f);
1595 BAMBOO_DEBUGPRINT(0xe888);
1601 corestatus[msgdata[2]] = msgdata[1];
1602 numsendobjs[msgdata[2]] = msgdata[3];
1603 numreceiveobjs[msgdata[2]] = msgdata[4];
1609 // receive a terminate msg
1612 BAMBOO_DEBUGPRINT(0xe889);
1621 // receive a shared memory request msg
1622 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1623 // wrong core to receive such msg
1625 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1627 BAMBOO_EXIT(0xa010);
1631 BAMBOO_DEBUGPRINT(0xe88a);
1636 // is currently doing gc, dump this msg
1641 void * mem = smemalloc(msgdata[1], &allocsize);
1645 // send the start_va to request core
1647 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1649 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1656 // receive a shared memory response msg
1659 BAMBOO_DEBUGPRINT(0xe88b);
1664 // is currently doing gc, dump this msg
1668 if(msgdata[2] == 0) {
1669 bamboo_smem_size = 0;
1672 // fill header to store the size of this mem block
1673 (*((int*)msgdata[1])) = msgdata[2];
1674 bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1676 bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1679 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1680 msgdata[2]-BAMBOO_CACHE_LINE_SIZE,
1692 gcphase = INITPHASE;
1694 // is waiting for response of mem request
1695 // let it return NULL and start gc
1696 bamboo_smem_size = 0;
1697 bamboo_cur_msp = NULL;
1704 // receive a start GC msg
1707 BAMBOO_DEBUGPRINT(0xe88c);
1711 gcphase = MARKPHASE;
1715 case GCSTARTCOMPACT: {
1716 // a compact phase start msg
1717 gcblock2fill = msgdata[1];
1718 gcphase = COMPACTPHASE;
1722 case GCSTARTFLUSH: {
1723 // received a flush phase start msg
1724 gcphase = FLUSHPHASE;
1728 case GCFINISHINIT: {
1729 // received a init phase finish msg
1730 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1731 // non startup core can not receive this msg
1733 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1735 BAMBOO_EXIT(0xb001);
1738 BAMBOO_DEBUGPRINT(0xe88c);
1739 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1741 if(msgdata[1] < NUMCORES) {
1742 gccorestatus[msgdata[1]] = 0;
1746 case GCFINISHMARK: {
1747 // received a mark phase finish msg
1748 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1749 // non startup core can not receive this msg
1751 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1753 BAMBOO_EXIT(0xb002);
1755 if(msgdata[1] < NUMCORES) {
1756 gccorestatus[msgdata[1]] = 0;
1757 gcnumsendobjs[msgdata[1]] = msgdata[2];
1758 gcnumreceiveobjs[msgdata[1]] = msgdata[3];
1763 case GCFINISHCOMPACT: {
1764 // received a compact phase finish msg
1765 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1766 // non startup core can not receive this msg
1769 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1771 BAMBOO_EXIT(0xb003);
1773 int cnum = msgdata[1];
1774 int filledblocks = msgdata[2];
1775 int heaptop = msgdata[3];
1776 int data4 = msgdata[4];
1777 if(cnum < NUMCORES) {
1778 if(COMPACTPHASE == gcphase) {
1779 gcfilledblocks[cnum] = filledblocks;
1780 gcloads[cnum] = heaptop;
1787 if(gcfindSpareMem_I(&startaddr, &tomove, &dstcore, data4, cnum)) {
1789 cache_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1791 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1795 gccorestatus[cnum] = 0;
1796 // check if there is pending move request
1797 /*if(gcmovepending > 0) {
1799 for(j = 0; j < NUMCORES; j++) {
1800 if(gcrequiredmems[j]>0) {
1808 gcrequiredmems[j] = assignSpareMem_I(cnum,
1812 if(STARTUPCORE == j) {
1815 gcmovestartaddr = startaddr;
1816 gcblock2fill = tomove;
1819 cache_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1821 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1823 } // if(STARTUPCORE == j)
1824 if(gcrequiredmems[j] == 0) {
1827 } // if(j < NUMCORES)
1828 } // if(gcmovepending > 0) */
1830 } // if(cnum < NUMCORES)
1834 case GCFINISHFLUSH: {
1835 // received a flush phase finish msg
1836 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1837 // non startup core can not receive this msg
1840 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1842 BAMBOO_EXIT(0xb004);
1844 if(msgdata[1] < NUMCORES) {
1845 gccorestatus[msgdata[1]] = 0;
1851 // received a GC finish msg
1852 gcphase = FINISHPHASE;
1856 case GCMARKCONFIRM: {
1857 // received a marked phase finish confirm request msg
1858 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1859 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1860 // wrong core to receive such msg
1861 BAMBOO_EXIT(0xb005);
1863 // send response msg
1865 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1866 gcbusystatus, gcself_numsendobjs,
1867 gcself_numreceiveobjs);
1869 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1870 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1876 case GCMARKREPORT: {
1877 // received a marked phase finish confirm response msg
1878 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1879 // wrong core to receive such msg
1881 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1883 BAMBOO_EXIT(0xb006);
1888 gccorestatus[msgdata[1]] = msgdata[2];
1889 gcnumsendobjs[msgdata[1]] = msgdata[3];
1890 gcnumreceiveobjs[msgdata[1]] = msgdata[4];
1896 // received a markedObj msg
1897 gc_enqueue_I(msgdata[1]);
1898 gcself_numreceiveobjs++;
1899 gcbusystatus = true;
1904 // received a start moving objs msg
1906 gcdstcore = msgdata[1];
1907 gcmovestartaddr = msgdata[2];
1908 gcblock2fill = msgdata[3];
1912 case GCMAPREQUEST: {
1913 // received a mapping info request msg
1914 void * dstptr = NULL;
1915 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1916 if(NULL == dstptr) {
1917 // no such pointer in this core, something is wrong
1919 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1920 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1922 BAMBOO_EXIT(0xb007);
1924 // send back the mapping info
1926 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1928 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1935 // received a mapping info response msg
1936 if(msgdata[1] != gcobj2map) {
1937 // obj not matched, something is wrong
1939 BAMBOO_DEBUGPRINT_REG(gcobj2map);
1940 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1942 BAMBOO_EXIT(0xb008);
1944 gcmappedobj = msgdata[2];
1945 RuntimeHashadd_I(gcpointertbl, gcobj2map, gcmappedobj);
1951 case GCLOBJREQUEST: {
1952 // received a large objs info request msg
1953 transferMarkResults_I();
1958 // received a large objs info response msg
1961 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1963 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1965 BAMBOO_EXIT(0xb009);
1967 // store the mark result info
1968 int cnum = msgdata[2];
1969 gcloads[cnum] = msgdata[3];
1970 if(gcheaptop < msgdata[4]) {
1971 gcheaptop = msgdata[4];
1973 // large obj info here
1974 for(int k = 5; k < msgdata[1];) {
1975 int lobj = msgdata[k++];
1976 int length = msgdata[k++];
1977 gc_lobjenqueue_I(lobj, length, cnum);
1979 } // for(int k = 5; k < msgdata[1];)
1983 case GCLOBJMAPPING: {
1984 // received a large obj mapping info msg
1985 RuntimeHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
1994 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1995 msgdata[msgdataindex] = -1;
2001 BAMBOO_DEBUGPRINT(0xe88d);
2005 if(BAMBOO_MSG_AVAIL() != 0) {
2018 BAMBOO_DEBUGPRINT(0xe88e);
2022 /* if(isInterrupt) {
2030 int enqueuetasks(struct parameterwrapper *parameter,
2031 struct parameterwrapper *prevptr,
2032 struct ___Object___ *ptr,
2034 int numenterflags) {
2035 void * taskpointerarray[MAXTASKPARAMS];
2037 //int numparams=parameter->task->numParameters;
2038 int numiterators=parameter->task->numTotal-1;
2041 struct taskdescriptor * task=parameter->task;
2043 //this add the object to parameterwrapper
2044 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
2045 numenterflags, enterflags==NULL);
2047 /* Add enqueued object to parameter vector */
2048 taskpointerarray[parameter->slot]=ptr;
2050 /* Reset iterators */
2051 for(j=0; j<numiterators; j++) {
2052 toiReset(¶meter->iterators[j]);
2055 /* Find initial state */
2056 for(j=0; j<numiterators; j++) {
2058 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2059 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2061 /* Need to backtrack */
2062 toiReset(¶meter->iterators[j]);
2066 /* Nothing to enqueue */
2072 /* Enqueue current state */
2074 struct taskparamdescriptor *tpd=
2075 RUNMALLOC(sizeof(struct taskparamdescriptor));
2077 tpd->numParameters=numiterators+1;
2078 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2080 for(j=0; j<=numiterators; j++) {
2081 //store the actual parameters
2082 tpd->parameterArray[j]=taskpointerarray[j];
2085 if ((/*!gencontains(failedtasks, tpd)&&*/
2086 !gencontains(activetasks,tpd))) {
2087 genputtable(activetasks, tpd, tpd);
2089 RUNFREE(tpd->parameterArray);
2093 /* This loop iterates to the next parameter combination */
2094 if (numiterators==0)
2097 for(j=numiterators-1; j<numiterators; j++) {
2099 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2100 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2102 /* Need to backtrack */
2103 toiReset(¶meter->iterators[j]);
2107 /* Nothing more to enqueue */
2115 int enqueuetasks_I(struct parameterwrapper *parameter,
2116 struct parameterwrapper *prevptr,
2117 struct ___Object___ *ptr,
2119 int numenterflags) {
2120 void * taskpointerarray[MAXTASKPARAMS];
2122 //int numparams=parameter->task->numParameters;
2123 int numiterators=parameter->task->numTotal-1;
2128 struct taskdescriptor * task=parameter->task;
2130 //this add the object to parameterwrapper
2131 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2132 numenterflags, enterflags==NULL);
2134 /* Add enqueued object to parameter vector */
2135 taskpointerarray[parameter->slot]=ptr;
2137 /* Reset iterators */
2138 for(j=0; j<numiterators; j++) {
2139 toiReset(¶meter->iterators[j]);
2142 /* Find initial state */
2143 for(j=0; j<numiterators; j++) {
2145 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2146 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2148 /* Need to backtrack */
2149 toiReset(¶meter->iterators[j]);
2153 /* Nothing to enqueue */
2159 /* Enqueue current state */
2161 struct taskparamdescriptor *tpd=
2162 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2164 tpd->numParameters=numiterators+1;
2165 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2167 for(j=0; j<=numiterators; j++) {
2168 //store the actual parameters
2169 tpd->parameterArray[j]=taskpointerarray[j];
2172 if ((/*!gencontains(failedtasks, tpd)&&*/
2173 !gencontains(activetasks,tpd))) {
2174 genputtable_I(activetasks, tpd, tpd);
2176 RUNFREE(tpd->parameterArray);
2180 /* This loop iterates to the next parameter combination */
2181 if (numiterators==0)
2184 for(j=numiterators-1; j<numiterators; j++) {
2186 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2187 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2189 /* Need to backtrack */
2190 toiReset(¶meter->iterators[j]);
2194 /* Nothing more to enqueue */
2208 int containstag(struct ___Object___ *ptr,
2209 struct ___TagDescriptor___ *tag);
2211 #ifndef MULTICORE_GC
2212 void releasewritelock_r(void * lock, void * redirectlock) {
2214 int reallock = (int)lock;
2215 targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2218 BAMBOO_DEBUGPRINT(0xe671);
2219 BAMBOO_DEBUGPRINT_REG((int)lock);
2220 BAMBOO_DEBUGPRINT_REG(reallock);
2221 BAMBOO_DEBUGPRINT_REG(targetcore);
2224 if(targetcore == BAMBOO_NUM_OF_CORE) {
2225 BAMBOO_START_CRITICAL_SECTION_LOCK();
2227 BAMBOO_DEBUGPRINT(0xf001);
2229 // reside on this core
2230 if(!RuntimeHashcontainskey(locktbl, reallock)) {
2231 // no locks for this object, something is wrong
2232 BAMBOO_EXIT(0xa011);
2235 struct LockValue * lockvalue = NULL;
2237 BAMBOO_DEBUGPRINT(0xe672);
2239 RuntimeHashget(locktbl, reallock, &rwlock_obj);
2240 lockvalue = (struct LockValue *)rwlock_obj;
2242 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2245 lockvalue->redirectlock = (int)redirectlock;
2247 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2250 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2252 BAMBOO_DEBUGPRINT(0xf000);
2256 // send lock release with redirect info msg
2257 // for 32 bit machine, the size is always 4 words
2258 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2263 void executetasks() {
2264 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2267 struct ___Object___ * tmpparam = NULL;
2268 struct parameterdescriptor * pd=NULL;
2269 struct parameterwrapper *pw=NULL;
2274 struct LockValue locks[MAXTASKPARAMS];
2282 while(hashsize(activetasks)>0) {
2287 BAMBOO_DEBUGPRINT(0xe990);
2290 /* See if there are any active tasks */
2291 if (hashsize(activetasks)>0) {
2294 #ifdef ACCURATEPROFILE
2295 profileTaskStart("tpd checking");
2299 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2300 genfreekey(activetasks, currtpd);
2302 numparams=currtpd->task->numParameters;
2303 numtotal=currtpd->task->numTotal;
2305 // clear the lockRedirectTbl
2306 // (TODO, this table should be empty after all locks are released)
2308 for(j = 0; j < MAXTASKPARAMS; j++) {
2309 locks[j].redirectlock = 0;
2312 // get all required locks
2314 // check which locks are needed
2315 for(i = 0; i < numparams; i++) {
2316 void * param = currtpd->parameterArray[i];
2320 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2322 taskpointerarray[i+OFFSET]=param;
2325 if(((struct ___Object___ *)param)->lock == NULL) {
2326 tmplock = (int)param;
2328 tmplock = (int)(((struct ___Object___ *)param)->lock);
2330 // insert into the locks array
2331 for(j = 0; j < locklen; j++) {
2332 if(locks[j].value == tmplock) {
2335 } else if(locks[j].value > tmplock) {
2342 locks[h].redirectlock = locks[h-1].redirectlock;
2343 locks[h].value = locks[h-1].value;
2345 locks[j].value = tmplock;
2346 locks[j].redirectlock = (int)param;
2349 } // line 2713: for(i = 0; i < numparams; i++)
2350 // grab these required locks
2352 BAMBOO_DEBUGPRINT(0xe991);
2354 for(i = 0; i < locklen; i++) {
2355 int * lock = (int *)(locks[i].redirectlock);
2357 // require locks for this parameter if it is not a startup object
2359 BAMBOO_DEBUGPRINT_REG((int)lock);
2360 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2363 BAMBOO_START_CRITICAL_SECTION();
2365 BAMBOO_DEBUGPRINT(0xf001);
2368 //isInterrupt = false;
2371 BAMBOO_WAITING_FOR_LOCK();
2375 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2379 grount = lockresult;
2389 //isInterrupt = true;
2391 BAMBOO_CLOSE_CRITICAL_SECTION();
2393 BAMBOO_DEBUGPRINT(0xf000);
2399 BAMBOO_DEBUGPRINT(0xe992);
2401 // can not get the lock, try later
2402 // releas all grabbed locks for previous parameters
2403 for(j = 0; j < i; ++j) {
2404 lock = (int*)(locks[j].redirectlock);
2405 releasewritelock(lock);
2407 genputtable(activetasks, currtpd, currtpd);
2408 if(hashsize(activetasks) == 1) {
2409 // only one task right now, wait a little while before next try
2415 #ifdef ACCURATEPROFILE
2416 // fail, set the end of the checkTaskInfo
2421 } // line 2794: if(grount == 0)
2422 } // line 2752: for(i = 0; i < locklen; i++)
2425 BAMBOO_DEBUGPRINT(0xe993);
2427 /* Make sure that the parameters are still in the queues */
2428 for(i=0; i<numparams; i++) {
2429 void * parameter=currtpd->parameterArray[i];
2433 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
2434 classsize[((struct ___Object___ *)parameter)->type]);
2436 tmpparam = (struct ___Object___ *)parameter;
2437 pd=currtpd->task->descriptorarray[i];
2438 pw=(struct parameterwrapper *) pd->queue;
2439 /* Check that object is still in queue */
2441 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2443 BAMBOO_DEBUGPRINT(0xe994);
2445 // release grabbed locks
2446 for(j = 0; j < locklen; ++j) {
2447 int * lock = (int *)(locks[j].redirectlock);
2448 releasewritelock(lock);
2450 RUNFREE(currtpd->parameterArray);
2456 /* Check if the object's flags still meets requirements */
2460 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2461 andmask=pw->intarray[tmpi*2];
2462 checkmask=pw->intarray[tmpi*2+1];
2463 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2469 // flags are never suitable
2470 // remove this obj from the queue
2472 int UNUSED, UNUSED2;
2475 BAMBOO_DEBUGPRINT(0xe995);
2477 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
2478 (int *) &enterflags, &UNUSED, &UNUSED2);
2479 ObjectHashremove(pw->objectset, (int)parameter);
2480 if (enterflags!=NULL)
2481 RUNFREE(enterflags);
2482 // release grabbed locks
2483 for(j = 0; j < locklen; ++j) {
2484 int * lock = (int *)(locks[j].redirectlock);
2485 releasewritelock(lock);
2487 RUNFREE(currtpd->parameterArray);
2491 #ifdef ACCURATEPROFILE
2492 // fail, set the end of the checkTaskInfo
2497 } // line 2878: if (!ismet)
2501 /* Check that object still has necessary tags */
2502 for(j=0; j<pd->numbertags; j++) {
2503 int slotid=pd->tagarray[2*j]+numparams;
2504 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2505 if (!containstag(parameter, tagd)) {
2507 BAMBOO_DEBUGPRINT(0xe996);
2510 // release grabbed locks
2512 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2513 int * lock = (int *)(locks[tmpj].redirectlock);
2514 releasewritelock(lock);
2517 RUNFREE(currtpd->parameterArray);
2521 } // line2911: if (!containstag(parameter, tagd))
2522 } // line 2808: for(j=0; j<pd->numbertags; j++)
2524 taskpointerarray[i+OFFSET]=parameter;
2525 } // line 2824: for(i=0; i<numparams; i++)
2527 for(; i<numtotal; i++) {
2528 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2533 /* Actually call task */
2535 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2536 taskpointerarray[1]=NULL;
2539 #ifdef ACCURATEPROFILE
2540 // check finish, set the end of the checkTaskInfo
2543 profileTaskStart(currtpd->task->name);
2547 BAMBOO_DEBUGPRINT(0xe997);
2549 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2551 #ifdef ACCURATEPROFILE
2552 // task finish, set the end of the checkTaskInfo
2554 // new a PostTaskInfo for the post-task execution
2555 profileTaskStart("post task execution");
2559 BAMBOO_DEBUGPRINT(0xe998);
2560 BAMBOO_DEBUGPRINT_REG(islock);
2565 BAMBOO_DEBUGPRINT(0xe999);
2567 for(i = 0; i < locklen; ++i) {
2568 void * ptr = (void *)(locks[i].redirectlock);
2569 int * lock = (int *)(locks[i].value);
2571 BAMBOO_DEBUGPRINT_REG((int)ptr);
2572 BAMBOO_DEBUGPRINT_REG((int)lock);
2574 #ifndef MULTICORE_GC
2575 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2577 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2578 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2579 releasewritelock_r(lock, (int *)redirectlock);
2584 releasewritelock(ptr);
2587 } // line 3015: if(islock)
2590 // post task execution finish, set the end of the postTaskInfo
2594 // Free up task parameter descriptor
2595 RUNFREE(currtpd->parameterArray);
2599 BAMBOO_DEBUGPRINT(0xe99a);
2602 } // if (hashsize(activetasks)>0)
2603 } // while(hashsize(activetasks)>0)
2605 BAMBOO_DEBUGPRINT(0xe99b);
2609 /* This function processes an objects tags */
2610 void processtags(struct parameterdescriptor *pd,
2612 struct parameterwrapper *parameter,
2613 int * iteratorcount,
2618 for(i=0; i<pd->numbertags; i++) {
2619 int slotid=pd->tagarray[2*i];
2620 int tagid=pd->tagarray[2*i+1];
2622 if (statusarray[slotid+numparams]==0) {
2623 parameter->iterators[*iteratorcount].istag=1;
2624 parameter->iterators[*iteratorcount].tagid=tagid;
2625 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2626 parameter->iterators[*iteratorcount].tagobjectslot=index;
2627 statusarray[slotid+numparams]=1;
2634 void processobject(struct parameterwrapper *parameter,
2636 struct parameterdescriptor *pd,
2642 struct ObjectHash * objectset=
2643 ((struct parameterwrapper *)pd->queue)->objectset;
2645 parameter->iterators[*iteratorcount].istag=0;
2646 parameter->iterators[*iteratorcount].slot=index;
2647 parameter->iterators[*iteratorcount].objectset=objectset;
2648 statusarray[index]=1;
2650 for(i=0; i<pd->numbertags; i++) {
2651 int slotid=pd->tagarray[2*i];
2652 //int tagid=pd->tagarray[2*i+1];
2653 if (statusarray[slotid+numparams]!=0) {
2654 /* This tag has already been enqueued, use it to narrow search */
2655 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2660 parameter->iterators[*iteratorcount].numtags=tagcount;
2665 /* This function builds the iterators for a task & parameter */
2667 void builditerators(struct taskdescriptor * task,
2669 struct parameterwrapper * parameter) {
2670 int statusarray[MAXTASKPARAMS];
2672 int numparams=task->numParameters;
2673 int iteratorcount=0;
2674 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2676 statusarray[index]=1; /* Initial parameter */
2677 /* Process tags for initial iterator */
2679 processtags(task->descriptorarray[index], index, parameter,
2680 &iteratorcount, statusarray, numparams);
2684 /* Check for objects with existing tags */
2685 for(i=0; i<numparams; i++) {
2686 if (statusarray[i]==0) {
2687 struct parameterdescriptor *pd=task->descriptorarray[i];
2689 for(j=0; j<pd->numbertags; j++) {
2690 int slotid=pd->tagarray[2*j];
2691 if(statusarray[slotid+numparams]!=0) {
2692 processobject(parameter, i, pd, &iteratorcount, statusarray,
2694 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2701 /* Next do objects w/ unbound tags*/
2703 for(i=0; i<numparams; i++) {
2704 if (statusarray[i]==0) {
2705 struct parameterdescriptor *pd=task->descriptorarray[i];
2706 if (pd->numbertags>0) {
2707 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2708 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2714 /* Nothing with a tag enqueued */
2716 for(i=0; i<numparams; i++) {
2717 if (statusarray[i]==0) {
2718 struct parameterdescriptor *pd=task->descriptorarray[i];
2719 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2720 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2733 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2736 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2737 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2739 printf("%s\n", task->name);
2741 for(j=0; j<task->numParameters; j++) {
2742 struct parameterdescriptor *param=task->descriptorarray[j];
2743 struct parameterwrapper *parameter=param->queue;
2744 struct ObjectHash * set=parameter->objectset;
2745 struct ObjectIterator objit;
2747 printf(" Parameter %d\n", j);
2749 ObjectHashiterator(set, &objit);
2750 while(ObjhasNext(&objit)) {
2751 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2752 struct ___Object___ * tagptr=obj->___tags___;
2753 int nonfailed=Objdata4(&objit);
2754 int numflags=Objdata3(&objit);
2755 int flags=Objdata2(&objit);
2758 printf(" Contains %lx\n", obj);
2759 printf(" flag=%d\n", obj->flag);
2762 } else if (tagptr->type==TAGTYPE) {
2764 printf(" tag=%lx\n",tagptr);
2770 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2771 for(; tagindex<ao->___cachedCode___; tagindex++) {
2773 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
2786 /* This function processes the task information to create queues for
2787 each parameter type. */
2789 void processtasks() {
2791 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2794 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2795 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2798 /* Build objectsets */
2799 for(j=0; j<task->numParameters; j++) {
2800 struct parameterdescriptor *param=task->descriptorarray[j];
2801 struct parameterwrapper *parameter=param->queue;
2802 parameter->objectset=allocateObjectHash(10);
2803 parameter->task=task;
2806 /* Build iterators for parameters */
2807 for(j=0; j<task->numParameters; j++) {
2808 struct parameterdescriptor *param=task->descriptorarray[j];
2809 struct parameterwrapper *parameter=param->queue;
2810 builditerators(task, j, parameter);
2815 void toiReset(struct tagobjectiterator * it) {
2818 } else if (it->numtags>0) {
2821 ObjectHashiterator(it->objectset, &it->it);
2825 int toiHasNext(struct tagobjectiterator *it,
2826 void ** objectarray OPTARG(int * failed)) {
2829 /* Get object with tags */
2830 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2831 struct ___Object___ *tagptr=obj->___tags___;
2832 if (tagptr->type==TAGTYPE) {
2833 if ((it->tagobjindex==0)&& /* First object */
2834 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2839 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2840 int tagindex=it->tagobjindex;
2841 for(; tagindex<ao->___cachedCode___; tagindex++) {
2842 struct ___TagDescriptor___ *td=
2843 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2844 if (td->flag==it->tagid) {
2845 it->tagobjindex=tagindex; /* Found right type of tag */
2851 } else if (it->numtags>0) {
2852 /* Use tags to locate appropriate objects */
2853 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2854 struct ___Object___ *objptr=tag->flagptr;
2856 if (objptr->type!=OBJECTARRAYTYPE) {
2857 if (it->tagobjindex>0)
2859 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2861 for(i=1; i<it->numtags; i++) {
2862 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2863 if (!containstag(objptr,tag2))
2868 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2871 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2872 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2873 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2875 for(i=1; i<it->numtags; i++) {
2876 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2877 if (!containstag(objptr,tag2))
2880 it->tagobjindex=tagindex;
2885 it->tagobjindex=tagindex;
2889 return ObjhasNext(&it->it);
2893 int containstag(struct ___Object___ *ptr,
2894 struct ___TagDescriptor___ *tag) {
2896 struct ___Object___ * objptr=tag->flagptr;
2897 if (objptr->type==OBJECTARRAYTYPE) {
2898 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2899 for(j=0; j<ao->___cachedCode___; j++) {
2900 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2908 void toiNext(struct tagobjectiterator *it,
2909 void ** objectarray OPTARG(int * failed)) {
2910 /* hasNext has all of the intelligence */
2913 /* Get object with tags */
2914 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2915 struct ___Object___ *tagptr=obj->___tags___;
2916 if (tagptr->type==TAGTYPE) {
2918 objectarray[it->slot]=tagptr;
2920 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2921 objectarray[it->slot]=
2922 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2924 } else if (it->numtags>0) {
2925 /* Use tags to locate appropriate objects */
2926 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2927 struct ___Object___ *objptr=tag->flagptr;
2928 if (objptr->type!=OBJECTARRAYTYPE) {
2930 objectarray[it->slot]=objptr;
2932 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2933 objectarray[it->slot]=
2934 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2937 /* Iterate object */
2938 objectarray[it->slot]=(void *)Objkey(&it->it);