• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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