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() );
206 // if the top of stack is not bogus one, it should be a non-bogus parent to the current sese
207 if(!seseStack.peek().getIsCallerSESEplaceholder()){
208 fsen.addSESEParent(seseStack.peek());
212 seseStack.push( fsen );
215 case FKind.FlatSESEExitNode: {
216 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
217 assert !seseStack.empty();
218 FlatSESEEnterNode fsen = seseStack.pop();
221 case FKind.FlatReturnNode: {
222 FlatReturnNode frn = (FlatReturnNode) fn;
223 if( !seseStack.empty() &&
224 !seseStack.peek().getIsCallerSESEplaceholder()
226 throw new Error( "Error: return statement enclosed within SESE "+
227 seseStack.peek().getPrettyIdentifier() );
235 protected void computeLeafSESEs() {
237 Set<FlatSESEEnterNode> all=new HashSet<FlatSESEEnterNode>();
238 all.addAll(allSESEs);
239 all.addAll(allBogusSESEs);
241 for (Iterator<FlatSESEEnterNode> itr = all.iterator(); itr.hasNext();) {
242 FlatSESEEnterNode fsen = itr.next();
244 boolean hasNoNestedChildren = fsen.getChildren().isEmpty();
245 boolean hasNoChildrenByCall = !hasChildrenByCall(fsen);
247 fsen.setIsLeafSESE(hasNoNestedChildren && hasNoChildrenByCall);
250 // for( Iterator<FlatSESEEnterNode> itr = allSESEs.iterator();
253 // FlatSESEEnterNode fsen = itr.next();
255 // boolean hasNoNestedChildren = fsen.getChildren().isEmpty();
256 // boolean hasNoChildrenByCall = !hasChildrenByCall( fsen );
258 // fsen.setIsLeafSESE( hasNoNestedChildren &&
259 // hasNoChildrenByCall );
264 protected boolean hasChildrenByCall(FlatSESEEnterNode fsen) {
265 boolean hasChildrenByCall=false;
267 // visit every flat node in SESE body, find method calls that
268 // may transitively call methods with SESEs enclosed
269 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
270 flatNodesToVisit.add(fsen);
272 Set<FlatNode> visited = new HashSet<FlatNode>();
274 while (!flatNodesToVisit.isEmpty()) {
275 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
276 FlatNode fn = fnItr.next();
278 flatNodesToVisit.remove(fn);
281 if (fn.kind() == FKind.FlatCall) {
282 FlatCall fc = (FlatCall) fn;
283 MethodDescriptor mdCallee = fc.getMethod();
284 Set reachable = new HashSet();
286 reachable.add(mdCallee);
287 reachable.addAll(callGraph.getAllMethods(mdCallee));
289 reachable.retainAll(methodsContainingSESEs);
291 if (!reachable.isEmpty()) {
292 hasChildrenByCall = true;
294 if (!fsen.getIsCallerSESEplaceholder()) {
295 Set reachableSESEMethodSet =
296 callGraph.getFirstReachableMethodContainingSESE(mdCallee, methodsContainingSESEs);
298 reachableSESEMethodSet.add(mdCallee);
300 for (Iterator iterator = reachableSESEMethodSet.iterator(); iterator.hasNext();) {
301 MethodDescriptor md = (MethodDescriptor) iterator.next();
302 FlatMethod fm = state.getMethodFlat(md);
303 FlatSESEEnterNode fsenBogus = (FlatSESEEnterNode) fm.getNext(0);
304 fsenBogus.addSESEParent(fsen);
307 reachableSESEMethodSet.retainAll(methodsContainingSESEs);
309 for (Iterator iterator = reachableSESEMethodSet.iterator(); iterator.hasNext();) {
310 MethodDescriptor md = (MethodDescriptor) iterator.next();
311 Set<FlatSESEEnterNode> seseSet = md2seseSet.get(md);
312 if (seseSet != null) {
313 fsen.addSESEChildren(seseSet);
314 for (Iterator iterator2 = seseSet.iterator(); iterator2.hasNext();) {
315 FlatSESEEnterNode child = (FlatSESEEnterNode) iterator2.next();
316 child.addSESEParent(fsen);
326 if (fn == fsen.getFlatExit()) {
327 // don't enqueue any futher nodes
331 for (int i = 0; i < fn.numNext(); i++) {
332 FlatNode nn = fn.getNext(i);
334 if (!visited.contains(nn)) {
335 flatNodesToVisit.add(nn);
340 return hasChildrenByCall;