Home | History | Annotate | Download | only in evaluation
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.evaluation;
     22 
     23 import proguard.classfile.Clazz;
     24 import proguard.classfile.attribute.CodeAttribute;
     25 import proguard.evaluation.value.InstructionOffsetValue;
     26 
     27 /**
     28  * This BranchUnit remembers the branch unit commands that are invoked on it.
     29  * I doesn't consider conditions when branching.
     30  *
     31  * @author Eric Lafortune
     32  */
     33 public class BasicBranchUnit
     34 implements   BranchUnit
     35 {
     36     private boolean                wasCalled;
     37     private InstructionOffsetValue traceBranchTargets;
     38 
     39 
     40     /**
     41      * Resets the flag that tells whether any of the branch unit commands was
     42      * called.
     43      */
     44     public void resetCalled()
     45     {
     46         wasCalled = false;
     47     }
     48 
     49     /**
     50      * Sets the flag that tells whether any of the branch unit commands was
     51      * called.
     52      */
     53     protected void setCalled()
     54     {
     55         wasCalled = true;
     56     }
     57 
     58     /**
     59      * Returns whether any of the branch unit commands was called.
     60      */
     61     public boolean wasCalled()
     62     {
     63         return wasCalled;
     64     }
     65 
     66 
     67     /**
     68      * Sets the initial branch targets, which will be updated as the branch
     69      * methods of the branch unit are called.
     70      */
     71     public void setTraceBranchTargets(InstructionOffsetValue branchTargets)
     72     {
     73         this.traceBranchTargets = branchTargets;
     74     }
     75 
     76     public InstructionOffsetValue getTraceBranchTargets()
     77     {
     78         return traceBranchTargets;
     79     }
     80 
     81 
     82     // Implementations for BranchUnit.
     83 
     84     public void branch(Clazz         clazz,
     85                        CodeAttribute codeAttribute,
     86                        int           offset,
     87                        int           branchTarget)
     88     {
     89         // Override the branch targets.
     90         traceBranchTargets = new InstructionOffsetValue(branchTarget);
     91 
     92         wasCalled = true;
     93     }
     94 
     95 
     96     public void branchConditionally(Clazz         clazz,
     97                                     CodeAttribute codeAttribute,
     98                                     int           offset,
     99                                     int           branchTarget,
    100                                     int           conditional)
    101     {
    102         // Accumulate the branch targets.
    103         traceBranchTargets =
    104             traceBranchTargets.generalize(new InstructionOffsetValue(branchTarget)).instructionOffsetValue();
    105 
    106         wasCalled = true;
    107     }
    108 
    109 
    110     public void returnFromMethod()
    111     {
    112         // Stop processing this block.
    113         traceBranchTargets = InstructionOffsetValue.EMPTY_VALUE;
    114 
    115         wasCalled = true;
    116     }
    117 
    118 
    119     public void throwException()
    120     {
    121         // Stop processing this block.
    122         traceBranchTargets = InstructionOffsetValue.EMPTY_VALUE;
    123 
    124         wasCalled = true;
    125     }
    126 }
    127