start of new file
[IRC.git] / Robust / src / Analysis / Locality / LocalityAnalysis.java
index 8a4907b0d57bae77739a27417b1fa650097873c6..adac83f89e7079dd898ee64bb95e61856b00994c 100644 (file)
@@ -14,12 +14,14 @@ public class LocalityAnalysis {
     Stack lbtovisit;
     Hashtable<LocalityBinding,LocalityBinding> discovered;
     Hashtable<LocalityBinding, Set<LocalityBinding>> dependence;
+    Hashtable<LocalityBinding, Set<LocalityBinding>> calldep;
     Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>> temptab;
     Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>> atomictab;
     Hashtable<LocalityBinding, Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>> tempstosave;
     Hashtable<ClassDescriptor, Set<LocalityBinding>> classtolb;
     Hashtable<MethodDescriptor, Set<LocalityBinding>> methodtolb;
     private LocalityBinding lbmain;
+    private LocalityBinding lbrun;
 
     CallGraph callgraph;
     TypeUtil typeutil;
@@ -33,6 +35,7 @@ public class LocalityAnalysis {
        this.state=state;
        this.discovered=new Hashtable<LocalityBinding,LocalityBinding>();
        this.dependence=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
+       this.calldep=new Hashtable<LocalityBinding, Set<LocalityBinding>>();
        this.temptab=new Hashtable<LocalityBinding, Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>>();
        this.atomictab=new Hashtable<LocalityBinding, Hashtable<FlatNode, Integer>>();
        this.lbtovisit=new Stack();
@@ -88,6 +91,10 @@ public class LocalityAnalysis {
        return methodtolb.get(md);
     }
 
+    public Set<MethodDescriptor> getMethods() {
+       return methodtolb.keySet();
+    }
+
     /** This method returns a set of LocalityBindings.  A
      * LocalityBinding specifies a context a method can be invoked in.
      * It specifies whether the method is in a transaction and whether
@@ -160,6 +167,34 @@ public class LocalityAnalysis {
     private void doAnalysis() {
        computeLocalityBindings();
        computeTempstoSave();
+       cleanSets();
+    }
+
+    private void cleanSets() {
+       HashSet<LocalityBinding> lbset=new HashSet<LocalityBinding>();
+       Stack<LocalityBinding> lbstack=new Stack<LocalityBinding>();
+       lbstack.add(lbmain);
+       lbstack.add(lbrun);
+       lbset.add(lbmain);
+       lbset.add(lbrun);
+       while(!lbstack.isEmpty()) {
+           LocalityBinding lb=lbstack.pop();
+           if (calldep.containsKey(lb)) {
+               Set<LocalityBinding> set=new HashSet<LocalityBinding>();
+               set.addAll(calldep.get(lb));
+               set.removeAll(lbset);
+               lbstack.addAll(set);
+               lbset.addAll(set);
+           }
+       }
+       for(Iterator<LocalityBinding> lbit=discovered.keySet().iterator();lbit.hasNext();) {
+           LocalityBinding lb=lbit.next();
+           if (!lbset.contains(lb)) {
+               lbit.remove();
+               classtolb.get(lb.getMethod().getClassDesc()).remove(lb);
+               methodtolb.get(lb.getMethod()).remove(lb);
+           }
+       }
     }
     
     private void computeLocalityBindings() {
@@ -177,7 +212,7 @@ public class LocalityAnalysis {
        methodtolb.get(lbmain.getMethod()).add(lbmain);
 
        //Do this to force a virtual table number for the run method
-       LocalityBinding lbrun=new LocalityBinding(typeutil.getRun(), false);
+       lbrun=new LocalityBinding(typeutil.getRun(), false);
        lbrun.setGlobalReturn(EITHER);
        lbrun.setGlobalThis(GLOBAL);
        lbtovisit.add(lbrun);
@@ -196,7 +231,14 @@ public class LocalityAnalysis {
            MethodDescriptor md=lb.getMethod();
            Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>> temptable=new Hashtable<FlatNode,Hashtable<TempDescriptor, Integer>>();
            Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
-           computeCallsFlags(md, lb, temptable, atomictable);
+           calldep.remove(lb);
+           try {
+               computeCallsFlags(md, lb, temptable, atomictable);
+           } catch (Error e) {
+               System.out.println("Error in "+md+" context "+lb);
+               e.printStackTrace();
+               System.exit(-1);
+           }
            atomictab.put(lb, atomictable);
            temptab.put(lb, temptable);
 
@@ -333,6 +375,7 @@ public class LocalityAnalysis {
        MethodDescriptor nodemd=fc.getMethod();
        Set methodset=null;
        Set runmethodset=null;
+
        if (nodemd.isStatic()||nodemd.getReturnType()==null) {
            methodset=new HashSet();
            methodset.add(nodemd);
@@ -358,14 +401,17 @@ public class LocalityAnalysis {
                } else throw new Error("Can't find run method");
            }
        }
+
        Integer currreturnval=EITHER; //Start off with the either value
        for(Iterator methodit=methodset.iterator();methodit.hasNext();) {
            MethodDescriptor md=(MethodDescriptor) methodit.next();
-           boolean isnative=md.getModifiers().isNative();
 
+           boolean isnative=md.getModifiers().isNative();
+           boolean isjoin = md.getClassDesc().getSymbol().equals(TypeUtil.ThreadClass)&&!nodemd.getModifiers().isStatic()&&nodemd.numParameters()==0&&md.getSymbol().equals("join");
+           
            LocalityBinding lb=new LocalityBinding(md, isatomic);
            if (isnative&&isatomic) {
-               System.out.println("Don't call native methods in atomic blocks!");
+               System.out.println("Don't call native methods in atomic blocks!"+currlb.getMethod());
            }
            if (runmethodset==null||!runmethodset.contains(md)) {
                //Skip this part if it is a run method
@@ -378,7 +424,6 @@ public class LocalityAnalysis {
                }
            }
 
-
            if (fc.getThis()!=null) {
                Integer thistype=currtable.get(fc.getThis());
                if (thistype==null)
@@ -386,11 +431,13 @@ public class LocalityAnalysis {
 
                if(runmethodset!=null&&runmethodset.contains(md)&&thistype.equals(LOCAL))
                    throw new Error("Starting thread on local object not allowed in context:\n"+currlb.getExplanation());
+               if(isjoin&&thistype.equals(LOCAL))
+                   throw new Error("Joining thread on local object not allowed in context:\n"+currlb.getExplanation());
                if(thistype.equals(CONFLICT))
                    throw new Error("Using type that can be either local or global in context:\n"+currlb.getExplanation());
-               if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic)
+               if(runmethodset==null&&thistype.equals(GLOBAL)&&!isatomic && !isjoin) 
                    throw new Error("Using global object outside of transaction in context:\n"+currlb.getExplanation());
-               if (runmethodset==null&&isnative&&thistype.equals(GLOBAL))
+               if (runmethodset==null&&isnative&&thistype.equals(GLOBAL) && !isjoin)
                    throw new Error("Potential call to native method "+md+" on global objects:\n"+currlb.getExplanation());
                lb.setGlobalThis(thistype);
            } 
@@ -416,6 +463,10 @@ public class LocalityAnalysis {
            if (!dependence.containsKey(lb))
                dependence.put(lb, new HashSet<LocalityBinding>());
            dependence.get(lb).add(currlb);
+
+           if (!calldep.containsKey(currlb))
+               calldep.put(currlb, new HashSet<LocalityBinding>());
+           calldep.get(currlb).add(lb);
        }
        if (fc.getReturnTemp()!=null) {
            currtable.put(fc.getReturnTemp(), currreturnval);
@@ -433,12 +484,12 @@ public class LocalityAnalysis {
        } else if (type.equals(GLOBAL)) {
            if (!transaction)
                throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
-           if (ffn.getField().getType().isPrimitive())
+           if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
                currtable.put(dst, LOCAL); // primitives are local
            else
                currtable.put(dst, GLOBAL);
        } else if (type.equals(EITHER)) {
-           if (ffn.getField().getType().isPrimitive())
+           if (ffn.getField().getType().isPrimitive()&&!ffn.getField().getType().isArray())
                currtable.put(dst, LOCAL); // primitives are local
            else if (ffn.getField().isGlobal())
                currtable.put(dst, GLOBAL);
@@ -453,7 +504,7 @@ public class LocalityAnalysis {
     void processSetFieldNode(LocalityBinding lb, FlatSetFieldNode fsfn, boolean transaction, Hashtable<TempDescriptor, Integer> currtable) {
        Integer srctype=currtable.get(fsfn.getSrc());
        Integer dsttype=currtable.get(fsfn.getDst());
-       
+
        if (dsttype.equals(LOCAL)) {
            if (fsfn.getField().isGlobal()) {
                if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
@@ -466,7 +517,7 @@ public class LocalityAnalysis {
            if (!transaction)
                throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
            //okay to store primitives in global object
-           if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive())
+           if (srctype.equals(LOCAL) && fsfn.getField().getType().isPrimitive() && ! fsfn.getField().getType().isArray())
                return;
            if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
                throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation()+" for FlatFieldNode "+fsfn);
@@ -491,10 +542,14 @@ public class LocalityAnalysis {
     void processOpNode(FlatOpNode fon, Hashtable<TempDescriptor, Integer> currtable) {
        /* Just propagate value */
        Integer srcvalue=currtable.get(fon.getLeft());
+
        if (srcvalue==null) {
-           throw new Error(fon.getLeft()+" is undefined!");
+           if (!fon.getLeft().getType().isPtr()) {
+               srcvalue=LOCAL;
+           } else
+               throw new Error(fon.getLeft()+" is undefined!");
        }
-       currtable.put(fon.getDest(), currtable.get(fon.getLeft()));
+       currtable.put(fon.getDest(), srcvalue);
     }
 
     void processCastNode(FlatCastNode fcn, Hashtable<TempDescriptor, Integer> currtable) {
@@ -522,8 +577,10 @@ public class LocalityAnalysis {
 
        if (dsttype.equals(LOCAL)) {
            if (!(srctype.equals(LOCAL)||srctype.equals(EITHER)))
-               throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation());
+               throw new Error("Writing possible global reference to local object in context:\n"+lb.getExplanation()+fsen);
        } else if (dsttype.equals(GLOBAL)) {
+           if (srctype.equals(LOCAL) && fsen.getDst().getType().dereference().isPrimitive() && ! fsen.getDst().getType().dereference().isArray())
+               return;
            if (!(srctype.equals(GLOBAL)||srctype.equals(EITHER)))
                throw new Error("Writing possible local reference to global object in context:\n"+lb.getExplanation());
            if (!isatomic)
@@ -544,9 +601,17 @@ public class LocalityAnalysis {
        } else if (type.equals(GLOBAL)) {
            if (!isatomic)
                throw new Error("Global access outside of a transaction in context:\n"+lb.getExplanation());
-           currtable.put(dst, GLOBAL);
+           if(fen.getSrc().getType().dereference().isPrimitive()&&
+              !fen.getSrc().getType().dereference().isArray())
+               currtable.put(dst, LOCAL);
+           else
+               currtable.put(dst, GLOBAL);
        } else if (type.equals(EITHER)) {
-           currtable.put(dst, EITHER);
+           if(fen.getSrc().getType().dereference().isPrimitive()&&
+              !fen.getSrc().getType().dereference().isArray())
+               currtable.put(dst, LOCAL);
+           else
+               currtable.put(dst, EITHER);
        } else if (type.equals(CONFLICT)) {
            throw new Error("Access to object that could be either global or local in context:\n"+lb.getExplanation());
        }
@@ -572,7 +637,7 @@ public class LocalityAnalysis {
            toprocess.remove(fn);
 
            List<TempDescriptor> reads=Arrays.asList(fn.readsTemps());
-           List<TempDescriptor> writes=Arrays.asList(fn.readsTemps());
+           List<TempDescriptor> writes=Arrays.asList(fn.writesTemps());
 
            HashSet<TempDescriptor> tempset=new HashSet<TempDescriptor>();
            for(int i=0;i<fn.numNext();i++) {
@@ -583,7 +648,7 @@ public class LocalityAnalysis {
            tempset.removeAll(writes);
            tempset.addAll(reads);
            if (!nodetotemps.containsKey(fn)||
-               nodetotemps.get(fn).equals(tempset)) {
+               !nodetotemps.get(fn).equals(tempset)) {
                nodetotemps.put(fn, tempset);
                for(int i=0;i<fn.numPrev();i++)
                    toprocess.add(fn.getPrev(i));
@@ -615,13 +680,10 @@ public class LocalityAnalysis {
        Hashtable<FlatNode, Hashtable<TempDescriptor, Integer>> temptab=getNodeTempInfo(lb);
        MethodDescriptor md=lb.getMethod();
        FlatMethod fm=state.getMethodFlat(md);
-
        Hashtable<FlatNode, Set<TempDescriptor>> nodetotemps=computeLiveTemps(fm);
        Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>> nodetosavetemps=new Hashtable<FlatAtomicEnterNode, Set<TempDescriptor>>();
        tempstosave.put(lb, nodetosavetemps);
-
        Hashtable<FlatNode, FlatAtomicEnterNode> nodemap=new Hashtable<FlatNode, FlatAtomicEnterNode>();
-       
        HashSet<FlatNode> toprocess=new HashSet<FlatNode>();
        HashSet<FlatNode> discovered=new HashSet<FlatNode>();
        toprocess.add(fm);