1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric@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 */ 21package proguard.evaluation; 22 23import proguard.classfile.Clazz; 24import proguard.classfile.attribute.CodeAttribute; 25import 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 */ 33public class BasicBranchUnit 34implements 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