4 import java.io.FileNotFoundException;
5 import java.io.PrintWriter;
6 import java.util.ArrayList;
7 import java.util.HashSet;
8 import java.util.Hashtable;
9 import java.util.Iterator;
11 import Analysis.Disjoint.*;
12 import IR.TypeDescriptor;
14 //TODO Make more efficient by only using ONE hashtable.
15 //TODO it appears that using the optimize flags screws with the invar naming.
17 /* An instance of this class manages all OoOJava coarse-grained runtime conflicts
18 * by generating C-code to either rule out the conflict at runtime or resolve one.
21 * 1) Instantiate singleton object
22 * 2a) Call void traverse(FlatSESEEnterNode rblock, Hashtable<Taint, Set<Effect>> effects, Hashtable<Taint, Set<Effect>> conflicts, ReachGraph rg)
23 * as many times as needed
24 * 2b) call String getTraverserInvocation(TempDescriptor invar, String varString, FlatSESEEnterNode sese) to get the name of the traverse method in C
25 * 3) Call void close()
27 public class RuntimeConflictResolver {
28 public static final boolean javaDebug = true;
29 public static final boolean cSideDebug = true;
31 private PrintWriter cFile;
32 private PrintWriter headerFile;
33 private static final String hashAndQueueCFileDir = "oooJava/";
34 //This keeps track of taints we've traversed to prevent printing duplicate traverse functions
35 private HashSet<Taint> doneTaints;
37 // initializing variables can be found in printHeader()
38 private static final String getAllocSiteInC = "->allocsite";
39 private static final String queryAndAddHashTableInC = "hashRCRInsert(";
40 private static final String addToQueueInC = "enqueueRCRQueue(";
41 private static final String dequeueFromQueueInC = "dequeueRCRQueue()";
43 private static final String clearQueue = "resetRCRQueue()";
44 // Make hashtable; hashRCRCreate(unsigned int size, double loadfactor)
45 private static final String mallocHashTable = "hashRCRCreate(1024, 0.25)";
46 private static final String deallocHashTable = "hashRCRDelete()";
47 private static final String resetHashTable = "hashRCRreset()";
49 public RuntimeConflictResolver(String buildir) throws FileNotFoundException {
50 String outputFile = buildir + "RuntimeConflictResolver";
52 cFile = new PrintWriter(new File(outputFile + ".c"));
53 headerFile = new PrintWriter(new File(outputFile + ".h"));
55 cFile.append("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
56 + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>\n");
57 cFile.append("#include \"classdefs.h\"\n");
58 cFile.append("#include \"RuntimeConflictResolver.h\"\n");
60 headerFile.append("#ifndef __3_RCR_H_\n");
61 headerFile.append("#define __3_RCR_H_\n");
62 //TODO more closely integrate this by asking generic type from other components?
64 cFile.append("struct genericObjectStruct {int type; int oid; int allocsite; int ___cachedCode___; int ___cachedHash___;};\n");
66 doneTaints = new HashSet<Taint>();
71 * 1) Create a hashed Effects Lookup Table (hashed by allocsite then fieldname)
72 * 1a) Use effects sets to verify if we can access something (reads)
73 * 1b) Use conflicts list to mark conflicts
74 * 2) Build runtime representation of data structure
75 * 2a) Mark conflicts with 2 flags (one for self, one for references down the line)
76 * 3) Printout via traversing data structure created in previous step.
78 public void traverseSESEBlock(FlatSESEEnterNode rblock,
79 Hashtable<Taint, Set<Effect>> effects,
80 Hashtable<Taint, Set<Effect>> conflicts,
82 Set<TempDescriptor> inVars = rblock.getInVarSet();
84 if (inVars.size() == 0)
87 // For every non-primitive variable, generate unique method
88 // Special Note: The Criteria for executing printCMethod in this loop should match
89 // exactly the criteria in buildcode.java to invoke the generated C method(s).
90 for (TempDescriptor invar : inVars) {
91 TypeDescriptor type = invar.getType();
92 if(type == null || type.isPrimitive()) {
96 //created stores nodes with specific alloc sites that have been traversed while building
97 //internal data structure. It is later traversed sequentially to find inset variables and
99 Hashtable<AllocSite, ConcreteRuntimeObjNode> created = new Hashtable<AllocSite, ConcreteRuntimeObjNode>();
100 VariableNode varNode = rg.getVariableNodeNoMutation(invar);
101 Hashtable<AllocSite, EffectsGroup> effectsLookupTable;
103 Taint taint = getProperTaintForFlatSESEEnterNode(rblock, varNode, effects);
105 printDebug(javaDebug, "Null FOR " +varNode.getTempDescriptor().getSafeSymbol() + rblock.toPrettyString());
109 //This is to prevent duplicate from being generated
110 if(!doneTaints.add(taint))
113 effectsLookupTable = generateEffectsLookupTable(taint, effects, conflicts);
114 createConcreteGraph(effectsLookupTable, created, varNode);
116 if (!created.isEmpty()) {
117 rblock.addInVarForDynamicCoarseConflictResolution(invar);
118 printCMethods(created, invar.getSafeSymbol(), rblock.getPrettyIdentifier());
123 public void traverseStallSite(
125 TempDescriptor invar,
126 Hashtable<Taint, Set<Effect>> effects,
127 Hashtable<Taint, Set<Effect>> conflicts,
129 TypeDescriptor type = invar.getType();
130 if(type == null || type.isPrimitive()) {
134 Hashtable<AllocSite, ConcreteRuntimeObjNode> created = new Hashtable<AllocSite, ConcreteRuntimeObjNode>();
135 VariableNode varNode = rg.getVariableNodeNoMutation(invar);
136 Hashtable<AllocSite, EffectsGroup> effectsLookupTable;
138 Taint taint = getProperTaintForEnterNode(enterNode, varNode, effects);
140 printDebug(javaDebug, "Null FOR " +varNode.getTempDescriptor().getSafeSymbol() + enterNode.toString());
144 if(!doneTaints.add(taint))
147 effectsLookupTable = generateEffectsLookupTable(taint, effects, conflicts);
148 createConcreteGraph(effectsLookupTable, created, varNode);
150 if (!created.isEmpty()) {
151 printCMethods(created, invar.getSafeSymbol(), enterNode.toString());
156 public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
158 if(fn instanceof FlatSESEEnterNode) {
159 flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
162 flatname = fn.toString();
165 return "traverse___" + removeInvalidChars(invar.getSafeSymbol()) +
166 removeInvalidChars(flatname) + "___("+varString+");";
171 public String removeInvalidChars(String in) {
172 StringBuilder s = new StringBuilder(in);
173 for(int i = 0; i < s.length(); i++) {
174 if(s.charAt(i) == ' ' || s.charAt(i) == '.' || s.charAt(i) == '=') {
182 public void close() {
183 // Adds Extra supporting methods
184 cFile.append("void initializeStructsRCR() { " + mallocHashTable + "; " + clearQueue + "; }");
185 cFile.append("void destroyRCR() { " + deallocHashTable + "; }\n");
187 headerFile.append("void initializeStructsRCR(); \nvoid destroyRCR(); \n");
188 headerFile.append("#endif\n");
194 private void createConcreteGraph(
195 Hashtable<AllocSite, EffectsGroup> table,
196 Hashtable<AllocSite, ConcreteRuntimeObjNode> created,
197 VariableNode varNode) {
199 // if table is null that means there's no conflicts, therefore we need not
200 // create a traversal
206 printLookupTableDebug(table);
209 Iterator<RefEdge> possibleEdges = varNode.iteratorToReferencees();
211 while (possibleEdges.hasNext()) {
212 RefEdge edge = possibleEdges.next();
215 ConcreteRuntimeObjNode singleRoot = new ConcreteRuntimeObjNode(edge.getDst(), true);
216 AllocSite rootKey = singleRoot.allocSite;
218 if (!created.containsKey(rootKey)) {
219 created.put(rootKey, singleRoot);
220 createHelper(singleRoot, edge.getDst().iteratorToReferencees(), created, table);
225 private Hashtable<AllocSite, EffectsGroup> generateEffectsLookupTable(
226 Taint taint, Hashtable<Taint,
227 Set<Effect>> effects,
228 Hashtable<Taint, Set<Effect>> conflicts) {
232 Set<Effect> localEffects = effects.get(taint);
233 Set<Effect> localConflicts = conflicts.get(taint);
235 //Debug Code for manually checking effects
237 printEffectsAndConflictsSets(taint, localEffects, localConflicts);
240 if (localEffects == null || localEffects.isEmpty() || localConflicts == null || localConflicts.isEmpty())
243 Hashtable<AllocSite, EffectsGroup> lookupTable = new Hashtable<AllocSite, EffectsGroup>();
245 for (Effect e : localEffects) {
246 boolean conflict = localConflicts.contains(e);
247 AllocSite key = e.getAffectedAllocSite();
248 EffectsGroup myEffects = lookupTable.get(key);
250 if(myEffects == null) {
251 myEffects = new EffectsGroup();
252 lookupTable.put(key, myEffects);
255 if(e.getField().getType().isPrimitive()) {
257 myEffects.addPrimative(e);
261 myEffects.addObjEffect(e, conflict);
268 // Plan is to add stuff to the tree depth-first sort of way. That way, we can
269 // propagate up conflicts
270 private void createHelper(ConcreteRuntimeObjNode curr,
271 Iterator<RefEdge> edges,
272 Hashtable<AllocSite, ConcreteRuntimeObjNode> created,
273 Hashtable<AllocSite, EffectsGroup> table) {
274 assert table != null;
275 AllocSite parentKey = curr.allocSite;
276 EffectsGroup currEffects = table.get(parentKey);
278 if (currEffects == null || currEffects.isEmpty())
281 //Handle Objects (and primitive conflict flag propagation)
282 if(currEffects.hasObjectEffects()) {
283 while(edges.hasNext()) {
284 RefEdge edge = edges.next();
285 String field = edge.getField();
286 CombinedObjEffects effectsForGivenField = currEffects.getObjEffect(field);
287 //If there are no effects, then there's no point in traversing this edge
288 if(effectsForGivenField != null) {
289 HeapRegionNode childHRN = edge.getDst();
290 AllocSite childKey = childHRN.getAllocSite();
291 boolean isNewChild = !created.containsKey(childKey);
292 ConcreteRuntimeObjNode child;
295 child = new ConcreteRuntimeObjNode(childHRN, false);
296 created.put(childKey, child);
299 child = created.get(childKey);
302 curr.addObjChild(field, child, effectsForGivenField);
304 if (effectsForGivenField.hasConflict()) {
305 propogateObjConflictFlag(curr);
308 if(effectsForGivenField.hasReadEffect) {
309 child.addReachableParent(curr);
311 //If isNewChild, flag propagation will be handled at recursive call
313 createHelper(child, childHRN.iteratorToReferencees(), created, table);
316 if(child.decendantsPrimConflict || child.hasPrimitiveConflicts()) {
317 propogatePrimConflictFlag(child);
320 if(child.decendantsObjConflict) {
321 propogateObjConflictFlag(child);
330 if(currEffects.hasPrimativeConflicts()) {
331 curr.conflictingPrimitiveFields = currEffects.primativeConflictingFields;
332 propogatePrimConflictFlag(curr);
336 // This will propagate the conflict up the data structure.
337 private void propogateObjConflictFlag(ConcreteRuntimeObjNode curr) {
338 for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
339 if(curr.parentsThatWillLeadToConflicts.add(referencer)) {
340 referencer.decendantsObjConflict = true;
341 propogateObjConflictFlag(referencer);
346 private void propogatePrimConflictFlag(ConcreteRuntimeObjNode curr) {
347 for(ConcreteRuntimeObjNode referencer: curr.parentsWithReadToNode) {
348 if(curr.parentsThatWillLeadToConflicts.add(referencer)) {
349 referencer.decendantsPrimConflict = true;
350 propogatePrimConflictFlag(referencer);
356 * This method generates a C method for every inset variable and rblock.
358 * The C method works by generating a large switch statement that will run the appropriate
359 * checking code for each object based on its allocation site. The switch statement is
360 * surrounded by a while statement which dequeues objects to be checked from a queue. An
361 * object is added to a queue only if it contains a conflict (in itself or in its referencees)
362 * and we came across it while checking through it's referencer. Because of this property,
363 * conflicts will be signaled by the referencer; the only exception is the inset variable which can
364 * signal a conflict within itself.
366 private void printCMethods(Hashtable<AllocSite, ConcreteRuntimeObjNode> created, String inVar, String rBlock) {
367 //This hash table keeps track of all the case statements generated. Although it may seem a bit much
368 //for its purpose, I think it may come in handy later down the road to do it this way.
369 //(i.e. what if we want to eliminate some cases? Or build filter for 1 case)
370 Hashtable<AllocSite, StringBuilder> cases = new Hashtable<AllocSite, StringBuilder>();
373 for (ConcreteRuntimeObjNode node : created.values()) {
374 if (!cases.containsKey(node.allocSite) && (
376 (node.isInsetVar && (node.decendantsConflict() || node.hasPrimitiveConflicts())) ||
377 //non-inline-able code cases
378 (node.getNumOfReachableParents() != 1 && node.decendantsConflict()))) {
380 printDebug(javaDebug, node.allocSite + " qualified for case statement");
381 addChecker(node, cases, null, "ptr", 0);
384 //IMPORTANT: remember to change getTraverserInvocation if you change the line below
385 String methodName = "void traverse___" + removeInvalidChars(inVar) +
386 removeInvalidChars(rBlock) + "___(void * InVar)";
388 cFile.append(methodName + " {\n");
389 headerFile.append(methodName + ";\n");
392 cFile.append("printf(\"The traverser ran for " + methodName + "\\n\");\n");
395 if(cases.size() == 0) {
396 cFile.append(" return; }");
399 //Casts the ptr to a genericObjectStruct so we can get to the ptr->allocsite field.
400 cFile.append("struct genericObjectStruct * ptr = (struct genericObjectStruct *) InVar; if(InVar != NULL) { " + queryAndAddHashTableInC
403 cFile.append("switch(ptr->allocsite) { ");
405 for(AllocSite singleCase: cases.keySet())
406 cFile.append(cases.get(singleCase));
408 cFile.append(" default : break; ");
409 cFile.append("}} while( (ptr = " + dequeueFromQueueInC + ") != NULL); ");
411 //Closes the method by clearing the Queue and reseting the hashTable to prevent
412 //overhead from freeing and mallocing the structures.
413 cFile.append(clearQueue + "; " + resetHashTable + "; }}\n");
419 * addChecker creates a case statement for every object that is either an inset variable
420 * or has multiple referencers (incoming edges). Else it just prints the checker for that object
421 * so that its processing can be pushed up to the referencer node.
423 private void addChecker(ConcreteRuntimeObjNode node,
424 Hashtable<AllocSite,StringBuilder> cases,
425 StringBuilder possibleContinuingCase,
428 StringBuilder currCase = possibleContinuingCase;
429 // We don't need a case statement for things with either 1 incoming or 0 out
430 // going edges, because they can be processed when checking the parent.
432 if((node.isInsetVar && (node.decendantsConflict() || node.hasPrimitiveConflicts())) ||
433 (node.getNumOfReachableParents() != 1 && node.decendantsConflict())) {
434 assert prefix.equals("ptr") && !cases.containsKey(node.allocSite);
435 currCase = new StringBuilder();
436 cases.put(node.allocSite, currCase);
437 currCase.append("case " + node.getAllocationSite() + ":\n { ");
439 //either currCase is continuing off a parent case or is its own.
440 assert currCase !=null;
442 //Specific Primitives test for invars
443 if(node.isInsetVar && node.hasPrimitiveConflicts()) {
444 handlePrimitiveConflict(currCase, prefix, node.conflictingPrimitiveFields, node.allocSite);
447 //Casts C pointer; depth is used to create unique "myPtr" name for when things are inlined
448 String currPtr = "myPtr" + depth;
449 String structType = node.original.getType().getSafeSymbol();
450 currCase.append("struct " + structType + " * "+currPtr+"= (struct "+ structType + " * ) " + prefix + "; ");
453 for (ObjRef ref : node.objectRefs) {
454 // Will only process edge if there is some sort of conflict with the Child
455 if (ref.hasConflictsDownThisPath()) {
456 String childPtr = currPtr +"->___" + ref.field + "___";
458 // Checks if the child exists and has allocsite matching the conflict
459 currCase.append("if(" + childPtr + " != NULL && " + childPtr + getAllocSiteInC + "=="
460 + ref.allocSite + ") { ");
462 // Prints out conflicts of child
463 if (ref.hasDirectObjConflict()) {
464 handleObjConflict(currCase, childPtr, node.allocSite, ref);
467 if(ref.child.hasPrimitiveConflicts()) {
468 handlePrimitiveConflict(currCase, childPtr, ref.child.conflictingPrimitiveFields, ref.child.allocSite);
471 if (ref.child.decendantsConflict()) {
472 // Checks if we have visited the child before
473 currCase.append("if(" + queryAndAddHashTableInC + childPtr + ")) { ");
474 if (ref.child.getNumOfReachableParents() == 1 && !ref.child.isInsetVar) {
475 addChecker(ref.child, cases, currCase, childPtr, depth + 1);
478 currCase.append(addToQueueInC + childPtr + ");");
481 currCase.append(" } ");
483 currCase.append(" } ");
487 if((node.isInsetVar && (node.decendantsConflict() || node.hasPrimitiveConflicts())) ||
488 (node.getNumOfReachableParents() != 1 && node.decendantsConflict())) {
489 currCase.append(" } break; \n");
493 private void handleObjConflict(StringBuilder currCase, String childPtr, AllocSite allocSite, ObjRef ref) {
494 currCase.append("printf(\"Conflict detected with %p from parent with allocation site %u\\n\"," + childPtr + "," + allocSite.hashCodeSpecific() + ");");
497 private void handlePrimitiveConflict(StringBuilder currCase, String ptr, ArrayList<String> conflicts, AllocSite allocSite) {
498 currCase.append("printf(\"Primitive Conflict detected with %p with alloc site %u\\n\", "+ptr+", "+allocSite.hashCodeSpecific()+"); ");
501 private Taint getProperTaintForFlatSESEEnterNode(FlatSESEEnterNode rblock, VariableNode var,
502 Hashtable<Taint, Set<Effect>> effects) {
503 Set<Taint> taints = effects.keySet();
504 for (Taint t : taints) {
505 FlatSESEEnterNode sese = t.getSESE();
506 if(sese != null && sese.equals(rblock) && t.getVar().equals(var.getTempDescriptor())) {
513 private Taint getProperTaintForEnterNode(FlatNode stallSite, VariableNode var,
514 Hashtable<Taint, Set<Effect>> effects) {
515 Set<Taint> taints = effects.keySet();
516 for (Taint t : taints) {
517 FlatNode flatnode = t.getStallSite();
518 if(flatnode != null && flatnode.equals(stallSite) && t.getVar().equals(var.getTempDescriptor())) {
525 private void printEffectsAndConflictsSets(Taint taint, Set<Effect> localEffects,
526 Set<Effect> localConflicts) {
527 System.out.println("#### List of Effects/Conflicts ####");
528 System.out.println("For Taint " + taint);
529 System.out.println("Effects");
530 if(localEffects != null) {
531 for(Effect e: localEffects) {
532 System.out.println(e);
535 System.out.println("Conflicts");
536 if(localConflicts != null) {
537 for(Effect e: localConflicts) {
538 System.out.println(e);
543 private void printLookupTableDebug(Hashtable<AllocSite, EffectsGroup> table) {
544 System.out.println("==========Table print out============");
545 System.out.print(" Key is effect Exists/Conflict\n");
546 for(AllocSite allockey: table.keySet()) {
547 EffectsGroup eg= table.get(allockey);
548 if(eg.hasPrimativeConflicts()) {
549 System.out.print("Primitive Conflicts at alloc " + allockey.hashCode() +" : ");
550 for(String field: eg.primativeConflictingFields) {
551 System.out.print(field + " ");
553 System.out.println();
555 for(String fieldKey: eg.myEffects.keySet()) {
556 CombinedObjEffects ce = eg.myEffects.get(fieldKey);
557 System.out.println("\nFor allocSite " + allockey.hashCode() + " && field " + fieldKey);
558 System.out.println("\tread " + ce.hasReadEffect + "/"+ce.hasReadConflict +
559 " write " + ce.hasWriteEffect + "/" + ce.hasWriteConflict +
560 " SU " + ce.hasStrongUpdateEffect + "/" + ce.hasStrongUpdateConflict);
561 for(Effect ef: ce.originalEffects) {
562 System.out.println("\t" + ef);
566 System.out.println("===========End print out=============");
569 private void printDebug(boolean guard, String debugStatements) {
571 System.out.println(debugStatements);
574 private class EffectsGroup
576 Hashtable<String, CombinedObjEffects> myEffects;
577 ArrayList<String> primativeConflictingFields;
579 public EffectsGroup() {
580 myEffects = new Hashtable<String, CombinedObjEffects>();
581 primativeConflictingFields = new ArrayList<String>();
584 public void addPrimative(Effect e) {
585 primativeConflictingFields.add(e.getField().toPrettyStringBrief());
588 public void addObjEffect(Effect e, boolean conflict) {
589 CombinedObjEffects effects;
590 if((effects = myEffects.get(e.getField().getSymbol())) == null) {
591 effects = new CombinedObjEffects();
592 myEffects.put(e.getField().getSymbol(), effects);
594 effects.add(e, conflict);
597 public boolean isEmpty() {
598 return myEffects.isEmpty() && primativeConflictingFields.isEmpty();
601 public boolean hasPrimativeConflicts(){
602 return !primativeConflictingFields.isEmpty();
605 public boolean hasObjectEffects() {
606 return !myEffects.isEmpty();
609 public CombinedObjEffects getObjEffect(String field) {
610 return myEffects.get(field);
614 //Is the combined effects for all effects with the same affectedAllocSite and field
615 private class CombinedObjEffects {
616 ArrayList<Effect> originalEffects;
618 public boolean hasReadEffect;
619 public boolean hasWriteEffect;
620 public boolean hasStrongUpdateEffect;
622 public boolean hasReadConflict;
623 public boolean hasWriteConflict;
624 public boolean hasStrongUpdateConflict;
627 public CombinedObjEffects() {
628 originalEffects = new ArrayList<Effect>();
630 hasReadEffect = false;
631 hasWriteEffect = false;
632 hasStrongUpdateEffect = false;
634 hasReadConflict = false;
635 hasWriteConflict = false;
636 hasStrongUpdateConflict = false;
639 public boolean add(Effect e, boolean conflict) {
640 if(!originalEffects.add(e))
643 switch(e.getType()) {
645 hasReadEffect = true;
646 hasReadConflict = conflict;
649 hasWriteEffect = true;
650 hasWriteConflict = conflict;
652 case Effect.strongupdate:
653 hasStrongUpdateEffect = true;
654 hasStrongUpdateConflict = conflict;
657 System.out.println("RCR ERROR: An Effect Type never seen before has been encountered");
664 public boolean hasConflict() {
665 return hasReadConflict || hasWriteConflict || hasStrongUpdateConflict;
669 //This will keep track of a reference
670 private class ObjRef {
673 CombinedObjEffects myEffects;
675 //This keeps track of the parent that we need to pass by inorder to get
676 //to the conflicting child (if there is one).
677 ConcreteRuntimeObjNode child;
679 public ObjRef(String fieldname,
680 ConcreteRuntimeObjNode ref,
681 CombinedObjEffects myEffects) {
683 allocSite = ref.getAllocationSite();
686 this.myEffects = myEffects;
689 public boolean hasConflictsDownThisPath() {
690 return child.decendantsObjConflict || child.decendantsPrimConflict || child.hasPrimitiveConflicts() || myEffects.hasConflict();
693 public boolean hasDirectObjConflict() {
694 return myEffects.hasConflict();
698 private class ConcreteRuntimeObjNode {
699 ArrayList<ObjRef> objectRefs;
700 ArrayList<String> conflictingPrimitiveFields;
701 HashSet<ConcreteRuntimeObjNode> parentsWithReadToNode;
702 HashSet<ConcreteRuntimeObjNode> parentsThatWillLeadToConflicts;
703 boolean decendantsPrimConflict;
704 boolean decendantsObjConflict;
707 HeapRegionNode original;
709 public ConcreteRuntimeObjNode(HeapRegionNode me, boolean isInVar) {
710 objectRefs = new ArrayList<ObjRef>();
711 conflictingPrimitiveFields = null;
712 parentsThatWillLeadToConflicts = new HashSet<ConcreteRuntimeObjNode>();
713 parentsWithReadToNode = new HashSet<ConcreteRuntimeObjNode>();
714 allocSite = me.getAllocSite();
716 isInsetVar = isInVar;
717 decendantsPrimConflict = false;
718 decendantsObjConflict = false;
721 public void addReachableParent(ConcreteRuntimeObjNode curr) {
722 parentsWithReadToNode.add(curr);
726 public int hashCode() {
727 // This gets allocsite number
728 return allocSite.hashCodeSpecific();
732 public boolean equals(Object obj) {
733 return original.equals(obj);
736 public int getAllocationSite() {
737 return allocSite.hashCodeSpecific();
740 public int getNumOfReachableParents() {
741 return parentsThatWillLeadToConflicts.size();
744 public boolean hasPrimitiveConflicts() {
745 return conflictingPrimitiveFields != null;
748 public boolean decendantsConflict() {
749 return decendantsPrimConflict || decendantsObjConflict;
752 public void addObjChild(String field, ConcreteRuntimeObjNode child, CombinedObjEffects ce) {
753 ObjRef ref = new ObjRef(field, child, ce);
757 public String toString()
759 return "AllocSite=" + getAllocationSite() + " myConflict=" + !parentsThatWillLeadToConflicts.isEmpty() +
760 " decCon="+decendantsObjConflict+
761 " NumOfConParents=" + getNumOfReachableParents() + " ObjectChildren=" + objectRefs.size();
765 //TODO integrate this code into the generateEffectsLookupTable method and
766 //others that may use this table.
767 private class EffectsTable {
768 private Hashtable<AllocSite, BucketOfEffects> table;
769 // hashtable provides fast access to heaproot # lookups
770 private Hashtable<Taint, Integer> WeaklyConnetedHeapRootNums;
771 private boolean analysisComplete;
773 public EffectsTable(Hashtable<Taint, Set<Effect>> effects,
774 Hashtable<Taint, Set<Effect>> conflicts) {
775 table = new Hashtable<AllocSite, BucketOfEffects>();
776 analysisComplete = false;
778 // rehash all effects (as a 5-tuple) by their affected allocation site
779 for (Taint t : effects.keySet()) {
780 Set<Effect> localConflicts = conflicts.get(t);
782 for (Effect e : effects.get(t)) {
783 BucketOfEffects bucket;
784 if ((bucket = table.get(e.getAffectedAllocSite())) == null) {
785 bucket = new BucketOfEffects();
786 table.put(e.getAffectedAllocSite(), bucket);
788 bucket.add(t, e, localConflicts.contains(e));
793 // Run Analysis will walk the data structure and figure out the weakly
794 // connected heap roots #'s
795 public void runAnaylsis() {
796 if (analysisComplete) {
797 if (RuntimeConflictResolver.javaDebug) {
798 System.out.println("Err: runAnaylsis was called twice in EffectsTable");
807 private class BucketOfEffects {
808 // This table is used for lookup while creating the traversal.
809 Hashtable<Taint, EffectsGroup> effects;
811 public BucketOfEffects() {
812 effects = new Hashtable<Taint, EffectsGroup>();
815 public void add(Taint t, Effect e, boolean conflict) {
816 EffectsGroup effectsForGivenTaint;
818 if ((effectsForGivenTaint = effects.get(t)) == null) {
819 effectsForGivenTaint = new EffectsGroup();
820 effects.put(t, effectsForGivenTaint);
823 if (e.getField().getType().isPrimitive()) {
825 effectsForGivenTaint.addPrimative(e);
828 effectsForGivenTaint.addObjEffect(e, conflict);