Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* Soot - a J*va Optimization Framework
   * Copyright (C) 1997-1999 Raja Vallee-Rai
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 /*
  * Modified by the Sable Research Group and others 1997-1999.  
  * See the 'credits' file distributed with Soot for the complete list of
  * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
  */
 
 /* Reference Version: $SootVersion: 1.2.5.dev.5 $ */
 
 package soot.jimple.toolkits.base;
 import soot.options.*;
 
 import soot.*;
 import soot.jimple.*;
 import soot.util.*;
 import java.util.*;
 
 public class Aggregator extends BodyTransformer
 {
     public AggregatorSingletons.Global g ) {}
     public static Aggregator v() { return G.v().soot_jimple_toolkits_base_Aggregator(); }

    
Traverse the statements in the given body, looking for aggregation possibilities; that is, given a def d and a use u, d has no other uses, u has no other defs, collapse d and u. option: only-stack-locals; if this is true, only aggregate variables starting with $
 
     protected void internalTransform(Body bString phaseNameMap options)
     {
         StmtBody body = (StmtBody)b;
         boolean onlyStackVars = PhaseOptions.getBoolean(options"only-stack-locals"); 
 
         int aggregateCount = 1;
 
         if(Options.v().time())
             Timers.v()..start();
          boolean changed = false;
 
         Map<ValueBoxZoneboxToZone = new HashMap<ValueBoxZone>(body.getUnits().size() * 2 + 1, 0.7f);
 
         // Determine the zone of every box
         {
             Zonation zonation = new Zonation(body);
             
             Iterator unitIt = body.getUnits().iterator();
             
             while(unitIt.hasNext())
             {
                 Unit u = (UnitunitIt.next();
                 Zone zone = zonation.getZoneOf(u);
                 
                 Iterator boxIt = u.getUseBoxes().iterator();
                 while(boxIt.hasNext())
                 {
                     ValueBox box = (ValueBoxboxIt.next();                    
                     boxToZone.put(boxzone);
                 }   
                 boxIt = u.getDefBoxes().iterator();
                 while(boxIt.hasNext())
                 {
                     ValueBox box = (ValueBoxboxIt.next();                    
                     boxToZone.put(boxzone);
                 }   
             }
         }        
         
                      
         do {
             if(Options.v().verbose())
                 G.v()..println("[" + body.getMethod().getName() + "] Aggregating iteration " + aggregateCount + "...");
         
             // body.printTo(new java.io.PrintWriter(G.v().out, true));
             
             changed = internalAggregate(bodyboxToZoneonlyStackVars);
             
             aggregateCount++;
         } while(changed);
         
        if(Options.v().time())
            Timers.v()..end();
            
    }
  
  private static boolean internalAggregate(StmtBody bodyMap<ValueBoxZoneboxToZoneboolean onlyStackVars)
    {
      Iterator stmtIt;
      LocalUses localUses;
      LocalDefs localDefs;
      ExceptionalUnitGraph graph;
      boolean hadAggregation = false;
      Chain units = body.getUnits();
      
      graph = new ExceptionalUnitGraph(body);
      localDefs = new SmartLocalDefs(graphnew SimpleLiveLocals(graph));
      localUses = new SimpleLocalUses(graphlocalDefs);
          
      stmtIt = (new PseudoTopologicalOrderer()).newList(graph,false).iterator();
      
      while (stmtIt.hasNext())
        {
          Stmt s = (Stmt)(stmtIt.next());
              
          if (!(s instanceof AssignStmt))
            continue;
          
          Value lhs = ((AssignStmt)s).getLeftOp();
          if (!(lhs instanceof Local))
            continue;
    
          if(onlyStackVars && !((Locallhs).getName().startsWith("$"))
            continue;
            
          List lu = localUses.getUsesOf(s);
          if (lu.size() != 1)
            continue;
            
          UnitValueBoxPair usepair = (UnitValueBoxPair)lu.get(0);
          Unit use = usepair.unit;
          ValueBox useBox = usepair.valueBox;
              
          List<Unitld = localDefs.getDefsOfAt((Local)lhsuse);
          if (ld.size() != 1)
            continue;
   
          // Check to make sure aggregation pair in the same zone
            if(boxToZone.get(((AssignStmts).getRightOpBox()) != boxToZone.get(usepair.valueBox))
            {
                continue;
            }  
             
          /* we need to check the path between def and use */
          /* to see if there are any intervening re-defs of RHS */
          /* in fact, we should check that this path is unique. */
          /* if the RHS uses only locals, then we know what
             to do; if RHS has a method invocation f(a, b,
             c) or field access, we must ban field writes, other method
             calls and (as usual) writes to a, b, c. */
          
          boolean cantAggr = false;
          boolean propagatingInvokeExpr = false;
          boolean propagatingFieldRef = false;
          boolean propagatingArrayRef = false;
          ArrayList<ValuefieldRefList = new ArrayList<Value>();
      
          LinkedList<ValuelocalsUsed = new LinkedList<Value>();
          for (Iterator useIt = (s.getUseBoxes()).iterator();
               useIt.hasNext(); )
            {
              Value v = ((ValueBox)(useIt.next())).getValue();
                if (v instanceof Local)
                    localsUsed.add(v);
                else if (v instanceof InvokeExpr)
                    propagatingInvokeExpr = true;
                else if(v instanceof ArrayRef)
                    propagatingArrayRef = true;
                else if(v instanceof FieldRef)
                {
                    propagatingFieldRef = true;
                    fieldRefList.add(v);
                }
            }
          
          // look for a path from s to use in graph.
          // only look in an extended basic block, though.
          List<Unitpath = graph.getExtendedBasicBlockPathBetween(suse);
      
          if (path == null)
            continue;
          Iterator<UnitpathIt = path.iterator();
          // skip s.
          if (pathIt.hasNext())
            pathIt.next();
          while (pathIt.hasNext() && !cantAggr)
          {
              Stmt between = (Stmt)(pathIt.next());
          
              if(between != use)    
              {
                // Check for killing definitions
                
                for (Iterator it = between.getDefBoxes().iterator();
                       it.hasNext(); )
                  {
                      Value v = ((ValueBox)(it.next())).getValue();
                      if (localsUsed.contains(v))
                      { 
                            cantAggr = true
                            break
                      }
                      
                      if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef)
                      {
                          if (v instanceof FieldRef)
                          {
                              if(propagatingInvokeExpr)
                              {
                                  cantAggr = true
                                  break;
                              }
                              else if(propagatingFieldRef)
                              {
                                  // Can't aggregate a field access if passing a definition of a field 
                                  // with the same name, because they might be aliased
                                  Iterator<ValuefrIt = fieldRefList.iterator();
                                  while (frIt.hasNext())
                                  {
                                      FieldRef fieldRef = (FieldReffrIt.next();
                                      if(((FieldRefv).getField() == fieldRef.getField())
                                      {
                                          cantAggr = true;
                                          break;
                                      } 
                                  }
                              } 
                           }
                           else if(v instanceof ArrayRef)
                           {
                                if(propagatingInvokeExpr)
                                {   
                                    // Cannot aggregate an invoke expr past an array write
                                    cantAggr = true;
                                    break;
                                }
                                else if(propagatingArrayRef)
                                {
                                    // cannot aggregate an array read past a write
                                    // this is somewhat conservative
                                    // (if types differ they may not be aliased)
                                    
                                    cantAggr = true;
                                    break;
                                }
                           }
                      }
                  }
                  
                  // Make sure not propagating past a {enter,exit}Monitor
                    if(propagatingInvokeExpr && between instanceof MonitorStmt)
                        cantAggr = true;
              }  
                            
              // Check for intervening side effects due to method calls
                if(propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef)
                    {
                      forIterator boxIt = (between.getUseBoxes()).iterator(); boxIt.hasNext(); ) {
                          final ValueBox box = (ValueBoxboxIt.next();
                          
                          if(between == use && box == useBox)
                          {
                                // Reached use point, stop looking for
                                // side effects
                                break;
                          }
                          
                          Value v = box.getValue();
                          
                            if (v instanceof InvokeExpr || 
                                (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef)))
                            {
                                cantAggr = true;
                                break;
                            }
                            
                        }
                    }
            }
          // we give up: can't aggregate.
          if (cantAggr)
          {
            continue;
          }
          /* assuming that the d-u chains are correct, */
          /* we need not check the actual contents of ld */
          
          Value aggregatee = ((AssignStmt)s).getRightOp();
          
          if (usepair.valueBox.canContainValue(aggregatee))
            {
              boolean wasSimpleCopy = isSimpleCopyusepair.unit );
              usepair.valueBox.setValue(aggregatee);
              units.remove(s);
              hadAggregation = true;
              // clean up the tags. If s was not a simple copy, the new statement should get
              // the tags of s.
              // OK, this fix was wrong. The condition should not be
              // "If s was not a simple copy", but rather "If usepair.unit
              // was a simple copy". This way, when there's a load of a constant
              // followed by an invoke, the invoke gets the tags.
              ifwasSimpleCopy ) {
                  //usepair.unit.removeAllTags();
                  usepair.unit.addAllTagsOfs );
              }
            }
          else
            {/*
            if(Options.v().verbose())
            {
                G.v().out.println("[debug] failed aggregation");
                  G.v().out.println("[debug] tried to put "+aggregatee+
                                 " into "+usepair.stmt + 
                                 ": in particular, "+usepair.valueBox);
                  G.v().out.println("[debug] aggregatee instanceof Expr: "
                                 +(aggregatee instanceof Expr));
            }*/
            }
        }
      return hadAggregation;
    }
  private static boolean isSimpleCopyUnit u ) {
      if( !(u instanceof DefinitionStmt) ) return false;
      DefinitionStmt defstmt = (DefinitionStmtu;
      if( !( defstmt.getRightOp() instanceof Local ) ) return false;
      if( !( defstmt.getLeftOp() instanceof Local ) ) return false;
      return true;
  }
        
New to GrepCode? Check out our FAQ X