3 #include "structdefs.h"
5 #include "checkpoint.h"
7 #include "SimpleHash.h"
8 #include "GenericHashtable.h"
9 #include <sys/select.h>
10 #include <sys/types.h>
14 extern int injectfailures;
15 extern float failurechance;
20 #include "instrument.h"
23 struct genhashtable * activetasks;
24 struct parameterwrapper * objectqueues[NUMCLASSES];
25 struct genhashtable * failedtasks;
26 struct taskparamdescriptor * currtpd;
27 struct RuntimeHash * forward;
28 struct RuntimeHash * reverse;
31 int main(int argc, char **argv) {
33 GC_init(); // Initialize the garbage collector
39 initializeexithandler();
40 /* Create table for failed tasks */
41 failedtasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
42 (int (*)(void *,void *)) &comparetpd);
43 /* Create queue of active tasks */
44 activetasks=genallocatehashtable((unsigned int (*)(void *)) &hashCodetpd,
45 (int (*)(void *,void *)) &comparetpd);
48 /* Process task information */
51 /* Create startup object */
52 createstartupobject(argc, argv);
54 /* Start executing the tasks */
58 void createstartupobject(int argc, char ** argv) {
61 /* Allocate startup object */
63 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
64 struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
66 struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
67 struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
69 /* Build array of strings */
70 startupobject->___parameters___=stringarray;
72 int length=strlen(argv[i]);
74 struct ___String___ *newstring=NewString(NULL, argv[i],length);
76 struct ___String___ *newstring=NewString(argv[i],length);
78 ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;
81 /* Set initialized flag for startup object */
82 flagorand(startupobject,1,0xFFFFFFFF);
85 int hashCodetpd(struct taskparamdescriptor *ftd) {
86 int hash=(int)ftd->task;
88 for(i=0;i<ftd->numParameters;i++) {
89 hash^=(int)ftd->parameterArray[i];
94 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
96 if (ftd1->task!=ftd2->task)
98 for(i=0;i<ftd1->numParameters;i++)
99 if (ftd1->parameterArray[i]!=ftd2->parameterArray[i])
105 /* This function sets a tag. */
107 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
109 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
111 struct ___Object___ * tagptr=obj->___tags___;
113 obj->___tags___=(struct ___Object___ *)tagd;
115 /* Have to check if it is already set */
116 if (tagptr->type==TAGTYPE) {
117 struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
121 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
122 struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
123 obj=(struct ___Object___ *)ptrarray[2];
124 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
125 td=(struct ___TagDescriptor___ *) obj->___tags___;
127 struct ArrayObject * ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
129 ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
130 ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
131 obj->___tags___=(struct ___Object___ *) ao;
132 ao->___cachedCode___=2;
136 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
137 for(i=0;i<ao->___cachedCode___;i++) {
138 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
142 if (ao->___cachedCode___<ao->___length___) {
143 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
144 ao->___cachedCode___++;
147 int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
148 struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
149 obj=(struct ___Object___ *)ptrarray[2];
150 tagd=(struct ___TagDescriptor___ *) ptrarray[3];
151 ao=(struct ArrayObject *)obj->___tags___;
153 struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
155 aonew->___cachedCode___=ao->___length___+1;
156 for(i=0;i<ao->___length___;i++) {
157 ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
159 ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
165 struct ___Object___ * tagset=tagd->flagptr;
169 } else if (tagset->type!=OBJECTARRAYTYPE) {
171 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
172 struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
173 obj=(struct ___Object___ *)ptrarray[2];
174 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
176 struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
178 ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
179 ARRAYSET(ao, struct ___Object___ *, 1, obj);
180 ao->___cachedCode___=2;
181 tagd->flagptr=(struct ___Object___ *)ao;
183 struct ArrayObject *ao=(struct ArrayObject *) tagset;
184 if (ao->___cachedCode___<ao->___length___) {
185 ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
189 int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
190 struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
191 obj=(struct ___Object___ *)ptrarray[2];
192 tagd=(struct ___TagDescriptor___ *)ptrarray[3];
193 ao=(struct ArrayObject *)tagd->flagptr;
195 struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
197 aonew->___cachedCode___=ao->___cachedCode___+1;
198 for(i=0;i<ao->___length___;i++) {
199 ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
201 ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
202 tagd->flagptr=(struct ___Object___ *) ao;
208 /* This function clears a tag. */
210 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
212 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
214 /* We'll assume that tag is alway there.
215 Need to statically check for this of course. */
216 struct ___Object___ * tagptr=obj->___tags___;
218 if (tagptr->type==TAGTYPE) {
219 if ((struct ___TagDescriptor___ *)tagptr==tagd)
220 obj->___tags___=NULL;
222 printf("ERROR 1 in tagclear\n");
224 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
226 for(i=0;i<ao->___cachedCode___;i++) {
227 struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
229 ao->___cachedCode___--;
230 if (i<ao->___cachedCode___)
231 ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
232 ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
233 if (ao->___cachedCode___==0)
234 obj->___tags___=NULL;
238 printf("ERROR 2 in tagclear\n");
242 struct ___Object___ *tagset=tagd->flagptr;
243 if (tagset->type!=OBJECTARRAYTYPE) {
247 printf("ERROR 3 in tagclear\n");
249 struct ArrayObject *ao=(struct ArrayObject *) tagset;
251 for(i=0;i<ao->___cachedCode___;i++) {
252 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
254 ao->___cachedCode___--;
255 if (i<ao->___cachedCode___)
256 ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
257 ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
258 if (ao->___cachedCode___==0)
263 printf("ERROR 4 in tagclear\n");
271 /* This function allocates a new tag. */
273 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
274 struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
276 struct ___TagDescriptor___ * allocate_tag(int index) {
277 struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
286 /* This function updates the flag for object ptr. It or's the flag
287 with the or mask and and's it with the andmask. */
289 void flagbody(struct ___Object___ *ptr, int flag);
291 void flagorand(void * ptr, int ormask, int andmask) {
292 int oldflag=((int *)ptr)[1];
293 int flag=ormask|oldflag;
295 // Not sure why this was necessary
296 // if (flag==oldflag) /* Don't do anything */
302 void intflagorand(void * ptr, int ormask, int andmask) {
303 int oldflag=((int *)ptr)[1];
304 int flag=ormask|oldflag;
306 if (flag==oldflag) /* Don't do anything */
308 else flagbody(ptr, flag);
311 void flagorandinit(void * ptr, int ormask, int andmask) {
312 int oldflag=((int *)ptr)[1];
313 int flag=ormask|oldflag;
318 void flagbody(struct ___Object___ *ptr, int flag) {
319 struct parameterwrapper *flagptr=(struct parameterwrapper *)ptr->flagptr;
322 /*Remove object from all queues */
323 while(flagptr!=NULL) {
324 struct parameterwrapper *next;
325 struct ___Object___ * tag=ptr->___tags___;
326 RuntimeHashget(flagptr->objectset, (int) ptr, (int *) &next);
327 RuntimeHashremove(flagptr->objectset, (int)ptr, (int) next);
332 struct QueueItem *tmpptr;
333 struct parameterwrapper * parameter=objectqueues[ptr->type];
335 struct parameterwrapper * prevptr=NULL;
336 struct ___Object___ *tagptr=ptr->___tags___;
338 /* Outer loop iterates through all parameter queues an object of
339 this type could be in. */
341 while(parameter!=NULL) {
343 if (parameter->numbertags>0) {
346 else if(tagptr->type==TAGTYPE) {
347 struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
348 for(i=0;i<parameter->numbertags;i++) {
349 //slotid is parameter->tagarray[2*i];
350 int tagid=parameter->tagarray[2*i+1];
351 if (tagid!=tagptr->flag)
352 goto nextloop; /*We don't have this tag */
355 struct ArrayObject * ao=(struct ArrayObject *) tagptr;
356 for(i=0;i<parameter->numbertags;i++) {
357 //slotid is parameter->tagarray[2*i];
358 int tagid=parameter->tagarray[2*i+1];
360 for(j=0;j<ao->___cachedCode___;j++) {
361 if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, i)->flag)
372 for(i=0;i<parameter->numberofterms;i++) {
373 int andmask=parameter->intarray[i*2];
374 int checkmask=parameter->intarray[i*2+1];
375 if ((flag&andmask)==checkmask) {
376 enqueuetasks(parameter, prevptr, ptr);
382 parameter=parameter->next;
384 ptr->flagptr=prevptr;
388 void enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr) {
389 void * taskpointerarray[MAXTASKPARAMS];
391 int numparams=parameter->task->numParameters;
392 int numiterators=parameter->task->numTotal-1;
394 struct taskdescriptor * task=parameter->task;
396 RuntimeHashadd(parameter->objectset, (int) ptr, (int) prevptr);
398 /* Add enqueued object to parameter vector */
399 taskpointerarray[parameter->slot]=ptr;
401 /* Reset iterators */
402 for(j=0;j<numiterators;j++) {
403 toiReset(¶meter->iterators[j]);
406 /* Find initial state */
407 for(j=0;j<numiterators;j++) {
409 if(toiHasNext(¶meter->iterators[j], taskpointerarray))
410 toiNext(¶meter->iterators[j], taskpointerarray);
412 /* Need to backtrack */
413 toiReset(¶meter->iterators[j]);
417 /* Nothing to enqueue */
424 /* Enqueue current state */
425 struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
427 tpd->numParameters=numiterators+1;
428 tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
429 for(j=0;j<=numiterators;j++)
430 tpd->parameterArray[j]=taskpointerarray[j];
433 if (!gencontains(failedtasks, tpd)&&!gencontains(activetasks,tpd)) {
434 genputtable(activetasks, tpd, tpd);
436 RUNFREE(tpd->parameterArray);
440 /* This loop iterates to the next parameter combination */
444 for(j=numiterators-1; j<numiterators;j++) {
446 if(toiHasNext(¶meter->iterators[j], taskpointerarray))
447 toiNext(¶meter->iterators[j], taskpointerarray);
449 /* Need to backtrack */
450 toiReset(¶meter->iterators[j]);
454 /* Nothing more to enqueue */
461 /* Handler for signals. The signals catch null pointer errors and
462 arithmatic errors. */
464 void myhandler(int sig, siginfo_t *info, void *uap) {
466 printf("sig=%d\n",sig);
469 longjmp(error_handler,1);
474 struct RuntimeHash *fdtoobject;
476 void addreadfd(int fd) {
479 FD_SET(fd, &readfds);
482 void removereadfd(int fd) {
483 FD_CLR(fd, &readfds);
484 if (maxreadfd==(fd+1)) {
486 while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
497 void executetasks() {
498 void * taskpointerarray[MAXTASKPARAMS+OFFSET];
500 /* Set up signal handlers */
501 struct sigaction sig;
502 sig.sa_sigaction=&myhandler;
503 sig.sa_flags=SA_SIGINFO;
504 sigemptyset(&sig.sa_mask);
506 /* Catch bus errors, segmentation faults, and floating point exceptions*/
507 sigaction(SIGBUS,&sig,0);
508 sigaction(SIGSEGV,&sig,0);
509 sigaction(SIGFPE,&sig,0);
510 sigaction(SIGPIPE,&sig,0);
515 fdtoobject=allocateRuntimeHash(100);
517 /* Map first block of memory to protected, anonymous page */
518 mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
521 while((hashsize(activetasks)>0)||(maxreadfd>0)) {
523 /* Check if any filedescriptors have IO pending */
526 struct timeval timeout={0,0};
530 numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
532 /* Process ready fd's */
534 for(fd=0;fd<maxreadfd;fd++) {
535 if (FD_ISSET(fd, &tmpreadfds)) {
536 /* Set ready flag on object */
538 // printf("Setting fd %d\n",fd);
539 if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
540 intflagorand(objptr,1,0xFFFFFFFF); /* Set the first flag to 1 */
547 /* See if there are any active tasks */
548 if (hashsize(activetasks)>0) {
550 currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
551 genfreekey(activetasks, currtpd);
553 /* Check if this task has failed */
554 if (gencontains(failedtasks, currtpd)) {
555 // Free up task parameter descriptor
556 RUNFREE(currtpd->parameterArray);
560 int numparams=currtpd->task->numParameters;
561 int numtotal=currtpd->task->numTotal;
563 /* Make sure that the parameters are still in the queues */
564 for(i=0;i<numparams;i++) {
565 void * parameter=currtpd->parameterArray[i];
566 struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
567 struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
569 /* Check that object is still in queue */
570 if (!RuntimeHashcontainskey(pw->objectset, (int) parameter)) {
571 RUNFREE(currtpd->parameterArray);
575 /* Check that object still has necessary tags */
576 for(j=0;j<pd->numbertags;j++) {
577 int slotid=pd->tagarray[2*j]+numparams;
578 struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
579 if (!containstag(parameter, tagd)) {
580 RUNFREE(currtpd->parameterArray);
586 taskpointerarray[i+OFFSET]=parameter;
589 for(;i<numtotal;i++) {
590 taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
594 /* Checkpoint the state */
595 forward=allocateRuntimeHash(100);
596 reverse=allocateRuntimeHash(100);
597 void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
599 if (x=setjmp(error_handler)) {
603 printf("Fatal Error=%d, Recovering!\n",x);
605 genputtable(failedtasks,currtpd,currtpd);
606 restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
607 freeRuntimeHash(forward);
608 freeRuntimeHash(reverse);
613 if (injectfailures) {
614 if ((((double)random())/RAND_MAX)<failurechance) {
615 printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
616 longjmp(error_handler,10);
619 /* Actually call task */
621 ((int *)taskpointerarray)[0]=currtpd->task->numParameters;
622 taskpointerarray[1]=NULL;
626 printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
627 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
628 printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
630 ((void (*) (void **)) currtpd->task->taskptr)(taskpointerarray);
631 freeRuntimeHash(forward);
632 freeRuntimeHash(reverse);
634 // Free up task parameter descriptor
635 RUNFREE(currtpd->parameterArray);
645 /* This function processes an objects tags */
646 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
649 for(i=0;i<pd->numbertags;i++) {
650 int slotid=pd->tagarray[2*i];
651 int tagid=pd->tagarray[2*i+1];
653 if (statusarray[slotid+numparams]==0) {
654 parameter->iterators[*iteratorcount].istag=1;
655 parameter->iterators[*iteratorcount].tagid=tagid;
656 parameter->iterators[*iteratorcount].slot=slotid+numparams;
657 parameter->iterators[*iteratorcount].tagobjectslot=index;
658 statusarray[slotid+numparams]=1;
665 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
668 struct RuntimeHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
670 parameter->iterators[*iteratorcount].istag=0;
671 parameter->iterators[*iteratorcount].slot=index;
672 parameter->iterators[*iteratorcount].objectset=objectset;
673 statusarray[index]=1;
675 for(i=0;i<pd->numbertags;i++) {
676 int slotid=pd->tagarray[2*i];
677 int tagid=pd->tagarray[2*i+1];
678 if (statusarray[slotid+numparams]!=0) {
679 /* This tag has already been enqueued, use it to narrow search */
680 parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
684 parameter->iterators[*iteratorcount].numtags=tagcount;
689 /* This function builds the iterators for a task & parameter */
691 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
692 int statusarray[MAXTASKPARAMS];
694 int numparams=task->numParameters;
696 for(i=0;i<MAXTASKPARAMS;i++) statusarray[i]=0;
698 statusarray[index]=1; /* Initial parameter */
699 /* Process tags for initial iterator */
701 processtags(task->descriptorarray[index], index, parameter, & iteratorcount, statusarray, numparams);
705 /* Check for objects with existing tags */
706 for(i=0;i<numparams;i++) {
707 if (statusarray[i]==0) {
708 struct parameterdescriptor *pd=task->descriptorarray[i];
710 for(j=0;j<pd->numbertags;j++) {
711 int slotid=pd->tagarray[2*j];
712 if(statusarray[slotid+numparams]!=0) {
713 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
714 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
720 /* Nothing with a tag enqueued */
722 for(i=0;i<numparams;i++) {
723 if (statusarray[i]==0) {
724 struct parameterdescriptor *pd=task->descriptorarray[i];
725 processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
726 processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
739 /* This function processes the task information to create queues for
740 each parameter type. */
742 void processtasks() {
744 for(i=0;i<numtasks;i++) {
745 struct taskdescriptor * task=taskarray[i];
748 for(j=0;j<task->numParameters;j++) {
749 struct parameterdescriptor *param=task->descriptorarray[j];
750 struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
751 struct parameterwrapper ** ptr=&objectqueues[param->type];
753 param->queue=parameter;
754 parameter->objectset=allocateRuntimeHash(10);
755 parameter->numberofterms=param->numberterms;
756 parameter->intarray=param->intarray;
757 parameter->numbertags=param->numbertags;
758 parameter->tagarray=param->tagarray;
759 parameter->task=task;
760 /* Link new queue in */
766 /* Build iterators for parameters */
767 for(j=0;j<task->numParameters;j++) {
768 struct parameterdescriptor *param=task->descriptorarray[j];
769 struct parameterwrapper *parameter=param->queue;
771 builditerators(task, j, parameter);
776 void toiReset(struct tagobjectiterator * it) {
779 } else if (it->numtags>0) {
782 RuntimeHashiterator(it->objectset, &it->it);
786 int toiHasNext(struct tagobjectiterator *it, void ** objectarray) {
789 /* Get object with tags */
790 struct ___Object___ *obj=objectarray[it->tagobjectslot];
791 struct ___Object___ *tagptr=obj->___tags___;
792 if (tagptr->type==TAGTYPE) {
793 if ((it->tagobjindex==0)&& /* First object */
794 (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
799 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
800 int tagindex=it->tagobjindex;
801 for(;tagindex<ao->___cachedCode___;tagindex++) {
802 struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
803 if (td->flag==it->tagid) {
804 it->tagobjindex=tagindex; /* Found right type of tag */
810 } else if (it->numtags>0) {
811 /* Use tags to locate appropriate objects */
812 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
813 struct ___Object___ *objptr=tag->flagptr;
815 if (objptr->type!=OBJECTARRAYTYPE) {
816 if (it->tagobjindex>0)
818 if (!RuntimeHashcontainskey(it->objectset, (int) objptr))
820 for(i=1;i<it->numtags;i++) {
821 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
822 if (!containstag(objptr,tag2))
827 struct ArrayObject *ao=(struct ArrayObject *) objptr;
830 for(tagindex=it->tagobjindex;tagindex<ao->___cachedCode___;tagindex++) {
831 struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
832 if (!RuntimeHashcontainskey(it->objectset, (int) objptr))
834 for(i=1;i<it->numtags;i++) {
835 struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
836 if (!containstag(objptr,tag2))
843 it->tagobjindex=tagindex;
847 return RunhasNext(&it->it);
851 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
853 struct ___Object___ * objptr=tag->flagptr;
854 if (objptr->type==OBJECTARRAYTYPE) {
855 struct ArrayObject *ao=(struct ArrayObject *)objptr;
856 for(j=0;j<ao->___cachedCode___;j++) {
857 if (ptr==ARRAYGET(ao, struct ___Object___*, j))
865 void toiNext(struct tagobjectiterator *it , void ** objectarray) {
866 /* hasNext has all of the intelligence */
869 /* Get object with tags */
870 struct ___Object___ *obj=objectarray[it->tagobjectslot];
871 struct ___Object___ *tagptr=obj->___tags___;
872 if (tagptr->type==TAGTYPE) {
874 objectarray[it->slot]=tagptr;
876 struct ArrayObject *ao=(struct ArrayObject *) tagptr;
877 objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
879 } else if (it->numtags>0) {
880 /* Use tags to locate appropriate objects */
881 struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
882 struct ___Object___ *objptr=tag->flagptr;
883 if (objptr->type!=OBJECTARRAYTYPE) {
885 objectarray[it->slot]=objptr;
887 struct ArrayObject *ao=(struct ArrayObject *) objptr;
888 objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
892 objectarray[it->slot]=(void *)Runkey(&it->it);