--- /dev/null
+package Analysis.Locality;
+import IR.State;
+import IR.MethodDescriptor;
+import IR.TypeDescriptor;
+import IR.FieldDescriptor;
+import IR.Flat.*;
+import Analysis.Loops.GlobalFieldType;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.Iterator;
+
+public class DelayComputation {
+ State state;
+ LocalityAnalysis locality;
+ TypeAnalysis typeanalysis;
+ GlobalFieldType gft;
+
+ public DelayComputation(LocalityAnalysis locality, State state, TypeAnalysis typeanalysis, GlobalFieldType gft) {
+ this.locality=locality;
+ this.state=state;
+ this.typeanalysis=typeanalysis;
+ this.gft=gft;
+ }
+
+ public void doAnalysis() {
+ Set<LocalityBinding> localityset=locality.getLocalityBindings();
+ for(Iterator<LocalityBinding> lb=localityset.iterator();lb.hasNext();) {
+ analyzeMethod(lb.next());
+ }
+ }
+
+ public void analyzeMethod(LocalityBinding lb) {
+ MethodDescriptor md=lb.getMethod();
+ FlatMethod fm=state.getMethodFlat(md);
+ HashSet<FlatNode> cannotdelay=new HashSet<FlatNode>();
+ Hashtable<FlatNode, Integer> atomictable=locality.getAtomic(lb);
+ if (lb.isAtomic()) {
+ //We are in a transaction already...
+ //skip past this method or something
+ return;
+ }
+
+ HashSet<FlatNode> toanalyze=new HashSet<FlatNode>();
+ toanalyze.addAll(fm.getNodeSet());
+
+ //Build the hashtables
+ Hashtable<FlatNode, HashSet<TempDescriptor>> nodelaytemps=new Hashtable<FlatNode, HashSet<TempDescriptor>>();
+ Hashtable<FlatNode, HashSet<FieldDescriptor>> nodelayfieldswr=new Hashtable<FlatNode, HashSet<FieldDescriptor>>();
+ Hashtable<FlatNode, HashSet<TypeDescriptor>> nodelayarrayswr=new Hashtable<FlatNode, HashSet<TypeDescriptor>>();
+ Hashtable<FlatNode, HashSet<FieldDescriptor>> nodelayfieldsrd=new Hashtable<FlatNode, HashSet<FieldDescriptor>>();
+ Hashtable<FlatNode, HashSet<TypeDescriptor>> nodelayarraysrd=new Hashtable<FlatNode, HashSet<TypeDescriptor>>();
+
+ //Effect of adding something to nodelay set is to move it up past everything in delay set
+ //Have to make sure we can do this commute
+
+ while(!toanalyze.isEmpty()) {
+ FlatNode fn=toanalyze.iterator().next();
+ toanalyze.remove(fn);
+
+ boolean isatomic=atomictable.get(fn).intValue()>0;
+
+ if (!isatomic)
+ continue;
+ boolean isnodelay=false;
+
+ /* Compute incoming nodelay sets */
+ HashSet<TempDescriptor> nodelaytempset=new HashSet<TempDescriptor>();
+ HashSet<FieldDescriptor> nodelayfieldwrset=new HashSet<FieldDescriptor>();
+ HashSet<TypeDescriptor> nodelayarraywrset=new HashSet<TypeDescriptor>();
+ HashSet<FieldDescriptor> nodelayfieldrdset=new HashSet<FieldDescriptor>();
+ HashSet<TypeDescriptor> nodelayarrayrdset=new HashSet<TypeDescriptor>();
+ for(int i=0;i<fn.numNext();i++) {
+ if (nodelaytemps.containsKey(fn.getNext(i)))
+ nodelaytempset.addAll(nodelaytemps.get(fn.getNext(i)));
+ //do field/array write sets
+ if (nodelayfieldswr.containsKey(fn.getNext(i)))
+ nodelayfieldwrset.addAll(nodelayfieldswr.get(fn.getNext(i)));
+ if (nodelayarrayswr.containsKey(fn.getNext(i)))
+ nodelayarraywrset.addAll(nodelayarrayswr.get(fn.getNext(i)));
+ //do read sets
+ if (nodelayfieldsrd.containsKey(fn.getNext(i)))
+ nodelayfieldrdset.addAll(nodelayfieldsrd.get(fn.getNext(i)));
+ if (nodelayarrayswr.containsKey(fn.getNext(i)))
+ nodelayarraywrset.addAll(nodelayarrayswr.get(fn.getNext(i)));
+ }
+
+ /* Check our temp write set */
+
+ TempDescriptor writeset[]=fn.writesTemps();
+ for(int i=0;i<writeset.length;i++) {
+ TempDescriptor tmp=writeset[i];
+ if (nodelaytempset.contains(tmp)) {
+ //We are writing to a nodelay temp
+ //Therefore we are nodelay
+ isnodelay=true;
+ //Kill temp we wrote to
+ nodelaytempset.remove(tmp);
+ }
+ }
+
+ //See if flatnode is definitely no delay
+ if (fn.kind()==FKind.FlatCall) {
+ isnodelay=true;
+ //Have to deal with fields/arrays
+ FlatCall fcall=(FlatCall)fn;
+ MethodDescriptor mdcall=fcall.getMethod();
+ nodelayfieldwrset.addAll(gft.getFieldsAll(mdcall));
+ nodelayarraywrset.addAll(typeanalysis.expandSet(gft.getArraysAll(mdcall)));
+ //Have to deal with field/array reads
+ nodelayfieldrdset.addAll(gft.getFieldsRdAll(mdcall));
+ nodelayarrayrdset.addAll(typeanalysis.expandSet(gft.getArraysRdAll(mdcall)));
+ }
+
+ // Can't delay branches
+ if (fn.kind()==FKind.FlatCondBranch) {
+ isnodelay=true;
+ }
+
+ //Check for field conflicts
+ if (fn.kind()==FKind.FlatSetFieldNode) {
+ FieldDescriptor fd=((FlatSetFieldNode)fn).getField();
+ //write conflicts
+ if (nodelayfieldwrset.contains(fd))
+ isnodelay=true;
+ //read
+ if (nodelayfieldrdset.contains(fd))
+ isnodelay=true;
+ }
+
+ if (fn.kind()==FKind.FlatFieldNode) {
+ FieldDescriptor fd=((FlatFieldNode)fn).getField();
+ //write conflicts
+ if (nodelayfieldwrset.contains(fd))
+ isnodelay=true;
+ }
+
+ //Check for array conflicts
+ if (fn.kind()==FKind.FlatSetElementNode) {
+ TypeDescriptor td=((FlatSetElementNode)fn).getDst().getType();
+ //check for write conflicts
+ if (nodelayarraywrset.contains(td))
+ isnodelay=true;
+ //check for read conflicts
+ if (nodelayarrayrdset.contains(td))
+ isnodelay=true;
+ }
+ if (fn.kind()==FKind.FlatElementNode) {
+ TypeDescriptor td=((FlatElementNode)fn).getSrc().getType();
+ //check for write conflicts
+ if (nodelayarraywrset.contains(td))
+ isnodelay=true;
+ }
+
+ //If we are no delay, then the temps we read are no delay
+ if (isnodelay) {
+ /* Add our read set */
+ TempDescriptor readset[]=fn.readsTemps();
+ for(int i=0;i<readset.length;i++) {
+ TempDescriptor tmp=readset[i];
+ nodelaytempset.add(tmp);
+ }
+ cannotdelay.add(fn);
+
+ /* Do we write to fields */
+ if (fn.kind()==FKind.FlatSetFieldNode) {
+ nodelayfieldwrset.add(((FlatSetFieldNode)fn).getField());
+ }
+ /* Do we read from fields */
+ if (fn.kind()==FKind.FlatFieldNode) {
+ nodelayfieldrdset.add(((FlatFieldNode)fn).getField());
+ }
+
+ /* Do we write to arrays */
+ if (fn.kind()==FKind.FlatSetElementNode) {
+ //have to do expansion
+ nodelayarraywrset.addAll(typeanalysis.expand(((FlatSetElementNode)fn).getDst().getType()));
+ }
+ /* Do we read from arrays */
+ if (fn.kind()==FKind.FlatElementNode) {
+ //have to do expansion
+ nodelayarrayrdset.addAll(typeanalysis.expand(((FlatSetElementNode)fn).getSrc().getType()));
+ }
+ }
+
+ boolean changed=false;
+ //See if we need to propagate changes
+ if (!nodelaytemps.containsKey(fn)||
+ !nodelaytemps.get(fn).equals(nodelaytempset)) {
+ nodelaytemps.put(fn, nodelaytempset);
+ changed=true;
+ }
+
+ //See if we need to propagate changes
+ if (!nodelayfieldswr.containsKey(fn)||
+ !nodelayfieldswr.get(fn).equals(nodelayfieldwrset)) {
+ nodelayfieldswr.put(fn, nodelayfieldwrset);
+ changed=true;
+ }
+
+ //See if we need to propagate changes
+ if (!nodelayfieldsrd.containsKey(fn)||
+ !nodelayfieldsrd.get(fn).equals(nodelayfieldrdset)) {
+ nodelayfieldsrd.put(fn, nodelayfieldrdset);
+ changed=true;
+ }
+
+ //See if we need to propagate changes
+ if (!nodelayarrayswr.containsKey(fn)||
+ !nodelayarrayswr.get(fn).equals(nodelayarraywrset)) {
+ nodelayarrayswr.put(fn, nodelayarraywrset);
+ changed=true;
+ }
+
+ //See if we need to propagate changes
+ if (!nodelayarraysrd.containsKey(fn)||
+ !nodelayarraysrd.get(fn).equals(nodelayarrayrdset)) {
+ nodelayarraysrd.put(fn, nodelayarrayrdset);
+ changed=true;
+ }
+
+ if (changed)
+ for(int i=0;i<fn.numPrev();i++)
+ toanalyze.add(fn.getPrev(i));
+ } //end of while loop
+
+ } //end of method
+} //end of class
\ No newline at end of file
}
public void doAnalysis() {
- //Compute fields and arrays for all transactions
+ //Compute fields and arrays for all transactions. Note that we
+ //only look at changes to old objects
+
Set<LocalityBinding> localityset=locality.getLocalityBindings();
for(Iterator<LocalityBinding> lb=localityset.iterator();lb.hasNext();) {
computeModified(lb.next());
return tmptofnset;
}
- /* See what fields and arrays transactions might modify. */
+ /* See what fields and arrays transactions might modify. We only
+ * look at changes to old objects. */
public void computeModified(LocalityBinding lb) {
MethodDescriptor md=lb.getMethod();
}
}
+
+ //Returns a table that maps a flatnode to a set of temporaries
+ //This set of temporaries is old (meaning they may point to object
+ //allocated before the beginning of the current transaction
+
Hashtable<FlatNode, Set<TempDescriptor>> computeOldTemps(LocalityBinding lb) {
Hashtable<FlatNode, Set<TempDescriptor>> fntooldtmp=new Hashtable<FlatNode, Set<TempDescriptor>>();
HashSet<FlatNode> discovered=new HashSet<FlatNode>();
{
FlatCall fc=(FlatCall) fn;
MethodDescriptor md=fc.getMethod();
- Set<FieldDescriptor> fields=gft.getFields(md);
- Set<TypeDescriptor> arrays=gft.getArrays(md);
- killexpressions(tab, fields, arrays, gft.containsAtomic(md)||gft.containsBarrier(md));
+ Set<FieldDescriptor> fields=gft.getFieldsAll(md);
+ Set<TypeDescriptor> arrays=gft.getArraysAll(md);
+ killexpressions(tab, fields, arrays, gft.containsAtomicAll(md)||gft.containsBarrierAll(md));
break;
}
case FKind.FlatOpNode:
MethodDescriptor root;
Hashtable<MethodDescriptor, Set<FieldDescriptor>> fields;
Hashtable<MethodDescriptor, Set<TypeDescriptor>> arrays;
+ Hashtable<MethodDescriptor, Set<FieldDescriptor>> fieldsrd;
+ Hashtable<MethodDescriptor, Set<TypeDescriptor>> arraysrd;
HashSet<MethodDescriptor> containsAtomic;
HashSet<MethodDescriptor> containsBarrier;
this.root=root;
this.fields=new Hashtable<MethodDescriptor, Set<FieldDescriptor>>();
this.arrays=new Hashtable<MethodDescriptor, Set<TypeDescriptor>>();
+ this.fieldsrd=new Hashtable<MethodDescriptor, Set<FieldDescriptor>>();
+ this.arraysrd=new Hashtable<MethodDescriptor, Set<TypeDescriptor>>();
this.containsAtomic=new HashSet<MethodDescriptor>();
this.containsBarrier=new HashSet<MethodDescriptor>();
doAnalysis();
changed=true;
if (arrays.get(md).addAll(arrays.get(md2)))
changed=true;
+ if (fieldsrd.get(md).addAll(fieldsrd.get(md2)))
+ changed=true;
+ if (arraysrd.get(md).addAll(arraysrd.get(md2)))
+ changed=true;
if (containsAtomic.contains(md2)) {
if (containsAtomic.add(md))
changed=true;
return arrays.get(md);
}
+ public Set<FieldDescriptor> getFieldsRd(MethodDescriptor md) {
+ return fieldsrd.get(md);
+ }
+
+ public Set<TypeDescriptor> getArraysRd(MethodDescriptor md) {
+ return arraysrd.get(md);
+ }
+
+ public boolean containsAtomicAll(MethodDescriptor md) {
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (containsAtomic.contains(md2))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean containsBarrierAll(MethodDescriptor md) {
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (containsBarrier.contains(md2))
+ return true;
+ }
+ return false;
+ }
+
+ public Set<FieldDescriptor> getFieldsAll(MethodDescriptor md) {
+ HashSet<FieldDescriptor> s=new HashSet<FieldDescriptor>();
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (fields.containsKey(md2))
+ s.addAll(fields.get(md2));
+ }
+ return s;
+ }
+
+ public Set<TypeDescriptor> getArraysAll(MethodDescriptor md) {
+ HashSet<TypeDescriptor> s=new HashSet<TypeDescriptor>();
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (arrays.containsKey(md2))
+ s.addAll(arrays.get(md2));
+ }
+ return s;
+ }
+
+ public Set<FieldDescriptor> getFieldsRdAll(MethodDescriptor md) {
+ HashSet<FieldDescriptor> s=new HashSet<FieldDescriptor>();
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (fieldsrd.containsKey(md2))
+ s.addAll(fieldsrd.get(md2));
+ }
+ return s;
+ }
+
+ public Set<TypeDescriptor> getArraysRdAll(MethodDescriptor md) {
+ HashSet<TypeDescriptor> s=new HashSet<TypeDescriptor>();
+ Set methodset=cg.getMethods(md);
+ for(Iterator it=methodset.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ if (arraysrd.containsKey(md2))
+ s.addAll(arraysrd.get(md2));
+ }
+ return s;
+ }
+
public void analyzeMethod(MethodDescriptor md) {
fields.put(md, new HashSet<FieldDescriptor>());
arrays.put(md, new HashSet<TypeDescriptor>());
+ fieldsrd.put(md, new HashSet<FieldDescriptor>());
+ arraysrd.put(md, new HashSet<TypeDescriptor>());
FlatMethod fm=st.getMethodFlat(md);
for(Iterator it=fm.getNodeSet().iterator();it.hasNext();) {
if (fn.kind()==FKind.FlatSetElementNode) {
FlatSetElementNode fsen=(FlatSetElementNode)fn;
arrays.get(md).add(fsen.getDst().getType());
+ } else if (fn.kind()==FKind.FlatElementNode) {
+ FlatElementNode fen=(FlatElementNode)fn;
+ arraysrd.get(md).add(fen.getSrc().getType());
} else if (fn.kind()==FKind.FlatSetFieldNode) {
FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
fields.get(md).add(fsfn.getField());
+ } else if (fn.kind()==FKind.FlatFieldNode) {
+ FlatFieldNode ffn=(FlatFieldNode)fn;
+ fieldsrd.get(md).add(ffn.getField());
} else if (fn.kind()==FKind.FlatAtomicEnterNode) {
containsAtomic.add(md);
} else if (fn.kind()==FKind.FlatCall) {
} else if (fn.kind()==FKind.FlatCall) {
FlatCall fcall=(FlatCall)fn;
MethodDescriptor md=fcall.getMethod();
- Set<FieldDescriptor> f=gft.getFields(md);
- Set<TypeDescriptor> t=gft.getArrays(md);
+ Set<FieldDescriptor> f=gft.getFieldsAll(md);
+ Set<TypeDescriptor> t=gft.getArraysAll(md);
if (f!=null)
fields.addAll(f);
if (t!=null)
types.addAll(t);
- if (gft.containsAtomic(md)||gft.containsBarrier(md)) {
+ if (gft.containsAtomicAll(md)||gft.containsBarrierAll(md)) {
unsafe=true;
}
} else if (fn.kind()==FKind.FlatSetFieldNode) {
//do side effects
FlatCall fc=(FlatCall)fn;
MethodDescriptor md=fc.getMethod();
- Set<FieldDescriptor> fields=gft.getFields(md);
- Set<TypeDescriptor> arrays=gft.getArrays(md);
- kill(table, fields, arrays, gft.containsAtomic(md), gft.containsBarrier(md));
+ Set<FieldDescriptor> fields=gft.getFieldsAll(md);
+ Set<TypeDescriptor> arrays=gft.getArraysAll(md);
+ kill(table, fields, arrays, gft.containsAtomicAll(md), gft.containsBarrierAll(md));
}
default: {
TempDescriptor[] writes=fn.writesTemps();
return flattenBlockNode(sbn.getBlockNode());
}
+ private NodePair flattenSynchronizedNode(SynchronizedNode sbn) {
+ TempDescriptor montmp=TempDescriptor.tempFactory("monitor",sbn.getExpr().getType());
+ NodePair npexp=flattenExpressionNode(sbn.getExpr(), montmp);
+ NodePair npblock=flattenBlockNode(sbn.getBlockNode());
+
+ MethodDescriptor menmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
+ FlatCall fcen=new FlatCall(menmd, null, montmp, new TempDescriptor[0]);
+
+ MethodDescriptor mexmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
+ FlatCall fcex=new FlatCall(mexmd, null, montmp, new TempDescriptor[0]);
+
+ npexp.getEnd().addNext(fcen);
+ fcen.addNext(npblock.getBegin());
+ npblock.getEnd().addNext(fcex);
+ return new NodePair(npexp.getBegin(), fcex);
+ }
+
private NodePair flattenAtomicNode(AtomicNode sbn) {
NodePair np=flattenBlockNode(sbn.getBlockNode());
FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
case Kind.AtomicNode:
return flattenAtomicNode((AtomicNode)bsn);
+ case Kind.SynchronizedNode:
+ return flattenSynchronizedNode((SynchronizedNode)bsn);
+
case Kind.SESENode:
return flattenSESENode((SESENode)bsn);
} else if (isNode(pn,"atomic")) {
BlockNode bn=parseBlockHelper(pn);
blockstatements.add(new AtomicNode(bn));
+ } else if (isNode(pn,"synchronized")) {
+ BlockNode bn=parseBlockHelper(pn.getChild("block"));
+ ExpressionNode en=parseExpression(pn.getChild("expr").getFirstChild());
+ blockstatements.add(new SynchronizedNode(en, bn));
} else if (isNode(pn,"return")) {
if (isEmpty(pn.getTerminal()))
blockstatements.add(new ReturnNode());
public final static int TertiaryNode=25;
public final static int InstanceOfNode=26;
public final static int ArrayInitializerNode=27;
+ public final static int SynchronizedNode=28;
}
checkAtomicNode(md, nametable, (AtomicNode)bsn);
return;
+ case Kind.SynchronizedNode:
+ checkSynchronizedNode(md, nametable, (SynchronizedNode)bsn);
+ return;
+
case Kind.ContinueBreakNode:
checkContinueBreakNode(md, nametable, (ContinueBreakNode) bsn);
return;
checkBlockNode(md, nametable, sbn.getBlockNode());
}
+ void checkSynchronizedNode(Descriptor md, SymbolTable nametable, SynchronizedNode sbn) {
+ checkBlockNode(md, nametable, sbn.getBlockNode());
+ //todo this could be Object
+ checkExpressionNode(md, nametable, sbn.getExpr(), null);
+ }
+
void checkContinueBreakNode(Descriptor md, SymbolTable nametable, ContinueBreakNode cbn) {
if (loopstack.empty())
throw new Error("continue/break outside of loop");
fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
if (fd==null)
throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0)+" in "+md);
+
if (fd.getType().iswrapper()) {
FieldAccessNode fan2=new FieldAccessNode(left, fieldname);
fan2.setField(fd);
}
public boolean iswrapper() {
- if (arraycount!=0||!isClass())
+ if (arraycount!=0||isClass())
return false;
return (name.equals("bytewrapper")||
name.equals("booleanwrapper")||
non terminal ParseNode break_statement, continue_statement;
non terminal ParseNode return_statement;
//non terminal ParseNode throw_statement;
-//non terminal ParseNode synchronized_statement, try_statement;
+non terminal ParseNode synchronized_statement;
+//non terminal ParseNode try_statement;
//non terminal ParseNode catches_opt;
//non terminal ParseNode catches, catch_clause;
//non terminal ParseNode finally;
| task_exitstatement:st {: RESULT=st; :}
| atomic_statement:st {: RESULT=st; :}
| sese_statement:st {: RESULT=st; :}
-// | synchronized_statement
+ | synchronized_statement:st {: RESULT=st; :}
// | throw_statement
// | try_statement
// | assert_statement
//throw_statement ::=
// THROW expression SEMICOLON
// ;
-//synchronized_statement ::=
-// SYNCHRONIZED LPAREN expression RPAREN block
-// ;
+synchronized_statement ::=
+ SYNCHRONIZED LPAREN expression:e RPAREN block:b {:
+ ParseNode pn=new ParseNode("synchronized");
+ pn.addChild("expr").addChild(e);
+ pn.addChild("block").addChild(b);
+ RESULT=pn;
+ :}
+ ;
atomic_statement ::=
ATOMIC block:blk {:
RESULT=(new ParseNode("atomic")).addChild(blk).getRoot();