1 package Analysis.OoOJava;
5 import Analysis.CallGraph.CallGraph;
6 import IR.MethodDescriptor;
10 // This analysis computes relations between rblocks
11 // and identifies important rblocks.
13 public class RBlockRelationAnalysis {
20 // an implicit SESE is automatically spliced into
21 // the IR graph around the C main before this analysis--it
22 // is nothing special except that we can make assumptions
23 // about it, such as the whole program ends when it ends
24 protected FlatSESEEnterNode mainSESE;
26 // SESEs that are the root of an SESE tree belong to this
27 // set--the main SESE is always a root, statically SESEs
28 // inside methods are a root because we don't know how they
29 // will fit into the runtime tree of SESEs
30 protected Set<FlatSESEEnterNode> rootSESEs;
32 // simply a set of every reachable SESE in the program, not
33 // including caller placeholder SESEs
34 protected Set<FlatSESEEnterNode> allSESEs;
36 // a set of every bogus palceholder SESEs
37 protected Set<FlatSESEEnterNode> allBogusSESEs;
39 // per method-per node-rblock stacks
40 protected Hashtable< FlatMethod,
42 Stack<FlatSESEEnterNode>
46 // to support calculation of leaf SESEs (no children even
47 // through method calls) for optimization during code gen
48 protected Set<MethodDescriptor> methodsContainingSESEs;
50 // maps method descriptor to SESE defined inside of it
51 // only contains top-level SESE definition in corresponding method
52 protected Hashtable<MethodDescriptor, Set<FlatSESEEnterNode>> md2seseSet;
54 public RBlockRelationAnalysis( State state,
56 CallGraph callGraph ) {
58 this.typeUtil = typeUtil;
59 this.callGraph = callGraph;
61 rootSESEs = new HashSet<FlatSESEEnterNode>();
62 allSESEs = new HashSet<FlatSESEEnterNode>();
63 allBogusSESEs = new HashSet<FlatSESEEnterNode>();
65 methodsContainingSESEs = new HashSet<MethodDescriptor>();
68 new Hashtable< FlatMethod, Hashtable< FlatNode, Stack<FlatSESEEnterNode> > >();
70 md2seseSet = new Hashtable<MethodDescriptor, Set<FlatSESEEnterNode>>();
73 MethodDescriptor mdSourceEntry = typeUtil.getMain();
74 FlatMethod fmMain = state.getMethodFlat( mdSourceEntry );
76 mainSESE = (FlatSESEEnterNode) fmMain.getNext( 0 );
77 mainSESE.setfmEnclosing( fmMain );
78 mainSESE.setmdEnclosing( fmMain.getMethod() );
79 mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
81 // add all methods transitively reachable from the
82 // source's main to set for analysis
83 Set<MethodDescriptor> descriptorsToAnalyze =
84 callGraph.getAllMethods( mdSourceEntry );
86 descriptorsToAnalyze.add( mdSourceEntry );
88 analyzeMethods( descriptorsToAnalyze );
94 public FlatSESEEnterNode getMainSESE() {
98 public Set<FlatSESEEnterNode> getRootSESEs() {
102 public Set<FlatSESEEnterNode> getAllSESEs() {
106 public Stack<FlatSESEEnterNode> getRBlockStacks( FlatMethod fm,
108 if( !fm2relmap.containsKey( fm ) ) {
109 fm2relmap.put( fm, computeRBlockRelations( fm ) );
111 return fm2relmap.get( fm ).get( fn );
115 protected void analyzeMethods( Set<MethodDescriptor> descriptorsToAnalyze ) {
117 Iterator<MethodDescriptor> mdItr = descriptorsToAnalyze.iterator();
118 while( mdItr.hasNext() ) {
119 FlatMethod fm = state.getMethodFlat( mdItr.next() );
121 Hashtable< FlatNode, Stack<FlatSESEEnterNode> > relmap =
122 computeRBlockRelations( fm );
124 fm2relmap.put( fm, relmap );
128 public Hashtable< FlatNode, Stack<FlatSESEEnterNode> >
129 computeRBlockRelations( FlatMethod fm ) {
131 Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks =
132 new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
134 // start from flat method top, visit every node in
135 // method exactly once, find SESE stack on every
137 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
138 flatNodesToVisit.add( fm );
140 Set<FlatNode> visited = new HashSet<FlatNode>();
142 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
143 seseStacks.put( fm, seseStackFirst );
145 while( !flatNodesToVisit.isEmpty() ) {
146 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
147 FlatNode fn = fnItr.next();
149 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
150 assert seseStack != null;
152 flatNodesToVisit.remove( fn );
155 nodeActions( fn, seseStack, fm );
157 for( int i = 0; i < fn.numNext(); i++ ) {
158 FlatNode nn = fn.getNext( i );
160 if( !visited.contains( nn ) ) {
161 flatNodesToVisit.add( nn );
163 // clone stack and send along each control path
164 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
172 protected void nodeActions( FlatNode fn,
173 Stack<FlatSESEEnterNode> seseStack,
175 switch( fn.kind() ) {
177 case FKind.FlatSESEEnterNode: {
178 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
180 if( !fsen.getIsCallerSESEplaceholder() ) {
181 allSESEs.add( fsen );
182 methodsContainingSESEs.add( fm.getMethod() );
184 allBogusSESEs.add(fsen);
187 fsen.setfmEnclosing( fm );
188 fsen.setmdEnclosing( fm.getMethod() );
189 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
191 if(!fsen.getIsCallerSESEplaceholder() && fsen.getParent()==null ){
192 Set<FlatSESEEnterNode> seseSet=md2seseSet.get(fm.getMethod());
194 seseSet=new HashSet<FlatSESEEnterNode>();
197 md2seseSet.put(fm.getMethod(), seseSet);
200 if( seseStack.empty() ) {
201 rootSESEs.add( fsen );
202 fsen.setParent( null );
204 seseStack.peek().addChild( fsen );
205 fsen.setParent( seseStack.peek() );
208 seseStack.push( fsen );
211 case FKind.FlatSESEExitNode: {
212 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
213 assert !seseStack.empty();
214 FlatSESEEnterNode fsen = seseStack.pop();
217 case FKind.FlatReturnNode: {
218 FlatReturnNode frn = (FlatReturnNode) fn;
219 if( !seseStack.empty() &&
220 !seseStack.peek().getIsCallerSESEplaceholder()
222 throw new Error( "Error: return statement enclosed within SESE "+
223 seseStack.peek().getPrettyIdentifier() );
231 protected void computeLeafSESEs() {
233 Set<FlatSESEEnterNode> all=new HashSet<FlatSESEEnterNode>();
234 all.addAll(allSESEs);
235 all.addAll(allBogusSESEs);
237 for (Iterator<FlatSESEEnterNode> itr = all.iterator(); itr.hasNext();) {
238 FlatSESEEnterNode fsen = itr.next();
240 boolean hasNoNestedChildren = fsen.getChildren().isEmpty();
241 boolean hasNoChildrenByCall = !hasChildrenByCall(fsen);
243 fsen.setIsLeafSESE(hasNoNestedChildren && hasNoChildrenByCall);
246 // for( Iterator<FlatSESEEnterNode> itr = allSESEs.iterator();
249 // FlatSESEEnterNode fsen = itr.next();
251 // boolean hasNoNestedChildren = fsen.getChildren().isEmpty();
252 // boolean hasNoChildrenByCall = !hasChildrenByCall( fsen );
254 // fsen.setIsLeafSESE( hasNoNestedChildren &&
255 // hasNoChildrenByCall );
260 protected boolean hasChildrenByCall(FlatSESEEnterNode fsen) {
262 boolean hasChildrenByCall=false;
264 // visit every flat node in SESE body, find method calls that
265 // may transitively call methods with SESEs enclosed
266 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
267 flatNodesToVisit.add(fsen);
269 Set<FlatNode> visited = new HashSet<FlatNode>();
271 while (!flatNodesToVisit.isEmpty()) {
272 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
273 FlatNode fn = fnItr.next();
275 flatNodesToVisit.remove(fn);
278 if (fn.kind() == FKind.FlatCall) {
279 FlatCall fc = (FlatCall) fn;
280 MethodDescriptor mdCallee = fc.getMethod();
281 Set reachable = new HashSet();
283 reachable.add(mdCallee);
284 reachable.addAll(callGraph.getAllMethods(mdCallee));
286 reachable.retainAll(methodsContainingSESEs);
288 if (!reachable.isEmpty()) {
289 hasChildrenByCall = true;
291 if (!fsen.getIsCallerSESEplaceholder()) {
292 // System.out.println("%%%mdCallee="+mdCallee+" from fsen="+fsen);
293 Set reachableSESEMethodSet =
294 callGraph.getFirstReachableMethodContainingSESE(mdCallee, methodsContainingSESEs);
296 // if (methodsContainingSESEs.contains(mdCallee)) {
297 reachableSESEMethodSet.add(mdCallee);
300 // System.out.println("#");
301 // System.out.println("fsen"+fsen);
302 // System.out.println("reachableSESEMethodSet="+reachableSESEMethodSet);
304 for (Iterator iterator = reachableSESEMethodSet.iterator(); iterator.hasNext();) {
305 MethodDescriptor md = (MethodDescriptor) iterator.next();
306 // Set<FlatSESEEnterNode> seseSet = md2seseSet.get(md);
307 FlatMethod fm = state.getMethodFlat(md);
308 FlatSESEEnterNode fsenBogus = (FlatSESEEnterNode) fm.getNext(0);
309 fsenBogus.addSESEParent(fsen);
310 // System.out.println("% "+fm+"->"+fsen);
313 reachableSESEMethodSet.retainAll(methodsContainingSESEs);
315 for (Iterator iterator = reachableSESEMethodSet.iterator(); iterator.hasNext();) {
316 MethodDescriptor md = (MethodDescriptor) iterator.next();
317 Set<FlatSESEEnterNode> seseSet = md2seseSet.get(md);
318 if (seseSet != null) {
319 fsen.addSESEChildren(seseSet);
320 for (Iterator iterator2 = seseSet.iterator(); iterator2.hasNext();) {
321 FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
322 child.addSESEParent(fsen);
332 if (fn == fsen.getFlatExit()) {
333 // don't enqueue any futher nodes
337 for (int i = 0; i < fn.numNext(); i++) {
338 FlatNode nn = fn.getNext(i);
340 if (!visited.contains(nn)) {
341 flatNodesToVisit.add(nn);
346 return hasChildrenByCall;