1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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 */ 21 package proguard.evaluation; 22 23 import proguard.evaluation.value.Value; 24 25 /** 26 * This Variables class saves additional information with variables, to keep 27 * track of their origins. 28 * <p> 29 * The Variables class stores a given producer Value along with each Value it 30 * stores. It then generalizes a given collected Value with the producer Value 31 * of each Value it loads. The producer Value and the initial collected Value 32 * can be set; the generalized collected Value can be retrieved. 33 * 34 * @author Eric Lafortune 35 */ 36 public class TracedVariables extends Variables 37 { 38 public static final int NONE = -1; 39 40 41 private Value producerValue; 42 private Variables producerVariables; 43 44 45 /** 46 * Creates a new TracedVariables with a given size. 47 */ TracedVariables(int size)48 public TracedVariables(int size) 49 { 50 super(size); 51 52 producerVariables = new Variables(size); 53 } 54 55 56 /** 57 * Creates a new TracedVariables that is a copy of the given TracedVariables. 58 */ TracedVariables(TracedVariables tracedVariables)59 public TracedVariables(TracedVariables tracedVariables) 60 { 61 super(tracedVariables); 62 63 producerVariables = new Variables(tracedVariables.producerVariables); 64 } 65 66 67 /** 68 * Sets the Value that will be stored along with all store instructions. 69 */ setProducerValue(Value producerValue)70 public void setProducerValue(Value producerValue) 71 { 72 this.producerValue = producerValue; 73 } 74 75 76 /** 77 * Gets the producer Value for the specified variable, without disturbing it. 78 * @param index the variable index. 79 * @return the producer value of the given variable. 80 */ getProducerValue(int index)81 public Value getProducerValue(int index) 82 { 83 return producerVariables.getValue(index); 84 } 85 86 87 /** 88 * Sets the given producer Value for the specified variable, without 89 * disturbing it. 90 * @param index the variable index. 91 * @param value the producer value to set. 92 */ setProducerValue(int index, Value value)93 public void setProducerValue(int index, Value value) 94 { 95 producerVariables.store(index, value); 96 } 97 98 99 // Implementations for Variables. 100 reset(int size)101 public void reset(int size) 102 { 103 super.reset(size); 104 105 producerVariables.reset(size); 106 } 107 initialize(TracedVariables other)108 public void initialize(TracedVariables other) 109 { 110 super.initialize(other); 111 112 producerVariables.initialize(other.producerVariables); 113 } 114 generalize(TracedVariables other, boolean clearConflictingOtherVariables)115 public boolean generalize(TracedVariables other, 116 boolean clearConflictingOtherVariables) 117 { 118 boolean variablesChanged = super.generalize(other, clearConflictingOtherVariables); 119 boolean producersChanged = producerVariables.generalize(other.producerVariables, clearConflictingOtherVariables); 120 /* consumerVariables.generalize(other.consumerVariables)*/ 121 122 // Clear any traces if a variable has become null. 123 if (variablesChanged) 124 { 125 for (int index = 0; index < size; index++) 126 { 127 if (values[index] == null) 128 { 129 producerVariables.values[index] = null; 130 131 if (clearConflictingOtherVariables) 132 { 133 other.producerVariables.values[index] = null; 134 } 135 } 136 } 137 } 138 139 return variablesChanged || producersChanged; 140 } 141 142 store(int index, Value value)143 public void store(int index, Value value) 144 { 145 // Store the value itself in the variable. 146 super.store(index, value); 147 148 // Store the producer value in its producer variable. 149 producerVariables.store(index, producerValue); 150 151 // Account for the extra space required by Category 2 values. 152 if (value.isCategory2()) 153 { 154 producerVariables.store(index+1, producerValue); 155 } 156 } 157 158 159 // Implementations for Object. 160 equals(Object object)161 public boolean equals(Object object) 162 { 163 if (object == null || 164 this.getClass() != object.getClass()) 165 { 166 return false; 167 } 168 169 TracedVariables other = (TracedVariables)object; 170 171 return super.equals(object) && 172 this.producerVariables.equals(other.producerVariables); 173 } 174 175 hashCode()176 public int hashCode() 177 { 178 return super.hashCode() ^ 179 producerVariables.hashCode(); 180 } 181 182 toString()183 public String toString() 184 { 185 StringBuffer buffer = new StringBuffer(); 186 187 for (int index = 0; index < this.size(); index++) 188 { 189 Value value = this.values[index]; 190 Value producerValue = producerVariables.getValue(index); 191 buffer = buffer.append('[') 192 .append(producerValue == null ? "empty:" : producerValue.toString()) 193 .append(value == null ? "empty" : value.toString()) 194 .append(']'); 195 } 196 197 return buffer.toString(); 198 } 199 } 200