3 import java.io.FileNotFoundException;
4 import java.util.ArrayList;
5 import java.util.HashSet;
6 import java.util.Hashtable;
7 import java.util.Iterator;
9 import java.util.Vector;
11 import Analysis.Disjoint.*;
13 import IR.TypeDescriptor;
14 import Analysis.OoOJava.ConflictGraph;
15 import Analysis.OoOJava.ConflictNode;
16 import Analysis.OoOJava.OoOJavaAnalysis;
17 import Analysis.OoOJava.SESELock;
18 import Analysis.OoOJava.WaitingElement;
19 import Analysis.OoOJava.CodePlan;
20 import Util.CodePrinter;
22 /* An instance of this class manages all OoOJava coarse-grained runtime conflicts
23 * by generating C-code to either rule out the conflict at runtime or resolve one.
26 * 1) Instantiate singleton object (String input is to specify output dir)
27 * 2) Call setGlobalEffects setGlobalEffects(Hashtable<Taint, Set<Effect>> ) ONCE
28 * 3) Input SESE blocks, for each block:
29 * 3a) call addToTraverseToDoList(FlatSESEEnterNode , ReachGraph , Hashtable<Taint, Set<Effect>>) for the seseBlock
30 * 3b) call String getTraverserInvocation(TempDescriptor, String, FlatSESEEnterNode) to get the name of the traverse method in C
31 * 4) Call void close()
32 * Note: All computation is done upon closing the object. Steps 1-3 only input data
34 public class RuntimeConflictResolver {
35 //Shows weakly connected heaproots and which allocation sites were considered for traversal
36 private boolean generalDebug = false;
38 //Prints out effects passed in, internal representation of effects, and internal representation of reach graph
39 private boolean verboseDebug = false;
41 private CodePrinter headerFile, cFile;
42 private static final String hashAndQueueCFileDir = "oooJava/";
44 //This keeps track of taints we've traversed to prevent printing duplicate traverse functions
45 //The Integer keeps track of the weakly connected group it's in (used in enumerateHeapRoots)
46 private Hashtable<Taint, Integer> doneTaints;
47 private Hashtable<Pair, Integer> idMap=new Hashtable<Pair,Integer>();
48 private Hashtable<Pair, Integer> weakMap=new Hashtable<Pair,Integer>();
49 private Hashtable<Taint, Set<Effect>> globalEffects;
50 private Hashtable<Taint, Set<Effect>> globalConflicts;
52 private ArrayList<TraversalInfo> traverserTODO;
54 // Hashtable provides fast access to heaproot # lookups
55 private Hashtable<Taint, WeaklyConectedHRGroup> connectedHRHash;
56 private ArrayList<WeaklyConectedHRGroup> num2WeaklyConnectedHRGroup;
57 private int traverserIDCounter;
58 public int currentID=1;
59 private int weaklyConnectedHRCounter;
60 private ArrayList<TaintAndInternalHeapStructure> pendingPrintout;
61 private EffectsTable effectsLookupTable;
62 private OoOJavaAnalysis oooa;
65 // initializing variables can be found in printHeader()
66 private static final String getAllocSiteInC = "->allocsite";
67 private static final String queryVistedHashtable = "hashRCRInsert";
68 private static final String addToQueueInC = "enqueueRCRQueue(";
69 private static final String dequeueFromQueueInC = "dequeueRCRQueue()";
70 private static final String clearQueue = "resetRCRQueue()";
71 // Make hashtable; hashRCRCreate(unsigned int size, double loadfactor)
72 private static final String mallocVisitedHashtable = "hashRCRCreate(128, 0.75)";
73 private static final String deallocVisitedHashTable = "hashRCRDelete()";
74 private static final String resetVisitedHashTable = "hashRCRreset()";
78 * 1) Get global effects and conflicts
79 * 2) Create a hash structure (EffectsTable) to manage effects (hashed by affected Allocsite, then taint, then field)
80 * 2a) Use Effects to verify we can access something (reads)
81 * 2b) Use conflicts to mark conflicts (read/write/strongupdate)
82 * 2c) At second level of hash, store Heaproots that can cause conflicts at the field
83 * 3) Walk hash structure to identify and enumerate weakly connected groups
84 * 4) Build internal representation of the rgs (pruned)
85 * 5) Print c methods by walking internal representation
87 public RuntimeConflictResolver(String buildir, OoOJavaAnalysis oooa, Hashtable<Taint, Set<Effect>> globalEffects, State state)
88 throws FileNotFoundException {
91 this.generalDebug = state.RCR_DEBUG || state.RCR_DEBUG_VERBOSE;
92 this.verboseDebug = state.RCR_DEBUG_VERBOSE;
94 doneTaints = new Hashtable<Taint, Integer>();
95 connectedHRHash = new Hashtable<Taint, WeaklyConectedHRGroup>();
96 pendingPrintout = new ArrayList<TaintAndInternalHeapStructure>();
97 traverserTODO = new ArrayList<TraversalInfo>();
98 globalConflicts = new Hashtable<Taint, Set<Effect>>();
99 //Note: globalEffects is not instantiated since it'll be passed in whole while conflicts comes in chunks
101 traverserIDCounter = 1;
102 weaklyConnectedHRCounter = 0;
104 //note: the order below MATTERS
105 setupOutputFiles(buildir);
106 setGlobalEffects(globalEffects);
107 getAllTasksAndConflicts();
108 buildEffectsLookupStructure();
109 createInternalGraphs();
110 //After the internal graphs are created, we can print,
111 //but printing is done in close();
114 private void setupOutputFiles(String buildir) throws FileNotFoundException {
115 cFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".c"));
116 headerFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".h"));
118 cFile.println("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
119 + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>");
120 cFile.println("#include \"classdefs.h\"");
121 cFile.println("#include \"structdefs.h\"");
122 cFile.println("#include \"mlp_runtime.h\"");
123 cFile.println("#include \"RuntimeConflictResolver.h\"");
124 cFile.println("#include \"hashStructure.h\"");
126 headerFile.println("#ifndef __3_RCR_H_");
127 headerFile.println("#define __3_RCR_H_");
130 private void setGlobalEffects(Hashtable<Taint, Set<Effect>> effects) {
131 globalEffects = effects;
134 System.out.println("============EFFECTS LIST AS PASSED IN============");
135 for(Taint t: globalEffects.keySet()) {
136 System.out.println("For Taint " + t);
137 for(Effect e: globalEffects.get(t)) {
138 System.out.println("\t" + e);
141 System.out.println("====================END LIST====================");
145 private void getAllTasksAndConflicts() {
146 FlatSESEEnterNode fsen;
147 FlatSESEEnterNode parentSESE;
148 ConflictGraph conflictGraph;
150 Hashtable<Taint, Set<Effect>> conflicts;
151 DisjointAnalysis disjointAnaylsis = oooa.getDisjointAnalysis();
153 //Go through the SESE's
154 printDebug(generalDebug, "======================SESE's======================");
155 for(Iterator<FlatSESEEnterNode> seseit = oooa.getAllSESEs().iterator();seseit.hasNext();) {
156 fsen = seseit.next();
158 if ( fsen.getParents().size() > 0 &&
159 (parentSESE = (FlatSESEEnterNode) fsen.getParents().iterator().next()) != null &&
160 (conflictGraph = oooa.getConflictGraph(parentSESE)) != null &&
161 (conflicts = conflictGraph.getConflictEffectSet(fsen)) != null &&
162 (rg = disjointAnaylsis.getEnterReachGraph(fsen)) != null ){
164 addToTraverseToDoList(fsen, rg, conflicts, conflictGraph);
167 printDebug(generalDebug, "==================END SESE LIST==================");
170 // Go through the stall sites
171 for(Iterator<FlatNode> codeit = oooa.getNodesWithPlans().iterator();codeit.hasNext();){
172 FlatNode fn = codeit.next();
173 CodePlan cp = oooa.getCodePlan(fn);
174 fsen = cp.getCurrentSESE();
176 if( fsen.getParents().size() != 0 &&
177 (conflictGraph = oooa.getConflictGraph(fsen)) != null &&
178 (conflicts = conflictGraph.getConflictEffectSet(fn)) != null &&
179 (rg = disjointAnaylsis.getEnterReachGraph(fn)) != null ){
181 Set<SESELock> seseLockSet = oooa.getLockMappings(conflictGraph);
182 Set<WaitingElement> waitingElementSet =
183 conflictGraph.getStallSiteWaitingElementSet(fn, seseLockSet);
185 if (waitingElementSet.size() > 0) {
186 for (Iterator<WaitingElement> iterator = waitingElementSet.iterator(); iterator.hasNext();) {
188 WaitingElement waitingElement = (WaitingElement) iterator.next();
189 addToTraverseToDoList(fn, waitingElement.getTempDesc(), rg, conflicts);
196 public void addToTraverseToDoList(FlatSESEEnterNode rblock,
198 Hashtable<Taint, Set<Effect>> conflicts,
199 ConflictGraph conflictGraph) {
201 traverserTODO.add(new TraversalInfo(rblock, rg));
202 addToGlobalConflicts(conflicts);
205 System.out.println(rblock);
206 System.out.println(rblock.getParents());
207 System.out.println("CG=" + conflictGraph);
209 rg.writeGraph("RCR_RG_SESE_DEBUG"+removeInvalidChars(rblock.getPrettyIdentifier()));
213 public void addToTraverseToDoList(FlatNode fn,
214 TempDescriptor tempDesc,
216 Hashtable<Taint, Set<Effect>> conflicts)
218 traverserTODO.add(new TraversalInfo(fn, rg, tempDesc));
219 addToGlobalConflicts(conflicts);
222 rg.writeGraph("RCR_RG_STALLSITE_DEBUG"+removeInvalidChars(fn.toString()));
225 private void addToGlobalConflicts(Hashtable<Taint, Set<Effect>> conflicts) {
226 for(Taint t: conflicts.keySet()) {
227 if(globalConflicts.containsKey(t)) {
228 globalConflicts.get(t).addAll(conflicts.get(t));
230 globalConflicts.put(t, conflicts.get(t));
235 //Builds Effects Table and runs the analysis on them to get weakly connected HRs
236 //SPECIAL NOTE: Only runs after we've taken all the conflicts and effects (via getAllTasksAndConflicts)
237 private void buildEffectsLookupStructure(){
238 effectsLookupTable = new EffectsTable(globalEffects, globalConflicts);
239 effectsLookupTable.runAnalysis();
240 enumerateHeaproots();
243 private void createInternalGraphs() {
244 for(TraversalInfo t: traverserTODO) {
245 printDebug(generalDebug, "Running Traversal on " + t.f);
247 //Runs stallsite graph creation
248 if(t.isStallSite()) {
249 assert t.invar != null;
250 createTraversalGraph(t.f, t.invar, t.rg);
252 //runs rblock graph creation
254 FlatSESEEnterNode rblock = (FlatSESEEnterNode)t.f;
256 for (TempDescriptor invar : rblock.getInVarSet()) {
257 createTraversalGraph(rblock, invar, t.rg);
263 //This method creates an pruned version of the reach graph using effects
264 //The graph ultimately steers the the runtime traverser and is used to generate output code
265 private void createTraversalGraph(FlatNode fn, TempDescriptor invar, ReachGraph rg) {
266 //"created" maps allocation site to RuntimeObjNode; keeps track of which parts of rg are visited.
267 Hashtable<Integer, ConcreteRuntimeObjNode> created;
268 VariableNode varNode = rg.getVariableNodeNoMutation(invar);
269 Taint taint = getProperTaintForEnterNode(fn, varNode);
271 if (taint == null || invar.getType() == null || isReallyAPrimitive(invar.getType())) {
272 printDebug(generalDebug, "Site " +varNode.getTempDescriptor().getSafeSymbol() + fn.toString() + " not traversed");
276 //If already done, don't need to redoit.
277 if(doneTaints.containsKey(taint))
280 created = new Hashtable<Integer, ConcreteRuntimeObjNode>(); //Pass 0: Create empty graph
281 createPrunedGraph(created, varNode, taint); //Pass 1: Create graph pruned graph
282 propagateConflicts(created); //Pass 2: Flag referencers with conflicts
284 //If there are valid nodes, add to printout queue
285 if (!created.isEmpty()) {
286 pendingPrintout.add(new TaintAndInternalHeapStructure(taint, created));
288 //IF is SESE we need to tell the EnterNode that it has a traverser waiting for it.
289 if(fn instanceof FlatSESEEnterNode) {
290 for(Iterator<ConcreteRuntimeObjNode> it=created.values().iterator();it.hasNext();) {
291 ConcreteRuntimeObjNode obj=it.next();
292 if (obj.hasConflict() || obj.hasPrimitiveConflicts()){
293 ((FlatSESEEnterNode) fn).addInVarForDynamicCoarseConflictResolution(invar);
300 doneTaints.put(taint, traverserIDCounter++);
303 //This is Pass 1 of internal graph creation.
304 private void createPrunedGraph(
305 Hashtable<Integer, ConcreteRuntimeObjNode> created,
306 VariableNode varNode,
308 // For every inset HRN, create a graph node, and run a DFT (buildPrunedGraphFromRG)
309 Iterator<RefEdge> possibleEdges = varNode.iteratorToReferencees();
310 while (possibleEdges.hasNext()) {
311 RefEdge edge = possibleEdges.next();
314 ConcreteRuntimeObjNode singleRoot = new ConcreteRuntimeObjNode(edge.getDst(), true);
315 int rootKey = singleRoot.allocSite.getUniqueAllocSiteID();
317 if (!created.containsKey(rootKey)) {
318 created.put(rootKey, singleRoot);
319 buildPrunedGraphFromRG(singleRoot, edge.getDst().iteratorToReferencees(), created, t);
324 //Performs Depth First Traversal on the ReachGraph to build an
325 //internal representation of it. It prunes ptrs not reachable
326 //by read Effects and stores in each node the effects by it.
327 private void buildPrunedGraphFromRG( ConcreteRuntimeObjNode curr,
328 Iterator<RefEdge> edges,
329 Hashtable<Integer, ConcreteRuntimeObjNode> created,
331 EffectsGroup currEffects = effectsLookupTable.getEffects(curr.allocSite, taint);
333 if (currEffects == null || currEffects.isEmpty())
336 //Update parent flags for primitive accesses
337 curr.primConfRead |= currEffects.primConfRead;
338 curr.primConfWrite |= currEffects.primConfWrite;
340 //Handle non-primitive references by creating a node for each reference
341 //and updating the parent's conflict flags. If child is reachable through
342 //a read effect, it recursively calls this function.
343 if(currEffects.hasObjectEffects()) {
344 while(edges.hasNext()) {
345 RefEdge edge = edges.next();
346 String field = edge.getField();
347 CombinedEffects effectsForGivenField = currEffects.getObjEffect(field);
349 //If there are no effects, then there's no point in traversing this edge
350 if(effectsForGivenField != null) {
351 HeapRegionNode childHRN = edge.getDst();
352 int childKey = childHRN.getAllocSite().getUniqueAllocSiteID();
353 boolean isNewChild = !created.containsKey(childKey);
354 ConcreteRuntimeObjNode child;
357 child = new ConcreteRuntimeObjNode(childHRN, false); //false = not inset
358 created.put(childKey, child);
360 child = created.get(childKey);
363 ObjRef reference = new ObjRef(field, curr, child, effectsForGivenField);
364 curr.addReferencee(field, reference);
366 //update parent flags
367 curr.objConfRead |= effectsForGivenField.hasReadConflict;
368 curr.objConfWrite |= effectsForGivenField.hasWriteConflict;
370 //Update flags and recurse
371 if(effectsForGivenField.hasReadEffect) {
372 child.hasPotentialToBeIncorrectDueToConflict |= effectsForGivenField.hasReadConflict;
373 child.addReferencer(reference);
376 buildPrunedGraphFromRG(child, childHRN.iteratorToReferencees(), created, taint);
384 //Performs a reverse traversal from the conflict nodes up to the
385 //inset variables and sets conflict flags on inner nodes.
386 private void propagateConflicts(Hashtable<Integer, ConcreteRuntimeObjNode> created) {
387 for(ConcreteRuntimeObjNode node: created.values()) {
388 if(node.hasConflict()) {
389 markReferencers(node, node.objConfRead || node.objConfWrite, node.primConfRead || node.primConfWrite);
394 private void markReferencers(ConcreteRuntimeObjNode node, boolean ObjConf, boolean PrimConf) {
395 for(ObjRef ref: node.referencers) {
396 //if not already marked or data does not match
397 if(!ref.reachesConflict ||
398 (ObjConf && !ref.parent.descendantsObjConflict) ||
399 (PrimConf && !ref.parent.descendantsPrimConflict)) {
401 ref.parent.descendantsObjConflict |= ObjConf;
402 ref.parent.descendantsPrimConflict |= PrimConf;
403 ref.reachesConflict = true;
404 markReferencers(ref.parent, ObjConf, PrimConf);
409 //This extends a tempDescriptor's isPrimitive test by also excluding primitive arrays.
410 private boolean isReallyAPrimitive(TypeDescriptor type) {
411 return (type.isPrimitive() && !type.isArray());
414 //The official way to generate the name for a traverser call
415 public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
417 if(fn instanceof FlatSESEEnterNode) { //is SESE block
418 flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
419 } else { //is stallsite
420 flatname = fn.toString();
423 return "traverse___" + invar.getSafeSymbol() +
424 removeInvalidChars(flatname) + "___("+varString+");";
427 public String removeInvalidChars(String in) {
428 StringBuilder s = new StringBuilder(in);
429 for(int i = 0; i < s.length(); i++) {
430 if(s.charAt(i) == ' ' ||
431 s.charAt(i) == '.' ||
432 s.charAt(i) == '=' ||
433 s.charAt(i) == '[' ||
434 s.charAt(i) == ']' ) {
443 public int getWeakID(TempDescriptor invar, FlatNode fn) {
444 return weakMap.get(new Pair(invar, fn)).intValue();
447 public int getTraverserID(TempDescriptor invar, FlatNode fn) {
448 Pair t=new Pair(invar, fn);
449 if (idMap.containsKey(t))
450 return idMap.get(t).intValue();
451 int value=currentID++;
452 idMap.put(t, new Integer(value));
457 public void close() {
458 //prints the traversal code
459 for(TaintAndInternalHeapStructure ths: pendingPrintout) {
460 printCMethod(ths.nodesInHeap, ths.t);
463 //Prints out the master traverser Invocation that'll call all other traversers
464 //based on traverserID
465 printMasterTraverserInvocation();
466 createMasterHashTableArray();
468 // Adds Extra supporting methods
469 cFile.println("void initializeStructsRCR() {\n " + mallocVisitedHashtable + ";\n " + clearQueue + ";\n}");
470 cFile.println("void destroyRCR() {\n " + deallocVisitedHashTable + ";\n}");
472 headerFile.println("void initializeStructsRCR();\nvoid destroyRCR();");
473 headerFile.println("#endif\n");
479 private void createMasterHashTableArray() {
480 headerFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray();");
481 cFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray() {");
482 cFile.println(" struct Hashtable_rcr **table=rcr_createMasterHashTableArray("+weaklyConnectedHRCounter + ");");
484 for(int i = 0; i < weaklyConnectedHRCounter; i++) {
485 cFile.println(" table["+i+"] = (struct Hashtable_rcr *) rcr_createHashtable();");
487 cFile.println(" return table;");
491 private void printMasterTraverserInvocation() {
492 headerFile.println("\nint tasktraverse(SESEcommon * record);");
493 cFile.println("\nint tasktraverse(SESEcommon * record) {");
494 cFile.println(" if(!CAS(&record->rcrstatus,1,2)) {");
496 //release traverser reference...no traversal necessary
497 cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
498 cFile.println(" RELEASE_REFERENCE_TO(record);");
499 cFile.println("#endif");
501 cFile.println(" return;");
503 cFile.println(" switch(record->classID) {");
505 for(Iterator<FlatSESEEnterNode> seseit=oooa.getAllSESEs().iterator();seseit.hasNext();) {
506 FlatSESEEnterNode fsen=seseit.next();
507 cFile.println( " /* "+fsen.getPrettyIdentifier()+" */");
508 cFile.println( " case "+fsen.getIdentifier()+": {");
509 cFile.println( " "+fsen.getSESErecordName()+" * rec=("+fsen.getSESErecordName()+" *) record;");
510 Vector<TempDescriptor> invars=fsen.getInVarsForDynamicCoarseConflictResolution();
511 for(int i=0;i<invars.size();i++) {
512 TempDescriptor tmp=invars.get(i);
514 // FIX IT LATER! Right now, we assume that there is only one parent
515 // JCJ ask yong hun what we should do in the multi-parent future!
516 FlatSESEEnterNode parentSESE = (FlatSESEEnterNode) fsen.getParents().iterator().next();
517 ConflictGraph graph = oooa.getConflictGraph(parentSESE);
518 String id = tmp + "_sese" + fsen.getPrettyIdentifier();
519 ConflictNode node = graph.getId2cn().get(id);
522 cFile.println(" if (record->rcrstatus!=0)");
525 if(state.NOSTALLTR && node.IsValidToPrune()){
526 cFile.println(" /* " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen)+"*/");
528 cFile.println(" " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
532 //release traverser reference...traversal finished...
533 //executing thread will clean bins for us
534 cFile.println(" record->rcrstatus=0;");
535 cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
536 cFile.println(" RELEASE_REFERENCE_TO(record);");
537 cFile.println("#endif");
538 cFile.println( " }");
539 cFile.println( " break;");
542 for(Taint t: doneTaints.keySet()) {
543 if (t.isStallSiteTaint()){
544 cFile.println( " case -" + getTraverserID(t.getVar(), t.getStallSite())+ ": {");
545 cFile.println( " SESEstall * rec=(SESEstall*) record;");
546 cFile.println( " " + this.getTraverserInvocation(t.getVar(), "rec->___obj___, rec", t.getStallSite())+";");
547 cFile.println( " record->rcrstatus=0;");
548 cFile.println( " }");
549 cFile.println(" break;");
553 cFile.println(" default:\n printf(\"Invalid SESE ID was passed in: %d.\\n\",record->classID);\n break;");
559 //Currently UNUSED method but may be useful in the future.
560 //This will print the traverser invocation that takes in a traverserID and starting ptr
561 private void printResumeTraverserInvocation() {
562 headerFile.println("\nint traverse(void * startingPtr, SESEcommon * record, int traverserID);");
563 cFile.println("\nint traverse(void * startingPtr, SESEcommon *record, int traverserID) {");
564 cFile.println(" switch(traverserID) {");
566 for(Taint t: doneTaints.keySet()) {
567 cFile.println(" case " + doneTaints.get(t)+ ":");
568 if(t.isRBlockTaint()) {
569 cFile.println(" " + this.getTraverserInvocation(t.getVar(), "startingPtr, ("+t.getSESE().getSESErecordName()+" *)record", t.getSESE()));
570 } else if (t.isStallSiteTaint()){
571 // JCJ either remove this or consider writing a comment explaining what it is commented out for
572 cFile.println("/* " + this.getTraverserInvocation(t.getVar(), "startingPtr, record", t.getStallSite())+"*/");
574 System.out.println("RuntimeConflictResolver encountered a taint that is neither SESE nor stallsite: " + t);
576 cFile.println(" break;");
579 cFile.println(" default:\n break;");
587 * This method generates a C method for every inset variable and rblock.
589 * The C method works by generating a large switch statement that will run the appropriate
590 * checking code for each object based on its allocation site. The switch statement is
591 * surrounded by a while statement which dequeues objects to be checked from a queue. An
592 * object is added to a queue only if it contains a conflict (in itself or in its referencees)
593 * and we came across it while checking through it's referencer. Because of this property,
594 * conflicts will be signaled by the referencer; the only exception is the inset variable which can
595 * signal a conflict within itself.
598 private void printCMethod(Hashtable<Integer, ConcreteRuntimeObjNode> created, Taint taint) {
599 String inVar = taint.getVar().getSafeSymbol();
602 if(taint.isStallSiteTaint()) {
603 rBlock = taint.getStallSite().toString();
604 } else if(taint.isRBlockTaint()) {
605 rBlock = taint.getSESE().getPrettyIdentifier();
607 System.out.println("RCR CRITICAL ERROR: TAINT IS NEITHER A STALLSITE NOR SESE! " + taint.toString());
611 //This hash table keeps track of all the case statements generated.
612 Hashtable<AllocSite, StringBuilder> cases = new Hashtable<AllocSite, StringBuilder>();
615 for (ConcreteRuntimeObjNode node : created.values()) {
616 printDebug(generalDebug, "Considering " + node.allocSite + " for traversal");
617 if (!cases.containsKey(node.allocSite) && qualifiesForCaseStatement(node)) {
618 printDebug(generalDebug, "+\t" + node.allocSite + " qualified for case statement");
619 addChecker(taint, node, cases, null, "ptr", 0);
626 if (taint.isStallSiteTaint()) {
627 methodName= "void traverse___" + inVar + removeInvalidChars(rBlock) + "___(void * InVar, SESEstall *record)";
629 methodName= "void traverse___" + inVar + removeInvalidChars(rBlock) + "___(void * InVar, "+taint.getSESE().getSESErecordName() +" *record)";
630 FlatSESEEnterNode fsese=taint.getSESE();
631 TempDescriptor tmp=taint.getVar();
632 index=fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
635 cFile.println(methodName + " {");
636 headerFile.println(methodName + ";");
638 if(cases.size() == 0) {
639 cFile.println(" return;");
641 cFile.println(" int totalcount=RUNBIAS;");
642 if (taint.isStallSiteTaint()) {
643 cFile.println(" record->rcrRecords[0].count=RUNBIAS;");
645 cFile.println(" record->rcrRecords["+index+"].count=RUNBIAS;");
648 //clears queue and hashtable that keeps track of where we've been.
649 cFile.println(clearQueue + ";\n" + resetVisitedHashTable + ";");
650 //generic cast to ___Object___ to access ptr->allocsite field.
651 cFile.println("struct ___Object___ * ptr = (struct ___Object___ *) InVar;\nif (InVar != NULL) {\n " + queryVistedHashtable + "(ptr);\n do {");
652 if (taint.isRBlockTaint()) {
653 cFile.println(" if(unlikely(record->common.doneExecuting)) {");
654 cFile.println(" record->common.rcrstatus=0;");
655 cFile.println(" return;");
658 cFile.println(" switch(ptr->allocsite) {");
660 for(AllocSite singleCase: cases.keySet()) {
661 cFile.append(cases.get(singleCase));
664 cFile.println(" default:\n break; ");
665 cFile.println(" }\n } while((ptr = " + dequeueFromQueueInC + ") != NULL);\n}");
667 if (taint.isStallSiteTaint()) {
669 cFile.println(" if(atomic_sub_and_test(totalcount,&(record->rcrRecords[0].count))) {");
670 cFile.println(" psem_give_tag(record->common.parentsStallSem, record->tag);");
671 cFile.println(" BARRIER();");
674 cFile.println(" if(atomic_sub_and_test(totalcount,&(record->rcrRecords["+index+"].count))) {");
675 cFile.println(" int flag=LOCKXCHG32(&(record->rcrRecords["+index+"].flag),0);");
676 cFile.println(" if(flag) {");
677 //we have resolved a heap root...see if this was the last dependence
678 cFile.println(" if(atomic_sub_and_test(1, &(record->common.unresolvedDependencies))) workScheduleSubmit((void *)record);");
688 * addChecker creates a case statement for every object that is an inset variable, has more
689 * than 1 parent && has conflicts, or where resumes are possible
690 * See .qualifiesForCaseStatement
692 private void addChecker(Taint taint,
693 ConcreteRuntimeObjNode node,
694 Hashtable<AllocSite,StringBuilder> cases,
695 StringBuilder possibleContinuingCase,
698 StringBuilder currCase = possibleContinuingCase;
699 if(qualifiesForCaseStatement(node)) {
700 assert prefix.equals("ptr");
701 assert !cases.containsKey(node.allocSite);
702 currCase = new StringBuilder();
703 cases.put(node.allocSite, currCase);
704 currCase.append(" case " + node.allocSite.getUniqueAllocSiteID() + ": {\n");
706 //either currCase is continuing off a parent case or is its own.
707 assert currCase !=null;
709 insertEntriesIntoHashStructure(taint, node, prefix, depth, currCase);
711 //Handle conflicts further down.
712 if(node.descendantsConflict()) {
714 currCase.append("{\n");
718 String childPtr = "((struct ___Object___ **)(((char *) &(((struct ArrayObject *)"+ prefix+")->___length___))+sizeof(int)))[i]";
719 String currPtr = "arrayElement" + pdepth;
721 currCase.append("{\n int i;\n");
722 currCase.append(" struct ___Object___ * "+currPtr+";\n");
723 currCase.append(" for(i = 0; i<((struct ArrayObject *) " + prefix + " )->___length___; i++ ) {\n");
725 //There should be only one field, hence we only take the first field in the keyset.
726 assert node.referencees.keySet().size() <= 1;
727 ObjRefList refsAtParticularField = node.referencees.get(node.referencees.keySet().iterator().next());
728 printObjRefSwitchStatement(taint,cases,pdepth,currCase,refsAtParticularField,childPtr,currPtr);
729 currCase.append(" }}\n");
732 String currPtr = "myPtr" + pdepth;
733 currCase.append(" struct ___Object___ * "+currPtr+";\n");
734 for(String field: node.referencees.keySet()) {
735 ObjRefList refsAtParticularField = node.referencees.get(field);
737 if(refsAtParticularField.hasConflicts()) {
738 String childPtr = "((struct "+node.original.getType().getSafeSymbol()+" *)"+prefix +")->___" + field + "___";
739 printObjRefSwitchStatement(taint,cases, pdepth, currCase, refsAtParticularField, childPtr, currPtr);
744 currCase.append("}\n"); //For particular top level case statement.
746 if(qualifiesForCaseStatement(node)) {
747 currCase.append(" }\n break;\n");
751 private void insertEntriesIntoHashStructure(Taint taint, ConcreteRuntimeObjNode curr,
752 String prefix, int depth, StringBuilder currCase) {
755 if (taint.isRBlockTaint()) {
756 FlatSESEEnterNode fsese=taint.getSESE();
757 TempDescriptor tmp=taint.getVar();
758 index=fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
761 String strrcr=taint.isRBlockTaint()?"&record->rcrRecords["+index+"], ":"NULL, ";
762 String tasksrc=taint.isRBlockTaint()?"(SESEcommon *) record, ":"(SESEcommon *)(((INTPTR)record)|1LL), ";
764 //Do call if we need it.
765 if(curr.primConfWrite||curr.objConfWrite) {
766 int heaprootNum = connectedHRHash.get(taint).id;
767 assert heaprootNum != -1;
768 currCase.append(" int tmpkey"+depth+"=rcr_generateKey("+prefix+");\n");
769 if (curr.descendantsConflict())
770 currCase.append(" int tmpvar"+depth+"=rcr_WTWRITEBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", "+tasksrc+strrcr+index+");\n");
772 currCase.append(" int tmpvar"+depth+"=rcr_WRITEBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", "+ tasksrc+strrcr+index+");\n");
773 } else if (curr.primConfRead||curr.objConfRead) {
774 int heaprootNum = connectedHRHash.get(taint).id;
775 assert heaprootNum != -1;
776 currCase.append(" int tmpkey"+depth+"=rcr_generateKey("+prefix+");\n");
777 if (curr.descendantsConflict())
778 currCase.append(" int tmpvar"+depth+"=rcr_WTREADBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", "+tasksrc+strrcr+index+");\n");
780 currCase.append(" int tmpvar"+depth+"=rcr_READBINCASE(allHashStructures["+heaprootNum+"], tmpkey"+depth+", "+tasksrc+strrcr+index+");\n");
783 if(curr.primConfWrite||curr.objConfWrite||curr.primConfRead||curr.objConfRead) {
784 currCase.append("if (!(tmpvar"+depth+"&READYMASK)) totalcount--;\n");
788 private void printObjRefSwitchStatement(Taint taint,
789 Hashtable<AllocSite, StringBuilder> cases,
791 StringBuilder currCase,
792 ArrayList<ObjRef> refsAtParticularField,
796 currCase.append(" "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";\n");
797 currCase.append(" if (" + currPtr + " != NULL) { \n");
798 currCase.append(" switch(" + currPtr + getAllocSiteInC + ") {\n");
800 for(ObjRef ref: refsAtParticularField) {
801 if(ref.child.descendantsConflict() || ref.child.hasPrimitiveConflicts()) {
802 currCase.append(" case "+ref.allocSite+":\n {\n");
803 //The hash insert is here because we don't want to enqueue things unless we know it conflicts.
804 currCase.append(" if (" + queryVistedHashtable +"("+ currPtr + ")) {\n");
806 if(qualifiesForCaseStatement(ref.child)){
807 currCase.append(" " + addToQueueInC + childPtr + ");\n ");
809 addChecker(taint, ref.child, cases, currCase, currPtr, pDepth + 1);
812 currCase.append(" }\n"); //close for queryVistedHashtable
814 currCase.append("}\n"); //close for internal case statement
818 currCase.append(" default:\n" +
820 " }}\n"); //internal switch.
823 private boolean qualifiesForCaseStatement(ConcreteRuntimeObjNode node) {
826 (node.isInsetVar && (node.descendantsConflict() || node.hasPrimitiveConflicts()) || node.hasDirectObjConflict()) ||
827 //non-inline-able code cases
828 (node.getNumOfReachableParents() != 1 && node.descendantsConflict()) ||
829 //Cases where resumes are possible
830 (node.hasPotentialToBeIncorrectDueToConflict) && node.descendantsObjConflict);
833 // decide whether the given SESE doesn't have traversers at all
834 public boolean hasEmptyTraversers(FlatSESEEnterNode fsen) {
835 boolean hasEmpty = true;
837 Set<FlatSESEEnterNode> children = fsen.getChildren();
838 for (Iterator iterator = children.iterator(); iterator.hasNext();) {
839 FlatSESEEnterNode child = (FlatSESEEnterNode) iterator.next();
840 hasEmpty &= child.getInVarsForDynamicCoarseConflictResolution().size() == 0;
845 //Note we assume instance of FlatSESEEnterNode to be sese blocks else they are considered stallsites.
846 private Taint getProperTaintForEnterNode(FlatNode fn, VariableNode var) {
848 Set<Taint> taints = globalEffects.keySet();
849 boolean isStallSite = !(fn instanceof FlatSESEEnterNode);
851 for (Taint t : taints) {
852 flatnode = (isStallSite) ? t.getStallSite():t.getSESE();
854 if( flatnode != null &&
855 flatnode.equals(fn) &&
856 t.getVar().equals(var.getTempDescriptor())) {
863 private void printDebug(boolean guard, String debugStatements) {
865 System.out.println(debugStatements);
868 //Walks the connected heaproot groups, coalesces them, and numbers them
869 //Special Note: Lookup Table must already be created
870 private void enumerateHeaproots() {
871 weaklyConnectedHRCounter = 0;
872 num2WeaklyConnectedHRGroup = new ArrayList<WeaklyConectedHRGroup>();
874 for(Taint t: connectedHRHash.keySet()) {
875 if(connectedHRHash.get(t).id == -1) {
876 WeaklyConectedHRGroup hg = connectedHRHash.get(t);
877 hg.id = weaklyConnectedHRCounter;
878 num2WeaklyConnectedHRGroup.add(weaklyConnectedHRCounter, hg);
879 weaklyConnectedHRCounter++;
882 if(t.isRBlockTaint()) {
883 int id=connectedHRHash.get(t).id;
884 Pair tup=new Pair(t.getVar(),t.getSESE());
885 if (weakMap.containsKey(tup)) {
886 if (weakMap.get(tup).intValue()!=id)
887 throw new Error("Var/SESE not unique for weak component.");
889 weakMap.put(tup, new Integer(id));
893 //output weakly connected groups for verification
895 System.out.println("==============Weakly Connected HeapRoots==============");
897 for(int i=0; i < num2WeaklyConnectedHRGroup.size(); i++){
898 System.out.println("Heap Group #" + i);
899 WeaklyConectedHRGroup hg = num2WeaklyConnectedHRGroup.get(i);
900 for(Taint t: hg.connectedHRs) {
901 System.out.println("\t" + t);
905 System.out.println("=======================END LIST=======================");
909 private void printoutTable(EffectsTable table) {
911 System.out.println("==============EFFECTS TABLE PRINTOUT==============");
912 for(AllocSite as: table.table.keySet()) {
913 System.out.println("\tFor AllocSite " + as.getUniqueAllocSiteID());
915 BucketOfEffects boe = table.table.get(as);
917 if(boe.potentiallyConflictingRoots != null && !boe.potentiallyConflictingRoots.isEmpty()) {
918 System.out.println("\t\tPotentially conflicting roots: ");
919 for(String key: boe.potentiallyConflictingRoots.keySet()) {
920 System.out.println("\t\t-Field: " + key);
921 System.out.println("\t\t\t" + boe.potentiallyConflictingRoots.get(key));
924 for(Taint t: boe.taint2EffectsGroup.keySet()) {
925 System.out.println("\t\t For Taint " + t);
926 EffectsGroup eg = boe.taint2EffectsGroup.get(t);
928 if(eg.hasPrimitiveConflicts()) {
929 System.out.print("\t\t\tPrimitive Conflicts at alloc " + as.getUniqueAllocSiteID() +" : ");
930 for(String field: eg.primitiveConflictingFields.keySet()) {
931 System.out.print(field + " ");
933 System.out.println();
935 for(String fieldKey: eg.myObjEffects.keySet()) {
936 CombinedEffects ce = eg.myObjEffects.get(fieldKey);
937 System.out.println("\n\t\t\tFor allocSite " + as.getUniqueAllocSiteID() + " && field " + fieldKey);
938 System.out.println("\t\t\t\tread " + ce.hasReadEffect + "/"+ce.hasReadConflict +
939 " write " + ce.hasWriteEffect + "/" + ce.hasWriteConflict +
940 " SU " + ce.hasStrongUpdateEffect + "/" + ce.hasStrongUpdateConflict);
941 for(Effect ef: ce.originalEffects) {
942 System.out.println("\t" + ef);
950 private class EffectsGroup {
951 Hashtable<String, CombinedEffects> myObjEffects;
952 //In the end, we don't really care what the primitive fields are.
953 Hashtable<String, CombinedEffects> primitiveConflictingFields;
954 private boolean primConfRead;
955 private boolean primConfWrite;
957 public EffectsGroup() {
958 myObjEffects = new Hashtable<String, CombinedEffects>();
959 primitiveConflictingFields = new Hashtable<String, CombinedEffects>();
961 primConfRead = false;
962 primConfWrite = false;
965 public void addPrimitive(Effect e, boolean conflict) {
966 CombinedEffects effects;
967 if((effects = primitiveConflictingFields.get(e.getField().getSymbol())) == null) {
968 effects = new CombinedEffects();
969 primitiveConflictingFields.put(e.getField().getSymbol(), effects);
971 effects.add(e, conflict);
973 primConfRead |= effects.hasReadConflict;
974 primConfWrite |= effects.hasWriteConflict;
977 public void addObjEffect(Effect e, boolean conflict) {
978 CombinedEffects effects;
979 if((effects = myObjEffects.get(e.getField().getSymbol())) == null) {
980 effects = new CombinedEffects();
981 myObjEffects.put(e.getField().getSymbol(), effects);
983 effects.add(e, conflict);
986 public boolean isEmpty() {
987 return myObjEffects.isEmpty() && primitiveConflictingFields.isEmpty();
990 public boolean hasPrimitiveConflicts(){
991 return !primitiveConflictingFields.isEmpty();
994 public CombinedEffects getPrimEffect(String field) {
995 return primitiveConflictingFields.get(field);
998 public boolean hasObjectEffects() {
999 return !myObjEffects.isEmpty();
1002 public CombinedEffects getObjEffect(String field) {
1003 return myObjEffects.get(field);
1007 //Is the combined effects for all effects with the same affectedAllocSite and field
1008 private class CombinedEffects {
1009 ArrayList<Effect> originalEffects;
1011 public boolean hasReadEffect;
1012 public boolean hasWriteEffect;
1013 public boolean hasStrongUpdateEffect;
1015 public boolean hasReadConflict;
1016 public boolean hasWriteConflict;
1017 public boolean hasStrongUpdateConflict;
1020 public CombinedEffects() {
1021 originalEffects = new ArrayList<Effect>();
1023 hasReadEffect = false;
1024 hasWriteEffect = false;
1025 hasStrongUpdateEffect = false;
1027 hasReadConflict = false;
1028 hasWriteConflict = false;
1029 hasStrongUpdateConflict = false;
1032 public boolean add(Effect e, boolean conflict) {
1033 if(!originalEffects.add(e))
1036 switch(e.getType()) {
1038 hasReadEffect = true;
1039 hasReadConflict = conflict;
1042 hasWriteEffect = true;
1043 hasWriteConflict = conflict;
1045 case Effect.strongupdate:
1046 hasStrongUpdateEffect = true;
1047 hasStrongUpdateConflict = conflict;
1050 System.out.println("RCR ERROR: An Effect Type never seen before has been encountered");
1057 public boolean hasConflict() {
1058 return hasReadConflict || hasWriteConflict || hasStrongUpdateConflict;
1061 public void mergeWith(CombinedEffects other) {
1062 for(Effect e: other.originalEffects) {
1063 if(!originalEffects.contains(e)){
1064 originalEffects.add(e);
1068 hasReadEffect |= other.hasReadEffect;
1069 hasWriteEffect |= other.hasWriteEffect;
1070 hasStrongUpdateEffect |= other.hasStrongUpdateEffect;
1072 hasReadConflict |= other.hasReadConflict;
1073 hasWriteConflict |= other.hasWriteConflict;
1074 hasStrongUpdateConflict |= other.hasStrongUpdateConflict;
1078 //This will keep track of a reference
1079 private class ObjRef {
1080 CombinedEffects myEffects;
1081 boolean reachesConflict;
1086 //This keeps track of the parent that we need to pass by inorder to get
1087 //to the conflicting child (if there is one).
1088 ConcreteRuntimeObjNode parent;
1089 ConcreteRuntimeObjNode child;
1091 public ObjRef(String fieldname,
1092 ConcreteRuntimeObjNode parent,
1093 ConcreteRuntimeObjNode ref,
1094 CombinedEffects myEffects) {
1096 allocSite = ref.allocSite.getUniqueAllocSiteID();
1098 this.parent = parent;
1100 this.myEffects = myEffects;
1101 reachesConflict = false;
1104 public boolean hasConflictsDownThisPath() {
1105 return child.descendantsConflict() || child.hasPrimitiveConflicts() || myEffects.hasConflict();
1108 public boolean hasDirectObjConflict() {
1109 return myEffects.hasConflict();
1112 public boolean equals(Object other) {
1113 if(other == null || !(other instanceof ObjRef))
1116 ObjRef o = (ObjRef) other;
1118 if(o.field == this.field && o.allocSite == this.allocSite && this.child.equals(o.child))
1124 public int hashCode() {
1125 return child.allocSite.hashCode() ^ field.hashCode();
1128 public void mergeWith(ObjRef ref) {
1129 myEffects.mergeWith(ref.myEffects);
1133 private class ConcreteRuntimeObjNode {
1134 HashSet<ObjRef> referencers;
1135 Hashtable<String, ObjRefList> referencees;
1136 HeapRegionNode original;
1137 AllocSite allocSite;
1140 //Accesses BY this node
1141 boolean primConfRead=false;
1142 boolean primConfWrite=false;
1143 boolean objConfRead=false;
1144 boolean objConfWrite=false;
1146 boolean descendantsObjConflict =false;
1147 boolean descendantsPrimConflict=false;
1148 boolean hasPotentialToBeIncorrectDueToConflict=false;
1150 public ConcreteRuntimeObjNode(HeapRegionNode HRN, boolean isInset) {
1151 referencers = new HashSet<ObjRef>(4);
1152 referencees = new Hashtable<String, ObjRefList>(5);
1155 allocSite = HRN.getAllocSite();
1156 isInsetVar = isInset;
1160 public void addReferencer(ObjRef refToMe) {
1161 referencers.add(refToMe);
1164 public void addReferencee(String field, ObjRef refToChild) {
1167 if((array = referencees.get(field)) == null) {
1168 array = new ObjRefList();
1169 referencees.put(field, array);
1172 array.add(refToChild);
1175 public boolean hasDirectObjConflict() {
1176 return objConfRead || objConfWrite;
1179 public boolean isArray() {
1180 return original.getType().isArray();
1183 public int getNumOfReachableParents() {
1184 return referencers.size();
1187 public boolean hasPrimitiveConflicts() {
1188 return primConfRead || primConfWrite;
1191 public boolean hasConflict() {
1192 return objConfRead || objConfWrite || primConfRead || primConfWrite;
1195 public boolean descendantsConflict() {
1196 return descendantsObjConflict||descendantsPrimConflict;
1200 //Simple extension of the ArrayList to allow it to find if any ObjRefs conflict.
1201 private class ObjRefList extends ArrayList<ObjRef> {
1202 private static final long serialVersionUID = 326523675530835596L;
1204 public ObjRefList() {
1208 public boolean add(ObjRef o){
1209 if(this.contains(o)) {
1210 ObjRef other = this.get(this.indexOf(o));
1215 return super.add(o);
1218 public boolean hasConflicts() {
1219 for(ObjRef r: this) {
1220 if(r.hasConflictsDownThisPath() || r.child.hasPrimitiveConflicts()) {
1229 private class EffectsTable {
1230 private Hashtable<AllocSite, BucketOfEffects> table;
1232 public EffectsTable(Hashtable<Taint, Set<Effect>> effects,
1233 Hashtable<Taint, Set<Effect>> conflicts) {
1234 table = new Hashtable<AllocSite, BucketOfEffects>();
1236 // rehash all effects (as a 5-tuple) by their affected allocation site
1237 for (Taint t : effects.keySet()) {
1238 Set<Effect> localConflicts = conflicts.get(t);
1239 for (Effect e : effects.get(t)) {
1240 BucketOfEffects bucket;
1241 if ((bucket = table.get(e.getAffectedAllocSite())) == null) {
1242 bucket = new BucketOfEffects();
1243 table.put(e.getAffectedAllocSite(), bucket);
1245 printDebug(verboseDebug, "Added Taint" + t + " Effect " + e + "Conflict Status = " + (localConflicts!=null?localConflicts.contains(e):false)+" localConflicts = "+localConflicts);
1246 bucket.add(t, e, localConflicts!=null?localConflicts.contains(e):false);
1251 public EffectsGroup getEffects(AllocSite parentKey, Taint taint) {
1252 //This would get the proper bucket of effects and then get all the effects
1253 //for a parent for a specific taint
1255 return table.get(parentKey).taint2EffectsGroup.get(taint);
1257 catch (NullPointerException e) {
1262 // Run Analysis will walk the data structure and figure out the weakly
1263 // connected heap roots.
1264 public void runAnalysis() {
1266 printoutTable(this);
1269 for(AllocSite key: table.keySet()) {
1270 BucketOfEffects effects = table.get(key);
1271 //make sure there are actually conflicts in the bucket
1272 if(effects.potentiallyConflictingRoots != null && !effects.potentiallyConflictingRoots.isEmpty()){
1273 for(String field: effects.potentiallyConflictingRoots.keySet()){
1274 ArrayList<Taint> taints = effects.potentiallyConflictingRoots.get(field);
1275 //For simplicity, we just create a new group and add everything to it instead of
1276 //searching through all of them for the largest group and adding everyone in.
1277 WeaklyConectedHRGroup group = new WeaklyConectedHRGroup();
1278 group.add(taints); //This will automatically add the taint to the connectedHRhash
1285 private class WeaklyConectedHRGroup {
1286 HashSet<Taint> connectedHRs;
1289 public WeaklyConectedHRGroup() {
1290 connectedHRs = new HashSet<Taint>();
1294 public void add(ArrayList<Taint> list) {
1295 for(Taint t: list) {
1300 public void add(Taint t) {
1301 connectedHRs.add(t);
1302 WeaklyConectedHRGroup oldGroup = connectedHRHash.get(t);
1303 connectedHRHash.put(t, this); //put new group into hash
1304 //If the taint was already in another group, move all its buddies over.
1305 if(oldGroup != this && oldGroup != null) {
1306 Iterator<Taint> it = oldGroup.connectedHRs.iterator();
1309 while(it.hasNext() && (relatedTaint = it.next()) != null) {
1310 if(!connectedHRs.contains(relatedTaint)){
1311 this.add(relatedTaint);
1318 //This is a class that stores all the effects for an affected allocation site
1319 //across ALL taints. The structure is a hashtable of EffectGroups (see above) hashed
1320 //by a Taint. This way, I can keep EffectsGroups so I can reuse most to all of my old code
1321 //and allows for easier tracking of effects. In addition, a hashtable (keyed by the string
1322 //of the field access) keeps track of an ArrayList of taints of SESEblocks that conflict on that
1324 private class BucketOfEffects {
1325 // This table is used for lookup while creating the traversal.
1326 Hashtable<Taint, EffectsGroup> taint2EffectsGroup;
1328 //This table is used to help identify weakly connected groups: Contains ONLY
1329 //conflicting effects AND is only initialized when needed
1330 //String stores the field
1331 Hashtable<String, ArrayList<Taint>> potentiallyConflictingRoots;
1333 public BucketOfEffects() {
1334 taint2EffectsGroup = new Hashtable<Taint, EffectsGroup>();
1337 public void add(Taint t, Effect e, boolean conflict) {
1338 EffectsGroup effectsForGivenTaint;
1340 if ((effectsForGivenTaint = taint2EffectsGroup.get(t)) == null) {
1341 effectsForGivenTaint = new EffectsGroup();
1342 taint2EffectsGroup.put(t, effectsForGivenTaint);
1345 if (isReallyAPrimitive(e.getField().getType())) {
1347 effectsForGivenTaint.addPrimitive(e, true);
1350 effectsForGivenTaint.addObjEffect(e, conflict);
1354 if(potentiallyConflictingRoots == null) {
1355 potentiallyConflictingRoots = new Hashtable<String, ArrayList<Taint>>();
1358 ArrayList<Taint> taintsForField = potentiallyConflictingRoots.get(e.getField().getSafeSymbol());
1359 if(taintsForField == null) {
1360 taintsForField = new ArrayList<Taint>();
1361 potentiallyConflictingRoots.put(e.getField().getSafeSymbol(), taintsForField);
1364 if(!taintsForField.contains(t)) {
1365 taintsForField.add(t);
1371 private class TaintAndInternalHeapStructure {
1373 public Hashtable<Integer, ConcreteRuntimeObjNode> nodesInHeap;
1375 public TaintAndInternalHeapStructure(Taint taint, Hashtable<Integer, ConcreteRuntimeObjNode> nodesInHeap) {
1377 this.nodesInHeap = nodesInHeap;
1381 private class TraversalInfo {
1383 public ReachGraph rg;
1384 public TempDescriptor invar;
1386 public TraversalInfo(FlatNode fn, ReachGraph rg1) {
1392 public TraversalInfo(FlatNode fn, ReachGraph rg1, TempDescriptor tempDesc) {
1398 public boolean isStallSite() {
1399 return !(f instanceof FlatSESEEnterNode);
1402 public boolean isRblock() {
1403 return (f instanceof FlatSESEEnterNode);