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 void initruntimedata() {
23 // initialize the arrays
24 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
25 // startup core to initialize corestatus[]
26 for(i = 0; i < NUMCORES; ++i) {
29 numreceiveobjs[i] = 0;
31 // initialize the profile data arrays
37 gcnumreceiveobjs[i] = 0;
39 gcrequiredmems[i] = 0;
42 } // for(i = 0; i < NUMCORES; ++i)
52 self_numreceiveobjs = 0;
54 for(i = 0; i < BAMBOO_MSG_BUF_LENGTH; ++i) {
59 msglength = BAMBOO_MSG_BUF_LENGTH;
60 for(i = 0; i < BAMBOO_OUT_BUF_LENGTH; ++i) {
70 bamboo_cur_msp = NULL;
76 gcphase = FINISHPHASE;
77 gcself_numsendobjs = 0;
78 gcself_numreceiveobjs = 0;
80 gcpointertbl = allocateRuntimeHash(20);
92 gchead = gctail = gctail2 = NULL;
93 gclobjhead = gclobjtail = gclobjtail2 = NULL;
103 // create the lock table, lockresult table and obj queue
106 (struct RuntimeNode **) RUNMALLOC_I(sizeof(struct RuntimeNode *)*20);
107 /* Set allocation blocks*/
108 locktable.listhead=NULL;
109 locktable.listtail=NULL;
111 locktable.numelements = 0;
116 lockRedirectTbl = allocateRuntimeHash(20);
117 objRedirectLockTbl = allocateRuntimeHash(20);
122 objqueue.head = NULL;
123 objqueue.tail = NULL;
127 //isInterrupt = true;
130 taskInfoOverflow = false;
131 /*interruptInfoIndex = 0;
132 interruptInfoOverflow = false;*/
136 inline void disruntimedata() {
138 freeRuntimeHash(gcpointertbl);
140 freeRuntimeHash(lockRedirectTbl);
141 freeRuntimeHash(objRedirectLockTbl);
142 RUNFREE(locktable.bucket);
144 genfreehashtable(activetasks);
148 bool checkObjQueue() {
150 struct transObjInfo * objInfo = NULL;
154 #ifdef ACCURATEPROFILE
155 bool isChecking = false;
156 if(!isEmpty(&objqueue)) {
157 profileTaskStart("objqueue checking");
159 } // if(!isEmpty(&objqueue))
163 while(!isEmpty(&objqueue)) {
165 BAMBOO_START_CRITICAL_SECTION_OBJ_QUEUE();
167 BAMBOO_DEBUGPRINT(0xf001);
170 //isInterrupt = false;
173 BAMBOO_DEBUGPRINT(0xeee1);
176 objInfo = (struct transObjInfo *)getItem(&objqueue);
177 obj = objInfo->objptr;
179 BAMBOO_DEBUGPRINT_REG((int)obj);
181 // grab lock and flush the obj
185 BAMBOO_WAITING_FOR_LOCK();
186 } // while(!lockflag)
189 BAMBOO_DEBUGPRINT_REG(grount);
204 BAMBOO_CACHE_FLUSH_RANGE((int)obj,sizeof(int));
205 BAMBOO_CACHE_FLUSH_RANGE((int)obj,
206 classsize[((struct ___Object___ *)obj)->type]);
208 // enqueue the object
209 for(k = 0; k < objInfo->length; ++k) {
210 int taskindex = objInfo->queues[2 * k];
211 int paramindex = objInfo->queues[2 * k + 1];
212 struct parameterwrapper ** queues =
213 &(paramqueues[BAMBOO_NUM_OF_CORE][taskindex][paramindex]);
215 BAMBOO_DEBUGPRINT_REG(taskindex);
216 BAMBOO_DEBUGPRINT_REG(paramindex);
217 struct ___Object___ * tmpptr = (struct ___Object___ *)obj;
218 tprintf("Process %x(%d): receive obj %x(%lld), ptrflag %x\n",
219 BAMBOO_NUM_OF_CORE, BAMBOO_NUM_OF_CORE, (int)obj,
220 (long)obj, tmpptr->flag);
222 enqueueObject_I(obj, queues, 1);
224 BAMBOO_DEBUGPRINT_REG(hashsize(activetasks));
226 } // for(k = 0; k < objInfo->length; ++k)
227 releasewritelock_I(obj);
228 RUNFREE(objInfo->queues);
232 // put it at the end of the queue if no update version in the queue
233 struct QueueItem * qitem = getHead(&objqueue);
234 struct QueueItem * prev = NULL;
235 while(qitem != NULL) {
236 struct transObjInfo * tmpinfo =
237 (struct transObjInfo *)(qitem->objectptr);
238 if(tmpinfo->objptr == obj) {
239 // the same object in the queue, which should be enqueued
240 // recently. Current one is outdate, do not re-enqueue it
241 RUNFREE(objInfo->queues);
246 } // if(tmpinfo->objptr == obj)
247 qitem = getNextQueueItem(prev);
248 } // while(qitem != NULL)
249 // try to execute active tasks already enqueued first
250 addNewItem_I(&objqueue, objInfo);
252 //isInterrupt = true;
255 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
257 BAMBOO_DEBUGPRINT(0xf000);
261 BAMBOO_CLOSE_CRITICAL_SECTION_OBJ_QUEUE();
263 BAMBOO_DEBUGPRINT(0xf000);
265 } // while(!isEmpty(&objqueue))
268 #ifdef ACCURATEPROFILE
276 BAMBOO_DEBUGPRINT(0xee02);
281 inline 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
500 while(receiveObject() != -1) {
505 BAMBOO_DEBUGPRINT(0xee01);
508 // check if there are some pending objects,
509 // if yes, enqueue them and executetasks again
510 tocontinue = checkObjQueue();
514 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
517 BAMBOO_DEBUGPRINT(0xee03);
525 BAMBOO_DEBUGPRINT(0xee09);
531 // wait for some time
534 BAMBOO_DEBUGPRINT(0xee0a);
540 // send StallMsg to startup core
542 BAMBOO_DEBUGPRINT(0xee0b);
545 send_msg_4(STARTUPCORE, 1, BAMBOO_NUM_OF_CORE,
546 self_numsendobjs, self_numreceiveobjs);
558 BAMBOO_DEBUGPRINT(0xee0c);
561 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
564 } // if(BAMBOO_NUM_OF_CORE > NUMCORES - 1)
568 void createstartupobject(int argc,
572 /* Allocate startup object */
574 struct ___StartupObject___ *startupobject=
575 (struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
576 struct ArrayObject * stringarray=
577 allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
579 struct ___StartupObject___ *startupobject=
580 (struct ___StartupObject___*) allocate_new(STARTUPTYPE);
581 struct ArrayObject * stringarray=
582 allocate_newarray(STRINGARRAYTYPE, argc-1);
584 /* Build array of strings */
585 startupobject->___parameters___=stringarray;
586 for(i=1; i<argc; i++) {
587 int length=strlen(argv[i]);
589 struct ___String___ *newstring=NewString(NULL, argv[i],length);
591 struct ___String___ *newstring=NewString(argv[i],length);
593 ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=
597 startupobject->version = 0;
598 startupobject->lock = NULL;
600 /* Set initialized flag for startup object */
601 flagorandinit(startupobject,1,0xFFFFFFFF);
602 enqueueObject(startupobject, NULL, 0);
604 BAMBOO_CACHE_FLUSH_ALL();
608 int hashCodetpd(struct taskparamdescriptor *ftd) {
609 int hash=(int)ftd->task;
611 for(i=0; i<ftd->numParameters; i++) {
612 hash^=(int)ftd->parameterArray[i];
617 int comparetpd(struct taskparamdescriptor *ftd1,
618 struct taskparamdescriptor *ftd2) {
620 if (ftd1->task!=ftd2->task)
622 for(i=0; i<ftd1->numParameters; i++)
623 if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
628 /* This function sets a tag. */
630 void tagset(void *ptr,
631 struct ___Object___ * obj,
632 struct ___TagDescriptor___ * tagd) {
634 void tagset(struct ___Object___ * obj,
635 struct ___TagDescriptor___ * tagd) {
637 struct ArrayObject * ao=NULL;
638 struct ___Object___ * tagptr=obj->___tags___;
640 obj->___tags___=(struct ___Object___ *)tagd;
642 /* Have to check if it is already set */
643 if (tagptr->type==TAGTYPE) {
644 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
649 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
650 struct ArrayObject * ao=
651 allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
652 obj=(struct ___Object___ *)ptrarray[2];
653 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
654 td=(struct ___TagDescriptor___ *) obj->___tags___;
656 ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
659 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
660 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
661 obj->___tags___=(struct ___Object___ *) ao;
662 ao->___cachedCode___=2;
666 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
667 for(i=0; i<ao->___cachedCode___; i++) {
668 struct ___TagDescriptor___ * td=
669 ARRAYGET(ao, struct ___TagDescriptor___*, i);
674 if (ao->___cachedCode___<ao->___length___) {
675 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
676 ao->___cachedCode___++;
679 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
680 struct ArrayObject * aonew=
681 allocate_newarray(&ptrarray,TAGARRAYTYPE,
682 TAGARRAYINTERVAL+ao->___length___);
683 obj=(struct ___Object___ *)ptrarray[2];
684 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
685 ao=(struct ArrayObject *)obj->___tags___;
687 struct ArrayObject * aonew=
688 allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
691 aonew->___cachedCode___=ao->___length___+1;
692 for(i=0; i<ao->___length___; i++) {
693 ARRAYSET(aonew, struct ___TagDescriptor___*, i,
694 ARRAYGET(ao, struct ___TagDescriptor___*, i));
696 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
702 struct ___Object___ * tagset=tagd->flagptr;
705 } else if (tagset->type!=OBJECTARRAYTYPE) {
707 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
708 struct ArrayObject * ao=
709 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
710 obj=(struct ___Object___ *)ptrarray[2];
711 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
713 struct ArrayObject * ao=
714 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
716 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
717 ARRAYSET(ao, struct ___Object___ *, 1, obj);
718 ao->___cachedCode___=2;
719 tagd->flagptr=(struct ___Object___ *)ao;
721 struct ArrayObject *ao=(struct ArrayObject *) tagset;
722 if (ao->___cachedCode___<ao->___length___) {
723 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
727 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
728 struct ArrayObject * aonew=
729 allocate_newarray(&ptrarray,OBJECTARRAYTYPE,
730 OBJECTARRAYINTERVAL+ao->___length___);
731 obj=(struct ___Object___ *)ptrarray[2];
732 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
733 ao=(struct ArrayObject *)tagd->flagptr;
735 struct ArrayObject * aonew=
736 allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
738 aonew->___cachedCode___=ao->___cachedCode___+1;
739 for(i=0; i<ao->___length___; i++) {
740 ARRAYSET(aonew, struct ___Object___*, i,
741 ARRAYGET(ao, struct ___Object___*, i));
743 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
744 tagd->flagptr=(struct ___Object___ *) aonew;
750 /* This function clears a tag. */
752 void tagclear(void *ptr,
753 struct ___Object___ * obj,
754 struct ___TagDescriptor___ * tagd) {
756 void tagclear(struct ___Object___ * obj,
757 struct ___TagDescriptor___ * tagd) {
759 /* We'll assume that tag is alway there.
760 Need to statically check for this of course. */
761 struct ___Object___ * tagptr=obj->___tags___;
763 if (tagptr->type==TAGTYPE) {
764 if ((struct ___TagDescriptor___ *)tagptr==tagd)
765 obj->___tags___=NULL;
767 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
769 for(i=0; i<ao->___cachedCode___; i++) {
770 struct ___TagDescriptor___ * td=
771 ARRAYGET(ao, struct ___TagDescriptor___ *, i);
773 ao->___cachedCode___--;
774 if (i<ao->___cachedCode___)
775 ARRAYSET(ao, struct ___TagDescriptor___ *, i,
776 ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
777 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
778 if (ao->___cachedCode___==0)
779 obj->___tags___=NULL;
786 struct ___Object___ *tagset=tagd->flagptr;
787 if (tagset->type!=OBJECTARRAYTYPE) {
791 struct ArrayObject *ao=(struct ArrayObject *) tagset;
793 for(i=0; i<ao->___cachedCode___; i++) {
794 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
796 ao->___cachedCode___--;
797 if (i<ao->___cachedCode___)
798 ARRAYSET(ao, struct ___Object___ *, i,
799 ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
800 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
801 if (ao->___cachedCode___==0)
812 /* This function allocates a new tag. */
814 struct ___TagDescriptor___ * allocate_tag(void *ptr,
816 struct ___TagDescriptor___ * v=
817 (struct ___TagDescriptor___ *) FREEMALLOC((struct garbagelist *) ptr,
820 struct ___TagDescriptor___ * allocate_tag(int index) {
821 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
830 /* This function updates the flag for object ptr. It or's the flag
831 with the or mask and and's it with the andmask. */
833 void flagbody(struct ___Object___ *ptr,
835 struct parameterwrapper ** queues,
839 int flagcomp(const int *val1, const int *val2) {
840 return (*val1)-(*val2);
843 void flagorand(void * ptr,
846 struct parameterwrapper ** queues,
849 int oldflag=((int *)ptr)[1];
850 int flag=ormask|oldflag;
852 flagbody(ptr, flag, queues, length, false);
856 bool intflagorand(void * ptr,
860 int oldflag=((int *)ptr)[1];
861 int flag=ormask|oldflag;
863 if (flag==oldflag) /* Don't do anything */
866 flagbody(ptr, flag, NULL, 0, false);
872 void flagorandinit(void * ptr,
875 int oldflag=((int *)ptr)[1];
876 int flag=ormask|oldflag;
878 flagbody(ptr,flag,NULL,0,true);
881 void flagbody(struct ___Object___ *ptr,
883 struct parameterwrapper ** vqueues,
886 struct parameterwrapper * flagptr = NULL;
888 struct parameterwrapper ** queues = vqueues;
889 int length = vlength;
892 int * enterflags = NULL;
893 if((!isnew) && (queues == NULL)) {
894 if(BAMBOO_NUM_OF_CORE < NUMCORES) {
895 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
896 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
903 /*Remove object from all queues */
904 for(i = 0; i < length; ++i) {
906 ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next,
907 (int *) &enterflags, &UNUSED, &UNUSED2);
908 ObjectHashremove(flagptr->objectset, (int)ptr);
909 if (enterflags!=NULL)
914 void enqueueObject(void * vptr,
915 struct parameterwrapper ** vqueues,
917 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
920 //struct QueueItem *tmpptr;
921 struct parameterwrapper * parameter=NULL;
924 struct parameterwrapper * prevptr=NULL;
925 struct ___Object___ *tagptr=NULL;
926 struct parameterwrapper ** queues = vqueues;
927 int length = vlength;
928 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
932 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
933 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
935 tagptr=ptr->___tags___;
937 /* Outer loop iterates through all parameter queues an object of
938 this type could be in. */
939 for(j = 0; j < length; ++j) {
940 parameter = queues[j];
942 if (parameter->numbertags>0) {
944 goto nextloop; //that means the object has no tag
945 //but that param needs tag
946 else if(tagptr->type==TAGTYPE) { //one tag
947 //struct ___TagDescriptor___ * tag=
948 //(struct ___TagDescriptor___*) tagptr;
949 for(i=0; i<parameter->numbertags; i++) {
950 //slotid is parameter->tagarray[2*i];
951 int tagid=parameter->tagarray[2*i+1];
952 if (tagid!=tagptr->flag)
953 goto nextloop; /*We don't have this tag */
955 } else { //multiple tags
956 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
957 for(i=0; i<parameter->numbertags; i++) {
958 //slotid is parameter->tagarray[2*i];
959 int tagid=parameter->tagarray[2*i+1];
961 for(j=0; j<ao->___cachedCode___; j++) {
962 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
973 for(i=0; i<parameter->numberofterms; i++) {
974 int andmask=parameter->intarray[i*2];
975 int checkmask=parameter->intarray[i*2+1];
976 if ((ptr->flag&andmask)==checkmask) {
977 enqueuetasks(parameter, prevptr, ptr, NULL, 0);
988 void enqueueObject_I(void * vptr,
989 struct parameterwrapper ** vqueues,
991 struct ___Object___ *ptr = (struct ___Object___ *)vptr;
994 //struct QueueItem *tmpptr;
995 struct parameterwrapper * parameter=NULL;
998 struct parameterwrapper * prevptr=NULL;
999 struct ___Object___ *tagptr=NULL;
1000 struct parameterwrapper ** queues = vqueues;
1001 int length = vlength;
1002 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1005 if(queues == NULL) {
1006 queues = objectqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1007 length = numqueues[BAMBOO_NUM_OF_CORE][ptr->type];
1009 tagptr=ptr->___tags___;
1011 /* Outer loop iterates through all parameter queues an object of
1012 this type could be in. */
1013 for(j = 0; j < length; ++j) {
1014 parameter = queues[j];
1016 if (parameter->numbertags>0) {
1018 goto nextloop; //that means the object has no tag
1019 //but that param needs tag
1020 else if(tagptr->type==TAGTYPE) { //one tag
1021 //struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
1022 for(i=0; i<parameter->numbertags; i++) {
1023 //slotid is parameter->tagarray[2*i];
1024 int tagid=parameter->tagarray[2*i+1];
1025 if (tagid!=tagptr->flag)
1026 goto nextloop; /*We don't have this tag */
1028 } else { //multiple tags
1029 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
1030 for(i=0; i<parameter->numbertags; i++) {
1031 //slotid is parameter->tagarray[2*i];
1032 int tagid=parameter->tagarray[2*i+1];
1034 for(j=0; j<ao->___cachedCode___; j++) {
1035 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
1046 for(i=0; i<parameter->numberofterms; i++) {
1047 int andmask=parameter->intarray[i*2];
1048 int checkmask=parameter->intarray[i*2+1];
1049 if ((ptr->flag&andmask)==checkmask) {
1050 enqueuetasks_I(parameter, prevptr, ptr, NULL, 0);
1062 int * getAliasLock(void ** ptrs,
1064 struct RuntimeHash * tbl) {
1066 return (int*)(RUNMALLOC(sizeof(int)));
1071 bool redirect = false;
1072 int redirectlock = 0;
1073 for(; i < length; i++) {
1074 struct ___Object___ * ptr = (struct ___Object___ *)(ptrs[i]);
1077 if(ptr->lock == NULL) {
1080 lock = (int)(ptr->lock);
1083 if(lock != redirectlock) {
1084 RuntimeHashadd(tbl, lock, redirectlock);
1087 if(RuntimeHashcontainskey(tbl, lock)) {
1088 // already redirected
1090 RuntimeHashget(tbl, lock, &redirectlock);
1091 for(; j < locklen; j++) {
1092 if(locks[j] != redirectlock) {
1093 RuntimeHashadd(tbl, locks[j], redirectlock);
1098 for(j = 0; j < locklen; j++) {
1099 if(locks[j] == lock) {
1102 } else if(locks[j] > lock) {
1109 locks[h] = locks[h-1];
1118 return (int *)redirectlock;
1120 return (int *)(locks[0]);
1125 void addAliasLock(void * ptr,
1127 struct ___Object___ * obj = (struct ___Object___ *)ptr;
1128 if(((int)ptr != lock) && (obj->lock != (int*)lock)) {
1129 // originally no alias lock associated or have a different alias lock
1130 // flush it as the new one
1131 obj->lock = (int *)lock;
1136 inline void setTaskExitIndex(int index) {
1137 taskInfoArray[taskInfoIndex]->exitIndex = index;
1140 inline void addNewObjInfo(void * nobj) {
1141 if(taskInfoArray[taskInfoIndex]->newObjs == NULL) {
1142 taskInfoArray[taskInfoIndex]->newObjs = createQueue();
1144 addNewItem(taskInfoArray[taskInfoIndex]->newObjs, nobj);
1148 void * smemalloc(int size,
1151 // go through free mem list for suitable blocks
1152 struct freeMemItem * freemem = bamboo_free_mem_list->head;
1153 struct freeMemItem * prev = NULL;
1155 if(freemem->size > size) {
1160 freemem = freemem->next;
1161 } while(freemem != NULL);
1162 if(freemem != NULL) {
1163 void * mem = (void *)(freemem->ptr);
1165 freemem->ptr = ((void*)freemem->ptr) + size;
1166 freemem->size -= size;
1167 // check how many blocks it acrosses
1169 BLOCKINDEX(mem, &b);
1170 // check the remaining space in this block
1171 int remain = (b < NUMCORES? (b+1)*BAMBOO_SMEM_SIZE_L
1172 : BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES+1)*BAMBOO_SMEM_SIZE)
1173 -(mem-BAMBOO_BASE_VA);
1175 // this object acrosses blocks
1176 int tmpsbs = 1+(size-remain-1)/BAMBOO_SMEM_SIZE;
1177 for(int k = 0; k < tmpsbs-1; k++) {
1178 sbstarttbl[k+b] = (INTPTR)(-1);
1180 if((size-remain)%BAMBOO_SMEM_SIZE == 0) {
1181 sbstarttbl[b+tmpsbs-1] = (INTPTR)(-1);
1183 sbstarttbl[b+tmpsbs-1] = (INTPTR)(mem+size);
1188 void * mem = mspace_calloc(bamboo_free_msp, 1, size);
1192 // no enough shared global memory
1196 gcrequiredmem = size;
1199 BAMBOO_DEBUGPRINT(0xa016);
1200 BAMBOO_EXIT(0xa016);
1206 // receive object transferred from other cores
1207 // or the terminate message from other cores
1208 // Should be invoked in critical sections!!
1209 // NOTICE: following format is for threadsimulate version only
1210 // RAW version please see previous description
1211 // format: type + object
1212 // type: -1--stall msg
1214 // return value: 0--received an object
1215 // 1--received nothing
1216 // 2--received a Stall Msg
1217 // 3--received a lock Msg
1218 // RAW version: -1 -- received nothing
1219 // otherwise -- received msg type
1220 int receiveObject() {
1224 if(receiveMsg() == -1) {
1228 if(msgdataindex == msglength) {
1229 // received a whole msg
1234 // receive a object transfer msg
1235 struct transObjInfo * transObj =
1236 RUNMALLOC_I(sizeof(struct transObjInfo));
1240 BAMBOO_DEBUGPRINT(0xe880);
1243 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1245 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1247 BAMBOO_EXIT(0xa005);
1249 // store the object and its corresponding queue info, enqueue it later
1250 transObj->objptr = (void *)msgdata[2];
1251 transObj->length = (msglength - 3) / 2;
1252 transObj->queues = RUNMALLOC_I(sizeof(int)*(msglength - 3));
1253 for(k = 0; k < transObj->length; ++k) {
1254 transObj->queues[2*k] = msgdata[3+2*k];
1257 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k]);
1260 transObj->queues[2*k+1] = msgdata[3+2*k+1];
1263 BAMBOO_DEBUGPRINT_REG(transObj->queues[2*k+1]);
1267 // check if there is an existing duplicate item
1269 struct QueueItem * qitem = getHead(&objqueue);
1270 struct QueueItem * prev = NULL;
1271 while(qitem != NULL) {
1272 struct transObjInfo * tmpinfo =
1273 (struct transObjInfo *)(qitem->objectptr);
1274 if(tmpinfo->objptr == transObj->objptr) {
1275 // the same object, remove outdate one
1276 removeItem(&objqueue, qitem);
1282 qitem = getHead(&objqueue);
1284 qitem = getNextQueueItem(prev);
1287 addNewItem_I(&objqueue, (void *)transObj);
1289 ++(self_numreceiveobjs);
1294 // receive a stall msg
1295 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1296 // non startup core can not receive stall msg
1298 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1300 BAMBOO_EXIT(0xa006);
1302 if(msgdata[1] < NUMCORES) {
1305 BAMBOO_DEBUGPRINT(0xe881);
1308 corestatus[msgdata[1]] = 0;
1309 numsendobjs[msgdata[1]] = msgdata[2];
1310 numreceiveobjs[msgdata[1]] = msgdata[3];
1315 // GC version have no lock msgs
1316 #ifndef MULTICORE_GC
1318 // receive lock request msg, handle it right now
1319 // check to see if there is a lock exist for the required obj
1320 // msgdata[1] -> lock type
1321 int data2 = msgdata[2]; // obj pointer
1322 int data3 = msgdata[3]; // lock
1323 int data4 = msgdata[4]; // request core
1324 // -1: redirected, 0: approved, 1: denied
1325 deny = processlockrequest(msgdata[1], data3, data2,
1326 data4, data4, true);
1328 // this lock request is redirected
1331 // send response msg
1332 // for 32 bit machine, the size is always 4 words
1333 int tmp = deny==1?LOCKDENY:LOCKGROUNT;
1335 cache_msg_4(data4, tmp, msgdata[1], data2, data3);
1337 send_msg_4(data4, tmp, msgdata[1], data2, data3);
1344 // receive lock grount msg
1345 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1347 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1349 BAMBOO_EXIT(0xa007);
1351 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1354 BAMBOO_DEBUGPRINT(0xe882);
1363 // conflicts on lockresults
1365 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1367 BAMBOO_EXIT(0xa008);
1373 // receive lock deny msg
1374 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1376 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1378 BAMBOO_EXIT(0xa009);
1380 if((lockobj == msgdata[2]) && (lock2require == msgdata[3])) {
1383 BAMBOO_DEBUGPRINT(0xe883);
1392 // conflicts on lockresults
1394 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1396 BAMBOO_EXIT(0xa00a);
1402 // receive lock release msg
1403 processlockrelease(msgdata[1], msgdata[2], 0, false);
1409 case PROFILEOUTPUT: {
1410 // receive an output profile data request msg
1411 if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1412 // startup core can not receive profile output finish msg
1413 BAMBOO_EXIT(0xa00c);
1417 BAMBOO_DEBUGPRINT(0xe885);
1421 totalexetime = msgdata[1];
1422 outputProfileData();
1424 cache_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1426 send_msg_2(STARTUPCORE, PROFILEFINISH, BAMBOO_NUM_OF_CORE);
1431 case PROFILEFINISH: {
1432 // receive a profile output finish msg
1433 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1434 // non startup core can not receive profile output finish msg
1436 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1438 BAMBOO_EXIT(0xa00d);
1442 BAMBOO_DEBUGPRINT(0xe886);
1445 profilestatus[msgdata[1]] = 0;
1450 // GC version has no lock msgs
1451 #ifndef MULTICORE_GC
1452 case REDIRECTLOCK: {
1453 // receive a redirect lock request msg, handle it right now
1454 // check to see if there is a lock exist for the required obj
1455 int data1 = msgdata[1]; // lock type
1456 int data2 = msgdata[2]; // obj pointer
1457 int data3 = msgdata[3]; // redirect lock
1458 int data4 = msgdata[4]; // root request core
1459 int data5 = msgdata[5]; // request core
1460 deny = processlockrequest(msgdata[1], data3, data2, data5, data4, true);
1462 // this lock request is redirected
1465 // send response msg
1466 // for 32 bit machine, the size is always 4 words
1468 cache_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1469 data1, data2, data3);
1471 send_msg_4(data4, deny==1?REDIRECTDENY:REDIRECTGROUNT,
1472 data1, data2, data3);
1478 case REDIRECTGROUNT: {
1479 // receive a lock grant msg with redirect info
1480 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1482 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1484 BAMBOO_EXIT(0xa00e);
1486 if(lockobj == msgdata[2]) {
1489 BAMBOO_DEBUGPRINT(0xe891);
1494 RuntimeHashadd_I(objRedirectLockTbl, lockobj, msgdata[3]);
1499 // conflicts on lockresults
1501 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1503 BAMBOO_EXIT(0xa00f);
1508 case REDIRECTDENY: {
1509 // receive a lock deny msg with redirect info
1510 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1512 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1514 BAMBOO_EXIT(0xa010);
1516 if(lockobj == msgdata[2]) {
1519 BAMBOO_DEBUGPRINT(0xe892);
1528 // conflicts on lockresults
1530 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1532 BAMBOO_EXIT(0xa011);
1537 case REDIRECTRELEASE: {
1538 // receive a lock release msg with redirect info
1539 processlockrelease(msgdata[1], msgdata[2], msgdata[3], true);
1544 case STATUSCONFIRM: {
1545 // receive a status confirm info
1546 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1547 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1548 // wrong core to receive such msg
1549 BAMBOO_EXIT(0xa013);
1551 // send response msg
1554 BAMBOO_DEBUGPRINT(0xe887);
1558 cache_msg_5(STARTUPCORE, STATUSREPORT,
1559 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1560 self_numsendobjs, self_numreceiveobjs);
1562 send_msg_5(STARTUPCORE, STATUSREPORT,
1563 busystatus?1:0, BAMBOO_NUM_OF_CORE,
1564 self_numsendobjs, self_numreceiveobjs);
1570 case STATUSREPORT: {
1571 // receive a status confirm info
1572 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1573 // wrong core to receive such msg
1575 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1577 BAMBOO_EXIT(0xa014);
1581 BAMBOO_DEBUGPRINT(0xe888);
1587 corestatus[msgdata[2]] = msgdata[1];
1588 numsendobjs[msgdata[1]] = msgdata[2];
1589 numreceiveobjs[msgdata[1]] = msgdata[3];
1595 // receive a terminate msg
1598 BAMBOO_DEBUGPRINT(0xe889);
1607 // receive a shared memory request msg
1608 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1609 // wrong core to receive such msg
1611 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1613 BAMBOO_EXIT(0xa015);
1617 BAMBOO_DEBUGPRINT(0xe88a);
1622 // is currently doing gc, dump this msg
1627 void * mem = smemalloc(msgdata[1], &allocsize);
1631 // send the start_va to request core
1633 cache_msg_3(msgdata[2], MEMRESPONSE, mem, allocsize);
1635 send_msg_3( msgdata[2], MEMRESPONSE, mem, allocsize);
1642 // receive a shared memory response msg
1645 BAMBOO_DEBUGPRINT(0xe88b);
1650 // is currently doing gc, dump this msg
1654 if(msgdata[2] == 0) {
1655 bamboo_smem_size = 0;
1658 // fill header to store the size of this mem block
1659 (*((int*)msgdata[1])) = msgdata[2];
1660 bamboo_smem_size = msgdata[2] - BAMBOO_CACHE_LINE_SIZE;
1662 bamboo_cur_msp = msgdata[1] + BAMBOO_CACHE_LINE_SIZE;
1665 create_mspace_with_base((void*)(msgdata[1]+BAMBOO_CACHE_LINE_SIZE),
1666 msgdata[2]-BAMBOO_CACHE_LINE_SIZE,
1677 // receive a start GC msg
1680 BAMBOO_DEBUGPRINT(0xe88c);
1685 gcphase = MARKPHASE;
1687 // is waiting for response of mem request
1688 // let it return NULL and start gc
1689 bamboo_smem_size = 0;
1690 bamboo_cur_msp = NULL;
1696 case GCSTARTCOMPACT: {
1697 // a compact phase start msg
1698 gcblocks2fill = msgdata[1];
1699 gcphase = COMPACTPHASE;
1703 case GCSTARTFLUSH: {
1704 // received a flush phase start msg
1705 gcphase = FLUSHPHASE;
1709 case GCFINISHMARK: {
1710 // received a mark phase finish msg
1711 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1712 // non startup core can not receive this msg
1714 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1716 BAMBOO_EXIT(0xb006);
1718 if(msgdata[1] < NUMCORES) {
1719 gccorestatus[msgdata[1]] = 0;
1720 gcnumsendobjs[msgdata[1]] = gcmsgdata[2];
1721 gcnumreceiveobjs[msgdata[1]] = gcmsgdata[3];
1726 case GCFINISHCOMPACT: {
1727 // received a compact phase finish msg
1728 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1729 // non startup core can not receive this msg
1732 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1734 BAMBOO_EXIT(0xb006);
1736 int cnum = msgdata[1];
1737 int filledblocks = msgdata[2];
1738 int heaptop = msgdata[3];
1739 int data4 = msgdata[4];
1740 if(cnum < NUMCORES) {
1741 if(COMPACTPHASE == gcphase) {
1742 gcfilledblocks[cnum] = filledblocks;
1743 gcloads[cnum] = heaptop;
1750 if(findSpareMem(&startaddr, &tomove, &dstcore, data4, cnum)) {
1751 send_msg_4(cnum, GCMOVESTART, dstcore, startaddr, tomove);
1754 gccorestatus[cnum] = 0;
1755 // check if there is pending move request
1756 if(gcmovepending > 0) {
1758 for(j = 0; j < NUMCORES; j++) {
1759 if(gcrequiredmems[j]>0) {
1767 gcrequiredmems[j] = assignSpareMem(cnum,
1771 if(STARTUPCORE == j) {
1774 gcmovestartaddr = startaddr;
1775 gcblock2fill = tomove;
1777 send_msg_4(j, GCMOVESTART, cnum, startaddr, tomove);
1778 } // if(STARTUPCORE == j)
1779 if(gcrequiredmems[j] == 0) {
1782 } // if(j < NUMCORES)
1783 } // if(gcmovepending > 0)
1785 } // if(cnum < NUMCORES)
1789 case GCFINISHFLUSH: {
1790 // received a flush phase finish msg
1791 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1792 // non startup core can not receive this msg
1795 BAMBOO_DEBUGPRINT_REG(msgdata[1]);
1797 BAMBOO_EXIT(0xb006);
1799 if(msgdata[1] < NUMCORES) {
1800 gccorestatus[msgdata[1]] = 0;
1806 // received a GC finish msg
1807 gcphase = FINISHPHASE;
1811 case GCMARKCONFIRM: {
1812 // received a marked phase finish confirm request msg
1813 if((BAMBOO_NUM_OF_CORE == STARTUPCORE)
1814 || (BAMBOO_NUM_OF_CORE > NUMCORES - 1)) {
1815 // wrong core to receive such msg
1816 BAMBOO_EXIT(0xa013);
1818 // send response msg
1820 cache_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1821 gcbusystatus, gcself_numsendobjs,
1822 gcself_numreceiveobjs);
1824 send_msg_5(STARTUPCORE, GCMARKREPORT, BAMBOO_NUM_OF_CORE,
1825 gcbusystatus, gcself_numsendobjs, gcself_numreceiveobjs);
1831 case GCMARKREPORT: {
1832 // received a marked phase finish confirm response msg
1833 if(BAMBOO_NUM_OF_CORE != STARTUPCORE) {
1834 // wrong core to receive such msg
1836 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1838 BAMBOO_EXIT(0xb014);
1843 gccorestatus[msgdata[1]] = gcmsgdata[2];
1844 gcnumsendobjs[msgdata[1]] = gcmsgdata[3];
1845 gcnumreceiveobjs[msgdata[1]] = gcmsgdata[4];
1851 // received a markedObj msg
1852 gc_enqueue(msgdata[1]);
1853 gcself_numreceiveobjs++;
1854 gcbusystatus = true;
1859 // received a start moving objs msg
1861 gcdstcore = msgdata[1];
1862 gcmovestartaddr = msgdata[2];
1863 gcblock2fill = msgdata[3];
1867 case GCMAPREQUEST: {
1868 // received a mapping info request msg
1869 void * dstptr = NULL;
1870 RuntimeHashget(gcpointertbl, msgdata[1], &dstptr);
1871 if(NULL == dstptr) {
1872 // no such pointer in this core, something is wrong
1873 BAMBOO_EXIT(0xb008);
1875 // send back the mapping info
1877 cache_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1879 send_msg_3(msgdata[2], GCMAPINFO, msgdata[1], (int)dstptr);
1886 // received a mapping info response msg
1887 if(msgdata[1] != gcobj2map) {
1888 // obj not matched, something is wrong
1889 BAMBOO_EXIT(0xb009);
1891 gcmappedobj = msgdata[2];
1892 RuntimeHashadd(gcpointertbl, gcobj2map, gcmappedobj);
1898 case GCLOBJREQUEST: {
1899 // received a large objs info request msg
1900 transferMarkResults();
1905 // received a large objs info response msg
1908 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
1910 BAMBOO_DEBUGPRINT_REG(msgdata[2]);
1912 BAMBOO_EXIT(0xa005);
1914 // store the mark result info
1915 int cnum = msgdata[2];
1916 gcloads[cnum] = msgdata[3];
1917 if(gcheaptop < msgdata[4]) {
1918 gcheaptop = msgdata[4];
1920 // large obj info here
1921 for(int k = 5; k < msgdata[1];) {
1922 gc_lobjenqueue(msgdata[k++], msgdata[k++], cnum, NULL);
1923 } // for(int k = 5; k < msgdata[1];)
1927 case GCLOBJMAPPING: {
1928 // received a large obj mapping info msg
1929 RuntimeHashadd(gcpointertbl, msgdata[1], msgdata[2]);
1938 for(msgdataindex--; msgdataindex > 0; --msgdataindex) {
1939 msgdata[msgdataindex] = -1;
1945 BAMBOO_DEBUGPRINT(0xe88d);
1949 if(BAMBOO_MSG_AVAIL() != 0) {
1962 BAMBOO_DEBUGPRINT(0xe88e);
1966 /* if(isInterrupt) {
1974 int enqueuetasks(struct parameterwrapper *parameter,
1975 struct parameterwrapper *prevptr,
1976 struct ___Object___ *ptr,
1978 int numenterflags) {
1979 void * taskpointerarray[MAXTASKPARAMS];
1981 //int numparams=parameter->task->numParameters;
1982 int numiterators=parameter->task->numTotal-1;
1985 struct taskdescriptor * task=parameter->task;
1987 //this add the object to parameterwrapper
1988 ObjectHashadd(parameter->objectset, (int) ptr, 0, (int) enterflags,
1989 numenterflags, enterflags==NULL);
1991 /* Add enqueued object to parameter vector */
1992 taskpointerarray[parameter->slot]=ptr;
1994 /* Reset iterators */
1995 for(j=0; j<numiterators; j++) {
1996 toiReset(¶meter->iterators[j]);
1999 /* Find initial state */
2000 for(j=0; j<numiterators; j++) {
2002 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2003 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2005 /* Need to backtrack */
2006 toiReset(¶meter->iterators[j]);
2010 /* Nothing to enqueue */
2016 /* Enqueue current state */
2018 struct taskparamdescriptor *tpd=
2019 RUNMALLOC(sizeof(struct taskparamdescriptor));
2021 tpd->numParameters=numiterators+1;
2022 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
2024 for(j=0; j<=numiterators; j++) {
2025 //store the actual parameters
2026 tpd->parameterArray[j]=taskpointerarray[j];
2029 if ((/*!gencontains(failedtasks, tpd)&&*/
2030 !gencontains(activetasks,tpd))) {
2031 genputtable(activetasks, tpd, tpd);
2033 RUNFREE(tpd->parameterArray);
2037 /* This loop iterates to the next parameter combination */
2038 if (numiterators==0)
2041 for(j=numiterators-1; j<numiterators; j++) {
2043 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2044 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2046 /* Need to backtrack */
2047 toiReset(¶meter->iterators[j]);
2051 /* Nothing more to enqueue */
2059 int enqueuetasks_I(struct parameterwrapper *parameter,
2060 struct parameterwrapper *prevptr,
2061 struct ___Object___ *ptr,
2063 int numenterflags) {
2064 void * taskpointerarray[MAXTASKPARAMS];
2066 //int numparams=parameter->task->numParameters;
2067 int numiterators=parameter->task->numTotal-1;
2072 struct taskdescriptor * task=parameter->task;
2074 //this add the object to parameterwrapper
2075 ObjectHashadd_I(parameter->objectset, (int) ptr, 0, (int) enterflags,
2076 numenterflags, enterflags==NULL);
2078 /* Add enqueued object to parameter vector */
2079 taskpointerarray[parameter->slot]=ptr;
2081 /* Reset iterators */
2082 for(j=0; j<numiterators; j++) {
2083 toiReset(¶meter->iterators[j]);
2086 /* Find initial state */
2087 for(j=0; j<numiterators; j++) {
2089 if(toiHasNext(¶meter->iterators[j],taskpointerarray OPTARG(failed)))
2090 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2092 /* Need to backtrack */
2093 toiReset(¶meter->iterators[j]);
2097 /* Nothing to enqueue */
2103 /* Enqueue current state */
2105 struct taskparamdescriptor *tpd=
2106 RUNMALLOC_I(sizeof(struct taskparamdescriptor));
2108 tpd->numParameters=numiterators+1;
2109 tpd->parameterArray=RUNMALLOC_I(sizeof(void *)*(numiterators+1));
2111 for(j=0; j<=numiterators; j++) {
2112 //store the actual parameters
2113 tpd->parameterArray[j]=taskpointerarray[j];
2116 if ((/*!gencontains(failedtasks, tpd)&&*/
2117 !gencontains(activetasks,tpd))) {
2118 genputtable_I(activetasks, tpd, tpd);
2120 RUNFREE(tpd->parameterArray);
2124 /* This loop iterates to the next parameter combination */
2125 if (numiterators==0)
2128 for(j=numiterators-1; j<numiterators; j++) {
2130 if(toiHasNext(¶meter->iterators[j], taskpointerarray OPTARG(failed)))
2131 toiNext(¶meter->iterators[j], taskpointerarray OPTARG(failed));
2133 /* Need to backtrack */
2134 toiReset(¶meter->iterators[j]);
2138 /* Nothing more to enqueue */
2152 int containstag(struct ___Object___ *ptr,
2153 struct ___TagDescriptor___ *tag);
2155 #ifndef MULTICORE_GC
2156 void releasewritelock_r(void * lock, void * redirectlock) {
2158 int reallock = (int)lock;
2159 targetcore = (reallock >> 5) % BAMBOO_TOTALCORE;
2162 BAMBOO_DEBUGPRINT(0xe671);
2163 BAMBOO_DEBUGPRINT_REG((int)lock);
2164 BAMBOO_DEBUGPRINT_REG(reallock);
2165 BAMBOO_DEBUGPRINT_REG(targetcore);
2168 if(targetcore == BAMBOO_NUM_OF_CORE) {
2169 BAMBOO_START_CRITICAL_SECTION_LOCK();
2171 BAMBOO_DEBUGPRINT(0xf001);
2173 // reside on this core
2174 if(!RuntimeHashcontainskey(locktbl, reallock)) {
2175 // no locks for this object, something is wrong
2176 BAMBOO_EXIT(0xa01d);
2179 struct LockValue * lockvalue = NULL;
2181 BAMBOO_DEBUGPRINT(0xe672);
2183 RuntimeHashget(locktbl, reallock, &rwlock_obj);
2184 lockvalue = (struct LockValue *)rwlock_obj;
2186 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2189 lockvalue->redirectlock = (int)redirectlock;
2191 BAMBOO_DEBUGPRINT_REG(lockvalue->value);
2194 BAMBOO_CLOSE_CRITICAL_SECTION_LOCK();
2196 BAMBOO_DEBUGPRINT(0xf000);
2200 // send lock release with redirect info msg
2201 // for 32 bit machine, the size is always 4 words
2202 send_msg_4(targetcore, REDIRECTRELEASE, 1, (int)lock, (int)redirectlock);
2207 void executetasks() {
2208 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
2211 struct ___Object___ * tmpparam = NULL;
2212 struct parameterdescriptor * pd=NULL;
2213 struct parameterwrapper *pw=NULL;
2218 struct LockValue locks[MAXTASKPARAMS];
2226 while(hashsize(activetasks)>0) {
2231 BAMBOO_DEBUGPRINT(0xe990);
2234 /* See if there are any active tasks */
2235 if (hashsize(activetasks)>0) {
2238 #ifdef ACCURATEPROFILE
2239 profileTaskStart("tpd checking");
2243 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
2244 genfreekey(activetasks, currtpd);
2246 numparams=currtpd->task->numParameters;
2247 numtotal=currtpd->task->numTotal;
2249 // clear the lockRedirectTbl
2250 // (TODO, this table should be empty after all locks are released)
2252 for(j = 0; j < MAXTASKPARAMS; j++) {
2253 locks[j].redirectlock = 0;
2256 // get all required locks
2258 // check which locks are needed
2259 for(i = 0; i < numparams; i++) {
2260 void * param = currtpd->parameterArray[i];
2264 if(((struct ___Object___ *)param)->type == STARTUPTYPE) {
2266 taskpointerarray[i+OFFSET]=param;
2269 if(((struct ___Object___ *)param)->lock == NULL) {
2270 tmplock = (int)param;
2272 tmplock = (int)(((struct ___Object___ *)param)->lock);
2274 // insert into the locks array
2275 for(j = 0; j < locklen; j++) {
2276 if(locks[j].value == tmplock) {
2279 } else if(locks[j].value > tmplock) {
2286 locks[h].redirectlock = locks[h-1].redirectlock;
2287 locks[h].value = locks[h-1].value;
2289 locks[j].value = tmplock;
2290 locks[j].redirectlock = (int)param;
2293 } // line 2713: for(i = 0; i < numparams; i++)
2294 // grab these required locks
2296 BAMBOO_DEBUGPRINT(0xe991);
2298 for(i = 0; i < locklen; i++) {
2299 int * lock = (int *)(locks[i].redirectlock);
2301 // require locks for this parameter if it is not a startup object
2303 BAMBOO_DEBUGPRINT_REG((int)lock);
2304 BAMBOO_DEBUGPRINT_REG((int)(locks[i].value));
2307 BAMBOO_START_CRITICAL_SECTION();
2309 BAMBOO_DEBUGPRINT(0xf001);
2312 //isInterrupt = false;
2315 BAMBOO_WAITING_FOR_LOCK();
2319 while(BAMBOO_WAITING_FOR_LOCK() != -1) {
2323 grount = lockresult;
2333 //isInterrupt = true;
2335 BAMBOO_CLOSE_CRITICAL_SECTION();
2337 BAMBOO_DEBUGPRINT(0xf000);
2343 BAMBOO_DEBUGPRINT(0xe992);
2345 // can not get the lock, try later
2346 // releas all grabbed locks for previous parameters
2347 for(j = 0; j < i; ++j) {
2348 lock = (int*)(locks[j].redirectlock);
2349 releasewritelock(lock);
2351 genputtable(activetasks, currtpd, currtpd);
2352 if(hashsize(activetasks) == 1) {
2353 // only one task right now, wait a little while before next try
2359 #ifdef ACCURATEPROFILE
2360 // fail, set the end of the checkTaskInfo
2365 } // line 2794: if(grount == 0)
2366 } // line 2752: for(i = 0; i < locklen; i++)
2369 BAMBOO_DEBUGPRINT(0xe993);
2371 /* Make sure that the parameters are still in the queues */
2372 for(i=0; i<numparams; i++) {
2373 void * parameter=currtpd->parameterArray[i];
2377 BAMBOO_CACHE_FLUSH_RANGE((int)parameter,
2378 classsize[((struct ___Object___ *)parameter)->type]);
2380 tmpparam = (struct ___Object___ *)parameter;
2381 pd=currtpd->task->descriptorarray[i];
2382 pw=(struct parameterwrapper *) pd->queue;
2383 /* Check that object is still in queue */
2385 if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
2387 BAMBOO_DEBUGPRINT(0xe994);
2389 // release grabbed locks
2390 for(j = 0; j < locklen; ++j) {
2391 int * lock = (int *)(locks[j].redirectlock);
2392 releasewritelock(lock);
2394 RUNFREE(currtpd->parameterArray);
2399 /* Check if the object's flags still meets requirements */
2403 for(tmpi = 0; tmpi < pw->numberofterms; ++tmpi) {
2404 andmask=pw->intarray[tmpi*2];
2405 checkmask=pw->intarray[tmpi*2+1];
2406 if((((struct ___Object___ *)parameter)->flag&andmask)==checkmask) {
2412 // flags are never suitable
2413 // remove this obj from the queue
2415 int UNUSED, UNUSED2;
2418 BAMBOO_DEBUGPRINT(0xe995);
2420 ObjectHashget(pw->objectset, (int) parameter, (int *) &next,
2421 (int *) &enterflags, &UNUSED, &UNUSED2);
2422 ObjectHashremove(pw->objectset, (int)parameter);
2423 if (enterflags!=NULL)
2424 RUNFREE(enterflags);
2425 // release grabbed locks
2426 for(j = 0; j < locklen; ++j) {
2427 int * lock = (int *)(locks[j].redirectlock);
2428 releasewritelock(lock);
2430 RUNFREE(currtpd->parameterArray);
2433 #ifdef ACCURATEPROFILE
2434 // fail, set the end of the checkTaskInfo
2439 } // line 2878: if (!ismet)
2443 /* Check that object still has necessary tags */
2444 for(j=0; j<pd->numbertags; j++) {
2445 int slotid=pd->tagarray[2*j]+numparams;
2446 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
2447 if (!containstag(parameter, tagd)) {
2449 BAMBOO_DEBUGPRINT(0xe996);
2452 // release grabbed locks
2454 for(tmpj = 0; tmpj < locklen; ++tmpj) {
2455 int * lock = (int *)(locks[tmpj].redirectlock);
2456 releasewritelock(lock);
2459 RUNFREE(currtpd->parameterArray);
2462 } // line2911: if (!containstag(parameter, tagd))
2463 } // line 2808: for(j=0; j<pd->numbertags; j++)
2465 taskpointerarray[i+OFFSET]=parameter;
2466 } // line 2824: for(i=0; i<numparams; i++)
2468 for(; i<numtotal; i++) {
2469 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
2473 /* Actually call task */
2475 ((int *)taskpointerarray)[0]=currtpd->numParameters;
2476 taskpointerarray[1]=NULL;
2480 #ifdef ACCURATEPROFILE
2481 // check finish, set the end of the checkTaskInfo
2484 profileTaskStart(currtpd->task->name);
2488 BAMBOO_DEBUGPRINT(0xe997);
2490 ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
2492 #ifdef ACCURATEPROFILE
2493 // task finish, set the end of the checkTaskInfo
2495 // new a PostTaskInfo for the post-task execution
2496 profileTaskStart("post task execution");
2500 BAMBOO_DEBUGPRINT(0xe998);
2501 BAMBOO_DEBUGPRINT_REG(islock);
2506 BAMBOO_DEBUGPRINT(0xe999);
2508 for(i = 0; i < locklen; ++i) {
2509 void * ptr = (void *)(locks[i].redirectlock);
2510 int * lock = (int *)(locks[i].value);
2512 BAMBOO_DEBUGPRINT_REG((int)ptr);
2513 BAMBOO_DEBUGPRINT_REG((int)lock);
2515 #ifndef MULTICORE_GC
2516 if(RuntimeHashcontainskey(lockRedirectTbl, (int)lock)) {
2518 RuntimeHashget(lockRedirectTbl, (int)lock, &redirectlock);
2519 RuntimeHashremovekey(lockRedirectTbl, (int)lock);
2520 releasewritelock_r(lock, (int *)redirectlock);
2525 releasewritelock(ptr);
2528 } // line 3015: if(islock)
2531 // post task execution finish, set the end of the postTaskInfo
2535 // Free up task parameter descriptor
2536 RUNFREE(currtpd->parameterArray);
2539 BAMBOO_DEBUGPRINT(0xe99a);
2542 } // if (hashsize(activetasks)>0)
2543 } // while(hashsize(activetasks)>0)
2545 BAMBOO_DEBUGPRINT(0xe99b);
2549 /* This function processes an objects tags */
2550 void processtags(struct parameterdescriptor *pd,
2552 struct parameterwrapper *parameter,
2553 int * iteratorcount,
2558 for(i=0; i<pd->numbertags; i++) {
2559 int slotid=pd->tagarray[2*i];
2560 int tagid=pd->tagarray[2*i+1];
2562 if (statusarray[slotid+numparams]==0) {
2563 parameter->iterators[*iteratorcount].istag=1;
2564 parameter->iterators[*iteratorcount].tagid=tagid;
2565 parameter->iterators[*iteratorcount].slot=slotid+numparams;
2566 parameter->iterators[*iteratorcount].tagobjectslot=index;
2567 statusarray[slotid+numparams]=1;
2574 void processobject(struct parameterwrapper *parameter,
2576 struct parameterdescriptor *pd,
2582 struct ObjectHash * objectset=
2583 ((struct parameterwrapper *)pd->queue)->objectset;
2585 parameter->iterators[*iteratorcount].istag=0;
2586 parameter->iterators[*iteratorcount].slot=index;
2587 parameter->iterators[*iteratorcount].objectset=objectset;
2588 statusarray[index]=1;
2590 for(i=0; i<pd->numbertags; i++) {
2591 int slotid=pd->tagarray[2*i];
2592 //int tagid=pd->tagarray[2*i+1];
2593 if (statusarray[slotid+numparams]!=0) {
2594 /* This tag has already been enqueued, use it to narrow search */
2595 parameter->iterators[*iteratorcount].tagbindings[tagcount]=
2600 parameter->iterators[*iteratorcount].numtags=tagcount;
2605 /* This function builds the iterators for a task & parameter */
2607 void builditerators(struct taskdescriptor * task,
2609 struct parameterwrapper * parameter) {
2610 int statusarray[MAXTASKPARAMS];
2612 int numparams=task->numParameters;
2613 int iteratorcount=0;
2614 for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
2616 statusarray[index]=1; /* Initial parameter */
2617 /* Process tags for initial iterator */
2619 processtags(task->descriptorarray[index], index, parameter,
2620 &iteratorcount, statusarray, numparams);
2624 /* Check for objects with existing tags */
2625 for(i=0; i<numparams; i++) {
2626 if (statusarray[i]==0) {
2627 struct parameterdescriptor *pd=task->descriptorarray[i];
2629 for(j=0; j<pd->numbertags; j++) {
2630 int slotid=pd->tagarray[2*j];
2631 if(statusarray[slotid+numparams]!=0) {
2632 processobject(parameter, i, pd, &iteratorcount, statusarray,
2634 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2641 /* Next do objects w/ unbound tags*/
2643 for(i=0; i<numparams; i++) {
2644 if (statusarray[i]==0) {
2645 struct parameterdescriptor *pd=task->descriptorarray[i];
2646 if (pd->numbertags>0) {
2647 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2648 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2654 /* Nothing with a tag enqueued */
2656 for(i=0; i<numparams; i++) {
2657 if (statusarray[i]==0) {
2658 struct parameterdescriptor *pd=task->descriptorarray[i];
2659 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
2660 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
2673 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2676 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2677 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2679 printf("%s\n", task->name);
2681 for(j=0; j<task->numParameters; j++) {
2682 struct parameterdescriptor *param=task->descriptorarray[j];
2683 struct parameterwrapper *parameter=param->queue;
2684 struct ObjectHash * set=parameter->objectset;
2685 struct ObjectIterator objit;
2687 printf(" Parameter %d\n", j);
2689 ObjectHashiterator(set, &objit);
2690 while(ObjhasNext(&objit)) {
2691 struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
2692 struct ___Object___ * tagptr=obj->___tags___;
2693 int nonfailed=Objdata4(&objit);
2694 int numflags=Objdata3(&objit);
2695 int flags=Objdata2(&objit);
2698 printf(" Contains %lx\n", obj);
2699 printf(" flag=%d\n", obj->flag);
2702 } else if (tagptr->type==TAGTYPE) {
2704 printf(" tag=%lx\n",tagptr);
2710 struct ArrayObject *ao=(struct ArrayObject *)tagptr;
2711 for(; tagindex<ao->___cachedCode___; tagindex++) {
2713 printf(" tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*,
2726 /* This function processes the task information to create queues for
2727 each parameter type. */
2729 void processtasks() {
2731 if(BAMBOO_NUM_OF_CORE > NUMCORES - 1) {
2734 for(i=0; i<numtasks[BAMBOO_NUM_OF_CORE]; i++) {
2735 struct taskdescriptor * task=taskarray[BAMBOO_NUM_OF_CORE][i];
2738 /* Build objectsets */
2739 for(j=0; j<task->numParameters; j++) {
2740 struct parameterdescriptor *param=task->descriptorarray[j];
2741 struct parameterwrapper *parameter=param->queue;
2742 parameter->objectset=allocateObjectHash(10);
2743 parameter->task=task;
2746 /* Build iterators for parameters */
2747 for(j=0; j<task->numParameters; j++) {
2748 struct parameterdescriptor *param=task->descriptorarray[j];
2749 struct parameterwrapper *parameter=param->queue;
2750 builditerators(task, j, parameter);
2755 void toiReset(struct tagobjectiterator * it) {
2758 } else if (it->numtags>0) {
2761 ObjectHashiterator(it->objectset, &it->it);
2765 int toiHasNext(struct tagobjectiterator *it,
2766 void ** objectarray OPTARG(int * failed)) {
2769 /* Get object with tags */
2770 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2771 struct ___Object___ *tagptr=obj->___tags___;
2772 if (tagptr->type==TAGTYPE) {
2773 if ((it->tagobjindex==0)&& /* First object */
2774 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
2779 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2780 int tagindex=it->tagobjindex;
2781 for(; tagindex<ao->___cachedCode___; tagindex++) {
2782 struct ___TagDescriptor___ *td=
2783 ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
2784 if (td->flag==it->tagid) {
2785 it->tagobjindex=tagindex; /* Found right type of tag */
2791 } else if (it->numtags>0) {
2792 /* Use tags to locate appropriate objects */
2793 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2794 struct ___Object___ *objptr=tag->flagptr;
2796 if (objptr->type!=OBJECTARRAYTYPE) {
2797 if (it->tagobjindex>0)
2799 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2801 for(i=1; i<it->numtags; i++) {
2802 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2803 if (!containstag(objptr,tag2))
2808 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2811 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
2812 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
2813 if (!ObjectHashcontainskey(it->objectset, (int) objptr))
2815 for(i=1; i<it->numtags; i++) {
2816 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
2817 if (!containstag(objptr,tag2))
2820 it->tagobjindex=tagindex;
2825 it->tagobjindex=tagindex;
2829 return ObjhasNext(&it->it);
2833 int containstag(struct ___Object___ *ptr,
2834 struct ___TagDescriptor___ *tag) {
2836 struct ___Object___ * objptr=tag->flagptr;
2837 if (objptr->type==OBJECTARRAYTYPE) {
2838 struct ArrayObject *ao=(struct ArrayObject *)objptr;
2839 for(j=0; j<ao->___cachedCode___; j++) {
2840 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
2848 void toiNext(struct tagobjectiterator *it,
2849 void ** objectarray OPTARG(int * failed)) {
2850 /* hasNext has all of the intelligence */
2853 /* Get object with tags */
2854 struct ___Object___ *obj=objectarray[it->tagobjectslot];
2855 struct ___Object___ *tagptr=obj->___tags___;
2856 if (tagptr->type==TAGTYPE) {
2858 objectarray[it->slot]=tagptr;
2860 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
2861 objectarray[it->slot]=
2862 ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
2864 } else if (it->numtags>0) {
2865 /* Use tags to locate appropriate objects */
2866 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
2867 struct ___Object___ *objptr=tag->flagptr;
2868 if (objptr->type!=OBJECTARRAYTYPE) {
2870 objectarray[it->slot]=objptr;
2872 struct ArrayObject *ao=(struct ArrayObject *) objptr;
2873 objectarray[it->slot]=
2874 ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
2877 /* Iterate object */
2878 objectarray[it->slot]=(void *)Objkey(&it->it);