+++ /dev/null
-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<LocalityBinding,LocalityBinding> discovered;
- Hashtable<MethodDescriptor, MethodDescriptor> 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<LocalityBinding,LocalityBinding>();
- this.dependence=new Hashtable<MethodDescriptor, MethodDescriptor>();
- 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<FlatNode, Hashtable<TempDescriptor,Integer>> computeCallsFlags(MethodDescriptor md, LocalityBinding lb) {
- FlatMethod fm=state.getMethodFlat(md);
- HashSet<FlatNode> tovisit=new HashSet<FlatNode>();
- Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
- tovisit.add(fm.getNext(0));
-
- {
- // Build table for initial node
- Hashtable<TempDescriptor,Integer> table=new Hashtable<TempDescriptor,Integer>();
- temptable.put(fm, table);
- for(int i=0;i<fm.numParameters();i++) {
- TempDescriptor temp=fm.getParameter(i);
- b=lb.isGlobal(i);
- table.put(temp,b);
- }
- }
-
- while(!tovisit.isEmpty()) {
- FlatNode fn=tovisit.iterator().next();
- Hashtable<TempDescriptor, Integer> currtable=new Hashtable<TempDescriptor, Integer>();
- for(int i=0;i<fn.numPrev();i++) {
- FlatNode prevnode=fn.getPrev(i);
- if (!temptable.containsKey(prevnode))
- continue;
- Hashtable<TempDescriptor, Integer> prevtable=temptable.get(prevnode);
- for(Iterator<TempDescriptor> 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<TempDescriptor,Integer> oldtable=temptable.get(fn);
- if (oldtable==null||!oldtable.equals(currtable)) {
- // Update table for this node
- temptable.put(fn, currtable);
- for(int i=0;i<fn.numNext();i++) {
- tovisit.add(fn.next(i));
- }
- }
- }
- }
-
- private static Integer merge(Integer a, Integer b) {
- if (a==null||a.equals(EITHER))
- return b;
- if (b==null||b.equals(EITHER))
- return a;
- if (a.equals(b))
- return a;
- return CONFLICT;
- }
-
- void processCall(LocalityBinding currlb, FlatCall fc, boolean transaction, Hashtable<TempDescriptor, Integer> 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<fc.numArgs();i++) {
- TempDescriptor arg=fc.getArg(i);
- lb.setGlobal(i,currtable.get(arg));
- }
- if (fc.getThis()!=null) {
- Integer thistype=currtable.get(fc.getThis());
- if(thistype.equals(CONFLICT))
- throw new Error("Using type that can be either local or global");
- if(thistype.equals(GLOBAL)&&!transaction)
- throw new Error("Using global object outside of transaction");
- lb.setGlobalThis(thistype);
- } else
- lb.setGlobalThis(EITHER);//default value
- //lb is built
- if (!discovered.containsKey(lb)) {
- lb.setGlobalReturn(EITHER);
- tovisit.add(lb);
- discovered.put(lb, lb);
- } else
- lb=discovered.get(lb);
- Integer returnval=lb.getGlobalReturn();
- currreturnval=merge(returnval, currreturnval);
- dependence.put(md, currlb.getMethod());
- }
- currtable.put(fc.getReturnTemp(), currreturnval);
- }
-
- void processFieldNode(LocalityBinding lb, FlatFieldNode ffn, boolean transaction, Hashtable<TempDescriptor, Integer> 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<TempDescriptor, Integer> 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<TempDescriptor, Integer> 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<TempDescriptor, Integer> currtable) {
- /* Just propagate value */
- currtable.put(fon.getDest(), currtable.get(fon.getLeft()));
- }
-
- void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
- currtable.put(fon.getDest(), currtable.get(fon.getSrc()));
- }
-
- void processLiteralNode(FlatLiteralNode fln, Hashtable<TempDescriptor, Integer> 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<TempDescriptor, Integer> currtable) {
- if(frn.getReturnTemp()!=null) {
- Integer returntype=currtable.get(frn.getReturnTemp());
- lb.setGlobalReturn(merge(returntype, lb.getGlobalReturn()));
- }
- }
-
- void processSetElementNode(FlatSetElementNode fsen, Hashtable<TempDescriptor, Integer> 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<TempDescriptor, Integer> 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");
- }
- }
-}