1 package Analysis.OoOJava;
6 import Analysis.Liveness;
7 import Analysis.CallGraph.CallGraph;
9 public class Accessible {
10 //Try to compute InAccessible
11 HashMap<FlatNode, Set<TempDescriptor>> inAccessible;
14 RBlockRelationAnalysis taskAnalysis;
16 Stack<Pair<FlatNode,MethodDescriptor>> toprocess=new Stack<Pair<FlatNode, MethodDescriptor>>();
17 HashMap<MethodDescriptor, Set<Pair<FlatCall, MethodDescriptor>>> methodmap=new HashMap<MethodDescriptor, Set<Pair<FlatCall, MethodDescriptor>>>();
19 public Accessible(State state, CallGraph callGraph, RBlockRelationAnalysis taskAnalysis, Liveness liveness) {
20 inAccessible=new HashMap<FlatNode, Set<TempDescriptor>>();
22 this.callGraph=callGraph;
23 this.taskAnalysis=taskAnalysis;
24 this.liveness=liveness;
27 public boolean isAccessible(FlatNode fn, TempDescriptor tmp) {
28 for(int i=0; i<fn.numPrev(); i++) {
29 FlatNode fprev=fn.getPrev(i);
30 if (inAccessible.containsKey(fprev)&&inAccessible.get(fprev).contains(tmp))
36 public void computeFixPoint() {
38 while(!toprocess.isEmpty()) {
39 Pair<FlatNode, MethodDescriptor> fnpair=toprocess.pop();
40 FlatNode fn=fnpair.getFirst();
41 MethodDescriptor pairmd=fnpair.getSecond();
42 HashSet<TempDescriptor> inAccessibleSet=new HashSet<TempDescriptor>();
43 for(int i=0; i<fn.numPrev(); i++) {
44 Set<TempDescriptor> inAccess=inAccessible.get(fn.getPrev(i));
46 inAccessibleSet.addAll(inAccess);
51 case FKind.FlatFieldNode:
52 case FKind.FlatElementNode:
53 case FKind.FlatSetFieldNode:
54 case FKind.FlatSetElementNode:
56 TempDescriptor[] rdtmps=fn.readsTemps();
57 for(int i=0; i<rdtmps.length; i++) {
58 inAccessibleSet.remove(rdtmps[i]);
60 TempDescriptor[] wrtmps=fn.writesTemps();
61 for(int i=0; i<wrtmps.length; i++) {
62 inAccessibleSet.remove(wrtmps[i]);
67 case FKind.FlatCastNode:
68 case FKind.FlatOpNode:
70 TempDescriptor[] rdtmps=fn.readsTemps();
71 TempDescriptor[] wrtmps=fn.writesTemps();
72 if (inAccessibleSet.contains(rdtmps[0]))
73 inAccessibleSet.add(wrtmps[0]);
77 case FKind.FlatReturnNode:
79 FlatReturnNode fr=(FlatReturnNode)fn;
80 if (fr.getReturnTemp()!=null&&inAccessibleSet.contains(fr.getReturnTemp())) {
81 //Need to inform callers
82 Set<Pair<FlatCall, MethodDescriptor>> callset=methodmap.get(pairmd);
83 for(Pair<FlatCall, MethodDescriptor> fcallpair : callset) {
84 FlatCall fcall=fcallpair.getFirst();
85 Set<TempDescriptor> inAccess=inAccessible.get(fcall);
86 if (fcall.getReturnTemp()!=null&&!inAccess.contains(fcall.getReturnTemp())) {
87 inAccess.add(fcall.getReturnTemp());
88 for(int i=0; i<fcall.numNext(); i++) {
89 toprocess.add(new Pair<FlatNode, MethodDescriptor>(fcall.getNext(i), fcallpair.getSecond()));
97 case FKind.FlatSESEEnterNode:
98 case FKind.FlatSESEExitNode:
101 case FKind.FlatCall: {
102 FlatCall fcall=(FlatCall)fn;
103 MethodDescriptor calledmethod=fcall.getMethod();
104 Set methodsthatcouldbecalled=fcall.getThis()==null?callGraph.getMethods(calledmethod):
105 callGraph.getMethods(calledmethod, fcall.getThis().getType());
106 for(Object o : methodsthatcouldbecalled) {
107 MethodDescriptor md=(MethodDescriptor)o;
108 FlatMethod fm=state.getMethodFlat(md);
110 if (!methodmap.containsKey(md))
111 methodmap.put(md, new HashSet<Pair<FlatCall, MethodDescriptor>>());
113 methodmap.get(md).add(new Pair<FlatCall, MethodDescriptor>(fcall, pairmd));
115 HashSet<TempDescriptor> tmpinaccess=new HashSet<TempDescriptor>();
116 for(int i=0; i<fm.numParameters(); i++) {
117 TempDescriptor fmtmp=fm.getParameter(i);
118 TempDescriptor tmpcall=fcall.getArgMatchingParamIndex(fm, i);
119 if (inAccessibleSet.contains(tmpcall)) {
120 tmpinaccess.add(fmtmp);
123 if (!tmpinaccess.isEmpty()&&(!inAccessible.containsKey(fm)||!inAccessible.get(fm).containsAll(tmpinaccess))) {
124 for(int i=0; i<fm.numNext(); i++)
125 toprocess.add(new Pair<FlatNode, MethodDescriptor>(fm.getNext(i),md));
126 if (!inAccessible.containsKey(fm))
127 inAccessible.put(fm, new HashSet<TempDescriptor>());
128 inAccessible.get(fm).addAll(tmpinaccess);
131 //be sure not to wipe out return value or other inaccessible temps
132 Set<TempDescriptor> oldtemps=inAccessible.get(fcall);
134 inAccessibleSet.addAll(oldtemps);
140 if (!inAccessibleSet.isEmpty()&&(!inAccessible.containsKey(fn)||!inAccessible.get(fn).equals(inAccessibleSet))) {
141 inAccessible.put(fn, inAccessibleSet);
142 for(int i=0; i<fn.numNext(); i++)
143 toprocess.add(new Pair<FlatNode, MethodDescriptor>(fn.getNext(i),pairmd));
148 public void doAnalysis() {
149 for(FlatSESEEnterNode sese : taskAnalysis.getAllSESEs()) {
150 FlatSESEExitNode seseexit=sese.getFlatExit();
151 HashSet<TempDescriptor> liveout=new HashSet<TempDescriptor>(liveness.getLiveOutTemps(sese.getfmEnclosing(), seseexit));
152 for(Iterator<TempDescriptor> tmpit=liveout.iterator(); tmpit.hasNext(); ) {
153 TempDescriptor tmp=tmpit.next();
154 if (!tmp.getType().isPtr())
157 inAccessible.put(seseexit, liveout);
158 for(int i=0; i<seseexit.numNext(); i++)
159 toprocess.add(new Pair<FlatNode, MethodDescriptor>(seseexit.getNext(i),sese.getmdEnclosing()));
162 Set<MethodDescriptor> methodSet=taskAnalysis.getMethodsWithSESEs();
163 Set<MethodDescriptor> canCallSESE=new HashSet<MethodDescriptor>(methodSet);
164 Stack<MethodDescriptor> methodStack=new Stack<MethodDescriptor>();
165 methodStack.addAll(methodSet);
166 //Set up exits of SESEs
167 while(!methodStack.isEmpty()) {
168 MethodDescriptor md=methodStack.pop();
169 Set callers=callGraph.getCallerSet(md);
170 for(Object o : callers) {
171 MethodDescriptor callermd=(MethodDescriptor)o;
172 if (!canCallSESE.contains(callermd)) {
173 //new method descriptor
174 canCallSESE.add(callermd);
175 methodStack.add(callermd);
180 //Set up exits of methods
181 for(MethodDescriptor md : canCallSESE) {
182 FlatMethod fm=state.getMethodFlat(md);
183 for(FlatNode fn : fm.getNodeSet()) {
184 if (fn.kind()==FKind.FlatCall) {
185 FlatCall fcall=(FlatCall)fn;
186 MethodDescriptor calledmethod=fcall.getMethod();
187 Set methodsthatcouldbecalled=fcall.getThis()==null?callGraph.getMethods(calledmethod):
188 callGraph.getMethods(calledmethod, fcall.getThis().getType());
189 boolean specialcall=false;
190 for(Object o : methodsthatcouldbecalled) {
191 MethodDescriptor callermd=(MethodDescriptor)o;
192 if (canCallSESE.contains(callermd)) {
193 //TODO: NEED TO BUILD MAP FROM MD -> CALLS
195 if (!methodmap.containsKey(callermd))
196 methodmap.put(callermd, new HashSet<Pair<FlatCall, MethodDescriptor>>());
197 methodmap.get(callermd).add(new Pair<FlatCall, MethodDescriptor>(fcall,md));
201 Set<TempDescriptor> liveout=new HashSet<TempDescriptor>(liveness.getLiveOutTemps(fm, fcall));
202 TempDescriptor returntmp=fcall.getReturnTemp();
203 liveout.remove(returntmp);
204 for(Iterator<TempDescriptor> tmpit=liveout.iterator(); tmpit.hasNext(); ) {
205 TempDescriptor tmp=tmpit.next();
206 if (!tmp.getType().isPtr())
209 inAccessible.put(fcall, liveout);
210 for(int i=0; i<fcall.numNext(); i++)
211 toprocess.add(new Pair<FlatNode, MethodDescriptor>(fcall.getNext(i),md));