d1a60285a07abac0eea6da65d048c63e224881c8
[IRC.git] / Robust / src / IR / Flat / BuildOoOJavaCode.java
1 package IR.Flat;
2 import IR.*;
3 import IR.Tree.*;
4
5 import java.util.*;
6 import java.io.*;
7
8 import Util.*;
9 import Analysis.TaskStateAnalysis.*;
10 import Analysis.CallGraph.*;
11 import Analysis.Disjoint.*;
12 import Analysis.OoOJava.*;
13 import Analysis.Loops.*;
14 import Analysis.Locality.*;
15
16
17
18 public class BuildOoOJavaCode extends BuildCode {
19
20   OoOJavaAnalysis oooa;
21
22   String maxTaskRecSizeStr="__maxTaskRecSize___";
23
24   String mlperrstr =
25     "if(status != 0) { "+
26     "sprintf(errmsg, \"MLP error at %s:%d\", __FILE__, __LINE__); "+
27     "perror(errmsg); exit(-1); }";
28
29   RuntimeConflictResolver rcr = null;
30
31   public BuildOoOJavaCode(State st,
32                           Hashtable temptovar,
33                           TypeUtil typeutil,
34                           SafetyAnalysis sa,
35                           OoOJavaAnalysis oooa, CallGraph callgraph
36                           ) {
37     super( st, temptovar, typeutil, sa, callgraph);
38
39     this.oooa = oooa;
40   }
41
42
43   protected void additionalIncludesMethodsHeader(PrintWriter outmethodheader) {
44
45     outmethodheader.println("#include <stdlib.h>");
46     outmethodheader.println("#include <stdio.h>");
47     outmethodheader.println("#include <string.h>");
48     outmethodheader.println("#include \"mlp_runtime.h\"");
49     outmethodheader.println("#include \"psemaphore.h\"");
50     outmethodheader.println("#include \"memPool.h\"");
51
52     if (state.RCR) {
53       outmethodheader.println("#include \"rcr_runtime.h\"");
54     }
55
56     // spit out a global to inform all worker threads what
57     // the maximum size is for any task record
58     outmethodheader.println("extern int "+maxTaskRecSizeStr+";");
59   }
60
61
62   protected void preCodeGenInitialization() {
63
64     // have to initialize some SESE compiler data before
65     // analyzing normal methods, which must happen before
66     // generating SESE internal code
67
68     Iterator<FlatSESEEnterNode> seseit = oooa.getAllSESEs().iterator();
69
70     while( seseit.hasNext() ) {
71       FlatSESEEnterNode fsen = seseit.next();
72       initializeSESE(fsen);
73     }
74
75     //TODO signal the object that will report errors
76     if( state.RCR ) {
77       try {
78         rcr = new RuntimeConflictResolver(PREFIX,
79                                           oooa,
80                                           state);
81         System.out.println("Runtime Conflict Resolver started.");
82       } catch (FileNotFoundException e) {
83         System.out.println("Runtime Conflict Resolver could not create output file.");
84       }
85     }
86   }
87
88
89   protected void initializeSESE(FlatSESEEnterNode fsen) {
90
91     FlatMethod fm = fsen.getfmEnclosing();
92     MethodDescriptor md = fm.getMethod();
93     ClassDescriptor cn = md.getClassDesc();
94
95     // Creates bogus method descriptor to index into tables
96     Modifiers modBogus = new Modifiers();
97     MethodDescriptor mdBogus =
98       new MethodDescriptor(modBogus,
99                            new TypeDescriptor(TypeDescriptor.VOID),
100                            "sese_"+fsen.getPrettyIdentifier()+fsen.getIdentifier()
101                            );
102
103     mdBogus.setClassDesc(fsen.getcdEnclosing() );
104     FlatMethod fmBogus = new FlatMethod(mdBogus, null);
105     fsen.setfmBogus(fmBogus);
106     fsen.setmdBogus(mdBogus);
107
108     Set<TempDescriptor> inSetAndOutSet = new HashSet<TempDescriptor>();
109     inSetAndOutSet.addAll(fsen.getInVarSet() );
110     inSetAndOutSet.addAll(fsen.getOutVarSet() );
111
112     // Build paramsobj for bogus method descriptor
113     ParamsObject objectparams = new ParamsObject(mdBogus, tag++);
114     paramstable.put(mdBogus, objectparams);
115
116     Iterator<TempDescriptor> itr = inSetAndOutSet.iterator();
117     while( itr.hasNext() ) {
118       TempDescriptor temp = itr.next();
119       TypeDescriptor type = temp.getType();
120       if( type.isPtr() ) {
121         objectparams.addPtr(temp);
122       } else {
123         objectparams.addPrim(temp);
124       }
125     }
126
127     // Build normal temp object for bogus method descriptor
128     TempObject objecttemps = new TempObject(objectparams, mdBogus, tag++);
129     tempstable.put(mdBogus, objecttemps);
130
131     for( Iterator nodeit = fsen.getNodeSet().iterator(); nodeit.hasNext(); ) {
132       FlatNode fn     = (FlatNode)nodeit.next();
133       TempDescriptor[] writes = fn.writesTemps();
134
135       for( int i = 0; i < writes.length; i++ ) {
136         TempDescriptor temp = writes[i];
137         TypeDescriptor type = temp.getType();
138
139         if( type.isPtr() ) {
140           objecttemps.addPtr(temp);
141         } else {
142           objecttemps.addPrim(temp);
143         }
144       }
145     }
146   }
147
148
149   protected void postCodeGenCleanUp() {
150     if(rcr != null) {
151       rcr.close();
152       System.out.println("Runtime Conflict Resolver Done.");
153     }
154   }
155
156
157   protected void additionalCodeGen(PrintWriter outmethodheader,
158                                    PrintWriter outstructs,
159                                    PrintWriter outmethod) {
160
161     // Output function prototypes and structures for SESE's and code
162
163     // spit out a global to inform all worker threads with
164     // the maximum size is for any task record
165     outmethod.println("int "+maxTaskRecSizeStr+" = 0;");
166
167     // first generate code for each sese's internals
168     Iterator<FlatSESEEnterNode> seseit;
169     seseit = oooa.getAllSESEs().iterator();
170
171     while( seseit.hasNext() ) {
172       FlatSESEEnterNode fsen = seseit.next();
173       generateMethodSESE(fsen, outstructs, outmethodheader, outmethod);
174     }
175
176     // then write the invokeSESE switch to decouple scheduler
177     // from having to do unique details of sese invocation
178     generateSESEinvocationMethod(outmethodheader, outmethod);
179   }
180
181
182   protected void additionalCodeAtTopOfMain(PrintWriter outmethod) {
183
184     // do a calculation to determine which task record
185     // is the largest, store that as a global value for
186     // allocating records
187     Iterator<FlatSESEEnterNode> seseit = oooa.getAllSESEs().iterator();
188     while( seseit.hasNext() ) {
189       FlatSESEEnterNode fsen = seseit.next();
190       outmethod.println("if( sizeof( "+fsen.getSESErecordName()+
191                         " ) > "+maxTaskRecSizeStr+
192                         " ) { "+maxTaskRecSizeStr+
193                         " = sizeof( "+fsen.getSESErecordName()+
194                         " ); }");
195     }
196
197     outmethod.println("  runningSESE = NULL;");
198
199     outmethod.println("  workScheduleInit( "+state.OOO_NUMCORES+", invokeSESEmethod );");
200
201     //initializes data structures needed for the RCR traverser
202     if( state.RCR && rcr != null ) {
203       outmethod.println("  initializeStructsRCR();");
204       outmethod.println("  createAndFillMasterHashStructureArray();");
205     }
206   }
207
208
209   protected void additionalCodeAtBottomOfMain(PrintWriter outmethod) {
210     outmethod.println("  workScheduleBegin();");
211   }
212
213
214   protected void additionalIncludesMethodsImplementation(PrintWriter outmethod) {
215     outmethod.println("#include <stdlib.h>");
216     outmethod.println("#include <stdio.h>");
217     outmethod.println("#include \"mlp_runtime.h\"");
218     outmethod.println("#include \"psemaphore.h\"");
219
220     if( state.RCR ) {
221       outmethod.println("#include \"trqueue.h\"");
222       outmethod.println("#include \"RuntimeConflictResolver.h\"");
223       outmethod.println("#include \"rcr_runtime.h\"");
224       outmethod.println("#include \"hashStructure.h\"");
225     }
226   }
227
228
229   protected void additionalIncludesStructsHeader(PrintWriter outstructs) {
230     outstructs.println("#include \"mlp_runtime.h\"");
231     outstructs.println("#include \"psemaphore.h\"");
232     if( state.RCR ) {
233       outstructs.println("#include \"rcr_runtime.h\"");
234     }
235   }
236
237
238   protected void additionalClassObjectFields(PrintWriter outclassdefs) {
239     outclassdefs.println("  int oid;");
240     outclassdefs.println("  int allocsite;");
241   }
242
243
244   protected void additionalCodeAtTopMethodsImplementation(PrintWriter outmethod) {
245     outmethod.print("extern __thread int oid;\n");
246     outmethod.print("extern int oidIncrement;\n");
247   }
248
249
250   protected void additionalCodeAtTopFlatMethodBody(PrintWriter output, FlatMethod fm) {
251
252     // declare variables for naming static and dynamic SESE's
253     ContextTaskNames context = oooa.getContextTaskNames(fm);
254
255     output.println("   /* static SESE names */");
256     Iterator<SESEandAgePair> pItr = context.getNeededStaticNames().iterator();
257     while( pItr.hasNext() ) {
258       SESEandAgePair pair = pItr.next();
259       output.println("   void* "+pair+" = NULL;");
260     }
261
262     output.println("   /* dynamic variable sources */");
263     Iterator<TempDescriptor> dynSrcItr = context.getDynamicVarSet().iterator();
264     while( dynSrcItr.hasNext() ) {
265       TempDescriptor dynSrcVar = dynSrcItr.next();
266       output.println("   SESEcommon*  "+dynSrcVar+"_srcSESE = NULL;");
267       output.println("   INTPTR       "+dynSrcVar+"_srcOffset = 0x1;");
268     }
269
270
271     // eom - set up related allocation sites's waiting queues
272     // TODO: we have to do a table-based thing here...
273     // jjenista, I THINK WE LOSE THIS ALTOGETHER!
274     /*
275        FlatSESEEnterNode callerSESEplaceholder = (FlatSESEEnterNode) fm.getNext( 0 );
276        if(callerSESEplaceholder!= oooa.getMainSESE()){
277        Analysis.OoOJava.ConflictGraph graph = oooa.getConflictGraph(callerSESEplaceholder);
278        if (graph != null && graph.hasConflictEdge()) {
279         output.println("   // set up waiting queues ");
280         output.println("   int numMemoryQueue=0;");
281         output.println("   int memoryQueueItemID=0;");
282         Set<Analysis.OoOJava.SESELock> lockSet = oooa.getLockMappings(graph);
283         System.out.println("#lockSet="+lockSet.hashCode());
284         System.out.println("lockset="+lockSet);
285         for (Iterator iterator = lockSet.iterator(); iterator.hasNext();) {
286           Analysis.OoOJava.SESELock seseLock = (Analysis.OoOJava.SESELock) iterator.next();
287           System.out.println("id="+seseLock.getID());
288           System.out.println("#="+seseLock);
289         }
290         System.out.println("size="+lockSet.size());
291         if (lockSet.size() > 0) {
292           output.println("   numMemoryQueue=" + lockSet.size() + ";");
293           output.println("   runningSESE->numMemoryQueue=numMemoryQueue;");
294           output.println("   runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
295           output.println();
296         }
297        }
298        }
299      */
300   }
301
302
303   protected void generateMethodSESE(FlatSESEEnterNode fsen,
304                                     PrintWriter outputStructs,
305                                     PrintWriter outputMethHead,
306                                     PrintWriter outputMethods) {
307
308     ParamsObject objectparams = (ParamsObject) paramstable.get(fsen.getmdBogus() );
309     TempObject objecttemps  = (TempObject)   tempstable.get(fsen.getmdBogus() );
310
311     // generate locals structure
312     outputStructs.println("struct "+
313                           fsen.getcdEnclosing().getSafeSymbol()+
314                           fsen.getmdBogus().getSafeSymbol()+"_"+
315                           fsen.getmdBogus().getSafeMethodDescriptor()+
316                           "_locals {");
317
318     outputStructs.println("  int size;");
319     outputStructs.println("  void * next;");
320
321     for(int i=0; i<objecttemps.numPointers(); i++) {
322       TempDescriptor temp=objecttemps.getPointer(i);
323
324       if (temp.getType().isNull())
325         outputStructs.println("  void * "+temp.getSafeSymbol()+";");
326       else
327         outputStructs.println("  struct "+
328                               temp.getType().getSafeSymbol()+" * "+
329                               temp.getSafeSymbol()+";");
330     }
331     outputStructs.println("};\n");
332
333
334     // divide in-set and out-set into objects and primitives to prep
335     // for the record generation just below
336     Set<TempDescriptor> inSetAndOutSet = new HashSet<TempDescriptor>();
337     inSetAndOutSet.addAll(fsen.getInVarSet() );
338     inSetAndOutSet.addAll(fsen.getOutVarSet() );
339
340     Set<TempDescriptor> inSetAndOutSetObjs  = new HashSet<TempDescriptor>();
341     Set<TempDescriptor> inSetAndOutSetPrims = new HashSet<TempDescriptor>();
342
343     Iterator<TempDescriptor> itr = inSetAndOutSet.iterator();
344     while( itr.hasNext() ) {
345       TempDescriptor temp = itr.next();
346       TypeDescriptor type = temp.getType();
347       if( type.isPtr() ) {
348         inSetAndOutSetObjs.add(temp);
349       } else {
350         inSetAndOutSetPrims.add(temp);
351       }
352     }
353
354
355     // generate the SESE record structure
356     outputStructs.println(fsen.getSESErecordName()+" {");
357
358     // data common to any SESE, and it must be placed first so
359     // a module that doesn't know what kind of SESE record this
360     // is can cast the pointer to a common struct
361     outputStructs.println("  SESEcommon common;");
362
363     // then garbage list stuff
364     outputStructs.println("  /* next is in-set and out-set objects that look like a garbage list */");
365     outputStructs.println("  int size;");
366     outputStructs.println("  void * next;");
367
368     // I think that the set of TempDescriptors inSetAndOutSetObjs
369     // calculated above should match the pointer object params
370     // used in the following code, but let's just leave the working
371     // implementation unless there is actually a problem...
372
373     Vector<TempDescriptor> inset=fsen.getInVarsForDynamicCoarseConflictResolution();
374     for(int i=0; i<inset.size(); i++) {
375       TempDescriptor temp=inset.get(i);
376       if (temp.getType().isNull())
377         outputStructs.println("  void * "+temp.getSafeSymbol()+
378                               ";  /* in-or-out-set obj in gl */");
379       else
380         outputStructs.println("  struct "+temp.getType().getSafeSymbol()+" * "+
381                               temp.getSafeSymbol()+"; /* in-or-out-set obj in gl */");
382     }
383
384     for(int i=0; i<objectparams.numPointers(); i++) {
385       TempDescriptor temp=objectparams.getPointer(i);
386       if (!inset.contains(temp)) {
387         if (temp.getType().isNull())
388           outputStructs.println("  void * "+temp.getSafeSymbol()+
389                                 ";  /* in-or-out-set obj in gl */");
390         else
391           outputStructs.println("  struct "+temp.getType().getSafeSymbol()+" * "+
392                                 temp.getSafeSymbol()+"; /* in-or-out-set obj in gl */");
393       }
394     }
395
396     outputStructs.println("  /* next is primitives for in-set and out-set and dynamic tracking */");
397
398     Iterator<TempDescriptor> itrPrims = inSetAndOutSetPrims.iterator();
399     while( itrPrims.hasNext() ) {
400       TempDescriptor temp = itrPrims.next();
401       TypeDescriptor type = temp.getType();
402       if(type.isPrimitive()) {
403         outputStructs.println("  "+temp.getType().getSafeSymbol()+" "+
404                               temp.getSafeSymbol()+"; /* in-set or out-set primitive */");
405       }
406     }
407
408     // note that the sese record pointer will be added below, just primitive part of tracking here
409     Iterator<TempDescriptor> itrDynInVars = fsen.getDynamicInVarSet().iterator();
410     while( itrDynInVars.hasNext() ) {
411       TempDescriptor dynInVar = itrDynInVars.next();
412       outputStructs.println("  INTPTR "+dynInVar+"_srcOffset; /* dynamic tracking primitive */");
413     }
414
415
416     outputStructs.println("  /* everything after this should be pointers to an SESE record */");
417
418     // other half of info for dynamic tracking, the SESE record pointer
419     itrDynInVars = fsen.getDynamicInVarSet().iterator();
420     while( itrDynInVars.hasNext() ) {
421       TempDescriptor dynInVar = itrDynInVars.next();
422       String depRecField = dynInVar+"_srcSESE";
423       outputStructs.println("  SESEcommon* "+depRecField+";");
424       addingDepRecField(fsen, depRecField);
425     }
426
427     // statically known sese sources are record pointers, too
428     Iterator<SESEandAgePair> itrStaticInVarSrcs = fsen.getStaticInVarSrcs().iterator();
429     while( itrStaticInVarSrcs.hasNext() ) {
430       SESEandAgePair srcPair = itrStaticInVarSrcs.next();
431       outputStructs.println("  "+srcPair.getSESE().getSESErecordName()+"* "+srcPair+";");
432       addingDepRecField(fsen, srcPair.toString());
433     }
434
435     if (state.RCR) {
436       if (inset.size()!=0) {
437         outputStructs.println("struct rcrRecord rcrRecords["+inset.size()+"];");
438       }
439     }
440
441     if( fsen.getFirstDepRecField() != null ) {
442       outputStructs.println("  /* compiler believes first dependent SESE record field above is: "+
443                             fsen.getFirstDepRecField()+" */");
444     }
445     outputStructs.println("};\n");
446
447
448     // write method declaration to header file
449     outputMethHead.print("void ");
450     outputMethHead.print(fsen.getSESEmethodName()+"(");
451     outputMethHead.print(fsen.getSESErecordName()+"* "+paramsprefix);
452     outputMethHead.println(");\n");
453
454
455     generateFlatMethodSESE(fsen.getfmBogus(),
456                            fsen.getcdEnclosing(),
457                            fsen,
458                            fsen.getFlatExit(),
459                            outputMethods);
460   }
461
462   // used when generating the specific SESE record struct
463   // to remember the FIRST field name of sese records
464   // that the current SESE depends on--we need to know the
465   // offset to the first one for garbage collection
466   protected void addingDepRecField(FlatSESEEnterNode fsen,
467                                    String field) {
468     if( fsen.getFirstDepRecField() == null ) {
469       fsen.setFirstDepRecField(field);
470     }
471     fsen.incNumDepRecs();
472   }
473
474
475   private void generateFlatMethodSESE(FlatMethod fm,
476                                       ClassDescriptor cn,
477                                       FlatSESEEnterNode fsen,
478                                       FlatSESEExitNode seseExit,
479                                       PrintWriter output
480                                       ) {
481
482     MethodDescriptor md = fm.getMethod();
483
484     output.print("void ");
485     output.print(fsen.getSESEmethodName()+"(");
486     output.print(fsen.getSESErecordName()+"* "+paramsprefix);
487     output.println("){\n");
488
489
490     TempObject objecttemp=(TempObject) tempstable.get(md);
491
492     if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
493       output.print("   struct "+
494                    cn.getSafeSymbol()+
495                    md.getSafeSymbol()+"_"+
496                    md.getSafeMethodDescriptor()+
497                    "_locals "+localsprefix+"={");
498       output.print(objecttemp.numPointers()+",");
499       output.print("&(((SESEcommon*)(___params___))[1])");
500       for(int j=0; j<objecttemp.numPointers(); j++)
501         output.print(", NULL");
502       output.println("};");
503     }
504
505     output.println("   /* regular local primitives */");
506     for(int i=0; i<objecttemp.numPrimitives(); i++) {
507       TempDescriptor td=objecttemp.getPrimitive(i);
508       TypeDescriptor type=td.getType();
509       if (type.isNull())
510         output.println("   void * "+td.getSafeSymbol()+";");
511       else if (type.isClass()||type.isArray())
512         output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
513       else
514         output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
515     }
516
517
518     // declare variables for naming static and dynamic SESE's
519     ContextTaskNames context = oooa.getContextTaskNames(fsen);
520
521     output.println("   /* static SESE names */");
522     Iterator<SESEandAgePair> pItr = context.getNeededStaticNames().iterator();
523     while( pItr.hasNext() ) {
524       SESEandAgePair pair = pItr.next();
525       output.println("   SESEcommon* "+pair+" = NULL;");
526     }
527
528     // declare variables for tracking dynamic sources
529     output.println("   /* dynamic variable sources */");
530     Iterator<TempDescriptor> dynSrcItr = context.getDynamicVarSet().iterator();
531     while( dynSrcItr.hasNext() ) {
532       TempDescriptor dynSrcVar = dynSrcItr.next();
533       output.println("   SESEcommon*  "+dynSrcVar+"_srcSESE = NULL;");
534       output.println("   INTPTR       "+dynSrcVar+"_srcOffset = 0x1;");
535     }
536
537
538     // declare local temps for in-set primitives, and if it is
539     // a ready-source variable, get the value from the record
540     output.println("   /* local temps for in-set primitives */");
541     Iterator<TempDescriptor> itrInSet = fsen.getInVarSet().iterator();
542     while( itrInSet.hasNext() ) {
543       TempDescriptor temp = itrInSet.next();
544       TypeDescriptor type = temp.getType();
545       if( !type.isPtr() ) {
546         if( fsen.getReadyInVarSet().contains(temp) ) {
547           output.println("   "+type+" "+temp+" = "+paramsprefix+"->"+temp+";");
548         } else {
549           output.println("   "+type+" "+temp+";");
550         }
551       }
552     }
553
554     // declare local temps for out-set primitives if its not already
555     // in the in-set, and it's value will get written so no problem
556     output.println("   /* local temp for out-set prim, not already in the in-set */");
557     Iterator<TempDescriptor> itrOutSet = fsen.getOutVarSet().iterator();
558     while( itrOutSet.hasNext() ) {
559       TempDescriptor temp = itrOutSet.next();
560       TypeDescriptor type = temp.getType();
561       if( !type.isPtr() && !fsen.getInVarSet().contains(temp) ) {
562         output.println("   "+type+" "+temp+";");
563       }
564     }
565
566
567     // initialize thread-local var to a the task's record, which is fused
568     // with the param list
569     output.println("   ");
570     output.println("   // code of this task's body should use this to access the running task record");
571     output.println("   runningSESE = &(___params___->common);");
572     output.println("   childSESE = 0;");
573     output.println("   ");
574
575
576     // eom - setup memory queue
577     output.println("   // set up memory queues ");
578     output.println("   int numMemoryQueue=0;");
579     output.println("   int memoryQueueItemID=0;");
580     Analysis.OoOJava.ConflictGraph graph = oooa.getConflictGraph(fsen);
581     if( graph != null && graph.hasConflictEdge() ) {
582       output.println("   {");
583       Set<Analysis.OoOJava.SESELock> lockSet = oooa.getLockMappings(graph);
584       System.out.println("#lockSet="+lockSet);
585       if( lockSet.size() > 0 ) {
586         output.println("   numMemoryQueue=" + lockSet.size() + ";");
587         output.println("   runningSESE->numMemoryQueue=numMemoryQueue;");
588         output.println("   runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);");
589         output.println();
590       }
591       output.println("   }");
592     }
593
594
595     // set up a task's mem pool to recycle the allocation of children tasks
596     // don't bother if the task never has children (a leaf task)
597     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
598     output.println("/////////////////////////////////////////////");
599     output.println("//");
600     output.println("//  TODO: use poolcreate to make one record pool");
601     output.println("//  per WORKER THREAD and never destroy it...");
602     output.println("//");
603     output.println("/////////////////////////////////////////////");
604     if( !fsen.getIsLeafSESE() ) {
605       output.println("   runningSESE->taskRecordMemPool = poolcreate( "+
606                      maxTaskRecSizeStr+", freshTaskRecordInitializer );");
607       if (state.RCR && !rcr.hasEmptyTraversers(fsen)) {
608         output.println("   createTR();");
609         output.println("   runningSESE->allHashStructures=TRqueue->allHashStructures;");
610       }
611     } else {
612       // make it clear we purposefully did not initialize this
613       output.println("   runningSESE->taskRecordMemPool = (MemPool*)0x7;");
614     }
615     output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
616
617
618     // copy in-set into place, ready vars were already
619     // copied when the SESE was issued
620     Iterator<TempDescriptor> tempItr;
621
622     // static vars are from a known SESE
623     output.println("   // copy variables from static sources");
624     tempItr = fsen.getStaticInVarSet().iterator();
625     while( tempItr.hasNext() ) {
626       TempDescriptor temp = tempItr.next();
627       VariableSourceToken vst = fsen.getStaticInVarSrc(temp);
628       SESEandAgePair srcPair = new SESEandAgePair(vst.getSESE(), vst.getAge() );
629       output.println("   "+generateTemp(fsen.getfmBogus(), temp)+
630                      " = "+paramsprefix+"->"+srcPair+"->"+vst.getAddrVar()+";");
631     }
632
633     output.println("   // decrement references to static sources");
634     for( Iterator<SESEandAgePair> pairItr = fsen.getStaticInVarSrcs().iterator(); pairItr.hasNext(); ) {
635       SESEandAgePair srcPair = pairItr.next();
636       output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
637       output.println("   {");
638       output.println("     SESEcommon* src = &("+paramsprefix+"->"+srcPair+"->common);");
639       output.println("     RELEASE_REFERENCE_TO( src );");
640       output.println("   }");
641       output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
642     }
643
644
645     // dynamic vars come from an SESE and src
646     output.println("     // copy variables from dynamic sources");
647     tempItr = fsen.getDynamicInVarSet().iterator();
648     while( tempItr.hasNext() ) {
649       TempDescriptor temp = tempItr.next();
650       TypeDescriptor type = temp.getType();
651
652       // go grab it from the SESE source
653       output.println("   if( "+paramsprefix+"->"+temp+"_srcSESE != NULL ) {");
654
655       String typeStr;
656       if( type.isNull() ) {
657         typeStr = "void*";
658       } else if( type.isClass() || type.isArray() ) {
659         typeStr = "struct "+type.getSafeSymbol()+"*";
660       } else {
661         typeStr = type.getSafeSymbol();
662       }
663
664       output.println("     "+generateTemp(fsen.getfmBogus(), temp)+
665                      " = *(("+typeStr+"*) ((void*)"+
666                      paramsprefix+"->"+temp+"_srcSESE + "+
667                      paramsprefix+"->"+temp+"_srcOffset));");
668
669       output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
670       output.println("     SESEcommon* src = "+paramsprefix+"->"+temp+"_srcSESE;");
671       output.println("     RELEASE_REFERENCE_TO( src );");
672       output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
673
674       // or if the source was our parent, its already in our record to grab
675       output.println("   } else {");
676       output.println("     "+generateTemp(fsen.getfmBogus(), temp)+
677                      " = "+paramsprefix+"->"+temp+";");
678       output.println("   }");
679     }
680
681     // Check to see if we need to do a GC if this is a
682     // multi-threaded program...
683     if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
684       output.println("if (unlikely(needtocollect)) checkcollect("+localsprefixaddr+");");
685       //Don't bother if we aren't in recursive methods...The loops case will catch it
686 //      if (callgraph.getAllMethods(md).contains(md)) {
687 //        if(this.state.MULTICOREGC) {
688 //          output.println("if(gcflag) gc("+localsprefixaddr+");");
689 //        } else {
690 //        output.println("if (unlikely(needtocollect)) checkcollect("+localsprefixaddr+");");
691 //      }
692 //      }
693     }
694
695     if( state.COREPROF ) {
696       output.println("#ifdef CP_EVENTID_TASKEXECUTE");
697       output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_BEGIN );");
698       output.println("#endif");
699     }
700
701     HashSet<FlatNode> exitset=new HashSet<FlatNode>();
702     exitset.add(seseExit);
703     generateCode(fsen.getNext(0), fm, exitset, output);
704     output.println("}\n\n");
705   }
706
707
708   // when a new mlp thread is created for an issued SESE, it is started
709   // by running this method which blocks on a cond variable until
710   // it is allowed to transition to execute.  Then a case statement
711   // allows it to invoke the method with the proper SESE body, and after
712   // exiting the SESE method, executes proper SESE exit code before the
713   // thread can be destroyed
714   private void generateSESEinvocationMethod(PrintWriter outmethodheader,
715                                             PrintWriter outmethod
716                                             ) {
717
718     outmethodheader.println("void* invokeSESEmethod( void* seseRecord );");
719     outmethod.println("void* invokeSESEmethod( void* seseRecord ) {");
720     outmethod.println("  int status;");
721     outmethod.println("  char errmsg[128];");
722
723     // generate a case for each SESE class that can be invoked
724     outmethod.println("  switch( ((SESEcommon*)seseRecord)->classID ) {");
725     outmethod.println("    ");
726     Iterator<FlatSESEEnterNode> seseit;
727     seseit = oooa.getAllSESEs().iterator();
728
729     while( seseit.hasNext() ) {
730       FlatSESEEnterNode fsen = seseit.next();
731
732       outmethod.println("    /* "+fsen.getPrettyIdentifier()+" */");
733       outmethod.println("    case "+fsen.getIdentifier()+":");
734       outmethod.println("      "+fsen.getSESEmethodName()+"( seseRecord );");
735
736       if( fsen.getIsMainSESE() ) {
737         outmethod.println("      workScheduleExit();");
738       }
739
740       outmethod.println("      break;");
741       outmethod.println("");
742     }
743
744     // default case should never be taken, error out
745     outmethod.println("    default:");
746     outmethod.println("      printf(\"Error: unknown SESE class ID in invoke method.\\n\");");
747     outmethod.println("      exit(-30);");
748     outmethod.println("      break;");
749     outmethod.println("  }");
750     outmethod.println("  return NULL;");
751     outmethod.println("}\n\n");
752   }
753
754
755
756   protected void stallMEMRCR(FlatMethod fm,
757                              FlatNode fn,
758                              Set<WaitingElement> waitingElementSet, PrintWriter output) {
759     output.println("// stall on parent's stall sites ");
760     output.println("   {");
761     output.println("     REntry* rentry;");
762     output.println("     // stallrecord sometimes is used as a task record for instance ");
763     output.println("     // when you call RELEASE_REFERENCE_TO on a stall record.");
764     output.println("     // so the parent field must be initialized.");
765     output.println("     SESEstall * stallrecord=(SESEstall *) poolalloc(runningSESE->taskRecordMemPool);");
766     output.println("     stallrecord->common.parent=runningSESE;");
767     output.println("     stallrecord->common.unresolvedDependencies=10000;");
768     output.println("     stallrecord->common.rcrstatus=1;");
769     output.println("     stallrecord->common.offsetToParamRecords=(INTPTR) & (((SESEstall *)0)->rcrRecords);");
770     output.println("     stallrecord->common.refCount = 3;");
771     output.println("     int localCount=10000;");
772     output.println("     stallrecord->rcrRecords[0].index=0;");
773     output.println("     stallrecord->rcrRecords[0].flag=0;");
774     output.println("     stallrecord->rcrRecords[0].next=NULL;");
775     output.println("     stallrecord->common.parentsStallSem=&runningSESEstallSem;");
776     output.println("     psem_reset( &runningSESEstallSem);");
777     output.println("     stallrecord->tag=runningSESEstallSem.tag;");
778
779     TempDescriptor stalltd=null;
780     for (Iterator iterator = waitingElementSet.iterator(); iterator.hasNext(); ) {
781       WaitingElement waitingElement =(WaitingElement) iterator.next();
782       if (waitingElement.getStatus() >= ConflictNode.COARSE) {
783         output.println("     rentry=mlpCreateREntry(runningSESE->memoryQueueArray["
784                        + waitingElement.getQueueID() + "]," + waitingElement.getStatus()
785                        + ", (SESEcommon *) stallrecord, 1LL);");
786       } else {
787         throw new Error("Fine-grained conflict: This should not happen in RCR");
788       }
789       output.println("     rentry->queue=runningSESE->memoryQueueArray["
790                      + waitingElement.getQueueID() + "];");
791       output.println("     if(ADDRENTRY(runningSESE->memoryQueueArray["
792                      + waitingElement.getQueueID() + "],rentry)==NOTREADY) {");
793       output.println("       localCount--;");
794       output.println("     }");
795       output.println("#if defined(RCR)&&!defined(OOO_DISABLE_TASKMEMPOOL)");
796       output.println("     else poolfreeinto(runningSESE->memoryQueueArray["+
797                      waitingElement.getQueueID()+
798                      "]->rentrypool, rentry);");
799       output.println("#endif");
800       if (stalltd==null) {
801         stalltd=waitingElement.getTempDesc();
802       } else if (stalltd!=waitingElement.getTempDesc()) {
803         throw new Error("Multiple temp descriptors at stall site"+stalltd+"!="+waitingElement.getTempDesc());
804       }
805     }
806
807     //did all of the course grained stuff
808     output.println("     if(!atomic_sub_and_test(localCount, &(stallrecord->common.unresolvedDependencies))) {");
809     //have to do fine-grained work also
810     output.println("       stallrecord->___obj___=(struct ___Object___ *)"
811                    + generateTemp(fm, stalltd) + ";");
812     output.println("       stallrecord->common.classID=-"
813                    + rcr.getTraverserID(stalltd, fn) + ";");
814
815     output.println("       enqueueTR(TRqueue, (void *)stallrecord);");
816
817     if (state.COREPROF) {
818       output.println("#ifdef CP_EVENTID_TASKSTALLMEM");
819       output
820       .println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
821       output.println("#endif");
822     }
823
824     output.println("       psem_take( &runningSESEstallSem, (struct garbagelist *)&___locals___ );");
825
826     if (state.COREPROF) {
827       output.println("#ifdef CP_EVENTID_TASKSTALLMEM");
828       output
829       .println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
830       output.println("#endif");
831     }
832
833     output.println("     } else {"); //exit if condition
834     //release traversers reference if we didn't use traverser
835     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
836     output.println("  RELEASE_REFERENCES_TO((SESEcommon *)stallrecord, 2);");
837     output.println("#endif");
838     output.println("     }");
839     //release our reference to stall record
840     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
841     output.println("  RELEASE_REFERENCE_TO((SESEcommon *)stallrecord);");
842     output.println("#endif");
843     output.println("   }"); //exit block
844   }
845
846
847   protected void additionalCodePreNode(FlatMethod fm,
848                                        FlatNode fn,
849                                        PrintWriter output) {
850     // insert pre-node actions from the code plan
851
852     CodePlan cp = oooa.getCodePlan(fn);
853
854     if( cp != null ) {
855
856       // the current task for a code plan is either the
857       // locally-defined enclosing task, or the caller proxy task.
858       // When it is the caller proxy, it is possible to ask what are
859       // all the possible tasks that the proxy might stand for
860       FlatSESEEnterNode currentSESE = cp.getCurrentSESE();
861
862       FlatMethod fmContext;
863       if( currentSESE.getIsCallerProxySESE() ) {
864         fmContext = oooa.getContainingFlatMethod(fn);
865       } else {
866         fmContext = currentSESE.getfmBogus();
867       }
868
869       ContextTaskNames contextTaskNames;
870       if( currentSESE.getIsCallerProxySESE() ) {
871         contextTaskNames = oooa.getContextTaskNames(oooa.getContainingFlatMethod(fn) );
872       } else {
873         contextTaskNames = oooa.getContextTaskNames(currentSESE);
874       }
875
876       // for each sese and age pair that this parent statement
877       // must stall on, take that child's stall semaphore, the
878       // copying of values comes after the statement
879       Iterator<VariableSourceToken> vstItr = cp.getStallTokens().iterator();
880       while( vstItr.hasNext() ) {
881         VariableSourceToken vst = vstItr.next();
882
883         SESEandAgePair pair = new SESEandAgePair(vst.getSESE(), vst.getAge() );
884
885         output.println("   {");
886         output.println("     "+
887                        pair.getSESE().getSESErecordName()+"* child = ("+
888                        pair.getSESE().getSESErecordName()+"*) "+pair+";");
889
890         output.println("     SESEcommon* childCom = (SESEcommon*) "+pair+";");
891
892         if( state.COREPROF ) {
893           output.println("#ifdef CP_EVENTID_TASKSTALLVAR");
894           output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
895           output.println("#endif");
896         }
897
898         output.println("     pthread_mutex_lock( &(childCom->lock) );");
899         output.println("     if( childCom->doneExecuting == FALSE ) {");
900         output.println("       psem_reset( &runningSESEstallSem );");
901         output.println("       childCom->parentsStallSem = &runningSESEstallSem;");
902         output.println("       pthread_mutex_unlock( &(childCom->lock) );");
903         output.println("       psem_take( &runningSESEstallSem, (struct garbagelist *)&___locals___ );");
904         output.println("     } else {");
905         output.println("       pthread_mutex_unlock( &(childCom->lock) );");
906         output.println("     }");
907
908         // copy things we might have stalled for
909         Iterator<TempDescriptor> tdItr = cp.getCopySet(vst).iterator();
910         while( tdItr.hasNext() ) {
911           TempDescriptor td = tdItr.next();
912           output.println("       "+generateTemp(fmContext, td)+
913                          " = child->"+vst.getAddrVar().getSafeSymbol()+";");
914         }
915
916         if( state.COREPROF ) {
917           output.println("#ifdef CP_EVENTID_TASKSTALLVAR");
918           output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
919           output.println("#endif");
920         }
921
922         output.println("   }");
923       }
924
925       // for each variable with a dynamic source, stall just for that variable
926       Iterator<TempDescriptor> dynItr = cp.getDynamicStallSet().iterator();
927       while( dynItr.hasNext() ) {
928         TempDescriptor dynVar = dynItr.next();
929
930         // only stall if the dynamic source is not yourself, denoted by src==NULL
931         // otherwise the dynamic write nodes will have the local var up-to-date
932         output.println("   {");
933         output.println("     if( "+dynVar+"_srcSESE != NULL ) {");
934
935         output.println("       SESEcommon* childCom = (SESEcommon*) "+dynVar+"_srcSESE;");
936
937         if( state.COREPROF ) {
938           output.println("#ifdef CP_EVENTID_TASKSTALLVAR");
939           output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
940           output.println("#endif");
941         }
942
943         output.println("     pthread_mutex_lock( &(childCom->lock) );");
944         output.println("     if( childCom->doneExecuting == FALSE ) {");
945         output.println("       psem_reset( &runningSESEstallSem );");
946         output.println("       childCom->parentsStallSem = &runningSESEstallSem;");
947         output.println("       pthread_mutex_unlock( &(childCom->lock) );");
948         output.println("       psem_take( &runningSESEstallSem, (struct garbagelist *)&___locals___ );");
949         output.println("     } else {");
950         output.println("       pthread_mutex_unlock( &(childCom->lock) );");
951         output.println("     }");
952
953         TypeDescriptor type = dynVar.getType();
954         String typeStr;
955         if( type.isNull() ) {
956           typeStr = "void*";
957         } else if( type.isClass() || type.isArray() ) {
958           typeStr = "struct "+type.getSafeSymbol()+"*";
959         } else {
960           typeStr = type.getSafeSymbol();
961         }
962
963         output.println("       "+generateTemp(fmContext, dynVar)+
964                        " = *(("+typeStr+"*) ((void*)"+
965                        dynVar+"_srcSESE + "+dynVar+"_srcOffset));");
966
967         if( state.COREPROF ) {
968           output.println("#ifdef CP_EVENTID_TASKSTALLVAR");
969           output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
970           output.println("#endif");
971         }
972
973         output.println("     }");
974         output.println("   }");
975       }
976
977       // for each assignment of a variable to rhs that has a dynamic source,
978       // copy the dynamic sources
979       Iterator dynAssignItr = cp.getDynAssigns().entrySet().iterator();
980       while( dynAssignItr.hasNext() ) {
981         Map.Entry me  = (Map.Entry)dynAssignItr.next();
982         TempDescriptor lhs = (TempDescriptor) me.getKey();
983         TempDescriptor rhs = (TempDescriptor) me.getValue();
984
985         output.println("   {");
986         output.println("   SESEcommon* oldSrc = "+lhs+"_srcSESE;");
987
988         output.println("   "+lhs+"_srcSESE   = "+rhs+"_srcSESE;");
989         output.println("   "+lhs+"_srcOffset = "+rhs+"_srcOffset;");
990
991         // no matter what we did above, track reference count of whatever
992         // this variable pointed to, do release last in case we're just
993         // copying the same value in because 1->2->1 is safe but ref count
994         // 1->0->1 has a window where it looks like it should be free'd
995         output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
996         output.println("     if( "+rhs+"_srcSESE != NULL ) {");
997         output.println("       ADD_REFERENCE_TO( "+rhs+"_srcSESE );");
998         output.println("     }");
999         output.println("     if( oldSrc != NULL ) {");
1000         output.println("       RELEASE_REFERENCE_TO( oldSrc );");
1001         output.println("     }");
1002         output.println("   }");
1003         output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1004       }
1005
1006       // for each lhs that is dynamic from a non-dynamic source, set the
1007       // dynamic source vars to the current SESE
1008       dynItr = cp.getDynAssignCurr().iterator();
1009       while( dynItr.hasNext() ) {
1010         TempDescriptor dynVar = dynItr.next();
1011
1012         assert contextTaskNames.getDynamicVarSet().contains(dynVar);
1013
1014         // first release a reference to current record
1015         output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1016         output.println("   if( "+dynVar+"_srcSESE != NULL ) {");
1017         output.println("     RELEASE_REFERENCE_TO( oldSrc );");
1018         output.println("   }");
1019         output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1020
1021         output.println("   "+dynVar+"_srcSESE = NULL;");
1022       }
1023
1024
1025       // handling stall site, consider that one of several tasks might be
1026       // executing, so create a switch on task ID, because waiting elements
1027       // generated by this stall site should be inserted into possibly a
1028       // different memory queue index, depending on which task type it is
1029       // update: only generate the switch statement if there is at least
1030       // one non-empty case that will go in it!
1031       boolean atLeastOneCase = false;
1032
1033       // create a case for each class of task that might be executing
1034       Iterator<FlatSESEEnterNode> taskItr = oooa.getPossibleExecutingRBlocks(fn).iterator();
1035       while( taskItr.hasNext() ) {
1036         FlatSESEEnterNode parent = taskItr.next();
1037         ConflictGraph graph  = oooa.getConflictGraph(parent);
1038
1039         if( graph == null ) {
1040           continue;
1041         }
1042
1043         Set<SESELock>       seseLockSet       = oooa.getLockMappings(graph);
1044         Set<WaitingElement> waitingElementSet = graph.getStallSiteWaitingElementSet(fn, seseLockSet);
1045
1046         if( waitingElementSet.size() == 0 ) {
1047           continue;
1048         }
1049
1050         // TODO: THIS STRATEGY CAN BE OPTIMIZED EVEN FURTHER, IF THERE
1051         // IS EXACTLY ONE CASE, DON'T GENERATE A SWITCH AT ALL
1052         if( atLeastOneCase == false ) {
1053           atLeastOneCase = true;
1054           output.println("   // potential stall site ");
1055           output.println("   switch( runningSESE->classID ) {");
1056         }
1057
1058         output.println("     case "+parent.getIdentifier()+": {");
1059
1060         if( state.RCR ) {
1061           stallMEMRCR(fm, fn, waitingElementSet, output);
1062         } else {
1063
1064           output.println("       REntry* rentry;");
1065
1066           for( Iterator iterator = waitingElementSet.iterator(); iterator.hasNext(); ) {
1067             WaitingElement waitingElement = (WaitingElement) iterator.next();
1068
1069             if (waitingElement.getStatus() >= ConflictNode.COARSE) {
1070               output.println("       rentry=mlpCreateREntry(runningSESE->memoryQueueArray["
1071                              + waitingElement.getQueueID() + "]," + waitingElement.getStatus()
1072                              + ", runningSESE);");
1073             } else {
1074               output.println("       rentry=mlpCreateFineREntry(runningSESE->memoryQueueArray["
1075                              + waitingElement.getQueueID() + "]," + waitingElement.getStatus()
1076                              + ", runningSESE,  (void*)&"
1077                              + generateTemp(fm, waitingElement.getTempDesc()) + ");");
1078             }
1079             output.println("       rentry->parentStallSem=&runningSESEstallSem;");
1080             output.println("       psem_reset( &runningSESEstallSem);");
1081             output.println("       rentry->tag=runningSESEstallSem.tag;");
1082             output.println("       rentry->queue=runningSESE->memoryQueueArray["
1083                            + waitingElement.getQueueID() + "];");
1084             output.println("       if(ADDRENTRY(runningSESE->memoryQueueArray["
1085                            + waitingElement.getQueueID() + "],rentry)==NOTREADY){");
1086             if (state.COREPROF) {
1087               output.println("#ifdef CP_EVENTID_TASKSTALLMEM");
1088               output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
1089               output.println("#endif");
1090             }
1091
1092             output.println("       psem_take( &runningSESEstallSem, (struct garbagelist *)&___locals___ );");
1093
1094             if (state.COREPROF) {
1095               output.println("#ifdef CP_EVENTID_TASKSTALLMEM");
1096               output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
1097               output.println("#endif");
1098             }
1099             output.println("     }  ");
1100           }
1101
1102         }
1103         output.println("     } break; // end case "+parent.getIdentifier());
1104       }
1105
1106       if( atLeastOneCase ) {
1107         output.println("   } // end stall site switch");
1108       }
1109     }
1110   }
1111
1112
1113   protected void additionalCodePostNode(FlatMethod fm,
1114                                         FlatNode fn,
1115                                         PrintWriter output) {
1116
1117     // insert post-node actions from the code-plan (none right now...)
1118   }
1119
1120
1121   public void generateFlatSESEEnterNode(FlatMethod fm,
1122                                         FlatSESEEnterNode fsen,
1123                                         PrintWriter output) {
1124
1125     // there may be an SESE in an unreachable method, skip over
1126     if( !oooa.getAllSESEs().contains(fsen) ) {
1127       return;
1128     }
1129
1130     // assert we are never generating code for the caller proxy
1131     // it should only appear in analysis results
1132     assert !fsen.getIsCallerProxySESE();
1133
1134
1135     output.println("   { // issue new task instance");
1136
1137     if( state.COREPROF ) {
1138       output.println("#ifdef CP_EVENTID_TASKDISPATCH");
1139       output.println("     CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_BEGIN );");
1140       output.println("#endif");
1141     }
1142
1143
1144     // before doing anything, lock your own record and increment the running children
1145     if( !fsen.getIsMainSESE() ) {
1146       output.println("     childSESE++;");
1147     }
1148
1149     // allocate the space for this record
1150     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1151
1152     output.println("#ifdef CP_EVENTID_POOLALLOC");
1153     output.println("     CP_LOGEVENT( CP_EVENTID_POOLALLOC, CP_EVENTTYPE_BEGIN );");
1154     output.println("#endif");
1155     if( !fsen.getIsMainSESE() ) {
1156       output.println("     "+
1157                      fsen.getSESErecordName()+"* seseToIssue = ("+
1158                      fsen.getSESErecordName()+"*) poolalloc( runningSESE->taskRecordMemPool );");
1159       output.println("     CHECK_RECORD( seseToIssue );");
1160     } else {
1161       output.println("     "+
1162                      fsen.getSESErecordName()+"* seseToIssue = ("+
1163                      fsen.getSESErecordName()+"*) mlpAllocSESErecord( sizeof( "+
1164                      fsen.getSESErecordName()+" ) );");
1165     }
1166     output.println("#ifdef CP_EVENTID_POOLALLOC");
1167     output.println("     CP_LOGEVENT( CP_EVENTID_POOLALLOC, CP_EVENTTYPE_END );");
1168     output.println("#endif");
1169
1170     output.println("#else // OOO_DISABLE_TASKMEMPOOL");
1171     output.println("     "+
1172                    fsen.getSESErecordName()+"* seseToIssue = ("+
1173                    fsen.getSESErecordName()+"*) mlpAllocSESErecord( sizeof( "+
1174                    fsen.getSESErecordName()+" ) );");
1175     output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1176
1177
1178     // set up the SESE in-set and out-set objects, which look
1179     // like a garbage list
1180     output.println("     struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(seseToIssue))[1]);");
1181     output.println("     gl->size="+calculateSizeOfSESEParamList(fsen)+";");
1182     output.println("     gl->next = NULL;");
1183     output.println("     seseToIssue->common.rentryIdx=0;");
1184
1185     if(state.RCR) {
1186       //flag the SESE status as 1...it will be reset
1187       output.println("     seseToIssue->common.rcrstatus=1;");
1188     }
1189
1190     // there are pointers to SESE records the newly-issued SESE
1191     // will use to get values it depends on them for--how many
1192     // are there, and what is the offset from the total SESE
1193     // record to the first dependent record pointer?
1194     output.println("     seseToIssue->common.numDependentSESErecords="+
1195                    fsen.getNumDepRecs()+";");
1196
1197     // we only need this (and it will only compile) when the number of dependent
1198     // SESE records is non-zero
1199     if( fsen.getFirstDepRecField() != null ) {
1200       output.println("     seseToIssue->common.offsetToDepSESErecords=(INTPTR)sizeof("+
1201                      fsen.getSESErecordName()+") - (INTPTR)&((("+
1202                      fsen.getSESErecordName()+"*)0)->"+fsen.getFirstDepRecField()+");"
1203                      );
1204     }
1205
1206     if( state.RCR &&
1207         fsen.getInVarsForDynamicCoarseConflictResolution().size() > 0
1208         ) {
1209       output.println("    seseToIssue->common.offsetToParamRecords=(INTPTR) & ((("+
1210                      fsen.getSESErecordName()+"*)0)->rcrRecords);");
1211     }
1212
1213     // fill in common data
1214     output.println("     int localCount=0;");
1215     output.println("     seseToIssue->common.classID = "+fsen.getIdentifier()+";");
1216     output.println("     seseToIssue->common.unresolvedDependencies = 10000;");
1217     output.println("     seseToIssue->common.parentsStallSem = NULL;");
1218     output.println("     initQueue(&seseToIssue->common.forwardList);");
1219     output.println("     seseToIssue->common.doneExecuting = FALSE;");
1220     output.println("     seseToIssue->common.numRunningChildren = 0;");
1221     output.println("#ifdef OOO_DISABLE_TASKMEMPOOL");
1222     output.println("     pthread_cond_init( &(seseToIssue->common.runningChildrenCond), NULL );");
1223     output.println("#endif");
1224     output.println("     seseToIssue->common.parent = runningSESE;");
1225     // start with refCount = 2, one being the count that the child itself
1226     // will decrement when it retires, to say it is done using its own
1227     // record, and the other count is for the parent that will remember
1228     // the static name of this new child below
1229     if( state.RCR ) {
1230       // if we're using RCR, ref count is 3 because the traverser has
1231       // a reference, too
1232       if( !fsen.getIsMainSESE() && fsen.getInVarsForDynamicCoarseConflictResolution().size()>0) {
1233         output.println("     seseToIssue->common.refCount = 10003;");
1234       } else {
1235         output.println("     seseToIssue->common.refCount = 10002;");
1236       }
1237       output.println("     int refCount=10000;");
1238     } else {
1239       output.println("     seseToIssue->common.refCount = 2;");
1240     }
1241
1242     // all READY in-vars should be copied now and be done with it
1243     Iterator<TempDescriptor> tempItr = fsen.getReadyInVarSet().iterator();
1244     while( tempItr.hasNext() ) {
1245       TempDescriptor temp = tempItr.next();
1246
1247       // determine whether this new task instance is in a method context,
1248       // or within the body of another task
1249       assert !fsen.getIsCallerProxySESE();
1250       FlatSESEEnterNode parent = fsen.getLocalParent();
1251       if( parent != null && !parent.getIsCallerProxySESE() ) {
1252         output.println("     seseToIssue->"+temp+" = "+
1253                        generateTemp(parent.getfmBogus(), temp)+";");
1254       } else {
1255         output.println("     seseToIssue->"+temp+" = "+
1256                        generateTemp(fsen.getfmEnclosing(), temp)+";");
1257       }
1258     }
1259
1260     // before potentially adding this SESE to other forwarding lists,
1261     // create it's lock
1262     output.println("#ifdef OOO_DISABLE_TASKMEMPOOL");
1263     output.println("     pthread_mutex_init( &(seseToIssue->common.lock), NULL );");
1264     output.println("#endif");
1265
1266     if( !fsen.getIsMainSESE() ) {
1267       // count up outstanding dependencies, static first, then dynamic
1268       Iterator<SESEandAgePair> staticSrcsItr = fsen.getStaticInVarSrcs().iterator();
1269       while( staticSrcsItr.hasNext() ) {
1270         SESEandAgePair srcPair = staticSrcsItr.next();
1271         output.println("     {");
1272         output.println("       SESEcommon* src = (SESEcommon*)"+srcPair+";");
1273         output.println("       pthread_mutex_lock( &(src->lock) );");
1274         // FORWARD TODO - ...what? make it a chain of arrays instead of true linked-list?
1275         output.println("       if( !src->doneExecuting ) {");
1276         output.println("         addNewItem( &src->forwardList, seseToIssue );");
1277         output.println("         ++(localCount);");
1278         output.println("       }");
1279         output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1280         output.println("       ADD_REFERENCE_TO( src );");
1281         output.println("#endif");
1282         output.println("       pthread_mutex_unlock( &(src->lock) );");
1283         output.println("     }");
1284
1285         // whether or not it is an outstanding dependency, make sure
1286         // to pass the static name to the child's record
1287         output.println("     seseToIssue->"+srcPair+" = "+
1288                        "("+srcPair.getSESE().getSESErecordName()+"*)"+
1289                        srcPair+";");
1290       }
1291
1292       // dynamic sources might already be accounted for in the static list,
1293       // so only add them to forwarding lists if they're not already there
1294       Iterator<TempDescriptor> dynVarsItr = fsen.getDynamicInVarSet().iterator();
1295       while( dynVarsItr.hasNext() ) {
1296         TempDescriptor dynInVar = dynVarsItr.next();
1297         output.println("     {");
1298         output.println("       SESEcommon* src = (SESEcommon*)"+dynInVar+"_srcSESE;");
1299
1300         // the dynamic source is NULL if it comes from your own space--you can't pass
1301         // the address off to the new child, because you're not done executing and
1302         // might change the variable, so copy it right now
1303         output.println("       if( src != NULL ) {");
1304         output.println("         pthread_mutex_lock( &(src->lock) );");
1305
1306         // FORWARD TODO
1307
1308         output.println("         if( isEmpty( &src->forwardList ) ||");
1309         output.println("             seseToIssue != peekItem( &src->forwardList ) ) {");
1310         output.println("           if( !src->doneExecuting ) {");
1311         output.println("             addNewItem( &src->forwardList, seseToIssue );");
1312         output.println("             ++(localCount);");
1313         output.println("           }");
1314         output.println("         }");
1315         output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1316         output.println("         ADD_REFERENCE_TO( src );");
1317         output.println("#endif");
1318         output.println("         pthread_mutex_unlock( &(src->lock) );");
1319         output.println("         seseToIssue->"+dynInVar+"_srcOffset = "+dynInVar+"_srcOffset;");
1320         output.println("       } else {");
1321
1322
1323         // determine whether this new task instance is in a method context,
1324         // or within the body of another task
1325         assert !fsen.getIsCallerProxySESE();
1326         FlatSESEEnterNode parent = fsen.getLocalParent();
1327         if( parent != null && !parent.getIsCallerProxySESE() ) {
1328           output.println("         seseToIssue->"+dynInVar+" = "+
1329                          generateTemp(parent.getfmBogus(), dynInVar)+";");
1330         } else {
1331           output.println("         seseToIssue->"+dynInVar+" = "+
1332                          generateTemp(fsen.getfmEnclosing(), dynInVar)+";");
1333         }
1334
1335         output.println("       }");
1336         output.println("     }");
1337
1338         // even if the value is already copied, make sure your NULL source
1339         // gets passed so child knows it already has the dynamic value
1340         output.println("     seseToIssue->"+dynInVar+"_srcSESE = "+dynInVar+"_srcSESE;");
1341       }
1342
1343
1344       // maintain pointers for finding dynamic SESE
1345       // instances from static names, do a shuffle as instances age
1346       // and also release references that have become too old
1347       if( !fsen.getIsMainSESE() ) {
1348
1349         FlatSESEEnterNode currentSESE = fsen.getLocalParent();
1350
1351         ContextTaskNames contextTaskNames;
1352         if( currentSESE == null ) {
1353           contextTaskNames = oooa.getContextTaskNames(oooa.getContainingFlatMethod(fsen) );
1354         } else {
1355           contextTaskNames = oooa.getContextTaskNames(currentSESE);
1356         }
1357
1358         SESEandAgePair pairNewest = new SESEandAgePair(fsen, 0);
1359         SESEandAgePair pairOldest = new SESEandAgePair(fsen, fsen.getOldestAgeToTrack() );
1360         if( contextTaskNames.getNeededStaticNames().contains(pairNewest) ) {
1361           output.println("     {");
1362           output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1363           output.println("       SESEcommon* oldest = "+pairOldest+";");
1364           output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1365
1366           for( int i = fsen.getOldestAgeToTrack(); i > 0; --i ) {
1367             SESEandAgePair pair1 = new SESEandAgePair(fsen, i);
1368             SESEandAgePair pair2 = new SESEandAgePair(fsen, i-1);
1369             output.println("       "+pair1+" = "+pair2+";");
1370           }
1371           output.println("       "+pairNewest+" = &(seseToIssue->common);");
1372
1373           // no need to add a reference to whatever is the newest record, because
1374           // we initialized seseToIssue->refCount to *2*
1375           // but release a reference to whatever was the oldest BEFORE the shift
1376           output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1377           output.println("       if( oldest != NULL ) {");
1378           output.println("         RELEASE_REFERENCE_TO( oldest );");
1379           output.println("       }");
1380           output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1381           output.println("     }");
1382         }
1383       }
1384     }
1385
1386
1387     //////////////////////
1388     // count up memory conflict dependencies,
1389     ///////////////////////
1390     if( !fsen.getIsMainSESE() ) {
1391
1392       if( state.COREPROF ) {
1393         output.println("#ifdef CP_EVENTID_PREPAREMEMQ");
1394         output.println("     CP_LOGEVENT( CP_EVENTID_PREPAREMEMQ, CP_EVENTTYPE_BEGIN );");
1395         output.println("#endif");
1396       }
1397
1398       if(state.RCR) {
1399         dispatchMEMRC(fm, fsen, output);
1400       } else {
1401
1402         // there may be several task types that can get to this
1403         // program point (issue this new task) so create a switch
1404         // based on task ID, each type of task has a different index
1405         // scheme for its memory queue's, and the cases here drop the
1406         // new task instance in the right bucket
1407         boolean atLeastOneCase = false;
1408
1409         // create a case for each class of task that might be executing
1410         Iterator<FlatSESEEnterNode> taskItr = oooa.getPossibleExecutingRBlocks(fsen).iterator();
1411         while( taskItr.hasNext() ) {
1412           FlatSESEEnterNode parent = taskItr.next();
1413           ConflictGraph graph  = oooa.getConflictGraph(parent);
1414
1415           if( graph == null || !graph.hasConflictEdge() ) {
1416             continue;
1417           }
1418
1419           Set<SESELock> seseLockSet = oooa.getLockMappings(graph);
1420
1421           SESEWaitingQueue seseWaitingQueue =
1422             graph.getWaitingElementSetBySESEID(fsen.getIdentifier(), seseLockSet);
1423
1424           if( seseWaitingQueue.getWaitingElementSize() == 0 ) {
1425             continue;
1426           }
1427
1428           if( atLeastOneCase == false ) {
1429             atLeastOneCase = true;
1430             output.println("   // add new task instance to current task's memory queues if needed ");
1431             output.println("   switch( runningSESE->classID ) {");
1432           }
1433
1434           output.println("     case "+parent.getIdentifier()+": {");
1435           output.println("       REntry* rentry=NULL;");
1436           output.println("       INTPTR* pointer=NULL;");
1437           output.println("       seseToIssue->common.rentryIdx=0;");
1438
1439           Set<Integer> queueIDSet=seseWaitingQueue.getQueueIDSet();
1440           for (Iterator iterator = queueIDSet.iterator(); iterator.hasNext(); ) {
1441             Integer key = (Integer) iterator.next();
1442             int queueID=key.intValue();
1443             Set<WaitingElement> waitingQueueSet =
1444               seseWaitingQueue.getWaitingElementSet(queueID);
1445             int enqueueType=seseWaitingQueue.getType(queueID);
1446             if(enqueueType==SESEWaitingQueue.EXCEPTION) {
1447               output.println("       INITIALIZEBUF(runningSESE->memoryQueueArray[" + queueID+ "]);");
1448             }
1449             for (Iterator iterator2 = waitingQueueSet.iterator(); iterator2.hasNext(); ) {
1450               WaitingElement waitingElement
1451                 = (WaitingElement) iterator2.next();
1452               if (waitingElement.getStatus() >= ConflictNode.COARSE) {
1453                 output.println("       rentry=mlpCreateREntry(runningSESE->memoryQueueArray["+ queueID+ "],"
1454                                + waitingElement.getStatus()
1455                                + ", &(seseToIssue->common));");
1456               } else {
1457                 TempDescriptor td = waitingElement.getTempDesc();
1458                 // decide whether waiting element is dynamic or static
1459                 if (fsen.getDynamicInVarSet().contains(td)) {
1460                   // dynamic in-var case
1461                   output.println("       pointer=seseToIssue->"
1462                                  + waitingElement.getDynID()
1463                                  + "_srcSESE+seseToIssue->"
1464                                  + waitingElement.getDynID()
1465                                  + "_srcOffset;");
1466                   output.println("       rentry=mlpCreateFineREntry(runningSESE->memoryQueueArray["+ queueID+ "],"
1467                                  + waitingElement.getStatus()
1468                                  + ", &(seseToIssue->common),  pointer );");
1469                 } else if (fsen.getStaticInVarSet().contains(td)) {
1470                   // static in-var case
1471                   VariableSourceToken vst = fsen.getStaticInVarSrc(td);
1472                   if (vst != null) {
1473
1474                     String srcId = "SESE_" + vst.getSESE().getPrettyIdentifier()
1475                                    + vst.getSESE().getIdentifier()
1476                                    + "_" + vst.getAge();
1477                     output.println("       pointer=(void*)&seseToIssue->"
1478                                    + srcId
1479                                    + "->"
1480                                    + waitingElement
1481                                    .getDynID()
1482                                    + ";");
1483                     output.println("       rentry=mlpCreateFineREntry(runningSESE->memoryQueueArray["+ queueID+ "],"
1484                                    + waitingElement.getStatus()
1485                                    + ", &(seseToIssue->common),  pointer );");
1486                   }
1487                 } else {
1488                   output.println("       rentry=mlpCreateFineREntry(runningSESE->memoryQueueArray["+ queueID+ "],"
1489                                  + waitingElement.getStatus()
1490                                  + ", &(seseToIssue->common), (void*)&seseToIssue->"
1491                                  + waitingElement.getDynID()
1492                                  + ");");
1493                 }
1494               }
1495               output.println("       rentry->queue=runningSESE->memoryQueueArray["
1496                              + waitingElement.getQueueID()
1497                              + "];");
1498
1499               if(enqueueType==SESEWaitingQueue.NORMAL) {
1500                 output.println("       seseToIssue->common.rentryArray[seseToIssue->common.rentryIdx++]=rentry;");
1501                 output.println("       if(ADDRENTRY(runningSESE->memoryQueueArray["
1502                                + waitingElement.getQueueID()
1503                                + "],rentry)==NOTREADY) {");
1504                 output.println("          localCount++;");
1505                 output.println("       }");
1506               } else {
1507                 output.println("       ADDRENTRYTOBUF(runningSESE->memoryQueueArray[" + waitingElement.getQueueID() + "],rentry);");
1508               }
1509             }
1510             if(enqueueType!=SESEWaitingQueue.NORMAL) {
1511               output.println("       localCount+=RESOLVEBUF(runningSESE->memoryQueueArray["
1512                              + queueID+ "],&seseToIssue->common);");
1513             }
1514           }
1515           output.println("     } break; // end case "+parent.getIdentifier());
1516           output.println();
1517         }
1518
1519         if( atLeastOneCase ) {
1520           output.println("   } // end stall site switch");
1521         }
1522       }
1523
1524       if( state.COREPROF ) {
1525         output.println("#ifdef CP_EVENTID_PREPAREMEMQ");
1526         output.println("     CP_LOGEVENT( CP_EVENTID_PREPAREMEMQ, CP_EVENTTYPE_END );");
1527         output.println("#endif");
1528       }
1529     }
1530
1531     // Enqueue Task Record
1532     if (state.RCR) {
1533       if( fsen != oooa.getMainSESE() && fsen.getInVarsForDynamicCoarseConflictResolution().size()>0) {
1534         output.println("    enqueueTR(TRqueue, (void *)seseToIssue);");
1535       }
1536     }
1537
1538     // if there were no outstanding dependencies, issue here
1539     output.println("     if(  atomic_sub_and_test(10000-localCount,&(seseToIssue->common.unresolvedDependencies) ) ) {");
1540     output.println("       workScheduleSubmit( (void*)seseToIssue );");
1541     output.println("     }");
1542
1543
1544
1545     if( state.COREPROF ) {
1546       output.println("#ifdef CP_EVENTID_TASKDISPATCH");
1547       output.println("     CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_END );");
1548       output.println("#endif");
1549     }
1550
1551     output.println("   } // end task issue");
1552   }
1553
1554
1555   void dispatchMEMRC(FlatMethod fm,
1556                      FlatSESEEnterNode newChild,
1557                      PrintWriter output) {
1558     // what we need to do here is create RCR records for the
1559     // new task and insert it into the appropriate parent queues
1560     // IF NEEDED!!!!!!!!
1561     assert newChild.getParents().size() > 0;
1562
1563     output.println("     switch( runningSESE->classID ) {");
1564
1565     Iterator<FlatSESEEnterNode> pItr = newChild.getParents().iterator();
1566     while( pItr.hasNext() ) {
1567
1568       FlatSESEEnterNode parent = pItr.next();
1569       ConflictGraph graph  = oooa.getConflictGraph(parent);
1570
1571       if( graph != null && graph.hasConflictEdge() ) {
1572         Set<SESELock> seseLockSet = oooa.getLockMappings(graph);
1573         SESEWaitingQueue seseWaitingQueue=graph.getWaitingElementSetBySESEID(newChild.getIdentifier(), seseLockSet);
1574         if(seseWaitingQueue.getWaitingElementSize()>0) {
1575
1576           output.println("       /* "+parent.getPrettyIdentifier()+" */");
1577           output.println("       case "+parent.getIdentifier()+": {");
1578
1579           output.println("         REntry* rentry=NULL;");
1580           output.println("         INTPTR* pointer=NULL;");
1581           output.println("         seseToIssue->common.rentryIdx=0;");
1582           Vector<TempDescriptor> invars=newChild.getInVarsForDynamicCoarseConflictResolution();
1583           //System.out.println(fm.getMethod()+"["+invars+"]");
1584
1585           Vector<Long> queuetovar=new Vector<Long>();
1586
1587           for(int i=0; i<invars.size(); i++) {
1588             TempDescriptor td=invars.get(i);
1589             Set<WaitingElement> weset=seseWaitingQueue.getWaitingElementSet(td);
1590
1591             //TODO FIX MEEEEE!!!!
1592             //Weset is sometimes null which breaks the following code and
1593             //we don't know what weset = null means. For now, we bail when it's null
1594             //until we find out what to do....
1595 //            if(weset == null) {
1596 //              continue;
1597 //            }
1598             //UPDATE: This hack DOES NOT FIX IT!.
1599
1600
1601
1602             int numqueues=0;
1603             Set<Integer> queueSet=new HashSet<Integer>();
1604             for (Iterator iterator = weset.iterator(); iterator.hasNext(); ) {
1605               WaitingElement we = (WaitingElement) iterator.next();
1606               Integer queueID=new Integer(we.getQueueID());
1607               if(!queueSet.contains(queueID)) {
1608                 numqueues++;
1609                 queueSet.add(queueID);
1610               }
1611             }
1612
1613             output.println("        seseToIssue->rcrRecords["+i+"].flag="+numqueues+";");
1614             output.println("        seseToIssue->rcrRecords["+i+"].index=0;");
1615             output.println("        seseToIssue->rcrRecords["+i+"].next=NULL;");
1616             output.println("        int dispCount"+i+"=0;");
1617
1618             for (Iterator<WaitingElement> wtit = weset.iterator(); wtit.hasNext(); ) {
1619               WaitingElement waitingElement = wtit.next();
1620               int queueID = waitingElement.getQueueID();
1621               if (queueID >= queuetovar.size())
1622                 queuetovar.setSize(queueID + 1);
1623               Long l = queuetovar.get(queueID);
1624               long val = (l != null)?l.longValue():0;
1625               val = val | (1 << i);
1626               queuetovar.set(queueID, new Long(val));
1627             }
1628           }
1629
1630           HashSet generatedqueueentry=new HashSet();
1631           for(int i=0; i<invars.size(); i++) {
1632             TempDescriptor td=invars.get(i);
1633             Set<WaitingElement> weset=seseWaitingQueue.getWaitingElementSet(td);
1634
1635
1636
1637             //TODO FIX MEEEEE!!!!
1638             //Weset is sometimes null which breaks the following code and
1639             //we don't know what weset = null means. For now, we bail when it's null
1640             //until we find out what to do....
1641 //            if(weset == null) {
1642 //              continue;
1643 //            }
1644             //UPDATE: This hack DOES NOT FIX IT!.
1645
1646
1647
1648             for(Iterator<WaitingElement> wtit=weset.iterator(); wtit.hasNext(); ) {
1649               WaitingElement waitingElement=wtit.next();
1650               int queueID=waitingElement.getQueueID();
1651
1652               if(waitingElement.isBogus()) {
1653                 continue;
1654               }
1655
1656               if (generatedqueueentry.contains(queueID))
1657                 continue;
1658               else
1659                 generatedqueueentry.add(queueID);
1660
1661               assert(waitingElement.getStatus()>=ConflictNode.COARSE);
1662               long mask=queuetovar.get(queueID);
1663               output.println("         rentry=mlpCreateREntry(runningSESE->memoryQueueArray["+ waitingElement.getQueueID()+ "]," + waitingElement.getStatus() + ", &(seseToIssue->common), "+mask+"LL);");
1664               output.println("         rentry->count=2;");
1665               output.println("         seseToIssue->common.rentryArray[seseToIssue->common.rentryIdx++]=rentry;");
1666               output.println("         rentry->queue=runningSESE->memoryQueueArray[" + waitingElement.getQueueID()+"];");
1667
1668               output.println("         if(ADDRENTRY(runningSESE->memoryQueueArray["+ waitingElement.getQueueID()+ "],rentry)==READY) {");
1669               for(int j=0; mask!=0; j++) {
1670                 if ((mask&1)==1)
1671                   output.println("            dispCount"+j+"++;");
1672                 mask=mask>>1;
1673               }
1674               output.println("         } else ");
1675               output.println("           refCount--;");
1676             }
1677
1678             if (newChild.getDynamicInVarSet().contains(td)) {
1679               // dynamic in-var case
1680               //output.println("       pointer=seseToIssue->"+waitingElement.getDynID()+
1681               //               "_srcSESE+seseToIssue->"+waitingElement.getDynID()+
1682               //               "_srcOffset;");
1683               //output.println("       rentry=mlpCreateFineREntry("+ waitingElement.getStatus()+
1684               //               ", &(seseToIssue->common),  pointer );");
1685             }
1686           }
1687           for(int i=0; i<invars.size(); i++) {
1688             output.println("       if(!dispCount"+i+" || !atomic_sub_and_test(dispCount"+i+",&(seseToIssue->rcrRecords["+i+"].flag)))");
1689             output.println("         localCount++;");
1690           }
1691           output.println("      } break;");
1692         }
1693       }
1694     }
1695
1696     output.println("     } // end switch");
1697
1698     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1699     output.println("  RELEASE_REFERENCES_TO((SESEcommon *)seseToIssue, refCount);");
1700     output.println("#endif");
1701   }
1702
1703
1704   public void generateFlatSESEExitNode(FlatMethod fm,
1705                                        FlatSESEExitNode fsexn,
1706                                        PrintWriter output) {
1707
1708     // get the enter node for this exit that has meta data embedded
1709     FlatSESEEnterNode fsen = fsexn.getFlatEnter();
1710
1711     // there may be an SESE in an unreachable method, skip over
1712     if( !oooa.getAllSESEs().contains(fsen) ) {
1713       return;
1714     }
1715
1716     // assert we are never generating code for the caller proxy
1717     // it should only appear in analysis results
1718     assert !fsen.getIsCallerProxySESE();
1719
1720
1721     if( state.COREPROF ) {
1722       output.println("#ifdef CP_EVENTID_TASKEXECUTE");
1723       output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_END );");
1724       output.println("#endif");
1725     }
1726
1727     output.println("   /* SESE exiting */");
1728
1729     if( state.COREPROF ) {
1730       output.println("#ifdef CP_EVENTID_TASKRETIRE");
1731       output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_BEGIN );");
1732       output.println("#endif");
1733     }
1734
1735
1736     // this SESE cannot be done until all of its children are done
1737     // so grab your own lock with the condition variable for watching
1738     // that the number of your running children is greater than zero
1739     output.println("   atomic_add(childSESE, &runningSESE->numRunningChildren);");
1740     output.println("   pthread_mutex_lock( &(runningSESE->lock) );");
1741     output.println("   if( runningSESE->numRunningChildren > 0 ) {");
1742     output.println("     stopforgc( (struct garbagelist *)&___locals___ );");
1743     output.println("     do {");
1744     output.println("       pthread_cond_wait( &(runningSESE->runningChildrenCond), &(runningSESE->lock) );");
1745     output.println("     } while( runningSESE->numRunningChildren > 0 );");
1746     output.println("     restartaftergc();");
1747     output.println("   }");
1748
1749
1750
1751     ////////////////////////////////////////
1752     // go through all out-vars and determine where to get them
1753     ////////////////////////////////////////
1754     output.println("   // copy ready out-set primitive variables from locals into record");
1755     Iterator<TempDescriptor> itr = fsen.getReadyOutVarSet().iterator();
1756     while( itr.hasNext() ) {
1757       TempDescriptor temp = itr.next();
1758
1759       // only have to do this for primitives, non-arrays
1760       if( !(
1761             temp.getType().isPrimitive() && !temp.getType().isArray()
1762             )
1763           ) {
1764         continue;
1765       }
1766
1767       String from = generateTemp(fsen.getfmBogus(), temp);
1768
1769       output.println("   "+paramsprefix+
1770                      "->"+temp.getSafeSymbol()+
1771                      " = "+from+";");
1772     }
1773
1774     // static vars are from a known SESE
1775     Iterator<TempDescriptor> tempItr;
1776     output.println("   // copy out-set from static sources");
1777     tempItr = fsen.getStaticOutVarSet().iterator();
1778     while( tempItr.hasNext() ) {
1779       TempDescriptor temp    = tempItr.next();
1780       VariableSourceToken vst     = fsen.getStaticOutVarSrc(temp);
1781       SESEandAgePair srcPair = new SESEandAgePair(vst.getSESE(), vst.getAge() );
1782       output.println("   "+paramsprefix+
1783                      "->"+temp.getSafeSymbol()+
1784                      " = "+paramsprefix+"->"+srcPair+"->"+vst.getAddrVar()+";");
1785     }
1786
1787     //output.println("   // decrement references to static sources");
1788     //for( Iterator<SESEandAgePair> pairItr = fsen.getStaticOutVarSrcs().iterator(); pairItr.hasNext(); ) {
1789     //  SESEandAgePair srcPair = pairItr.next();
1790     //  output.println("#ifndef OOO_DISABLE_TASKMEMPOOL" );
1791     //  output.println("   {");
1792     //  output.println("     SESEcommon* src = &("+paramsprefix+"->"+srcPair+"->common);");
1793     //  output.println("     RELEASE_REFERENCE_TO( src );");
1794     //  output.println("   }");
1795     //  output.println("#endif // OOO_DISABLE_TASKMEMPOOL" );
1796     //}
1797
1798     output.println("     // copy out-set from dynamic sources");
1799     tempItr = fsen.getDynamicOutVarSet().iterator();
1800     while( tempItr.hasNext() ) {
1801       TempDescriptor temp = tempItr.next();
1802       TypeDescriptor type = temp.getType();
1803
1804       // go grab it from the SESE source, when the source is NULL it is
1805       // this exiting task, so nothing to do!
1806       output.println("   if( "+temp+"_srcSESE != NULL ) {");
1807
1808       output.println("     "+paramsprefix+
1809                      "->"+temp.getSafeSymbol()+
1810                      " = *(void**)( (void*)"+
1811                      temp+"_srcSESE + "+
1812                      temp+"_srcOffset);");
1813
1814       //output.println("#ifndef OOO_DISABLE_TASKMEMPOOL" );
1815       //output.println("     SESEcommon* src = "+paramsprefix+"->"+temp+"_srcSESE;");
1816       //output.println("     RELEASE_REFERENCE_TO( src );");
1817       //output.println("#endif // OOO_DISABLE_TASKMEMPOOL" );
1818
1819       output.println("   }");
1820     }
1821
1822
1823
1824
1825     // mark yourself done, your task data is now read-only
1826     output.println("   runningSESE->doneExecuting = TRUE;");
1827
1828     // if parent is stalling on you, let them know you're done
1829     if( !fsen.getIsMainSESE() ) {
1830       output.println("   if( runningSESE->parentsStallSem != NULL ) {");
1831       output.println("     psem_give( runningSESE->parentsStallSem );");
1832       output.println("   }");
1833     }
1834
1835     output.println("   pthread_mutex_unlock( &(runningSESE->lock) );");
1836
1837     // decrement dependency count for all SESE's on your forwarding list
1838
1839     // FORWARD TODO
1840     output.println("   while( !isEmpty( &runningSESE->forwardList ) ) {");
1841     output.println("     SESEcommon* consumer = (SESEcommon*) getItem( &runningSESE->forwardList );");
1842
1843
1844     if (!state.RCR) {
1845       output.println("     if(consumer->rentryIdx>0){");
1846       output.println("        // resolved null pointer");
1847       output.println("        int idx;");
1848       output.println("        for(idx=0;idx<consumer->rentryIdx;idx++){");
1849       output.println("           resolvePointer(consumer->rentryArray[idx]);");
1850       output.println("        }");
1851       output.println("     }");
1852     }
1853
1854     output.println("     if( atomic_sub_and_test( 1, &(consumer->unresolvedDependencies) ) ){");
1855     output.println("       workScheduleSubmit( (void*)consumer );");
1856     output.println("     }");
1857     output.println("   }");
1858
1859
1860     // clean up its lock element from waiting queue, and decrement dependency count for next SESE block
1861     if( !fsen.getIsMainSESE() ) {
1862       output.println();
1863       output.println("   /* check memory dependency*/");
1864       output.println("  {");
1865       output.println("      int idx;");
1866       output.println("      for(idx=0;idx<___params___->common.rentryIdx;idx++){");
1867       output.println("           REntry* re=___params___->common.rentryArray[idx];");
1868       output.println("           RETIRERENTRY(re->queue,re);");
1869       output.println("      }");
1870       output.println("   }");
1871     }
1872
1873     Vector<TempDescriptor> inset=fsen.getInVarsForDynamicCoarseConflictResolution();
1874     if (state.RCR && inset.size() > 0) {
1875       /* Make sure the running SESE is finished */
1876       output.println("   if (unlikely(runningSESE->rcrstatus!=0)) {");
1877       output.println("     if(CAS(&runningSESE->rcrstatus,1,0)==2) {");
1878       output.println("       while(runningSESE->rcrstatus) {");
1879       output.println("         BARRIER();");
1880       output.println("         sched_yield();");
1881       output.println("       }");
1882       output.println("     }");
1883       output.println("   }");
1884       output.println("{");
1885       output.println("  int idx,idx2;");
1886
1887       output.println("    struct rcrRecord *rec;");
1888       output.println("    struct Hashtable_rcr ** hashstruct=runningSESE->parent->allHashStructures;");
1889
1890       for (int i = 0; i < inset.size(); i++) {
1891         output.println("    rec=&" + paramsprefix + "->rcrRecords[" + i + "];");
1892         output.println("    while(rec!=NULL) {");
1893         output.println("      for(idx2=0;idx2<rec->index;idx2++) {");
1894
1895         int weaklyConnectedComponentIndex = rcr.getWeakID(inset.get(i), fsen);
1896
1897         output.println("        rcr_RETIREHASHTABLE(hashstruct[" + weaklyConnectedComponentIndex
1898                        + "],&(___params___->common), rec->array[idx2], (BinItem_rcr *) rec->ptrarray[idx2]);");
1899
1900         output.println("      }"); // exit idx2 for loop
1901         output.println("      rec=rec->next;");
1902         output.println("    }"); // exit rec while loop
1903       }
1904       output.println("}");
1905     }
1906
1907
1908     // a task has variables to track static/dynamic instances
1909     // that serve as sources, release the parent's ref of each
1910     // non-null var of these types
1911     output.println("   // releasing static SESEs");
1912     output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1913
1914     ContextTaskNames contextTaskNames = oooa.getContextTaskNames(fsen);
1915
1916     Iterator<SESEandAgePair> pItr = contextTaskNames.getNeededStaticNames().iterator();
1917     while( pItr.hasNext() ) {
1918       SESEandAgePair pair = pItr.next();
1919       output.println("   if( "+pair+" != NULL ) {");
1920       output.println("     RELEASE_REFERENCE_TO( "+pair+" );");
1921       output.println("   }");
1922     }
1923     output.println("   // releasing dynamic variable sources");
1924     Iterator<TempDescriptor> dynSrcItr = contextTaskNames.getDynamicVarSet().iterator();
1925     while( dynSrcItr.hasNext() ) {
1926       TempDescriptor dynSrcVar = dynSrcItr.next();
1927       output.println("   if( "+dynSrcVar+"_srcSESE != NULL ) {");
1928       output.println("     RELEASE_REFERENCE_TO( "+dynSrcVar+"_srcSESE );");
1929       output.println("   }");
1930     }
1931
1932     // destroy this task's mempool if it is not a leaf task
1933     if( !fsen.getIsLeafSESE() ) {
1934       output.println("     pooldestroy( runningSESE->taskRecordMemPool );");
1935       if (state.RCR && fsen.getInVarsForDynamicCoarseConflictResolution().size() > 0 ) {
1936         output.println("     returnTR();");
1937       }
1938     }
1939     output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1940
1941
1942     output.println("{");
1943     output.println("SESEcommon *myparent=runningSESE->parent;");
1944
1945     // if this is not the Main sese (which has no parent) then return
1946     // THIS task's record to the PARENT'S task record pool, and only if
1947     // the reference count is now zero
1948     if( !fsen.getIsMainSESE() ) {
1949       output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
1950       output.println("   RELEASE_REFERENCE_TO( runningSESE );");
1951       output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
1952     } else {
1953       // the main task has no parent, just free its record
1954       output.println("   mlpFreeSESErecord( runningSESE );");
1955     }
1956
1957
1958     // last of all, decrement your parent's number of running children
1959     output.println("   if( myparent != NULL ) {");
1960     output.println("     if( atomic_sub_and_test( 1, &(myparent->numRunningChildren) ) ) {");
1961     output.println("       pthread_mutex_lock  ( &(myparent->lock) );");
1962     output.println("       pthread_cond_signal ( &(myparent->runningChildrenCond) );");
1963     output.println("       pthread_mutex_unlock( &(myparent->lock) );");
1964     output.println("     }");
1965     output.println("   }");
1966
1967     output.println("}");
1968
1969     // as this thread is wrapping up the task, make sure the thread-local var
1970     // for the currently running task record references an invalid task
1971     output.println("   runningSESE = (SESEcommon*) 0x1;");
1972
1973     if( state.COREPROF ) {
1974       output.println("#ifdef CP_EVENTID_TASKRETIRE");
1975       output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_END );");
1976       output.println("#endif");
1977     }
1978   }
1979
1980
1981   public void generateFlatWriteDynamicVarNode(FlatMethod fm,
1982                                               FlatWriteDynamicVarNode fwdvn,
1983                                               PrintWriter output
1984                                               ) {
1985
1986     Hashtable<TempDescriptor, VSTWrapper> writeDynamic = fwdvn.getVar2src();
1987
1988     assert writeDynamic != null;
1989
1990     Iterator wdItr = writeDynamic.entrySet().iterator();
1991     while( wdItr.hasNext() ) {
1992       Map.Entry me     = (Map.Entry)wdItr.next();
1993       TempDescriptor refVar = (TempDescriptor) me.getKey();
1994       VSTWrapper vstW   = (VSTWrapper)     me.getValue();
1995       VariableSourceToken vst    =                  vstW.vst;
1996
1997       output.println("     {");
1998       output.println("       SESEcommon* oldSrc = "+refVar+"_srcSESE;");
1999
2000       if( vst == null ) {
2001         // if there is no given source, this variable is ready so
2002         // mark src pointer NULL to signify that the var is up-to-date
2003         output.println("       "+refVar+"_srcSESE   = NULL;");
2004       } else {
2005         // otherwise we track where it will come from
2006         SESEandAgePair instance = new SESEandAgePair(vst.getSESE(), vst.getAge() );
2007         output.println("       "+refVar+"_srcSESE = "+instance+";");
2008         output.println("       "+refVar+"_srcOffset = (INTPTR) &((("+
2009                        vst.getSESE().getSESErecordName()+"*)0)->"+vst.getAddrVar()+");");
2010       }
2011
2012       // no matter what we did above, track reference count of whatever
2013       // this variable pointed to, do release last in case we're just
2014       // copying the same value in because 1->2->1 is safe but ref count
2015       // 1->0->1 has a window where it looks like it should be free'd
2016       output.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
2017       output.println("       if( "+refVar+"_srcSESE != NULL ) {");
2018       output.println("         ADD_REFERENCE_TO( "+refVar+"_srcSESE );");
2019       output.println("       }");
2020       output.println("       if( oldSrc != NULL ) {");
2021       output.println("         RELEASE_REFERENCE_TO( oldSrc );");
2022       output.println("       }");
2023       output.println("#endif // OOO_DISABLE_TASKMEMPOOL");
2024
2025       output.println("     }");
2026     }
2027   }
2028
2029
2030   protected void generateFlatNew(FlatMethod fm,
2031                                  FlatNew fn,
2032                                  PrintWriter output) {
2033
2034     if( fn.getType().isArray() ) {
2035       int arrayid = state.getArrayNumber(fn.getType() )+state.numClasses();
2036
2037       if( GENERATEPRECISEGC ) {
2038         output.println(generateTemp(fm, fn.getDst())+
2039                        "=allocate_newarray_mlp("+localsprefixaddr+
2040                        ", "+arrayid+", "+generateTemp(fm, fn.getSize())+
2041                        ", oid, "+
2042                        oooa.getDisjointAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+
2043                        ");");
2044         output.println("    oid += oidIncrement;");
2045       } else {
2046         output.println(generateTemp(fm, fn.getDst())+
2047                        "=allocate_newarray("+arrayid+
2048                        ", "+generateTemp(fm, fn.getSize())+
2049                        ");");
2050       }
2051
2052     } else {
2053       // not an array
2054       if( GENERATEPRECISEGC ) {
2055         output.println(generateTemp(fm, fn.getDst())+
2056                        "=allocate_new_mlp("+localsprefixaddr+
2057                        ", "+fn.getType().getClassDesc().getId()+
2058                        ", oid, "+
2059                        oooa.getDisjointAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+
2060                        ");");
2061         output.println("    oid += oidIncrement;");
2062       } else {
2063         output.println(generateTemp(fm, fn.getDst())+
2064                        "=allocate_new("+fn.getType().getClassDesc().getId()+
2065                        ");");
2066       }
2067     }
2068   }
2069
2070
2071   private int calculateSizeOfSESEParamList(FlatSESEEnterNode fsen) {
2072
2073     Set<TempDescriptor> tdSet=new HashSet<TempDescriptor>();
2074
2075     for (Iterator iterator = fsen.getInVarSet().iterator(); iterator.hasNext(); ) {
2076       TempDescriptor tempDescriptor = (TempDescriptor) iterator.next();
2077       if(!tempDescriptor.getType().isPrimitive() || tempDescriptor.getType().isArray()) {
2078         tdSet.add(tempDescriptor);
2079       }
2080     }
2081
2082     for (Iterator iterator = fsen.getOutVarSet().iterator(); iterator.hasNext(); ) {
2083       TempDescriptor tempDescriptor = (TempDescriptor) iterator.next();
2084       if(!tempDescriptor.getType().isPrimitive() || tempDescriptor.getType().isArray()) {
2085         tdSet.add(tempDescriptor);
2086       }
2087     }
2088
2089     return tdSet.size();
2090   }
2091
2092
2093   private String calculateSizeOfSESEParamSize(FlatSESEEnterNode fsen) {
2094     HashMap <String,Integer> map=new HashMap();
2095     HashSet <TempDescriptor> processed=new HashSet<TempDescriptor>();
2096     String rtr="";
2097
2098     // space for all in and out set primitives
2099     Set<TempDescriptor> inSetAndOutSet = new HashSet<TempDescriptor>();
2100     inSetAndOutSet.addAll(fsen.getInVarSet() );
2101     inSetAndOutSet.addAll(fsen.getOutVarSet() );
2102
2103     Set<TempDescriptor> inSetAndOutSetPrims = new HashSet<TempDescriptor>();
2104
2105     Iterator<TempDescriptor> itr = inSetAndOutSet.iterator();
2106     while( itr.hasNext() ) {
2107       TempDescriptor temp = itr.next();
2108       TypeDescriptor type = temp.getType();
2109       if( !type.isPtr() ) {
2110         inSetAndOutSetPrims.add(temp);
2111       }
2112     }
2113
2114     Iterator<TempDescriptor> itrPrims = inSetAndOutSetPrims.iterator();
2115     while( itrPrims.hasNext() ) {
2116       TempDescriptor temp = itrPrims.next();
2117       TypeDescriptor type = temp.getType();
2118       if(type.isPrimitive()) {
2119         Integer count=map.get(type.getSymbol());
2120         if(count==null) {
2121           count=new Integer(1);
2122           map.put(type.getSymbol(), count);
2123         } else {
2124           map.put(type.getSymbol(), new Integer(count.intValue()+1));
2125         }
2126       }
2127     }
2128
2129     Set<String> keySet=map.keySet();
2130     for (Iterator iterator = keySet.iterator(); iterator.hasNext(); ) {
2131       String key = (String) iterator.next();
2132       rtr+="+sizeof("+key+")*"+map.get(key);
2133     }
2134     return rtr;
2135   }
2136
2137 }