All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.scalar.CopyPropagator Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* 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)
 */






package soot.jimple.toolkits.scalar;
import soot.options.*;

import soot.*;
import soot.jimple.*;
import soot.toolkits.scalar.*;
import soot.toolkits.graph.*;
import soot.util.*;
import java.util.*;
import soot.options.CPOptions;

public class CopyPropagator extends BodyTransformer
{
    public CopyPropagator( Singletons.Global g ) {}
    public static CopyPropagator v() { return G.v().soot_jimple_toolkits_scalar_CopyPropagator(); }

    /** Cascaded copy propagator.
    
        If it encounters situations of the form: A: a = ...; B: ... x = a; C:... use (x); 
        where a has only one definition, and x has only one definition (B), then it can 
        propagate immediately without checking between B and C for redefinitions
        of a (namely) A because they cannot occur.  In this case the propagator is global.
        
        Otherwise, if a has multiple definitions then it only checks for redefinitions of
        Propagates constants and copies in extended basic blocks. 
        
        Does not propagate stack locals when the "only-regular-locals" option is true.
    */
    protected void internalTransform(Body b, String phaseName, Map opts)
    {
        CPOptions options = new CPOptions( opts );
        StmtBody stmtBody = (StmtBody)b;
        int fastCopyPropagationCount = 0;
        int slowCopyPropagationCount = 0;
        
        if(Options.v().verbose())
            G.v().out.println("[" + stmtBody.getMethod().getName() +
                "] Propagating copies...");

        if(Options.v().time())
            Timers.v().propagatorTimer.start();                
                
        Chain units = stmtBody.getUnits();

        Map localToDefCount = new HashMap();
        
        // Count number of definitions for each local.
        {
            Iterator stmtIt = units.iterator();
        
            while(stmtIt.hasNext())
            {
                Stmt s = (Stmt) stmtIt.next();
                
                if(s instanceof DefinitionStmt &&
                    ((DefinitionStmt) s).getLeftOp() instanceof Local)
                {
                    Local l = (Local) ((DefinitionStmt) s).getLeftOp();
                     
                    if(!localToDefCount.containsKey(l))
                        localToDefCount.put(l, new Integer(1));
                    else 
                        localToDefCount.put(l, new Integer(localToDefCount.get(l).intValue() + 1));
                }
                
            }
        }
        
//            ((JimpleBody) stmtBody).printDebugTo(new java.io.PrintWriter(G.v().out, true));
            
        ExceptionalUnitGraph graph = new ExceptionalUnitGraph(stmtBody);

        LocalDefs localDefs;
        
        localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph));

        // Perform a local propagation pass.
        {
            Iterator stmtIt = (new PseudoTopologicalOrderer()).newList(graph,false).iterator();

            while(stmtIt.hasNext())
            {
                Stmt stmt = (Stmt) stmtIt.next();
                Iterator useBoxIt = stmt.getUseBoxes().iterator();

                while(useBoxIt.hasNext())
                {
                    ValueBox useBox = (ValueBox) useBoxIt.next();

                    if(useBox.getValue() instanceof Local)
                    {
                        Local l = (Local) useBox.getValue();

                        if(options.only_regular_locals() && l.getName().startsWith("$"))
                            continue;
       
                        if(options.only_stack_locals() && !l.getName().startsWith("$"))
                            continue;
                            
                        List defsOfUse = localDefs.getDefsOfAt(l, stmt);

                        if(defsOfUse.size() == 1)
                        {
                            DefinitionStmt def = (DefinitionStmt) defsOfUse.get(0);

                            if(def.getRightOp() instanceof Local)
                            {
                                Local m = (Local) def.getRightOp();

                                if(l != m)
                                {   
                                    Object dcObj = localToDefCount.get(m);

                                    if (dcObj == null)
                                        throw new RuntimeException("Variable " + m + " used without definition!");

                                    int defCount = ((Integer)dcObj).intValue();
                                    
                                    if(defCount == 0)
                                        throw new RuntimeException("Variable " + m + " used without definition!");
                                    else if(defCount == 1)
                                    {
                                        useBox.setValue(m);
                                        fastCopyPropagationCount++;
                                        continue;
                                    }

                                    List path = graph.getExtendedBasicBlockPathBetween(def, stmt);
                                    
                                    if(path == null)
                                    {
                                        // no path in the extended basic block
                                        continue;
                                    }
                                     
                                    Iterator pathIt = path.iterator();
                                    
                                    // Skip first node
                                        pathIt.next();
                                        
                                    // Make sure that m is not redefined along path
                                    {
                                        boolean isRedefined = false;
                                        
                                        while(pathIt.hasNext())
                                        {
                                            Stmt s = (Stmt) pathIt.next();
                                            
                                            if(stmt == s)
                                            {
                                                // Don't look at the last statement 
                                                // since it is evaluated after the uses
                                                
                                                break;
                                            }   
                                            if(s instanceof DefinitionStmt)
                                            {
                                                if(((DefinitionStmt) s).getLeftOp() == m)
                                                {
                                                    isRedefined = true;
                                                    break;
                                                }        
                                            }
                                        }
                                        
                                        if(isRedefined)
                                            continue;
                                            
                                    }
                                    
                                    useBox.setValue(m);
                                    slowCopyPropagationCount++;
                                }
                            }
                        }
                    }

                 }
            }
        }


        if(Options.v().verbose())
            G.v().out.println("[" + stmtBody.getMethod().getName() +
                "]     Propagated: " +
                fastCopyPropagationCount + " fast copies  " +
                slowCopyPropagationCount + " slow copies");
     
        if(Options.v().time())
            Timers.v().propagatorTimer.end();
    
    }
    
}


































© 2015 - 2024 Weber Informatics LLC | Privacy Policy