From: bdemsky Date: Fri, 20 Jul 2007 19:21:58 +0000 (+0000) Subject: check in locality analysis X-Git-Tag: preEdgeChange~516 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4aed159276b8950757ed4f0980db69190d8a5119;p=IRC.git check in locality analysis --- diff --git a/Robust/src/Analysis/Locality/LocalityAnalysis.java b/Robust/src/Analysis/Locality/LocalityAnalysis.java new file mode 100644 index 00000000..8d74ae39 --- /dev/null +++ b/Robust/src/Analysis/Locality/LocalityAnalysis.java @@ -0,0 +1,311 @@ +package Analysis.Locality; + +import java.util.Hashtable; +import java.util.Stack; +import java.util.Set; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Arrays; +import Analysis.CallGraph.CallGraph; +import IR.SymbolTable; +import IR.State; +import IR.MethodDescriptor; +import IR.Flat.*; + +public class LocalityAnalysis { + State state; + Stack tovisit; + Hashtable discovered; + Hashtable dependence; + CallGraph callgraph; + TypeUtil typeutil; + public static final Integer LOCAL=new Integer(0); + public static final Integer GLOBAL=new Integer(1); + public static final Integer EITHER=new Integer(2); + public static final Integer CONFLICT=new Integer(3); + + + public LocalityAnalysis(State state, CallGraph callgraph, TypeUtil typeutil) { + this.state=state; + this.discovered=new Hashtable(); + this.dependence=new Hashtable(); + this.tovisit=new Stack(); + this.callgraph=callgraph; + doAnalysis(); + } + + private void doAnalysis() { + computeLocalityBindings(); + } + + private void computeLocalityBindings() { + LocalityBinding lb=new LocalityBinding(typeutil.getMain(), false); + tovisit.add(lb); + discovered.put(lb, lb); + + while(!tovisit.empty()) { + LocalityBinding lb=(LocalityBinding) tovisit.pop(); + MethodDescriptor md=lb.getMethod(); + computeCallsFlags(md, lb); + } + } + + public Hashtable> computeCallsFlags(MethodDescriptor md, LocalityBinding lb) { + FlatMethod fm=state.getMethodFlat(md); + HashSet tovisit=new HashSet(); + Hashtable> temptable=new Hashtable>(); + tovisit.add(fm.getNext(0)); + + { + // Build table for initial node + Hashtable table=new Hashtable(); + temptable.put(fm, table); + for(int i=0;i currtable=new Hashtable(); + for(int i=0;i prevtable=temptable.get(prevnode); + for(Iterator tempit=prevtable.keySet().iterator();tempit.hasNext();) { + TempDescriptor temp=tempit.next(); + Integer tmpint=prevtable.get(temp); + Integer oldint=currtable.containsKey(temp)?currtable.get(temp):null; + Integer newint=merge(tmpint, oldint); + currtable.put(temp, newint); + } + } + // Process this node + switch(fn.kind()) { + case FlatCall: + processCall(md, (FlatCall)fn, currtable); + break; + case FlatFieldNode: + processFieldNode((FlatFieldNode)fn, currtable); + break; + case FlatSetFieldNode: + processSetFieldNode((FlatSetFieldNode)fn, currtable); + break; + case FlatNew: + processNew((FlatNew)fn, currtable); + break; + case FlatOpNode: + processOpNode((FlatOpNode)fn, currtable); + break; + case FlatCastNode: + processCastNode((FlatCastNode)fn, currtable); + break; + case FlatLiteralNode: + processLiteralNode((FlatLiteralNode)fn, currtable); + break; + case FlatReturnNode: + processReturnNode((FlatReturnNode)fn, currtable); + break; + case FlatSetElementNode: + processSetElement((FlatSetElementNode)fn, currtable); + break; + case FlatElementNode: + processElement((FlatElementNode)fn, currtable); + break; + + case FlatCondBranch: + case FlatBackEdge: + case FlatNop: + //No action needed for these + break; + case FlatFlagActionNode: + case FlatCheckNode: + case FlatTagDeclaration: + throw new Error("Incompatible with tasks!"); + case FlatMethod: + default: + throw new Error(); + } + Hashtable oldtable=temptable.get(fn); + if (oldtable==null||!oldtable.equals(currtable)) { + // Update table for this node + temptable.put(fn, currtable); + for(int i=0;i currtable) { + MethodDescriptor nodemd=fc.getMethod(); + Set methodset=fc.getThis()==null?callgraph.getMethods(nodemd): + callgraph.getMethods(nodemd, fc.getThis().getType()); + Integer currreturnval=null; + for(Iterator methodit=methodset.iterator();methodit.hasNext();) { + MethodDescriptor md=(MethodDescriptor) methodit.next(); + LocalityBinding lb=new LocalityBinding(md, transaction); + for(int i=0;i currtable) { + Integer type=currtable.get(ffn.getSrc()); + TempDescriptor dst=ffn.getDst(); + if (type.equals(LOCAL)) { + if (ffn.getField().isGlobal()) + currtable.put(dst,GLOBAL); + else + currtable.put(dst,LOCAL); + } else if (type.equals(GLOBAL)) { + if (!transaction) + throw Error("Global access outside of a transaction"); + if (ffn.getField().getType().isPrimitive()) + currtable.put(dst, LOCAL); // primitives are local + else + currtable.put(dst, GLOBAL); + } else if (type.equals(EITHER)) { + if (ffn.getField().getType().isPrimitive()) + currtable.put(dst, LOCAL); // primitives are local + else + currtable.put(dst, EITHER); + } else if (type.equals(CONFLICT)) { + throw new Error("Access to object that could be either global or local"); + } + } + + //need to handle primitives + void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable currtable) { + Integer srctype=currtable.get(ffn.getSrc()); + Integer dsttype=currtable.get(ffn.getDst()); + + if (dsttype.equals(LOCAL)) { + if (ffn.getField().isGlobal()) { + if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER))) + throw new Error("Writing possible local reference to global field"); + } else { + if (!(srctype.equals(LOCAL)||srctype.equals(EITHER))) + throw new Error("Writing possible global reference to local object"); + } + } else if (dsttype.equals(GLOBAL)) { + if (!transaction) + throw Error("Global access outside of a transaction"); + //okay to store primitives in global object + if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive()) + return; + if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER))) + throw new Error("Writing possible local reference to global object"); + } else if (dsttype.equals(EITHER)) { + if (srctype.equals(CONFLICT)) + throw new Error("Using reference that could be local or global"); + } else if (dsttype.equals(CONFLICT)) { + throw new Error("Access to object that could be either global or local"); + } + } + + void processNew(LocalityBinding lb, FlatNew fn, boolean transaction, Hashtable currtable) { + if (fn.isGlobal()&&!transaction) { + throw new Error("Allocating global object outside of transaction"); + } + if (fn.isGlobal()) + currtable.put(fn.getDst(), GLOBAL); + else + currtable.put(fn.getDst(), LOCAL); + } + + void processOpNode(FlatOpNode fon, Hashtable currtable) { + /* Just propagate value */ + currtable.put(fon.getDest(), currtable.get(fon.getLeft())); + } + + void processCastNode(FlatCastNode fcn, Hashtable currtable) { + currtable.put(fon.getDest(), currtable.get(fon.getSrc())); + } + + void processLiteralNode(FlatLiteralNode fln, Hashtable currtable) { + //null is either + if (fln.getValue()==null) + currtable.put(fln.getDst(), EITHER); + else + currtable.put(fln.getDst(), LOCAL); + } + + void processReturnNode(LocalityBinding lb, FlatReturnNode frn, Hashtable currtable) { + if(frn.getReturnTemp()!=null) { + Integer returntype=currtable.get(frn.getReturnTemp()); + lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn())); + } + } + + void processSetElementNode(FlatSetElementNode fsen, Hashtable currtable) { + Integer srctype=currtable.get(fsen.getSrc()); + Integer dsttype=currtable.get(fsen.getDst()); + + if (dsttype.equals(LOCAL)) { + if (!(srctype.equals(LOCAL)||srctype.equals(EITHER))) + throw new Error("Writing possible global reference to local object"); + } else if (dsttype.equals(GLOBAL)) { + if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER))) + throw new Error("Writing possible local reference to global object"); + if (!transaction) + throw Error("Global access outside of a transaction"); + } else if (dsttype.equals(EITHER)) { + if (srctype.equals(CONFLICT)) + throw new Error("Using reference that could be local or global"); + } else if (dsttype.equals(CONFLICT)) { + throw new Error("Access to object that could be either global or local"); + } + } + + void processElementNode(FlatElementNode fen, Hashtable currtable) { + Integer type=currtable.get(fen.getSrc()); + TempDescriptor dst=fen.getDst(); + if (type.equals(LOCAL)) { + currtable.put(dst,LOCAL); + } else if (type.equals(GLOBAL)) { + if (!transaction) + throw Error("Global access outside of a transaction"); + currtable.put(dst, GLOBAL); + } else if (type.equals(EITHER)) { + currtable.put(dst, EITHER); + } else if (type.equals(CONFLICT)) { + throw new Error("Access to object that could be either global or local"); + } + } +} diff --git a/Robust/src/Analysis/Locality/LocalityBinding.java b/Robust/src/Analysis/Locality/LocalityBinding.java new file mode 100644 index 00000000..5df96d9e --- /dev/null +++ b/Robust/src/Analysis/Locality/LocalityBinding.java @@ -0,0 +1,82 @@ +package Analysis.Locality; +import IR.MethodDescriptor; + +public class LocalityBinding { + private MethodDescriptor md; + private Integer[] isglobal; + private boolean istransaction; + private Integer isglobalreturn; + private Integer isglobalthis; + + public LocalityBinding(MethodDescriptor md, boolean transaction) { + this.md=md; + isglobal=new boolean[md.numParameters()]; + istransaction=transaction; + } + + public String toString() { + String st=md.toString()+" "; + for(int i=0;i