*
* How to Use:
* 1) Instantiate singleton object (String input is to specify output dir)
- * 2) Call setGlobalEffects setGlobalEffects(Hashtable<Taint, Set<Effect>> ) ONCE
- * 3) Input SESE blocks, for each block:
- * 3a) call addToTraverseToDoList(FlatSESEEnterNode , ReachGraph , Hashtable<Taint, Set<Effect>>) for the seseBlock
- * 3b) call String getTraverserInvocation(TempDescriptor, String, FlatSESEEnterNode) to get the name of the traverse method in C
- * 4) Call void close()
- * Note: All computation is done upon closing the object. Steps 1-3 only input data
+ * 2) Call void close()
*/
public class RuntimeConflictResolver {
- //Shows weakly connected heaproots and which allocation sites were considered for traversal
+ //Shows which SMFEStates and allocation sites were considered for traversal
private boolean generalDebug = false;
- //Prints out effects passed in, internal representation of effects, and internal representation of reach graph
+ //Prints out effects passed in, internal representation of effects, and C debug code
private boolean verboseDebug = false;
private CodePrinter headerFile, cFile;
//Keeps track of stallsites that we've generated code for.
protected Hashtable <FlatNode, TempDescriptor> processedStallSites = new Hashtable <FlatNode, TempDescriptor>();
- //private Hashtable<Pair, Integer> weakMap=new Hashtable<Pair,Integer>();
- //private Hashtable<Taint, Set<Effect>> globalEffects;
- //private Hashtable<Taint, Set<Effect>> globalConflicts;
-
- //private ArrayList<TraversalInfo> traverserTODO;
-
- // Hashtable provides fast access to heaproot # lookups
- //private Hashtable<Taint, WeaklyConectedHRGroup> connectedHRHash;
- //private ArrayList<WeaklyConectedHRGroup> num2WeaklyConnectedHRGroup;
- //private int traverserIDCounter;
+
public int currentID=1;
private int totalWeakGroups;
- //private ArrayList<TaintAndInternalHeapStructure> pendingPrintout;
- //private EffectsTable effectsLookupTable;
private OoOJavaAnalysis oooa;
private State globalState;
private static final String deallocVisitedHashTable = "hashRCRDelete()";
private static final String resetVisitedHashTable = "hashRCRreset()";
- /*
- * Basic Strategy:
- * 1) Get global effects and conflicts
- * 2) Create a hash structure (EffectsTable) to manage effects (hashed by affected Allocsite, then taint, then field)
- * 2a) Use Effects to verify we can access something (reads)
- * 2b) Use conflicts to mark conflicts (read/write/strongupdate)
- * 2c) At second level of hash, store Heaproots that can cause conflicts at the field
- * 3) Walk hash structure to identify and enumerate weakly connected groups
- * 4) Build internal representation of the rgs (pruned)
- * 5) Print c methods by walking internal representation
- */
+ //TODO get rid of this chunk of code when we're SURE we don't want it anymore.
+ //private Hashtable<Pair, Integer> weakMap=new Hashtable<Pair,Integer>();
+ //private Hashtable<Taint, Set<Effect>> globalEffects;
+ //private Hashtable<Taint, Set<Effect>> globalConflicts;
+ //private ArrayList<TraversalInfo> traverserTODO;
+ // Hashtable provides fast access to heaproot # lookups
+ //private Hashtable<Taint, WeaklyConectedHRGroup> connectedHRHash;
+ //private ArrayList<WeaklyConectedHRGroup> num2WeaklyConnectedHRGroup;
+ //private int traverserIDCounter
+ //private ArrayList<TaintAndInternalHeapStructure> pendingPrintout;
+ //private EffectsTable effectsLookupTable;
public RuntimeConflictResolver( String buildir,
OoOJavaAnalysis oooa,
State state)
throws FileNotFoundException {
- setupOutputFiles(buildir);
-
this.oooa = oooa;
this.globalState = state;
//TODO I'm manually switching the debug states on to make it easier for Jim/Brian to debug, change this back later.
// this.generalDebug = state.RCR_DEBUG || state.RCR_DEBUG_VERBOSE;
// this.verboseDebug = state.RCR_DEBUG_VERBOSE;
this.generalDebug = this.verboseDebug = true;
-
- //doneTaints = new Hashtable<Taint, Integer>();
- //connectedHRHash = new Hashtable<Taint, WeaklyConectedHRGroup>();
- //pendingPrintout = new ArrayList<TaintAndInternalHeapStructure>();
- //traverserTODO = new ArrayList<TraversalInfo>();
-
+
+ processedStallSites = new Hashtable <FlatNode, TempDescriptor>();
BuildStateMachines bsm = oooa.getBuildStateMachines();
totalWeakGroups = bsm.getTotalNumOfWeakGroups();
+
+ setupOutputFiles(buildir);
- for( Pair p: bsm.getAllMachineNames() ) {
- FlatNode taskOrStallSite = (FlatNode) p.getFirst();
- TempDescriptor var = (TempDescriptor) p.getSecond();
+ for( Pair<FlatNode, TempDescriptor> p: bsm.getAllMachineNames() ) {
+ FlatNode taskOrStallSite = p.getFirst();
+ TempDescriptor var = p.getSecond();
+ StateMachineForEffects stateMachine = bsm.getStateMachine( taskOrStallSite, var );
//prints the traversal code
- printCMethod( taskOrStallSite,
- var,
- bsm.getStateMachine( taskOrStallSite, var )
- );
+ printCMethod( taskOrStallSite, var, stateMachine);
}
//IMPORTANT must call .close() elsewhere to finish printing the C files.
}
-
- private void setupOutputFiles(String buildir) throws FileNotFoundException {
- cFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".c"));
- headerFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".h"));
-
- cFile.println("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
- + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>");
- cFile.println("#include \"classdefs.h\"");
- cFile.println("#include \"structdefs.h\"");
- cFile.println("#include \"mlp_runtime.h\"");
- cFile.println("#include \"RuntimeConflictResolver.h\"");
- cFile.println("#include \"hashStructure.h\"");
-
- headerFile.println("#ifndef __3_RCR_H_");
- headerFile.println("#define __3_RCR_H_");
- }
-
- //Performs a reverse traversal from the conflict nodes up to the
- //inset variables and sets conflict flags on inner nodes.
- private void propagateConflicts(Hashtable<Alloc, ConcreteRuntimeObjNode> created) {
- for(ConcreteRuntimeObjNode node: created.values()) {
- if(node.hasConflict()) {
- markReferencers(node, node.objConfRead || node.objConfWrite, node.primConfRead || node.primConfWrite);
- }
- }
- }
-
- private void markReferencers(ConcreteRuntimeObjNode node, boolean ObjConf, boolean PrimConf) {
- for(ObjRef ref: node.referencers) {
- //if not already marked or data does not match
- if(!ref.reachesConflict ||
- (ObjConf && !ref.parent.descendantsObjConflict) ||
- (PrimConf && !ref.parent.descendantsPrimConflict)) {
-
- ref.parent.descendantsObjConflict |= ObjConf;
- ref.parent.descendantsPrimConflict |= PrimConf;
- ref.reachesConflict = true;
- markReferencers(ref.parent, ObjConf, PrimConf);
- }
- }
- }
-
- //This extends a tempDescriptor's isPrimitive test by also excluding primitive arrays.
- private boolean isReallyAPrimitive(TypeDescriptor type) {
- return (type.isPrimitive() && !type.isArray());
- }
-
- //The official way to generate the name for a traverser call
- public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
- String flatname;
- if(fn instanceof FlatSESEEnterNode) { //is SESE block
- flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
- } else { //is stallsite
- flatname = fn.toString();
- }
-
- return "traverse___" + invar.getSafeSymbol() +
- removeInvalidChars(flatname) + "___("+varString+");";
- }
-
- public String removeInvalidChars(String in) {
- StringBuilder s = new StringBuilder(in);
- for(int i = 0; i < s.length(); i++) {
- if(s.charAt(i) == ' ' ||
- s.charAt(i) == '.' ||
- s.charAt(i) == '=' ||
- s.charAt(i) == '[' ||
- s.charAt(i) == ']' ) {
-
- s.deleteCharAt(i);
- i--;
- }
- }
- return s.toString();
- }
-
- // TODO, THIS WORKS A NEW WAY
- public int getWeakID(TempDescriptor invar, FlatNode fn) {
- //return weakMap.get(new Pair(invar, fn)).intValue();
- return -12;
- }
- public int getTraverserID(TempDescriptor invar, FlatNode fn) {
- Pair t=new Pair(invar, fn);
- if (idMap.containsKey(t))
- return idMap.get(t).intValue();
- int value=currentID++;
- idMap.put(t, new Integer(value));
- return value;
- }
-
- public void close() {
-
-
- //Prints out the master traverser Invocation that'll call all other traversers
- //based on traverserID
- printMasterTraverserInvocation();
- createMasterHashTableArray();
-
- // Adds Extra supporting methods
- cFile.println("void initializeStructsRCR() {\n " + mallocVisitedHashtable + ";\n " + clearQueue + ";\n}");
- cFile.println("void destroyRCR() {\n " + deallocVisitedHashTable + ";\n}");
-
- headerFile.println("void initializeStructsRCR();\nvoid destroyRCR();");
- headerFile.println("#endif\n");
-
- cFile.close();
- headerFile.close();
- }
-
- private void createMasterHashTableArray() {
- headerFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray();");
- cFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray() {");
-
- cFile.println(" struct Hashtable_rcr **table=rcr_createMasterHashTableArray("+totalWeakGroups + ");");
-
- for(int i = 0; i < totalWeakGroups; i++) {
- cFile.println(" table["+i+"] = (struct Hashtable_rcr *) rcr_createHashtable();");
- }
- cFile.println(" return table;");
- cFile.println("}");
- }
-
- private void printMasterTraverserInvocation() {
- headerFile.println("\nint tasktraverse(SESEcommon * record);");
- cFile.println("\nint tasktraverse(SESEcommon * record) {");
- cFile.println(" if(!CAS(&record->rcrstatus,1,2)) {");
-
- //release traverser reference...no traversal necessary
- cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
- cFile.println(" RELEASE_REFERENCE_TO(record);");
- cFile.println("#endif");
-
- cFile.println(" return;");
- cFile.println(" }");
- cFile.println(" switch(record->classID) {");
-
- for(Iterator<FlatSESEEnterNode> seseit=oooa.getAllSESEs().iterator();seseit.hasNext();) {
- FlatSESEEnterNode fsen=seseit.next();
- cFile.println( " /* "+fsen.getPrettyIdentifier()+" */");
- cFile.println( " case "+fsen.getIdentifier()+": {");
- cFile.println( " "+fsen.getSESErecordName()+" * rec=("+fsen.getSESErecordName()+" *) record;");
- Vector<TempDescriptor> invars=fsen.getInVarsForDynamicCoarseConflictResolution();
- for(int i=0;i<invars.size();i++) {
- TempDescriptor tmp=invars.get(i);
-
- // TODO: Blame this on Jim.
- // what is a conflict node that is valid to prune? Prune what?
- // is it a conflict for which the traverser is never invoked?
- // let's assume NOTHING is valid to prune in order to get the system
- // running again.
- boolean isValidToPrune = false;
-
- // Jim again: this is what we might want to do...
- //boolean isValidToPrune = true;
- //for( FlatSESEEnterNode parentSESE: fsen.getParents() ) {
- // ConflictGraph graph = oooa.getConflictGraph(parentSESE);
- // String id = tmp + "_sese" + fsen.getPrettyIdentifier();
- // ConflictNode node = graph.getId2cn().get(id);
- //
- // isValidToPrune &= node.IsValidToPrune();
- //}
-
- if (i!=0) {
- cFile.println(" if (record->rcrstatus!=0)");
- }
-
- if(globalState.NOSTALLTR && isValidToPrune){
- cFile.println(" // " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
- }else{
- cFile.println(" " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
- }
- }
- //release traverser reference...traversal finished...
- //executing thread will clean bins for us
- cFile.println(" record->rcrstatus=0;");
- cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
- cFile.println(" RELEASE_REFERENCE_TO(record);");
- cFile.println("#endif");
- cFile.println( " }");
- cFile.println( " break;");
- }
-
- for(FlatNode stallsite: processedStallSites.keySet()) {
- TempDescriptor var = processedStallSites.get(stallsite);
-
- cFile.println( " case -" + getTraverserID(var, stallsite)+ ": {");
- cFile.println( " SESEstall * rec=(SESEstall*) record;");
- cFile.println( " " + this.getTraverserInvocation(var, "rec->___obj___, rec", stallsite)+";");
- cFile.println( " record->rcrstatus=0;");
- cFile.println( " }");
- cFile.println(" break;");
- }
-
- cFile.println(" default:\n printf(\"Invalid SESE ID was passed in: %d.\\n\",record->classID);\n break;");
- cFile.println(" }");
- cFile.println("}");
- }
-
-
- //Currently UNUSED method but may be useful in the future.
- //This will print the traverser invocation that takes in a traverserID and starting ptr
- private void printResumeTraverserInvocation() {
- headerFile.println("\nint traverse(void * startingPtr, SESEcommon * record, int traverserID);");
- cFile.println("\nint traverse(void * startingPtr, SESEcommon *record, int traverserID) {");
- cFile.println(" switch(traverserID) {");
-
- /*
- TODO WHAT IS THE RIGHT THING TO DO HERE?@!?!?
- for(Taint t: doneTaints.keySet()) {
- cFile.println(" case " + doneTaints.get(t)+ ":");
- if(t.isRBlockTaint()) {
- cFile.println(" " + this.getTraverserInvocation(t.getVar(), "startingPtr, ("+t.getSESE().getSESErecordName()+" *)record", t.getSESE()));
- } else if (t.isStallSiteTaint()){
- // JCJ either remove this or consider writing a comment explaining what it is commented out for
- cFile.println("// " + this.getTraverserInvocation(t.getVar(), "startingPtr, record", t.getStallSite())+"");
- } else {
- System.out.println("RuntimeConflictResolver encountered a taint that is neither SESE nor stallsite: " + t);
- }
- cFile.println(" break;");
- }
- */
-
- cFile.println(" default:\n break;");
-
- cFile.println(" }");
- cFile.println("}");
- }
-
/*
* This method generates a C method for every inset variable and rblock.
*
* The C method works by generating a large switch statement that will run the appropriate
- * checking code for each object based on its allocation site. The switch statement is
+ * checking code for each object based on the current state. The switch statement is
* surrounded by a while statement which dequeues objects to be checked from a queue. An
* object is added to a queue only if it contains a conflict (in itself or in its referencees)
* and we came across it while checking through it's referencer. Because of this property,
* signal a conflict within itself.
*/
- private void printCMethod( FlatNode taskOrStallSite,
- TempDescriptor var,
+ private void printCMethod( FlatNode taskOrStallSite,
+ TempDescriptor var,
StateMachineForEffects smfe) {
// collect info for code gen
methodName += "SESEstall *record)";
} else {
methodName += task.getSESErecordName() +" *record)";
- //TODO check that this is correct
+ //TODO check that this HACK is correct (i.e. adding and then polling immediately afterwards)
task.addInVarForDynamicCoarseConflictResolution(var);
index = task.getInVarsForDynamicCoarseConflictResolution().indexOf( var );
}
cFile.println(" case "+state.getID()+":");
cFile.println(" switch(ptr->allocsite) {");
- printChecksInsideState(state, toVisit, taskOrStallSite, var, "ptr", 0, weakID);
+ printAllocChecksInsideState(state, toVisit, taskOrStallSite, var, "ptr", 0, weakID);
cFile.println(" default: break;");
cFile.println(" } // end switch on allocsite");
cFile.flush();
}
- public void printChecksInsideState(SMFEState state, Set<SMFEState> todo, FlatNode fn,
+ public void printAllocChecksInsideState(SMFEState state, Set<SMFEState> todo, FlatNode fn,
TempDescriptor tmp, String prefix, int depth, int weakID) {
EffectsTable et = new EffectsTable(state);
cFile.println(" //debug EffectsTable reports " + et.getAllAllocs().size() + " unique alloc(s)");
cFile.println(" //debug State's inCount = " + state.getRefCount());
}
+
//we assume that all allocs given in the effects are starting locs.
for(Alloc a: et.getAllAllocs()) {
printDebug(generalDebug, "++ Generating code for Alloc: " + a.getUniqueAllocSiteID());
public void addChecker(Alloc a, FlatNode fn, TempDescriptor tmp, EffectsTable et,
String prefix, int depth, Set<SMFEState> stateTodo, int weakID) {
- EffectsGroup eg = et.getEffectsGroup(a);
+ EffectsGroup eg = et.getEffectsGroup(a);
insertEntriesIntoHashStructureNew(fn, tmp, eg, prefix, depth, weakID);
if(eg.leadsToConflict()) {
//There should be only one field, hence we only take the first field in the keyset.
CombinedEffects ce = et.getArrayValue(a);
-
- System.out.println("###########################################");
- System.out.println("Stuffs!" + ce.leadsToTransition());
- System.out.println("###########################################");
-
printRefSwitch(fn, tmp, stateTodo, pdepth, childPtr, currPtr, ce,weakID);
cFile.println(" }}"); // break for the for loop and open curly brace above "int i;"
//All other cases
String currPtr = "myPtr" + pdepth;
cFile.println(" struct ___Object___ * "+currPtr+";");
+
for(String field: et.getAllFields(a)) {
String childPtr = "((struct "+a.getType().getSafeSymbol()+" *)"+prefix +")->" + field;
CombinedEffects ce = et.getCombinedEffects(a, field);
printRefSwitch(fn, tmp, stateTodo, pdepth, childPtr, currPtr, ce, weakID);
}
}
-
cFile.println("}"); //CB0
}
}
cFile.println(" //In-lined state " + tr.getID());
System.out.println("+++ Inlined " + tr.getID());
}
- printChecksInsideState(tr, stateTodo, fn, tmp, currPtr, pdepth+1, weakID);
+ printAllocChecksInsideState(tr, stateTodo, fn, tmp, currPtr, pdepth+1, weakID);
cFile.println(" default:");
cFile.println(" break;");
cFile.println("}");
}
+
+ private void setupOutputFiles(String buildir) throws FileNotFoundException {
+ cFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".c"));
+ headerFile = new CodePrinter(new File(buildir + "RuntimeConflictResolver" + ".h"));
+
+ cFile.println("#include \"" + hashAndQueueCFileDir + "hashRCR.h\"\n#include \""
+ + hashAndQueueCFileDir + "Queue_RCR.h\"\n#include <stdlib.h>");
+ cFile.println("#include \"classdefs.h\"");
+ cFile.println("#include \"structdefs.h\"");
+ cFile.println("#include \"mlp_runtime.h\"");
+ cFile.println("#include \"RuntimeConflictResolver.h\"");
+ cFile.println("#include \"hashStructure.h\"");
+
+ headerFile.println("#ifndef __3_RCR_H_");
+ headerFile.println("#define __3_RCR_H_");
+ }
-
- /*
- private Hashtable<Alloc, ConcreteRuntimeObjNode> createTraversalGraph(EffectsTable et, Graph ptrGraph, TempDescriptor var) {
- Hashtable<Alloc, ConcreteRuntimeObjNode> created
- = new Hashtable<Alloc, ConcreteRuntimeObjNode>(); //Pass 0: Create empty graph
- // what if we have more than one way in?! >< i.e. more than 1 temp descriptor...
- Set<Edge> insetVars = ptrGraph.getEdges(var);
- for(Edge invar: insetVars) {
- Alloc rootKey = invar.getSrcAlloc().getAllocSite();
-
- if(!created.contains(rootKey)) {
- //null -> no transitions by reading this object (does not apply to its references
- //bool true -> this is an inset variable
- ConcreteRuntimeObjNode root = new ConcreteRuntimeObjNode(rootKey, var.getType(), null, true);
- addToTraversalGraphStartingAt(root, et, ptrGraph.getEdges((AllocNode) rootKey), ptrGraph, created);
- }
+ //The official way to generate the name for a traverser call
+ public String getTraverserInvocation(TempDescriptor invar, String varString, FlatNode fn) {
+ String flatname;
+ if(fn instanceof FlatSESEEnterNode) { //is SESE block
+ flatname = ((FlatSESEEnterNode) fn).getPrettyIdentifier();
+ } else { //is stallsite
+ flatname = fn.toString();
}
- return created;
+ return "traverse___" + invar.getSafeSymbol() +
+ removeInvalidChars(flatname) + "___("+varString+");";
}
+ public String removeInvalidChars(String in) {
+ StringBuilder s = new StringBuilder(in);
+ for(int i = 0; i < s.length(); i++) {
+ if(s.charAt(i) == ' ' ||
+ s.charAt(i) == '.' ||
+ s.charAt(i) == '=' ||
+ s.charAt(i) == '[' ||
+ s.charAt(i) == ']' ) {
+
+ s.deleteCharAt(i);
+ i--;
+ }
+ }
+ return s.toString();
+ }
+
+ // TODO, THIS WORKS A NEW WAY
+ public int getWeakID(TempDescriptor invar, FlatNode fn) {
+ //return weakMap.get(new Pair(invar, fn)).intValue();
+ return -12;
+ }
+ public int getTraverserID(TempDescriptor invar, FlatNode fn) {
+ Pair<TempDescriptor, FlatNode> t = new Pair<TempDescriptor, FlatNode>(invar, fn);
+ if (idMap.containsKey(t)) {
+ return idMap.get(t).intValue();
+ }
+ int value=currentID++;
+ idMap.put(t, new Integer(value));
+ return value;
+ }
- private void addToTraversalGraphStartingAt(
- ConcreteRuntimeObjNode curr,
- EffectsTable et,
- MySet<Edge> edges,
- Graph ptrGraph,
- Hashtable<Alloc, ConcreteRuntimeObjNode> created) {
- CombinedEffects ce;
+ public void close() {
+ //Prints out the master traverser Invocation that'll call all other traversers
+ //based on traverserID
+ printMasterTraverserInvocation();
+ createMasterHashTableArray();
- //Handle Primitives
- for(String field: et.getAllFields(curr.alloc).keySet()) {
- if((ce = et.getCombinedEffects(curr.alloc, field)).isPrimitive);
- curr.primConfRead |= ce.hasReadConflict;
- curr.primConfWrite |= ce.hasWriteConflict;
- }
+ // Adds Extra supporting methods
+ cFile.println("void initializeStructsRCR() {\n " + mallocVisitedHashtable + ";\n " + clearQueue + ";\n}");
+ cFile.println("void destroyRCR() {\n " + deallocVisitedHashTable + ";\n}");
- //Handle Object Conflicts
- for(Edge e: edges) {
- //since we're starting from a src, it should match...
- assert e.getSrcAlloc().equals(curr.alloc);
- Alloc dst = e.getDst().getAllocSite();
- String field = e.getFieldDesc().getSafeSymbol();
- ce = et.getCombinedEffects(curr.alloc, field);
- ConcreteRuntimeObjNode child;
-
- //if ce is null, then that means we never go down that branch.
- if(ce!=null) {
- boolean isNewChild = !created.containsKey(dst);
+ headerFile.println("void initializeStructsRCR();\nvoid destroyRCR();");
+ headerFile.println("#endif\n");
+
+ cFile.close();
+ headerFile.close();
+ }
+
+ private void printMasterTraverserInvocation() {
+ headerFile.println("\nint tasktraverse(SESEcommon * record);");
+ cFile.println("\nint tasktraverse(SESEcommon * record) {");
+ cFile.println(" if(!CAS(&record->rcrstatus,1,2)) {");
+
+ //release traverser reference...no traversal necessary
+ cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
+ cFile.println(" RELEASE_REFERENCE_TO(record);");
+ cFile.println("#endif");
+
+ cFile.println(" return;");
+ cFile.println(" }");
+ cFile.println(" switch(record->classID) {");
+
+ for(Iterator<FlatSESEEnterNode> seseit=oooa.getAllSESEs().iterator();seseit.hasNext();) {
+ FlatSESEEnterNode fsen=seseit.next();
+ cFile.println( " /* "+fsen.getPrettyIdentifier()+" */");
+ cFile.println( " case "+fsen.getIdentifier()+": {");
+ cFile.println( " "+fsen.getSESErecordName()+" * rec=("+fsen.getSESErecordName()+" *) record;");
+ Vector<TempDescriptor> invars=fsen.getInVarsForDynamicCoarseConflictResolution();
+ for(int i=0;i<invars.size();i++) {
+ TempDescriptor tmp=invars.get(i);
- if(isNewChild) {
- //false = not inset
- child = new ConcreteRuntimeObjNode(dst, e.getFieldDesc().getType(), ce.transitions, false);
- created.put(dst, child);
- } else {
- child = created.get(dst);
- }
+ // TODO: Blame this on Jim.
+ // what is a conflict node that is valid to prune? Prune what?
+ // is it a conflict for which the traverser is never invoked?
+ // let's assume NOTHING is valid to prune in order to get the system
+ // running again.
+ boolean isValidToPrune = false;
- ObjRef reference = new ObjRef(field, curr, child, ce);
- curr.addReferencee(field, reference);
-
- //update parent flags
- curr.objConfRead |= ce.hasReadConflict;
- curr.objConfWrite |= ce.hasWriteConflict;
+ // Jim again: this is what we might want to do...
+ //boolean isValidToPrune = true;
+ //for( FlatSESEEnterNode parentSESE: fsen.getParents() ) {
+ // ConflictGraph graph = oooa.getConflictGraph(parentSESE);
+ // String id = tmp + "_sese" + fsen.getPrettyIdentifier();
+ // ConflictNode node = graph.getId2cn().get(id);
+ //
+ // isValidToPrune &= node.IsValidToPrune();
+ //}
- //Update flags and recurse
- if(ce.hasReadEffect) {
- child.hasPotentialToBeIncorrectDueToConflict |= ce.hasReadConflict;
- child.addReferencer(reference);
-
- if(isNewChild) {
- MySet<Edge> childEdges = ptrGraph.getEdges((AllocNode)dst);
- addToTraversalGraphStartingAt(child, et, childEdges, ptrGraph, created);
- }
+ if (i!=0) {
+ cFile.println(" if (record->rcrstatus!=0)");
+ }
+
+ if(globalState.NOSTALLTR && isValidToPrune){
+ cFile.println(" // " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
+ }else{
+ cFile.println(" " + this.getTraverserInvocation(tmp, "rec->"+tmp+", rec", fsen));
}
}
+ //release traverser reference...traversal finished...
+ //executing thread will clean bins for us
+ cFile.println(" record->rcrstatus=0;");
+ cFile.println("#ifndef OOO_DISABLE_TASKMEMPOOL");
+ cFile.println(" RELEASE_REFERENCE_TO(record);");
+ cFile.println("#endif");
+ cFile.println( " }");
+ cFile.println( " break;");
+ }
+
+ for(FlatNode stallsite: processedStallSites.keySet()) {
+ TempDescriptor var = processedStallSites.get(stallsite);
+
+ cFile.println( " case -" + getTraverserID(var, stallsite)+ ": {");
+ cFile.println( " SESEstall * rec=(SESEstall*) record;");
+ cFile.println( " " + this.getTraverserInvocation(var, "rec->___obj___, rec", stallsite)+";");
+ cFile.println( " record->rcrstatus=0;");
+ cFile.println( " }");
+ cFile.println(" break;");
}
+
+ cFile.println(" default:\n printf(\"Invalid SESE ID was passed in: %d.\\n\",record->classID);\n break;");
+ cFile.println(" }");
+ cFile.println("}");
}
+
+ private void createMasterHashTableArray() {
+ headerFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray();");
+ cFile.println("struct Hashtable_rcr ** createAndFillMasterHashStructureArray() {");
- //Note: FlatNode and temp descriptor are what used to be the taint.
- void addAllocChecker(FlatNode fn, TempDescriptor tmp, EffectsTable et, ConcreteRuntimeObjNode node, String prefix, int depth, int heaprootNum, int stateID, Set<SMFEState> toVisit) {
- insertEntriesIntoHashStructure(fn, tmp, node,prefix, depth, heaprootNum);
+ cFile.println(" struct Hashtable_rcr **table=rcr_createMasterHashTableArray("+totalWeakGroups + ");");
- //Handle conflicts further down.
- if(node.descendantsConflict()) {
- int pdepth=depth+1;
- cFile.println("{");
-
- //Array Case
- if(node.isArray()) {
- String childPtr = "((struct ___Object___ **)(((char *) &(((struct ArrayObject *)"+ prefix+")->___length___))+sizeof(int)))[i]";
- String currPtr = "arrayElement" + pdepth;
-
- cFile.println("{\n int i;");
- cFile.println(" struct ___Object___ * "+currPtr+";");
- cFile.println(" for(i = 0; i<((struct ArrayObject *) " + prefix + " )->___length___; i++ ) {");
-
- //There should be only one field, hence we only take the first field in the keyset.
- assert node.referencees.keySet().size() <= 1;
- ObjRefList refsAtParticularField = node.referencees.get(node.referencees.keySet().iterator().next());
- printObjRefSwitchStatement(fn,tmp,et,pdepth,refsAtParticularField,childPtr,currPtr,heaprootNum,stateID,toVisit);
- cFile.println(" }}");
- } else {
- //All other cases
- String currPtr = "myPtr" + pdepth;
- cFile.println(" struct ___Object___ * "+currPtr+";");
- for(String field: node.referencees.keySet()) {
- ObjRefList refsAtParticularField = node.referencees.get(field);
-
- if(refsAtParticularField.hasConflicts()) {
- String childPtr = "((struct "+node.getType().getSafeSymbol()+" *)"+prefix +")->___" + field + "___";
- printObjRefSwitchStatement(fn,tmp,et,pdepth,refsAtParticularField,childPtr,currPtr,heaprootNum, stateID, toVisit);
- }
- }
- }
- cFile.println("}\n"); //For particular top level case statement.
+ for(int i = 0; i < totalWeakGroups; i++) {
+ cFile.println(" table["+i+"] = (struct Hashtable_rcr *) rcr_createHashtable();");
}
+ cFile.println(" return table;");
+ cFile.println("}");
}
- // update to include state changes!
- //If state changes branches INTO this object, then it needs its own state.
- //Possible solution, have a hashtable to keep track of Alloc->PossibleTransition
- //And add to it as we go through the effects.
- private boolean qualifiesForCaseStatement(ConcreteRuntimeObjNode node) {
- return true;
-// return (
-// //insetVariable case
-// (node.isInsetVar && (node.descendantsConflict() || node.hasPrimitiveConflicts()) || node.hasDirectObjConflict()) ||
-// //non-inline-able code cases
-// (node.getNumOfReachableParents() != 1 && node.descendantsConflict()) ||
-// //Cases where resumes are possible
-// (node.hasPotentialToBeIncorrectDueToConflict && node.descendantsObjConflict));
- }
-
- //FlatNode and TempDescriptor are what are used to make the taint
- private void insertEntriesIntoHashStructure(FlatNode fn, TempDescriptor tmp,
- ConcreteRuntimeObjNode curr, String prefix, int depth, int heaprootNum) {
-
- int index = 0;
- boolean isRblock = (fn instanceof FlatSESEEnterNode);
- if (isRblock) {
- FlatSESEEnterNode fsese = (FlatSESEEnterNode) fn;
- index = fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
- }
-
- String strrcr = isRblock ? "&record->rcrRecords[" + index + "], " : "NULL, ";
- String tasksrc =isRblock ? "(SESEcommon *) record, ":"(SESEcommon *)(((INTPTR)record)|1LL), ";
-
- // Do call if we need it.
- if (curr.primConfWrite || curr.objConfWrite) {
- assert heaprootNum != -1;
- cFile.append(" int tmpkey" + depth + "=rcr_generateKey(" + prefix + ");\n");
- if (curr.descendantsConflict())
- cFile.append(" int tmpvar" + depth + "=rcr_WTWRITEBINCASE(allHashStructures[" + heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
- else
- cFile.append(" int tmpvar" + depth + "=rcr_WRITEBINCASE(allHashStructures["+ heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
- } else if (curr.primConfRead || curr.objConfRead) {
- assert heaprootNum != -1;
- cFile.append(" int tmpkey" + depth + "=rcr_generateKey(" + prefix + ");\n");
- if (curr.descendantsConflict())
- cFile.append(" int tmpvar" + depth + "=rcr_WTREADBINCASE(allHashStructures[" + heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
- else
- cFile.append(" int tmpvar" + depth + "=rcr_READBINCASE(allHashStructures["+ heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
- }
-
- if (curr.primConfWrite || curr.objConfWrite || curr.primConfRead || curr.objConfRead) {
- cFile.append("if (!(tmpvar" + depth + "&READYMASK)) totalcount--;\n");
- }
- }
-
- private void printObjRefSwitchStatement(FlatNode fn,
- EffectsTable et,
- int pDepth,
- ArrayList<ObjRef> refsAtParticularField,
- String childPtr,
- String currPtr,
- int heaprootNum,
- int stateID,
- Set<SMFEState> toVisit) {
-
- cFile.println(" "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";");
- cFile.println(" if (" + currPtr + " != NULL) { ");
- cFile.println(" switch(" + currPtr + getAllocSiteInC + ") {");
-
- for(ObjRef ref: refsAtParticularField) {
- cFile.println(" case "+ref.allocID+":\n {");
- //The hash insert is here because we don't want to enqueue things unless we know it conflicts.
- cFile.println(" if (" + queryAndAddToVistedHashtable +"("+ currPtr + ", "+stateID+")) {");
-
- if(ref.child.isTransition()) {
- for(SMFEState s: ref.child.transitions) {
- cFile.println(" " + addToQueueInC + childPtr + ", "+s.getID()+");");
- }
- } else if(qualifiesForCaseStatement(ref.child)){
- cFile.println(" " + addToQueueInC + childPtr + ", "+stateID+");");
- } else {
-// public void addChecker(AllocNode a, FlatNode fn, EffectsTable et, String prefix, int depth)
- addCheker(..);
- }
-
- cFile.println(" }"); //close for queryVistedHashtable
-
- cFile.println("}"); //close for internal case statement
- }
-
- cFile.append(" default:\n" +
- " break;\n"+
- " }}\n"); //internal switch.
- }
-
- */
// decide whether the given SESE doesn't have traversers at all
public boolean hasEmptyTraversers(FlatSESEEnterNode fsen) {
boolean hasEmpty = true;
Set<FlatSESEEnterNode> children = fsen.getChildren();
- for (Iterator iterator = children.iterator(); iterator.hasNext();) {
+ for (Iterator<FlatSESEEnterNode> iterator = children.iterator(); iterator.hasNext();) {
FlatSESEEnterNode child = (FlatSESEEnterNode) iterator.next();
hasEmpty &= child.getInVarsForDynamicCoarseConflictResolution().size() == 0;
}
System.out.println(debugStatements);
}
- /*
- //Walks the connected heaproot groups, coalesces them, and numbers them
- //Special Note: Lookup Table must already be created
- private void enumerateHeaproots() {
- weaklyConnectedHRCounter = 0;
- num2WeaklyConnectedHRGroup = new ArrayList<WeaklyConectedHRGroup>();
-
- for(Taint t: connectedHRHash.keySet()) {
- if(connectedHRHash.get(t).id == -1) {
- WeaklyConectedHRGroup hg = connectedHRHash.get(t);
- hg.id = weaklyConnectedHRCounter;
- num2WeaklyConnectedHRGroup.add(weaklyConnectedHRCounter, hg);
- weaklyConnectedHRCounter++;
- }
-
- if(t.isRBlockTaint()) {
- int id=connectedHRHash.get(t).id;
- Pair tup=new Pair(t.getVar(),t.getSESE());
- if (weakMap.containsKey(tup)) {
- if (weakMap.get(tup).intValue()!=id)
- throw new Error("Var/SESE not unique for weak component.");
- } else
- weakMap.put(tup, new Integer(id));
- }
- }
-
- //output weakly connected groups for verification
- if(generalDebug) {
- System.out.println("==============Weakly Connected HeapRoots==============");
-
- for(int i=0; i < num2WeaklyConnectedHRGroup.size(); i++){
- System.out.println("Heap Group #" + i);
- WeaklyConectedHRGroup hg = num2WeaklyConnectedHRGroup.get(i);
- for(Taint t: hg.connectedHRs) {
- System.out.println("\t" + t);
- }
- }
-
- System.out.println("=======================END LIST=======================");
- }
- }
- */
-
-
- //This will keep track of a reference
- private class ObjRef {
- CombinedEffects myEffects;
- boolean reachesConflict;
- int allocID;
- String field;
-
-
- //This keeps track of the parent that we need to pass by inorder to get
- //to the conflicting child (if there is one).
- ConcreteRuntimeObjNode parent;
- ConcreteRuntimeObjNode child;
-
- public ObjRef(String fieldname,
- ConcreteRuntimeObjNode parent,
- ConcreteRuntimeObjNode ref,
- CombinedEffects myEffects) {
- field = fieldname;
- allocID = ref.alloc.getUniqueAllocSiteID();
- child = ref;
- this.parent = parent;
-
- this.myEffects = myEffects;
- reachesConflict = false;
- }
-
- public boolean hasConflictsDownThisPath() {
- return child.descendantsConflict() || child.hasPrimitiveConflicts() || myEffects.hasConflict();
- }
-
- public boolean hasDirectObjConflict() {
- return myEffects.hasConflict();
- }
-
- public boolean equals(Object other) {
- if(other == null || !(other instanceof ObjRef))
- return false;
-
- ObjRef o = (ObjRef) other;
-
- if(o.field == this.field && o.allocID == this.allocID && this.child.equals(o.child))
- return true;
-
- return false;
- }
-
- public int hashCode() {
- return child.alloc.hashCode() ^ field.hashCode();
- }
-
- public void mergeWith(ObjRef ref) {
- myEffects.mergeWith(ref.myEffects);
- }
- }
-
- //Stores effects for a given alloc.
- private class EffectsGroup {
- private boolean hasReadConf = false;
- private boolean hasWriteConf = false;
- private boolean leadsToConf = false;
-
- Hashtable<String,CombinedEffects> field2Effects;
-
- public EffectsGroup() {
- field2Effects = new Hashtable<String,CombinedEffects>();
-
- }
-
- public void add(Effect e, boolean conflict, Set<SMFEState> transitions) {
- CombinedEffects ce;
- if((ce= field2Effects.get(e.getField().getSafeSymbol()))== null) {
- ce = new CombinedEffects();
- field2Effects.put(e.getField().getSafeSymbol(), ce);
- }
-
- ce.add(e, conflict, transitions);
-
- hasReadConf |= ce.hasReadConflict;
- hasWriteConf |= ce.hasWriteConflict;
- leadsToConf |= ce.leadsToTransition();
- }
-
- public CombinedEffects get(String field) {
- return field2Effects.get(field);
- }
-
- public boolean leadsToConflict() {
- return leadsToConf;
- }
-
- public boolean hasWriteConfict() {
- return hasWriteConf;
- }
-
- public boolean hasReadConflict() {
- return hasReadConf;
- }
-
- }
-
//Simply rehashes and combines all effects for a AffectedAllocSite + Field.
private class EffectsTable {
Set<SMFEState> transitions = (state.getTransistionEffects().contains(e))?state.transitionsTo(e):null;
eg.add(e, state.getConflicts().contains(e), transitions);
-
//debug
if(verboseDebug && e.getField().getType().isArray()) {
System.out.println("++++++++++++++++++++++++++++++++");
System.out.println("Other valid effects that lead to transitions");
for(Effect e2: state.getTransistionEffects()) {
- System.out.println(" "+e);
+ System.out.println(" "+e2);
}
System.out.println("++++++++++++++++++++++++++++++++");
}
/*
+ //This code was what was used to generate weakly connected numbers. It's kept in case we need it for
+ // Jim's analysis.
public EffectsTable(Hashtable<Taint, Set<Effect>> effects,
Hashtable<Taint, Set<Effect>> conflicts) {
table = new Hashtable<Alloc, CombinedEffects>();
*/
}
- private class ConcreteRuntimeObjNode {
- HashSet<ObjRef> referencers;
- Hashtable<String, ObjRefList> referencees;
- Alloc alloc;
- TypeDescriptor type;
- SMFEState myState;
- Set<SMFEState> transitions;
-
- boolean isInsetVar;
-
- //Accesses BY this node
- boolean primConfRead=false;
- boolean primConfWrite=false;
- boolean objConfRead=false;
- boolean objConfWrite=false;
+
+ //Stores effects for a given alloc.
+ private class EffectsGroup {
+ private boolean hasReadConf = false;
+ private boolean hasWriteConf = false;
+ private boolean leadsToConf = false;
- public boolean descendantsPrimConflict = false;
- public boolean descendantsObjConflict = false;
- public boolean hasPotentialToBeIncorrectDueToConflict = false;
+ Hashtable<String,CombinedEffects> field2Effects;
- public ConcreteRuntimeObjNode(Alloc a, TypeDescriptor type, SMFEState state, Set<SMFEState> transitions, boolean isInset) {
- referencers = new HashSet<ObjRef>(4);
- referencees = new Hashtable<String, ObjRefList>(5);
-
- alloc = a;
- isInsetVar = isInset;
- this.type = type;
- myState = state;
-
- if(transitions != null && !transitions.isEmpty()) {
- if(this.transitions == null) {
- this.transitions = new MySet<SMFEState>();
- this.transitions.addAll(transitions);
- } else {
- this.transitions.addAll(transitions);
- }
- }
- }
-
- public void addReferencer(ObjRef refToMe) {
- referencers.add(refToMe);
- }
-
- public void addReferencee(String field, ObjRef refToChild) {
- ObjRefList array;
-
- if((array = referencees.get(field)) == null) {
- array = new ObjRefList();
- referencees.put(field, array);
- }
+ public EffectsGroup() {
+ field2Effects = new Hashtable<String,CombinedEffects>();
- array.add(refToChild);
- }
-
- public boolean hasDirectObjConflict() {
- return objConfRead || objConfWrite;
- }
-
- public TypeDescriptor getType() {
- return type;
- }
-
- public boolean isArray() {
- return type.isArray();
- }
-
- public boolean isTransition() {
- return (transitions != null);
- }
-
- public int getNumOfReachableParents() {
- return referencers.size();
}
- public boolean hasPrimitiveConflicts() {
- return primConfRead || primConfWrite;
- }
-
- public boolean hasConflict() {
- return objConfRead || objConfWrite || primConfRead || primConfWrite;
- }
-
- public boolean descendantsConflict() {
- return descendantsObjConflict||descendantsPrimConflict;
- }
-
- public boolean equals(Object o) {
- if (o == null || !(o instanceof ConcreteRuntimeObjNode))
- return false;
-
- ConcreteRuntimeObjNode other = (ConcreteRuntimeObjNode) o;
- return (alloc.equals(other.alloc) && myState.equals(other.myState));
- }
- }
-
- //Simple extension of the ArrayList to allow it to find if any ObjRefs conflict.
- private class ObjRefList extends ArrayList<ObjRef> {
- private static final long serialVersionUID = 326523675530835596L;
-
- public ObjRefList() {
- super();
- }
-
- public boolean add(ObjRef o){
- if(this.contains(o)) {
- ObjRef other = this.get(this.indexOf(o));
- other.mergeWith(o);
- return false;
- }
- else
- return super.add(o);
- }
-
- public boolean hasConflicts() {
- for(ObjRef r: this) {
- if(r.hasConflictsDownThisPath() || r.child.hasPrimitiveConflicts()) {
- return true;
- }
+ public void add(Effect e, boolean conflict, Set<SMFEState> transitions) {
+ CombinedEffects ce;
+ if((ce= field2Effects.get(e.getField().getSafeSymbol()))== null) {
+ ce = new CombinedEffects();
+ field2Effects.put(e.getField().getSafeSymbol(), ce);
}
- return false;
- }
- }
-
- /*
- private class EffectsGroup {
- Hashtable<String, CombinedEffects> myObjEffects;
- //In the end, we don't really care what the primitive fields are.
- Hashtable<String, CombinedEffects> primitiveConflictingFields;
- private boolean primConfRead;
- private boolean primConfWrite;
-
- public EffectsGroup() {
- myObjEffects = new Hashtable<String, CombinedEffects>();
- primitiveConflictingFields = new Hashtable<String, CombinedEffects>();
+ ce.add(e, conflict, transitions);
- primConfRead = false;
- primConfWrite = false;
+ hasReadConf |= ce.hasReadConflict;
+ hasWriteConf |= ce.hasWriteConflict;
+ leadsToConf |= ce.leadsToTransition();
}
-
- public void add(Effect e, boolean conflict, boolean leadsToTransistion) {
- CombinedEffects effects;
- if ((effects = myObjEffects.get(e.getField().getSymbol())) == null) {
- effects = new CombinedEffects();
- myObjEffects.put(e.getField().getSymbol(), effects);
- }
-
- effects.add(e, conflict, leadsToTransistion);
-
- if (isReallyAPrimitive(e.getField().getType())) {
- effects.add(e, conflict, false);
- primConfRead |= effects.hasReadConflict;
- primConfWrite |= effects.hasWriteConflict;
- }
- }
-
-
- public boolean isEmpty() {
- return myObjEffects.isEmpty() && primitiveConflictingFields.isEmpty();
+ public CombinedEffects get(String field) {
+ return field2Effects.get(field);
}
-
- public boolean hasPrimitiveConflicts(){
- return !primitiveConflictingFields.isEmpty();
+
+ public boolean leadsToConflict() {
+ return leadsToConf;
}
- public CombinedEffects getPrimEffect(String field) {
- return primitiveConflictingFields.get(field);
- }
-
- public boolean hasObjectEffects() {
- return !myObjEffects.isEmpty();
+ public boolean hasWriteConfict() {
+ return hasWriteConf;
}
- public CombinedEffects getObjEffect(String field) {
- return myObjEffects.get(field);
+ public boolean hasReadConflict() {
+ return hasReadConf;
}
}
- */
-
-//Is the combined effects for all effects with the same affectedAllocSite and field
+ //Is the combined effects for all effects with the same affectedAllocSite and field
private class CombinedEffects {
ArrayList<Effect> originalEffects;
Set<SMFEState> transitions;
}
}
+ //This extends a tempDescriptor's isPrimitive test by also excluding primitive arrays.
+ private boolean isReallyAPrimitive(TypeDescriptor type) {
+ return (type.isPrimitive() && !type.isArray());
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //Currently UNUSED method but may be useful in the future.
+ //This will print the traverser invocation that takes in a traverserID and starting ptr
+ private void printResumeTraverserInvocation() {
+ headerFile.println("\nint traverse(void * startingPtr, SESEcommon * record, int traverserID);");
+ cFile.println("\nint traverse(void * startingPtr, SESEcommon *record, int traverserID) {");
+ cFile.println(" switch(traverserID) {");
+
+ /*
+ TODO WHAT IS THE RIGHT THING TO DO HERE?@!?!?
+ for(Taint t: doneTaints.keySet()) {
+ cFile.println(" case " + doneTaints.get(t)+ ":");
+ if(t.isRBlockTaint()) {
+ cFile.println(" " + this.getTraverserInvocation(t.getVar(), "startingPtr, ("+t.getSESE().getSESErecordName()+" *)record", t.getSESE()));
+ } else if (t.isStallSiteTaint()){
+ // JCJ either remove this or consider writing a comment explaining what it is commented out for
+ cFile.println("// " + this.getTraverserInvocation(t.getVar(), "startingPtr, record", t.getStallSite())+"");
+ } else {
+ System.out.println("RuntimeConflictResolver encountered a taint that is neither SESE nor stallsite: " + t);
+ }
+ cFile.println(" break;");
+ }
+ */
+
+ cFile.println(" default:\n break;");
+
+ cFile.println(" }");
+ cFile.println("}");
+ }
+
+ private class ConcreteRuntimeObjNode {
+ HashSet<ObjRef> referencers;
+ Hashtable<String, ObjRefList> referencees;
+ Alloc alloc;
+ TypeDescriptor type;
+ SMFEState myState;
+ Set<SMFEState> transitions;
+
+ boolean isInsetVar;
+
+ //Accesses BY this node
+ boolean primConfRead=false;
+ boolean primConfWrite=false;
+ boolean objConfRead=false;
+ boolean objConfWrite=false;
+
+ public boolean descendantsPrimConflict = false;
+ public boolean descendantsObjConflict = false;
+ public boolean hasPotentialToBeIncorrectDueToConflict = false;
+
+ public ConcreteRuntimeObjNode(Alloc a, TypeDescriptor type, SMFEState state, Set<SMFEState> transitions, boolean isInset) {
+ referencers = new HashSet<ObjRef>(4);
+ referencees = new Hashtable<String, ObjRefList>(5);
+
+ alloc = a;
+ isInsetVar = isInset;
+ this.type = type;
+ myState = state;
+
+ if(transitions != null && !transitions.isEmpty()) {
+ if(this.transitions == null) {
+ this.transitions = new MySet<SMFEState>();
+ this.transitions.addAll(transitions);
+ } else {
+ this.transitions.addAll(transitions);
+ }
+ }
+ }
+
+ public void addReferencer(ObjRef refToMe) {
+ referencers.add(refToMe);
+ }
+
+ public void addReferencee(String field, ObjRef refToChild) {
+ ObjRefList array;
+
+ if((array = referencees.get(field)) == null) {
+ array = new ObjRefList();
+ referencees.put(field, array);
+ }
+
+ array.add(refToChild);
+ }
+
+ public boolean hasDirectObjConflict() {
+ return objConfRead || objConfWrite;
+ }
+
+ public TypeDescriptor getType() {
+ return type;
+ }
+
+ public boolean isArray() {
+ return type.isArray();
+ }
+
+ public boolean isTransition() {
+ return (transitions != null);
+ }
+
+ public int getNumOfReachableParents() {
+ return referencers.size();
+ }
+
+ public boolean hasPrimitiveConflicts() {
+ return primConfRead || primConfWrite;
+ }
+
+ public boolean hasConflict() {
+ return objConfRead || objConfWrite || primConfRead || primConfWrite;
+ }
+
+ public boolean descendantsConflict() {
+ return descendantsObjConflict||descendantsPrimConflict;
+ }
+
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof ConcreteRuntimeObjNode))
+ return false;
+
+ ConcreteRuntimeObjNode other = (ConcreteRuntimeObjNode) o;
+ return (alloc.equals(other.alloc) && myState.equals(other.myState));
+ }
+ }
+
+//This will keep track of a reference
+ private class ObjRef {
+ CombinedEffects myEffects;
+ boolean reachesConflict;
+ int allocID;
+ String field;
+
+
+ //This keeps track of the parent that we need to pass by inorder to get
+ //to the conflicting child (if there is one).
+ ConcreteRuntimeObjNode parent;
+ ConcreteRuntimeObjNode child;
+
+ public ObjRef(String fieldname,
+ ConcreteRuntimeObjNode parent,
+ ConcreteRuntimeObjNode ref,
+ CombinedEffects myEffects) {
+ field = fieldname;
+ allocID = ref.alloc.getUniqueAllocSiteID();
+ child = ref;
+ this.parent = parent;
+
+ this.myEffects = myEffects;
+ reachesConflict = false;
+ }
+
+ public boolean hasConflictsDownThisPath() {
+ return child.descendantsConflict() || child.hasPrimitiveConflicts() || myEffects.hasConflict();
+ }
+
+ public boolean hasDirectObjConflict() {
+ return myEffects.hasConflict();
+ }
+
+ public boolean equals(Object other) {
+ if(other == null || !(other instanceof ObjRef))
+ return false;
+
+ ObjRef o = (ObjRef) other;
+
+ if(o.field == this.field && o.allocID == this.allocID && this.child.equals(o.child))
+ return true;
+
+ return false;
+ }
+
+ public int hashCode() {
+ return child.alloc.hashCode() ^ field.hashCode();
+ }
+
+ public void mergeWith(ObjRef ref) {
+ myEffects.mergeWith(ref.myEffects);
+ }
+ }
+
+
+ //Simple extension of the ArrayList to allow it to find if any ObjRefs conflict.
+ private class ObjRefList extends ArrayList<ObjRef> {
+ private static final long serialVersionUID = 326523675530835596L;
+
+ public ObjRefList() {
+ super();
+ }
+
+ public boolean add(ObjRef o){
+ if(this.contains(o)) {
+ ObjRef other = this.get(this.indexOf(o));
+ other.mergeWith(o);
+ return false;
+ }
+ else
+ return super.add(o);
+ }
+
+ public boolean hasConflicts() {
+ for(ObjRef r: this) {
+ if(r.hasConflictsDownThisPath() || r.child.hasPrimitiveConflicts()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /*
+ private Hashtable<Alloc, ConcreteRuntimeObjNode> createTraversalGraph(EffectsTable et, Graph ptrGraph, TempDescriptor var) {
+ Hashtable<Alloc, ConcreteRuntimeObjNode> created
+ = new Hashtable<Alloc, ConcreteRuntimeObjNode>(); //Pass 0: Create empty graph
+ // what if we have more than one way in?! >< i.e. more than 1 temp descriptor...
+ Set<Edge> insetVars = ptrGraph.getEdges(var);
+ for(Edge invar: insetVars) {
+ Alloc rootKey = invar.getSrcAlloc().getAllocSite();
+
+ if(!created.contains(rootKey)) {
+ //null -> no transitions by reading this object (does not apply to its references
+ //bool true -> this is an inset variable
+ ConcreteRuntimeObjNode root = new ConcreteRuntimeObjNode(rootKey, var.getType(), null, true);
+ addToTraversalGraphStartingAt(root, et, ptrGraph.getEdges((AllocNode) rootKey), ptrGraph, created);
+ }
+ }
+
+ return created;
+ }
+
+
+ private void addToTraversalGraphStartingAt(
+ ConcreteRuntimeObjNode curr,
+ EffectsTable et,
+ MySet<Edge> edges,
+ Graph ptrGraph,
+ Hashtable<Alloc, ConcreteRuntimeObjNode> created) {
+ CombinedEffects ce;
+
+ //Handle Primitives
+ for(String field: et.getAllFields(curr.alloc).keySet()) {
+ if((ce = et.getCombinedEffects(curr.alloc, field)).isPrimitive);
+ curr.primConfRead |= ce.hasReadConflict;
+ curr.primConfWrite |= ce.hasWriteConflict;
+ }
+
+ //Handle Object Conflicts
+ for(Edge e: edges) {
+ //since we're starting from a src, it should match...
+ assert e.getSrcAlloc().equals(curr.alloc);
+ Alloc dst = e.getDst().getAllocSite();
+ String field = e.getFieldDesc().getSafeSymbol();
+ ce = et.getCombinedEffects(curr.alloc, field);
+ ConcreteRuntimeObjNode child;
+
+ //if ce is null, then that means we never go down that branch.
+ if(ce!=null) {
+ boolean isNewChild = !created.containsKey(dst);
+
+ if(isNewChild) {
+ //false = not inset
+ child = new ConcreteRuntimeObjNode(dst, e.getFieldDesc().getType(), ce.transitions, false);
+ created.put(dst, child);
+ } else {
+ child = created.get(dst);
+ }
+
+ ObjRef reference = new ObjRef(field, curr, child, ce);
+ curr.addReferencee(field, reference);
+
+ //update parent flags
+ curr.objConfRead |= ce.hasReadConflict;
+ curr.objConfWrite |= ce.hasWriteConflict;
+
+ //Update flags and recurse
+ if(ce.hasReadEffect) {
+ child.hasPotentialToBeIncorrectDueToConflict |= ce.hasReadConflict;
+ child.addReferencer(reference);
+
+ if(isNewChild) {
+ MySet<Edge> childEdges = ptrGraph.getEdges((AllocNode)dst);
+ addToTraversalGraphStartingAt(child, et, childEdges, ptrGraph, created);
+ }
+ }
+ }
+ }
+ }
+
+ //Note: FlatNode and temp descriptor are what used to be the taint.
+ void addAllocChecker(FlatNode fn, TempDescriptor tmp, EffectsTable et, ConcreteRuntimeObjNode node, String prefix, int depth, int heaprootNum, int stateID, Set<SMFEState> toVisit) {
+ insertEntriesIntoHashStructure(fn, tmp, node,prefix, depth, heaprootNum);
+
+ //Handle conflicts further down.
+ if(node.descendantsConflict()) {
+ int pdepth=depth+1;
+ cFile.println("{");
+
+ //Array Case
+ if(node.isArray()) {
+ String childPtr = "((struct ___Object___ **)(((char *) &(((struct ArrayObject *)"+ prefix+")->___length___))+sizeof(int)))[i]";
+ String currPtr = "arrayElement" + pdepth;
+
+ cFile.println("{\n int i;");
+ cFile.println(" struct ___Object___ * "+currPtr+";");
+ cFile.println(" for(i = 0; i<((struct ArrayObject *) " + prefix + " )->___length___; i++ ) {");
+
+ //There should be only one field, hence we only take the first field in the keyset.
+ assert node.referencees.keySet().size() <= 1;
+ ObjRefList refsAtParticularField = node.referencees.get(node.referencees.keySet().iterator().next());
+ printObjRefSwitchStatement(fn,tmp,et,pdepth,refsAtParticularField,childPtr,currPtr,heaprootNum,stateID,toVisit);
+ cFile.println(" }}");
+ } else {
+ //All other cases
+ String currPtr = "myPtr" + pdepth;
+ cFile.println(" struct ___Object___ * "+currPtr+";");
+ for(String field: node.referencees.keySet()) {
+ ObjRefList refsAtParticularField = node.referencees.get(field);
+
+ if(refsAtParticularField.hasConflicts()) {
+ String childPtr = "((struct "+node.getType().getSafeSymbol()+" *)"+prefix +")->___" + field + "___";
+ printObjRefSwitchStatement(fn,tmp,et,pdepth,refsAtParticularField,childPtr,currPtr,heaprootNum, stateID, toVisit);
+ }
+ }
+ }
+ cFile.println("}\n"); //For particular top level case statement.
+ }
+ }
+
+ // update to include state changes!
+ //If state changes branches INTO this object, then it needs its own state.
+ //Possible solution, have a hashtable to keep track of Alloc->PossibleTransition
+ //And add to it as we go through the effects.
+ private boolean qualifiesForCaseStatement(ConcreteRuntimeObjNode node) {
+ return true;
+// return (
+// //insetVariable case
+// (node.isInsetVar && (node.descendantsConflict() || node.hasPrimitiveConflicts()) || node.hasDirectObjConflict()) ||
+// //non-inline-able code cases
+// (node.getNumOfReachableParents() != 1 && node.descendantsConflict()) ||
+// //Cases where resumes are possible
+// (node.hasPotentialToBeIncorrectDueToConflict && node.descendantsObjConflict));
+ }
+
+ //FlatNode and TempDescriptor are what are used to make the taint
+ private void insertEntriesIntoHashStructure(FlatNode fn, TempDescriptor tmp,
+ ConcreteRuntimeObjNode curr, String prefix, int depth, int heaprootNum) {
+
+ int index = 0;
+ boolean isRblock = (fn instanceof FlatSESEEnterNode);
+ if (isRblock) {
+ FlatSESEEnterNode fsese = (FlatSESEEnterNode) fn;
+ index = fsese.getInVarsForDynamicCoarseConflictResolution().indexOf(tmp);
+ }
+
+ String strrcr = isRblock ? "&record->rcrRecords[" + index + "], " : "NULL, ";
+ String tasksrc =isRblock ? "(SESEcommon *) record, ":"(SESEcommon *)(((INTPTR)record)|1LL), ";
+
+ // Do call if we need it.
+ if (curr.primConfWrite || curr.objConfWrite) {
+ assert heaprootNum != -1;
+ cFile.append(" int tmpkey" + depth + "=rcr_generateKey(" + prefix + ");\n");
+ if (curr.descendantsConflict())
+ cFile.append(" int tmpvar" + depth + "=rcr_WTWRITEBINCASE(allHashStructures[" + heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
+ else
+ cFile.append(" int tmpvar" + depth + "=rcr_WRITEBINCASE(allHashStructures["+ heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
+ } else if (curr.primConfRead || curr.objConfRead) {
+ assert heaprootNum != -1;
+ cFile.append(" int tmpkey" + depth + "=rcr_generateKey(" + prefix + ");\n");
+ if (curr.descendantsConflict())
+ cFile.append(" int tmpvar" + depth + "=rcr_WTREADBINCASE(allHashStructures[" + heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
+ else
+ cFile.append(" int tmpvar" + depth + "=rcr_READBINCASE(allHashStructures["+ heaprootNum + "], tmpkey" + depth + ", " + tasksrc + strrcr + index + ");\n");
+ }
+
+ if (curr.primConfWrite || curr.objConfWrite || curr.primConfRead || curr.objConfRead) {
+ cFile.append("if (!(tmpvar" + depth + "&READYMASK)) totalcount--;\n");
+ }
+ }
+
+ private void printObjRefSwitchStatement(FlatNode fn,
+ EffectsTable et,
+ int pDepth,
+ ArrayList<ObjRef> refsAtParticularField,
+ String childPtr,
+ String currPtr,
+ int heaprootNum,
+ int stateID,
+ Set<SMFEState> toVisit) {
+
+ cFile.println(" "+currPtr+"= (struct ___Object___ * ) " + childPtr + ";");
+ cFile.println(" if (" + currPtr + " != NULL) { ");
+ cFile.println(" switch(" + currPtr + getAllocSiteInC + ") {");
+
+ for(ObjRef ref: refsAtParticularField) {
+ cFile.println(" case "+ref.allocID+":\n {");
+ //The hash insert is here because we don't want to enqueue things unless we know it conflicts.
+ cFile.println(" if (" + queryAndAddToVistedHashtable +"("+ currPtr + ", "+stateID+")) {");
+
+ if(ref.child.isTransition()) {
+ for(SMFEState s: ref.child.transitions) {
+ cFile.println(" " + addToQueueInC + childPtr + ", "+s.getID()+");");
+ }
+ } else if(qualifiesForCaseStatement(ref.child)){
+ cFile.println(" " + addToQueueInC + childPtr + ", "+stateID+");");
+ } else {
+// public void addChecker(AllocNode a, FlatNode fn, EffectsTable et, String prefix, int depth)
+ addCheker(..);
+ }
+
+ cFile.println(" }"); //close for queryVistedHashtable
+
+ cFile.println("}"); //close for internal case statement
+ }
+
+ cFile.append(" default:\n" +
+ " break;\n"+
+ " }}\n"); //internal switch.
+ }
+
+ //Walks the connected heaproot groups, coalesces them, and numbers them
+ //Special Note: Lookup Table must already be created
+ private void enumerateHeaproots() {
+ weaklyConnectedHRCounter = 0;
+ num2WeaklyConnectedHRGroup = new ArrayList<WeaklyConectedHRGroup>();
+
+ for(Taint t: connectedHRHash.keySet()) {
+ if(connectedHRHash.get(t).id == -1) {
+ WeaklyConectedHRGroup hg = connectedHRHash.get(t);
+ hg.id = weaklyConnectedHRCounter;
+ num2WeaklyConnectedHRGroup.add(weaklyConnectedHRCounter, hg);
+ weaklyConnectedHRCounter++;
+ }
+
+ if(t.isRBlockTaint()) {
+ int id=connectedHRHash.get(t).id;
+ Pair tup=new Pair(t.getVar(),t.getSESE());
+ if (weakMap.containsKey(tup)) {
+ if (weakMap.get(tup).intValue()!=id)
+ throw new Error("Var/SESE not unique for weak component.");
+ } else
+ weakMap.put(tup, new Integer(id));
+ }
+ }
+
+ //output weakly connected groups for verification
+ if(generalDebug) {
+ System.out.println("==============Weakly Connected HeapRoots==============");
+
+ for(int i=0; i < num2WeaklyConnectedHRGroup.size(); i++){
+ System.out.println("Heap Group #" + i);
+ WeaklyConectedHRGroup hg = num2WeaklyConnectedHRGroup.get(i);
+ for(Taint t: hg.connectedHRs) {
+ System.out.println("\t" + t);
+ }
+ }
+
+ System.out.println("=======================END LIST=======================");
+ }
+ }
+ */
+
+
+ /*
+ private class EffectsGroup {
+ Hashtable<String, CombinedEffects> myObjEffects;
+ //In the end, we don't really care what the primitive fields are.
+ Hashtable<String, CombinedEffects> primitiveConflictingFields;
+ private boolean primConfRead;
+ private boolean primConfWrite;
+
+ public EffectsGroup() {
+ myObjEffects = new Hashtable<String, CombinedEffects>();
+ primitiveConflictingFields = new Hashtable<String, CombinedEffects>();
+
+ primConfRead = false;
+ primConfWrite = false;
+ }
+
+ public void add(Effect e, boolean conflict, boolean leadsToTransistion) {
+ CombinedEffects effects;
+ if ((effects = myObjEffects.get(e.getField().getSymbol())) == null) {
+ effects = new CombinedEffects();
+ myObjEffects.put(e.getField().getSymbol(), effects);
+ }
+
+ effects.add(e, conflict, leadsToTransistion);
+
+ if (isReallyAPrimitive(e.getField().getType())) {
+ effects.add(e, conflict, false);
+
+ primConfRead |= effects.hasReadConflict;
+ primConfWrite |= effects.hasWriteConflict;
+ }
+ }
+
+
+ public boolean isEmpty() {
+ return myObjEffects.isEmpty() && primitiveConflictingFields.isEmpty();
+ }
+
+ public boolean hasPrimitiveConflicts(){
+ return !primitiveConflictingFields.isEmpty();
+ }
+
+ public CombinedEffects getPrimEffect(String field) {
+ return primitiveConflictingFields.get(field);
+ }
+
+ public boolean hasObjectEffects() {
+ return !myObjEffects.isEmpty();
+ }
+
+ public CombinedEffects getObjEffect(String field) {
+ return myObjEffects.get(field);
+ }
+ }
+ */
+
+
+
+
+
+ /*
+ //Performs a reverse traversal from the conflict nodes up to the
+ //inset variables and sets conflict flags on inner nodes.
+ private void propagateConflicts(Hashtable<Alloc, ConcreteRuntimeObjNode> created) {
+ for(ConcreteRuntimeObjNode node: created.values()) {
+ if(node.hasConflict()) {
+ markReferencers(node, node.objConfRead || node.objConfWrite, node.primConfRead || node.primConfWrite);
+ }
+ }
+ }
+
+ private void markReferencers(ConcreteRuntimeObjNode node, boolean ObjConf, boolean PrimConf) {
+ for(ObjRef ref: node.referencers) {
+ //if not already marked or data does not match
+ if(!ref.reachesConflict ||
+ (ObjConf && !ref.parent.descendantsObjConflict) ||
+ (PrimConf && !ref.parent.descendantsPrimConflict)) {
+
+ ref.parent.descendantsObjConflict |= ObjConf;
+ ref.parent.descendantsPrimConflict |= PrimConf;
+ ref.reachesConflict = true;
+ markReferencers(ref.parent, ObjConf, PrimConf);
+ }
+ }
+ }
+ */
/*